mirror of
https://github.com/LibreELEC/LibreELEC.tv
synced 2025-09-24 19:46:01 +07:00
19238 lines
621 KiB
Diff
19238 lines
621 KiB
Diff
From bfd49543c49747236d401df4351767d584f756ac Mon Sep 17 00:00:00 2001
|
|
From: wsnipex <wsnipex@a1.net>
|
|
Date: Sun, 4 Nov 2012 14:05:52 +0100
|
|
Subject: [PATCH 01/72] configure: add --enable-pvraddons-with-dependencies
|
|
switch for intree building of PVR Addons
|
|
|
|
---
|
|
configure.in | 12 ++++++++++++
|
|
1 file changed, 12 insertions(+)
|
|
|
|
diff --git a/configure.in b/configure.in
|
|
index 4769315..350d960 100644
|
|
--- a/configure.in
|
|
+++ b/configure.in
|
|
@@ -521,6 +521,14 @@ AC_ARG_ENABLE([external-ffmpeg],
|
|
[use_external_ffmpeg=$use_external_libraries])
|
|
|
|
### End of external library options
|
|
+### PVR addons specific
|
|
+AC_ARG_ENABLE([pvraddons-with-dependencies],
|
|
+ [AS_HELP_STRING([--enable-pvraddons-with-dependencies],
|
|
+ [enable build of pvr addons with dependencies (default is no) 'Linux only'])],
|
|
+ [use_pvraddons_with_deps=$enableval],
|
|
+ [use_pvraddons_with_deps=no])
|
|
+
|
|
+### End PVR addons specific
|
|
|
|
if test "x$host_vendor" != "xapple"; then
|
|
DEFAULT_COMPILE_FLAGS="-fPIC -DPIC -D_REENTRANT"
|
|
@@ -2770,12 +2778,16 @@ XB_CONFIG_MODULE([pvr-addons], [
|
|
if test "$USE_EXTERNAL_FFMPEG" = 1; then
|
|
PVR_EXT_FFMPEG="--enable-external-ffmpeg"
|
|
fi
|
|
+ if test "$use_pvraddons_with_deps" = "yes"; then
|
|
+ ADDONS_WITH_DEPS="--enable-addons-with-dependencies"
|
|
+ fi
|
|
./configure \
|
|
--prefix="${prefix}" \
|
|
--host=$host_alias \
|
|
--build=$build_alias \
|
|
--target=$target_alias \
|
|
$PVR_EXT_FFMPEG \
|
|
+ $ADDONS_WITH_DEPS \
|
|
CC="$CC" \
|
|
CXX="$CXX" \
|
|
CFLAGS="$CFLAGS" \
|
|
--
|
|
1.7.10
|
|
|
|
|
|
From dc83e2351e8bf8e904102782ea489d2c8caa2802 Mon Sep 17 00:00:00 2001
|
|
From: xbmc <fernetmenta@online.de>
|
|
Date: Mon, 28 May 2012 10:03:31 +0200
|
|
Subject: [PATCH 02/72] VideoRenerers: add buffering
|
|
|
|
---
|
|
xbmc/Application.cpp | 3 +
|
|
xbmc/cores/VideoRenderers/BaseRenderer.h | 5 +-
|
|
xbmc/cores/VideoRenderers/LinuxRendererGL.cpp | 41 ++--
|
|
xbmc/cores/VideoRenderers/LinuxRendererGL.h | 13 +-
|
|
xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp | 8 +-
|
|
xbmc/cores/VideoRenderers/LinuxRendererGLES.h | 4 +-
|
|
xbmc/cores/VideoRenderers/OverlayRenderer.cpp | 19 +-
|
|
xbmc/cores/VideoRenderers/OverlayRenderer.h | 6 +-
|
|
xbmc/cores/VideoRenderers/RenderManager.cpp | 296 +++++++++++++++++++----
|
|
xbmc/cores/VideoRenderers/RenderManager.h | 48 +++-
|
|
xbmc/cores/VideoRenderers/WinRenderer.cpp | 8 +-
|
|
xbmc/cores/VideoRenderers/WinRenderer.h | 2 +-
|
|
xbmc/cores/dvdplayer/DVDPlayer.cpp | 2 +-
|
|
xbmc/cores/dvdplayer/DVDPlayerVideo.cpp | 18 +-
|
|
14 files changed, 380 insertions(+), 93 deletions(-)
|
|
|
|
diff --git a/xbmc/Application.cpp b/xbmc/Application.cpp
|
|
index c6f0a14..18e6310 100644
|
|
--- a/xbmc/Application.cpp
|
|
+++ b/xbmc/Application.cpp
|
|
@@ -2367,7 +2367,10 @@ void CApplication::Render()
|
|
m_lastFrameTime = XbmcThreads::SystemClockMillis();
|
|
|
|
if (flip)
|
|
+ {
|
|
g_graphicsContext.Flip(dirtyRegions);
|
|
+ g_renderManager.NotifyDisplayFlip();
|
|
+ }
|
|
CTimeUtils::UpdateFrameTime(flip);
|
|
|
|
g_TextureManager.FreeUnusedTextures();
|
|
diff --git a/xbmc/cores/VideoRenderers/BaseRenderer.h b/xbmc/cores/VideoRenderers/BaseRenderer.h
|
|
index 81d21d8..b02d536 100644
|
|
--- a/xbmc/cores/VideoRenderers/BaseRenderer.h
|
|
+++ b/xbmc/cores/VideoRenderers/BaseRenderer.h
|
|
@@ -80,10 +80,13 @@ class CBaseRenderer
|
|
void GetVideoRect(CRect &source, CRect &dest);
|
|
float GetAspectRatio() const;
|
|
|
|
- virtual bool AddVideoPicture(DVDVideoPicture* picture) { return false; }
|
|
+ virtual bool AddVideoPicture(DVDVideoPicture* picture, int index) { return false; }
|
|
virtual void Flush() {};
|
|
|
|
virtual unsigned int GetProcessorSize() { return 0; }
|
|
+ virtual unsigned int GetMaxProcessorSize() { return 0; }
|
|
+ virtual void SetProcessorSize(int numBuffers) { }
|
|
+ virtual void ReleaseBuffer(int idx) { }
|
|
|
|
virtual bool Supports(ERENDERFEATURE feature) { return false; }
|
|
|
|
diff --git a/xbmc/cores/VideoRenderers/LinuxRendererGL.cpp b/xbmc/cores/VideoRenderers/LinuxRendererGL.cpp
|
|
index 1cf52d3..b32a7ea 100644
|
|
--- a/xbmc/cores/VideoRenderers/LinuxRendererGL.cpp
|
|
+++ b/xbmc/cores/VideoRenderers/LinuxRendererGL.cpp
|
|
@@ -235,14 +235,6 @@ bool CLinuxRendererGL::ValidateRenderer()
|
|
return true;
|
|
}
|
|
|
|
-
|
|
-void CLinuxRendererGL::ManageTextures()
|
|
-{
|
|
- m_NumYV12Buffers = 2;
|
|
- //m_iYV12RenderBuffer = 0;
|
|
- return;
|
|
-}
|
|
-
|
|
bool CLinuxRendererGL::ValidateRenderTarget()
|
|
{
|
|
if (!m_bValidated)
|
|
@@ -603,13 +595,28 @@ void CLinuxRendererGL::Flush()
|
|
glFinish();
|
|
m_bValidated = false;
|
|
m_fbo.fbo.Cleanup();
|
|
+ m_iYV12RenderBuffer = 0;
|
|
+}
|
|
+
|
|
+void CLinuxRendererGL::ReleaseBuffer(int idx)
|
|
+{
|
|
+ YUVBUFFER &buf = m_buffers[idx];
|
|
+#ifdef HAVE_LIBVDPAU
|
|
+ SAFE_RELEASE(buf.vdpau);
|
|
+#endif
|
|
+#ifdef HAVE_LIBVA
|
|
+ buf.vaapi.surface.reset();
|
|
+#endif
|
|
+#ifdef TARGET_DARWIN
|
|
+ if (buf.cvBufferRef)
|
|
+ CVBufferRelease(buf.cvBufferRef);
|
|
+#endif
|
|
}
|
|
|
|
void CLinuxRendererGL::Update(bool bPauseDrawing)
|
|
{
|
|
if (!m_bConfigured) return;
|
|
ManageDisplay();
|
|
- ManageTextures();
|
|
}
|
|
|
|
void CLinuxRendererGL::RenderUpdate(bool clear, DWORD flags, DWORD alpha)
|
|
@@ -625,7 +632,6 @@ void CLinuxRendererGL::RenderUpdate(bool clear, DWORD flags, DWORD alpha)
|
|
}
|
|
|
|
ManageDisplay();
|
|
- ManageTextures();
|
|
|
|
g_graphicsContext.BeginPaint();
|
|
|
|
@@ -782,7 +788,6 @@ unsigned int CLinuxRendererGL::PreInit()
|
|
m_resolution = RES_DESKTOP;
|
|
|
|
m_iYV12RenderBuffer = 0;
|
|
- m_NumYV12Buffers = 2;
|
|
|
|
m_formats.push_back(RENDER_FMT_YUV420P);
|
|
GLint size;
|
|
@@ -2465,7 +2470,7 @@ void CLinuxRendererGL::UploadVAAPITexture(int index)
|
|
|| status == VA_STATUS_ERROR_INVALID_DISPLAY)
|
|
{
|
|
va.display->lost(true);
|
|
- for(int i = 0; i < NUM_BUFFERS; i++)
|
|
+ for(int i = 0; i < m_NumYV12Buffers; i++)
|
|
{
|
|
m_buffers[i].vaapi.display.reset();
|
|
m_buffers[i].vaapi.surface.reset();
|
|
@@ -3412,26 +3417,26 @@ void CLinuxRendererGL::UnBindPbo(YUVBUFFER& buff)
|
|
}
|
|
|
|
#ifdef HAVE_LIBVDPAU
|
|
-void CLinuxRendererGL::AddProcessor(CVDPAU* vdpau)
|
|
+void CLinuxRendererGL::AddProcessor(CVDPAU* vdpau, int index)
|
|
{
|
|
- YUVBUFFER &buf = m_buffers[NextYV12Texture()];
|
|
+ YUVBUFFER &buf = m_buffers[index];
|
|
SAFE_RELEASE(buf.vdpau);
|
|
buf.vdpau = (CVDPAU*)vdpau->Acquire();
|
|
}
|
|
#endif
|
|
|
|
#ifdef HAVE_LIBVA
|
|
-void CLinuxRendererGL::AddProcessor(VAAPI::CHolder& holder)
|
|
+void CLinuxRendererGL::AddProcessor(VAAPI::CHolder& holder, int index)
|
|
{
|
|
- YUVBUFFER &buf = m_buffers[NextYV12Texture()];
|
|
+ YUVBUFFER &buf = m_buffers[index];
|
|
buf.vaapi.surface = holder.surface;
|
|
}
|
|
#endif
|
|
|
|
#ifdef TARGET_DARWIN
|
|
-void CLinuxRendererGL::AddProcessor(struct __CVBuffer *cvBufferRef)
|
|
+void CLinuxRendererGL::AddProcessor(struct __CVBuffer *cvBufferRef, int index)
|
|
{
|
|
- YUVBUFFER &buf = m_buffers[NextYV12Texture()];
|
|
+ YUVBUFFER &buf = m_buffers[index];
|
|
if (buf.cvBufferRef)
|
|
CVBufferRelease(buf.cvBufferRef);
|
|
buf.cvBufferRef = cvBufferRef;
|
|
diff --git a/xbmc/cores/VideoRenderers/LinuxRendererGL.h b/xbmc/cores/VideoRenderers/LinuxRendererGL.h
|
|
index acebfe0..9f55fcb 100644
|
|
--- a/xbmc/cores/VideoRenderers/LinuxRendererGL.h
|
|
+++ b/xbmc/cores/VideoRenderers/LinuxRendererGL.h
|
|
@@ -44,7 +44,7 @@
|
|
namespace Shaders { class BaseVideoFilterShader; }
|
|
namespace VAAPI { struct CHolder; }
|
|
|
|
-#define NUM_BUFFERS 3
|
|
+#define NUM_BUFFERS 10
|
|
|
|
|
|
#undef ALIGN
|
|
@@ -138,15 +138,19 @@ class CLinuxRendererGL : public CBaseRenderer
|
|
virtual void UnInit();
|
|
virtual void Reset(); /* resets renderer after seek for example */
|
|
virtual void Flush();
|
|
+ virtual void ReleaseBuffer(int idx);
|
|
+ virtual void SetProcessorSize(int numBuffers) { m_NumYV12Buffers = numBuffers; }
|
|
+ virtual unsigned int GetMaxProcessorSize() { return NUM_BUFFERS; }
|
|
+ virtual unsigned int GetProcessorSize() { return m_NumYV12Buffers; }
|
|
|
|
#ifdef HAVE_LIBVDPAU
|
|
- virtual void AddProcessor(CVDPAU* vdpau);
|
|
+ virtual void AddProcessor(CVDPAU* vdpau, int index);
|
|
#endif
|
|
#ifdef HAVE_LIBVA
|
|
- virtual void AddProcessor(VAAPI::CHolder& holder);
|
|
+ virtual void AddProcessor(VAAPI::CHolder& holder, int index);
|
|
#endif
|
|
#ifdef TARGET_DARWIN
|
|
- virtual void AddProcessor(struct __CVBuffer *cvBufferRef);
|
|
+ virtual void AddProcessor(struct __CVBuffer *cvBufferRef, int index);
|
|
#endif
|
|
|
|
virtual void RenderUpdate(bool clear, DWORD flags = 0, DWORD alpha = 255);
|
|
@@ -168,7 +172,6 @@ class CLinuxRendererGL : public CBaseRenderer
|
|
void DrawBlackBars();
|
|
|
|
bool ValidateRenderer();
|
|
- virtual void ManageTextures();
|
|
int NextYV12Texture();
|
|
virtual bool ValidateRenderTarget();
|
|
virtual void LoadShaders(int field=FIELD_FULL);
|
|
diff --git a/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp b/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp
|
|
index cb0939f..2a59e2b 100644
|
|
--- a/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp
|
|
+++ b/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp
|
|
@@ -1982,16 +1982,16 @@ EINTERLACEMETHOD CLinuxRendererGLES::AutoInterlaceMethod()
|
|
}
|
|
|
|
#ifdef HAVE_LIBOPENMAX
|
|
-void CLinuxRendererGLES::AddProcessor(COpenMax* openMax, DVDVideoPicture *picture)
|
|
+void CLinuxRendererGLES::AddProcessor(COpenMax* openMax, DVDVideoPicture *picture, int index)
|
|
{
|
|
- YUVBUFFER &buf = m_buffers[NextYV12Texture()];
|
|
+ YUVBUFFER &buf = m_buffers[index];
|
|
buf.openMaxBuffer = picture->openMaxBuffer;
|
|
}
|
|
#endif
|
|
#ifdef HAVE_VIDEOTOOLBOXDECODER
|
|
-void CLinuxRendererGLES::AddProcessor(struct __CVBuffer *cvBufferRef)
|
|
+void CLinuxRendererGLES::AddProcessor(struct __CVBuffer *cvBufferRef, int index)
|
|
{
|
|
- YUVBUFFER &buf = m_buffers[NextYV12Texture()];
|
|
+ YUVBUFFER &buf = m_buffers[index];
|
|
if (buf.cvBufferRef)
|
|
CVBufferRelease(buf.cvBufferRef);
|
|
buf.cvBufferRef = cvBufferRef;
|
|
diff --git a/xbmc/cores/VideoRenderers/LinuxRendererGLES.h b/xbmc/cores/VideoRenderers/LinuxRendererGLES.h
|
|
index 76b5437..c6b69db 100644
|
|
--- a/xbmc/cores/VideoRenderers/LinuxRendererGLES.h
|
|
+++ b/xbmc/cores/VideoRenderers/LinuxRendererGLES.h
|
|
@@ -153,10 +153,10 @@ class CLinuxRendererGLES : public CBaseRenderer
|
|
virtual std::vector<ERenderFormat> SupportedFormats() { return m_formats; }
|
|
|
|
#ifdef HAVE_LIBOPENMAX
|
|
- virtual void AddProcessor(COpenMax* openMax, DVDVideoPicture *picture);
|
|
+ virtual void AddProcessor(COpenMax* openMax, DVDVideoPicture *picture, int index);
|
|
#endif
|
|
#ifdef HAVE_VIDEOTOOLBOXDECODER
|
|
- virtual void AddProcessor(struct __CVBuffer *cvBufferRef);
|
|
+ virtual void AddProcessor(struct __CVBuffer *cvBufferRef, int index);
|
|
#endif
|
|
|
|
protected:
|
|
diff --git a/xbmc/cores/VideoRenderers/OverlayRenderer.cpp b/xbmc/cores/VideoRenderers/OverlayRenderer.cpp
|
|
index 19d2d7d..94aaaf5 100644
|
|
--- a/xbmc/cores/VideoRenderers/OverlayRenderer.cpp
|
|
+++ b/xbmc/cores/VideoRenderers/OverlayRenderer.cpp
|
|
@@ -89,7 +89,6 @@ long COverlayMainThread::Release()
|
|
CRenderer::CRenderer()
|
|
{
|
|
m_render = 0;
|
|
- m_decode = (m_render + 1) % 2;
|
|
}
|
|
|
|
CRenderer::~CRenderer()
|
|
@@ -151,20 +150,30 @@ void CRenderer::Flush()
|
|
{
|
|
CSingleLock lock(m_section);
|
|
|
|
- for(int i = 0; i < 2; i++)
|
|
+ for(int i = 0; i < m_iNumBuffers; i++)
|
|
Release(m_buffers[i]);
|
|
|
|
+ m_render = 0;
|
|
Release(m_cleanup);
|
|
}
|
|
|
|
void CRenderer::Flip()
|
|
{
|
|
CSingleLock lock(m_section);
|
|
+ m_render = (m_render + 1) % m_iNumBuffers;
|
|
+}
|
|
|
|
- m_render = m_decode;
|
|
- m_decode =(m_decode + 1) % 2;
|
|
+void CRenderer::SetBuffer(int idx)
|
|
+{
|
|
+ CSingleLock lock(m_section);
|
|
+ Release(m_buffers[idx]);
|
|
+ m_decode = idx;
|
|
+}
|
|
|
|
- Release(m_buffers[m_decode]);
|
|
+void CRenderer::ReleaseBuffer(int idx)
|
|
+{
|
|
+ CSingleLock lock(m_section);
|
|
+ Release(m_buffers[idx]);
|
|
}
|
|
|
|
void CRenderer::Render()
|
|
diff --git a/xbmc/cores/VideoRenderers/OverlayRenderer.h b/xbmc/cores/VideoRenderers/OverlayRenderer.h
|
|
index d2175d8..c6740a5 100644
|
|
--- a/xbmc/cores/VideoRenderers/OverlayRenderer.h
|
|
+++ b/xbmc/cores/VideoRenderers/OverlayRenderer.h
|
|
@@ -98,6 +98,9 @@
|
|
void Flip();
|
|
void Render();
|
|
void Flush();
|
|
+ void SetNumBuffers(int numBuffers) { m_iNumBuffers = numBuffers; }
|
|
+ void SetBuffer(int idx);
|
|
+ void ReleaseBuffer(int idx);
|
|
|
|
protected:
|
|
|
|
@@ -124,7 +127,8 @@
|
|
void Release(SElementV& list);
|
|
|
|
CCriticalSection m_section;
|
|
- SElementV m_buffers[2];
|
|
+ SElementV m_buffers[10];
|
|
+ int m_iNumBuffers;
|
|
int m_decode;
|
|
int m_render;
|
|
|
|
diff --git a/xbmc/cores/VideoRenderers/RenderManager.cpp b/xbmc/cores/VideoRenderers/RenderManager.cpp
|
|
index d22287d..eeb6c6f 100644
|
|
--- a/xbmc/cores/VideoRenderers/RenderManager.cpp
|
|
+++ b/xbmc/cores/VideoRenderers/RenderManager.cpp
|
|
@@ -28,6 +28,7 @@
|
|
#include "utils/MathUtils.h"
|
|
#include "threads/SingleLock.h"
|
|
#include "utils/log.h"
|
|
+#include "utils/TimeUtils.h"
|
|
|
|
#include "Application.h"
|
|
#include "ApplicationMessenger.h"
|
|
@@ -247,6 +248,11 @@ bool CXBMCRenderManager::Configure(unsigned int width, unsigned int height, unsi
|
|
return false;
|
|
}
|
|
|
|
+ // check if decoder supports buffering
|
|
+ m_bCodecSupportsBuffering = false;
|
|
+// if (format == RENDER_FMT_VDPAU)
|
|
+// m_bCodecSupportsBuffering = true;
|
|
+
|
|
bool result = m_pRenderer->Configure(width, height, d_width, d_height, fps, flags, format, extended_format, orientation);
|
|
if(result)
|
|
{
|
|
@@ -261,6 +267,7 @@ bool CXBMCRenderManager::Configure(unsigned int width, unsigned int height, unsi
|
|
m_bReconfigured = true;
|
|
m_presentstep = PRESENT_IDLE;
|
|
m_presentevent.Set();
|
|
+ ResetRenderBuffer();
|
|
}
|
|
|
|
return result;
|
|
@@ -292,8 +299,12 @@ void CXBMCRenderManager::RenderUpdate(bool clear, DWORD flags, DWORD alpha)
|
|
if (!m_pRenderer)
|
|
return;
|
|
|
|
+ if (m_presentstep == PRESENT_IDLE)
|
|
+ PrepareNextRender();
|
|
+
|
|
if(m_presentstep == PRESENT_FLIP)
|
|
{
|
|
+ FlipRenderBuffer();
|
|
m_overlays.Flip();
|
|
m_pRenderer->FlipPage(m_presentsource);
|
|
m_presentstep = PRESENT_FRAME;
|
|
@@ -312,7 +323,7 @@ void CXBMCRenderManager::RenderUpdate(bool clear, DWORD flags, DWORD alpha)
|
|
m_presentevent.Set();
|
|
}
|
|
|
|
-unsigned int CXBMCRenderManager::PreInit()
|
|
+unsigned int CXBMCRenderManager::PreInit(CDVDClock *pClock)
|
|
{
|
|
CRetakeLock<CExclusiveLock> lock(m_sharedSection);
|
|
|
|
@@ -320,6 +331,7 @@ unsigned int CXBMCRenderManager::PreInit()
|
|
m_presenterr = 0.0;
|
|
m_errorindex = 0;
|
|
memset(m_errorbuff, 0, sizeof(m_errorbuff));
|
|
+ m_pClock = pClock;
|
|
|
|
m_bIsStarted = false;
|
|
m_bPauseDrawing = false;
|
|
@@ -338,6 +350,10 @@ unsigned int CXBMCRenderManager::PreInit()
|
|
|
|
UpdateDisplayLatency();
|
|
|
|
+ m_bUseBuffering = false;
|
|
+ m_bCodecSupportsBuffering = true;
|
|
+ ResetRenderBuffer();
|
|
+
|
|
return m_pRenderer->PreInit();
|
|
}
|
|
|
|
@@ -366,7 +382,9 @@ bool CXBMCRenderManager::Flush()
|
|
|
|
CRetakeLock<CExclusiveLock> lock(m_sharedSection);
|
|
m_pRenderer->Flush();
|
|
+ m_overlays.Flush();
|
|
m_flushEvent.Set();
|
|
+ ResetRenderBuffer();
|
|
}
|
|
else
|
|
{
|
|
@@ -534,25 +552,21 @@ 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*/, int source /*= -1*/, EFIELDSYNC sync /*= FS_NONE*/, int speed /*= 0*/)
|
|
{
|
|
- if(timestamp - GetPresentTime() > MAXPRESENTDELAY)
|
|
- timestamp = GetPresentTime() + MAXPRESENTDELAY;
|
|
-
|
|
- /* can't flip, untill timestamp */
|
|
- if(!g_graphicsContext.IsFullScreenVideo())
|
|
- WaitPresentTime(timestamp);
|
|
-
|
|
- /* make sure any queued frame was fully presented */
|
|
- double timeout = m_presenttime + 1.0;
|
|
- while(m_presentstep != PRESENT_IDLE && !bStop)
|
|
+ if (!m_bUseBuffering)
|
|
{
|
|
- if(!m_presentevent.WaitMSec(100) && GetPresentTime() > timeout && !bStop)
|
|
+ /* make sure any queued frame was fully presented */
|
|
+ double timeout = m_presenttime + 1.0;
|
|
+ while(m_presentstep != PRESENT_IDLE && !bStop)
|
|
{
|
|
- CLog::Log(LOGWARNING, "CRenderManager::FlipPage - timeout waiting for previous frame");
|
|
- return;
|
|
+ if(!m_presentevent.WaitMSec(100) && GetPresentTime() > timeout && !bStop)
|
|
+ {
|
|
+ CLog::Log(LOGWARNING, "CRenderManager::FlipPage - timeout waiting for previous frame");
|
|
+ return;
|
|
+ }
|
|
}
|
|
- };
|
|
+ }
|
|
|
|
if(bStop)
|
|
return;
|
|
@@ -560,58 +574,67 @@ void CXBMCRenderManager::FlipPage(volatile bool& bStop, double timestamp /* = 0L
|
|
{ CRetakeLock<CExclusiveLock> lock(m_sharedSection);
|
|
if(!m_pRenderer) return;
|
|
|
|
- m_presenttime = timestamp;
|
|
- m_presentfield = sync;
|
|
- m_presentstep = PRESENT_FLIP;
|
|
- m_presentsource = source;
|
|
+ double presenttime = timestamp;
|
|
+ EFIELDSYNC presentfield = sync;
|
|
+ EPRESENTMETHOD presentmethod;
|
|
+
|
|
EDEINTERLACEMODE deinterlacemode = g_settings.m_currentVideoSettings.m_DeinterlaceMode;
|
|
EINTERLACEMETHOD interlacemethod = AutoInterlaceMethodInternal(g_settings.m_currentVideoSettings.m_InterlaceMethod);
|
|
|
|
bool invert = false;
|
|
|
|
if (deinterlacemode == VS_DEINTERLACEMODE_OFF)
|
|
- m_presentmethod = PRESENT_METHOD_SINGLE;
|
|
+ presentmethod = PRESENT_METHOD_SINGLE;
|
|
else
|
|
{
|
|
- if (deinterlacemode == VS_DEINTERLACEMODE_AUTO && m_presentfield == FS_NONE)
|
|
- m_presentmethod = PRESENT_METHOD_SINGLE;
|
|
+ if (deinterlacemode == VS_DEINTERLACEMODE_AUTO && presentfield == FS_NONE)
|
|
+ presentmethod = PRESENT_METHOD_SINGLE;
|
|
else
|
|
{
|
|
- if (interlacemethod == VS_INTERLACEMETHOD_RENDER_BLEND) m_presentmethod = PRESENT_METHOD_BLEND;
|
|
- else if (interlacemethod == VS_INTERLACEMETHOD_RENDER_WEAVE) m_presentmethod = PRESENT_METHOD_WEAVE;
|
|
- else if (interlacemethod == VS_INTERLACEMETHOD_RENDER_WEAVE_INVERTED) { m_presentmethod = PRESENT_METHOD_WEAVE ; invert = true; }
|
|
- else if (interlacemethod == VS_INTERLACEMETHOD_RENDER_BOB) m_presentmethod = PRESENT_METHOD_BOB;
|
|
- else if (interlacemethod == VS_INTERLACEMETHOD_RENDER_BOB_INVERTED) { m_presentmethod = PRESENT_METHOD_BOB; invert = true; }
|
|
- else if (interlacemethod == VS_INTERLACEMETHOD_DXVA_BOB) m_presentmethod = PRESENT_METHOD_BOB;
|
|
- else if (interlacemethod == VS_INTERLACEMETHOD_DXVA_BEST) m_presentmethod = PRESENT_METHOD_BOB;
|
|
- else m_presentmethod = PRESENT_METHOD_SINGLE;
|
|
+ if (interlacemethod == VS_INTERLACEMETHOD_RENDER_BLEND) presentmethod = PRESENT_METHOD_BLEND;
|
|
+ else if (interlacemethod == VS_INTERLACEMETHOD_RENDER_WEAVE) presentmethod = PRESENT_METHOD_WEAVE;
|
|
+ else if (interlacemethod == VS_INTERLACEMETHOD_RENDER_WEAVE_INVERTED) { presentmethod = PRESENT_METHOD_WEAVE ; invert = true; }
|
|
+ else if (interlacemethod == VS_INTERLACEMETHOD_RENDER_BOB) presentmethod = PRESENT_METHOD_BOB;
|
|
+ else if (interlacemethod == VS_INTERLACEMETHOD_RENDER_BOB_INVERTED) { presentmethod = PRESENT_METHOD_BOB; invert = true; }
|
|
+ else if (interlacemethod == VS_INTERLACEMETHOD_DXVA_BOB) presentmethod = PRESENT_METHOD_BOB;
|
|
+ else if (interlacemethod == VS_INTERLACEMETHOD_DXVA_BEST) presentmethod = PRESENT_METHOD_BOB;
|
|
+ else presentmethod = PRESENT_METHOD_SINGLE;
|
|
|
|
/* default to odd field if we want to deinterlace and don't know better */
|
|
- if (deinterlacemode == VS_DEINTERLACEMODE_FORCE && m_presentfield == FS_NONE)
|
|
- m_presentfield = FS_TOP;
|
|
+ if (deinterlacemode == VS_DEINTERLACEMODE_FORCE && presentfield == FS_NONE)
|
|
+ presentfield = FS_TOP;
|
|
|
|
/* invert present field */
|
|
if(invert)
|
|
{
|
|
- if( m_presentfield == FS_BOT )
|
|
- m_presentfield = FS_TOP;
|
|
+ if( presentfield == FS_BOT )
|
|
+ presentfield = FS_TOP;
|
|
else
|
|
- m_presentfield = FS_BOT;
|
|
+ presentfield = FS_BOT;
|
|
}
|
|
}
|
|
}
|
|
|
|
+ FlipFreeBuffer();
|
|
+ m_renderBuffers[m_iOutputRenderBuffer].pts = timestamp;
|
|
+ m_renderBuffers[m_iOutputRenderBuffer].presentfield = presentfield;
|
|
+ m_renderBuffers[m_iOutputRenderBuffer].presentmethod = presentmethod;
|
|
+ m_speed = speed;
|
|
}
|
|
|
|
g_application.NewFrame();
|
|
- /* wait untill render thread have flipped buffers */
|
|
- timeout = m_presenttime + 1.0;
|
|
- while(m_presentstep == PRESENT_FLIP && !bStop)
|
|
+
|
|
+ if (!m_bUseBuffering)
|
|
{
|
|
- if(!m_presentevent.WaitMSec(100) && GetPresentTime() > timeout && !bStop)
|
|
+ /* wait untill render thread have flipped buffers */
|
|
+ double timeout = m_presenttime + 1.0;
|
|
+ while(m_presentstep == PRESENT_FLIP && !bStop)
|
|
{
|
|
- CLog::Log(LOGWARNING, "CRenderManager::FlipPage - timeout waiting for flip to complete");
|
|
- return;
|
|
+ if(!m_presentevent.WaitMSec(100) && GetPresentTime() > timeout && !bStop)
|
|
+ {
|
|
+ CLog::Log(LOGWARNING, "CRenderManager::FlipPage - timeout waiting for flip to complete");
|
|
+ return;
|
|
+ }
|
|
}
|
|
}
|
|
}
|
|
@@ -675,8 +698,12 @@ void CXBMCRenderManager::Present()
|
|
if (!m_pRenderer)
|
|
return;
|
|
|
|
+ if (m_presentstep == PRESENT_IDLE)
|
|
+ PrepareNextRender();
|
|
+
|
|
if(m_presentstep == PRESENT_FLIP)
|
|
{
|
|
+ FlipRenderBuffer();
|
|
m_overlays.Flip();
|
|
m_pRenderer->FlipPage(m_presentsource);
|
|
m_presentstep = PRESENT_FRAME;
|
|
@@ -800,11 +827,11 @@ int CXBMCRenderManager::AddVideoPicture(DVDVideoPicture& pic)
|
|
if (!m_pRenderer)
|
|
return -1;
|
|
|
|
- if(m_pRenderer->AddVideoPicture(&pic))
|
|
+ if(m_pRenderer->AddVideoPicture(&pic, (m_iOutputRenderBuffer + 1) % m_iNumRenderBuffers))
|
|
return 1;
|
|
|
|
YV12Image image;
|
|
- int index = m_pRenderer->GetImage(&image);
|
|
+ int index = m_pRenderer->GetImage(&image, (m_iOutputRenderBuffer + 1) % m_iNumRenderBuffers);
|
|
|
|
if(index < 0)
|
|
return index;
|
|
@@ -830,19 +857,19 @@ int CXBMCRenderManager::AddVideoPicture(DVDVideoPicture& pic)
|
|
}
|
|
#ifdef HAVE_LIBVDPAU
|
|
else if(pic.format == RENDER_FMT_VDPAU)
|
|
- m_pRenderer->AddProcessor(pic.vdpau);
|
|
+ m_pRenderer->AddProcessor(pic.vdpau, index);
|
|
#endif
|
|
#ifdef HAVE_LIBOPENMAX
|
|
else if(pic.format == RENDER_FMT_OMXEGL)
|
|
- m_pRenderer->AddProcessor(pic.openMax, &pic);
|
|
+ m_pRenderer->AddProcessor(pic.openMax, &pic, index);
|
|
#endif
|
|
#ifdef TARGET_DARWIN
|
|
else if(pic.format == RENDER_FMT_CVBREF)
|
|
- m_pRenderer->AddProcessor(pic.cvBufferRef);
|
|
+ m_pRenderer->AddProcessor(pic.cvBufferRef, index);
|
|
#endif
|
|
#ifdef HAVE_LIBVA
|
|
else if(pic.format == RENDER_FMT_VAAPI)
|
|
- m_pRenderer->AddProcessor(*pic.vaapi);
|
|
+ m_pRenderer->AddProcessor(*pic.vaapi, index);
|
|
#endif
|
|
m_pRenderer->ReleaseImage(index, false);
|
|
|
|
@@ -904,3 +931,176 @@ EINTERLACEMETHOD CXBMCRenderManager::AutoInterlaceMethodInternal(EINTERLACEMETHO
|
|
|
|
return mInt;
|
|
}
|
|
+
|
|
+int CXBMCRenderManager::WaitForBuffer(volatile bool& bStop)
|
|
+{
|
|
+ CSharedLock lock(m_sharedSection);
|
|
+ if (!m_pRenderer)
|
|
+ return -1;
|
|
+
|
|
+ //wait up to a second as this is our slowest allowed output rate
|
|
+ double timeout = GetPresentTime() + 0.1;
|
|
+ while(!HasFreeBuffer() && !bStop)
|
|
+ {
|
|
+ lock.Leave();
|
|
+ m_flipEvent.WaitMSec(50);
|
|
+ if(GetPresentTime() > timeout && !bStop)
|
|
+ {
|
|
+ CLog::Log(LOGWARNING, "CRenderManager::WaitForBuffer - timeout waiting for buffer");
|
|
+ return -1;
|
|
+ }
|
|
+ lock.Enter();
|
|
+ }
|
|
+ lock.Leave();
|
|
+
|
|
+ { CRetakeLock<CExclusiveLock> lock(m_sharedSection);
|
|
+ m_overlays.SetBuffer((m_iOutputRenderBuffer + 1) % m_iNumRenderBuffers);
|
|
+ }
|
|
+
|
|
+ if (bStop)
|
|
+ return -1;
|
|
+
|
|
+ return 1;
|
|
+}
|
|
+
|
|
+int CXBMCRenderManager::GetNextRenderBufferIndex()
|
|
+{
|
|
+ if (m_iOutputRenderBuffer == m_iCurrentRenderBuffer)
|
|
+ return -1;
|
|
+ return (m_iCurrentRenderBuffer + 1) % m_iNumRenderBuffers;
|
|
+}
|
|
+
|
|
+void CXBMCRenderManager::FlipRenderBuffer()
|
|
+{
|
|
+ m_iCurrentRenderBuffer = GetNextRenderBufferIndex();
|
|
+}
|
|
+
|
|
+int CXBMCRenderManager::FlipFreeBuffer()
|
|
+{
|
|
+ // See "Render Buffer State Description" in header for information.
|
|
+ if (HasFreeBuffer())
|
|
+ {
|
|
+ m_bAllRenderBuffersDisplayed = false;
|
|
+ m_iOutputRenderBuffer = (m_iOutputRenderBuffer + 1) % m_iNumRenderBuffers;
|
|
+ return m_iOutputRenderBuffer;
|
|
+ }
|
|
+}
|
|
+
|
|
+bool CXBMCRenderManager::HasFreeBuffer()
|
|
+{
|
|
+ if (!m_bUseBuffering)
|
|
+ {
|
|
+ if (m_iOutputRenderBuffer != m_iCurrentRenderBuffer)
|
|
+ return false;
|
|
+ else
|
|
+ return true;
|
|
+ }
|
|
+
|
|
+ int outputPlus1 = (m_iOutputRenderBuffer + 1) % m_iNumRenderBuffers;
|
|
+ if ((m_iOutputRenderBuffer == m_iDisplayedRenderBuffer && !m_bAllRenderBuffersDisplayed)
|
|
+ || outputPlus1 == m_iCurrentRenderBuffer)
|
|
+ return false;
|
|
+ else
|
|
+ return true;
|
|
+}
|
|
+
|
|
+void CXBMCRenderManager::ResetRenderBuffer()
|
|
+{
|
|
+ m_iNumRenderBuffers = m_pRenderer->GetMaxProcessorSize();
|
|
+ m_iNumRenderBuffers = std::min(5, m_iNumRenderBuffers);
|
|
+ m_iNumRenderBuffers = std::max(2, m_iNumRenderBuffers);
|
|
+
|
|
+ if (!m_bCodecSupportsBuffering)
|
|
+ m_iNumRenderBuffers = 2;
|
|
+
|
|
+ CLog::Log(LOGNOTICE,"CXBMCRenderManager::ResetRenderBuffer - using %d render buffers", m_iNumRenderBuffers);
|
|
+ m_overlays.SetNumBuffers(m_iNumRenderBuffers);
|
|
+ m_pRenderer->SetProcessorSize(m_iNumRenderBuffers);
|
|
+
|
|
+ m_iCurrentRenderBuffer = 0;
|
|
+ m_iOutputRenderBuffer = 0;
|
|
+ m_iDisplayedRenderBuffer = 0;
|
|
+ m_bAllRenderBuffersDisplayed = true;
|
|
+ m_sleeptime = 1.0;
|
|
+ m_presentPts = DVD_NOPTS_VALUE;
|
|
+ m_speed = 0;
|
|
+}
|
|
+
|
|
+void CXBMCRenderManager::PrepareNextRender()
|
|
+{
|
|
+ int idx = GetNextRenderBufferIndex();
|
|
+ if (idx < 0)
|
|
+ {
|
|
+ if (m_speed >= DVD_PLAYSPEED_NORMAL && g_graphicsContext.IsFullScreenVideo())
|
|
+ CLog::Log(LOGDEBUG,"%s no buffer, out: %d, current: %d, display: %d",
|
|
+ __FUNCTION__, m_iOutputRenderBuffer, m_iCurrentRenderBuffer, m_iDisplayedRenderBuffer);
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ double iClockSleep, iPlayingClock, iCurrentClock;
|
|
+ iPlayingClock = m_pClock->GetClock(iCurrentClock, false);
|
|
+ iClockSleep = m_renderBuffers[idx].pts - iPlayingClock;
|
|
+
|
|
+ if (m_speed)
|
|
+ iClockSleep = iClockSleep * DVD_PLAYSPEED_NORMAL / m_speed;
|
|
+
|
|
+ double presenttime = (iCurrentClock + iClockSleep) / DVD_TIME_BASE;
|
|
+ double clocktime = iCurrentClock / DVD_TIME_BASE;
|
|
+ if(presenttime - clocktime > MAXPRESENTDELAY)
|
|
+ presenttime = clocktime + MAXPRESENTDELAY;
|
|
+
|
|
+ m_sleeptime = presenttime - clocktime;
|
|
+
|
|
+ if (g_graphicsContext.IsFullScreenVideo() || presenttime <= clocktime+0.01)
|
|
+ {
|
|
+ m_presentPts = m_renderBuffers[idx].pts;
|
|
+ m_presenttime = presenttime;
|
|
+ m_presentmethod = m_renderBuffers[idx].presentmethod;
|
|
+ m_presentfield = m_renderBuffers[idx].presentfield;
|
|
+ m_presentstep = PRESENT_FLIP;
|
|
+ m_presentsource = idx;
|
|
+ }
|
|
+}
|
|
+
|
|
+void CXBMCRenderManager::EnableBuffering(bool enable)
|
|
+{
|
|
+ CRetakeLock<CExclusiveLock> lock(m_sharedSection);
|
|
+
|
|
+ if (m_iNumRenderBuffers < 3)
|
|
+ return;
|
|
+
|
|
+ m_bUseBuffering = enable;
|
|
+ if (!m_bUseBuffering)
|
|
+ m_iOutputRenderBuffer = m_iCurrentRenderBuffer;
|
|
+
|
|
+ CLog::Log(LOGDEBUG, "CXBMCRenderManager::EnableBuffering - %d", m_bUseBuffering);
|
|
+}
|
|
+
|
|
+void CXBMCRenderManager::DiscardBuffer()
|
|
+{
|
|
+ CRetakeLock<CExclusiveLock> lock(m_sharedSection);
|
|
+ m_iOutputRenderBuffer = m_iCurrentRenderBuffer;
|
|
+}
|
|
+
|
|
+void CXBMCRenderManager::NotifyDisplayFlip()
|
|
+{
|
|
+ CRetakeLock<CExclusiveLock> lock(m_sharedSection);
|
|
+ if (!m_pRenderer)
|
|
+ return;
|
|
+
|
|
+ if (m_iNumRenderBuffers < 3)
|
|
+ return;
|
|
+
|
|
+ int last = m_iDisplayedRenderBuffer;
|
|
+ m_iDisplayedRenderBuffer = (m_iCurrentRenderBuffer + m_iNumRenderBuffers - 1) % m_iNumRenderBuffers;
|
|
+
|
|
+ if (last != m_iDisplayedRenderBuffer
|
|
+ && m_iDisplayedRenderBuffer != m_iCurrentRenderBuffer)
|
|
+ {
|
|
+ m_pRenderer->ReleaseBuffer(m_iDisplayedRenderBuffer);
|
|
+ m_overlays.ReleaseBuffer(m_iDisplayedRenderBuffer);
|
|
+ }
|
|
+
|
|
+ lock.Leave();
|
|
+ m_flipEvent.Set();
|
|
+}
|
|
diff --git a/xbmc/cores/VideoRenderers/RenderManager.h b/xbmc/cores/VideoRenderers/RenderManager.h
|
|
index 7fe6bb2..34ff8d0 100644
|
|
--- a/xbmc/cores/VideoRenderers/RenderManager.h
|
|
+++ b/xbmc/cores/VideoRenderers/RenderManager.h
|
|
@@ -31,6 +31,7 @@
|
|
#include "OverlayRenderer.h"
|
|
|
|
class CRenderCapture;
|
|
+class CDVDClock;
|
|
|
|
namespace DXVA { class CProcessor; }
|
|
namespace VAAPI { class CSurfaceHolder; }
|
|
@@ -70,8 +71,8 @@ class CXBMCRenderManager
|
|
|
|
int AddVideoPicture(DVDVideoPicture& picture);
|
|
|
|
- void FlipPage(volatile bool& bStop, double timestamp = 0.0, int source = -1, EFIELDSYNC sync = FS_NONE);
|
|
- unsigned int PreInit();
|
|
+ void FlipPage(volatile bool& bStop, double timestamp = 0.0, int source = -1, EFIELDSYNC sync = FS_NONE, int speed = 0);
|
|
+ unsigned int PreInit(CDVDClock *pClock);
|
|
void UnInit();
|
|
bool Flush();
|
|
|
|
@@ -131,6 +132,10 @@ class CXBMCRenderManager
|
|
CSharedSection& GetSection() { return m_sharedSection; };
|
|
|
|
void RegisterRenderUpdateCallBack(const void *ctx, RenderUpdateCallBackFn fn);
|
|
+ int WaitForBuffer(volatile bool& bStop);
|
|
+ void NotifyDisplayFlip();
|
|
+ void EnableBuffering(bool enable);
|
|
+ void DiscardBuffer();
|
|
|
|
protected:
|
|
void Render(bool clear, DWORD flags, DWORD alpha);
|
|
@@ -139,6 +144,13 @@ class CXBMCRenderManager
|
|
void PresentFields(bool clear, DWORD flags, DWORD alpha);
|
|
void PresentBlend(bool clear, DWORD flags, DWORD alpha);
|
|
|
|
+ int GetNextRenderBufferIndex();
|
|
+ void FlipRenderBuffer();
|
|
+ int FlipFreeBuffer();
|
|
+ bool HasFreeBuffer();
|
|
+ void ResetRenderBuffer();
|
|
+ void PrepareNextRender();
|
|
+
|
|
EINTERLACEMETHOD AutoInterlaceMethodInternal(EINTERLACEMETHOD mInt);
|
|
|
|
bool m_bPauseDrawing; // true if we should pause rendering
|
|
@@ -169,6 +181,37 @@ class CXBMCRenderManager
|
|
double m_displayLatency;
|
|
void UpdateDisplayLatency();
|
|
|
|
+ // Render Buffer State Description:
|
|
+ //
|
|
+ // Output: is the buffer about to or having its texture prepared for render (ie from output thread).
|
|
+ // Cannot go past the "Displayed" buffer (otherwise we will probably overwrite buffers not yet
|
|
+ // displayed or even rendered).
|
|
+ // Current: is the current buffer being or having been submitted for render to back buffer.
|
|
+ // Cannot go past "Output" buffer (else it would be rendering old output).
|
|
+ // Displayed: is the buffer that is now considered to be safely copied from back buffer to front buffer
|
|
+ // (we assume that after two swap-buffer flips for the same "Current" render buffer that that
|
|
+ // buffer will be safe, but otherwise we consider that only the previous-to-"Current" is guaranteed).
|
|
+
|
|
+ int m_iCurrentRenderBuffer;
|
|
+ int m_iNumRenderBuffers;
|
|
+ int m_iOutputRenderBuffer;
|
|
+ int m_iDisplayedRenderBuffer;
|
|
+ bool m_bAllRenderBuffersDisplayed;
|
|
+ bool m_bUseBuffering;
|
|
+ bool m_bCodecSupportsBuffering;
|
|
+ int m_speed;
|
|
+ CEvent m_flipEvent;
|
|
+
|
|
+ struct
|
|
+ {
|
|
+ double pts;
|
|
+ EFIELDSYNC presentfield;
|
|
+ EPRESENTMETHOD presentmethod;
|
|
+ }m_renderBuffers[5];
|
|
+
|
|
+ double m_sleeptime;
|
|
+ double m_presentPts;
|
|
+
|
|
double m_presenttime;
|
|
double m_presentcorr;
|
|
double m_presenterr;
|
|
@@ -180,6 +223,7 @@ class CXBMCRenderManager
|
|
int m_presentsource;
|
|
CEvent m_presentevent;
|
|
CEvent m_flushEvent;
|
|
+ CDVDClock *m_pClock;
|
|
|
|
|
|
OVERLAY::CRenderer m_overlays;
|
|
diff --git a/xbmc/cores/VideoRenderers/WinRenderer.cpp b/xbmc/cores/VideoRenderers/WinRenderer.cpp
|
|
index 7842089..6e4433c 100644
|
|
--- a/xbmc/cores/VideoRenderers/WinRenderer.cpp
|
|
+++ b/xbmc/cores/VideoRenderers/WinRenderer.cpp
|
|
@@ -253,12 +253,12 @@ int CWinRenderer::NextYV12Texture()
|
|
return -1;
|
|
}
|
|
|
|
-bool CWinRenderer::AddVideoPicture(DVDVideoPicture* picture)
|
|
+bool CWinRenderer::AddVideoPicture(DVDVideoPicture* picture, int index)
|
|
{
|
|
if (m_renderMethod == RENDER_DXVA)
|
|
{
|
|
- int source = NextYV12Texture();
|
|
- if(source < 0)
|
|
+ int source = index;
|
|
+ if(source < 0 || NextYV12Texture() < 0)
|
|
return false;
|
|
|
|
DXVABuffer *buf = (DXVABuffer*)m_VideoBuffers[source];
|
|
@@ -274,7 +274,7 @@ int CWinRenderer::GetImage(YV12Image *image, int source, bool readonly)
|
|
if( source == AUTOSOURCE )
|
|
source = NextYV12Texture();
|
|
|
|
- if( source < 0 )
|
|
+ if( source < 0 || NextYV12Texture() < 0)
|
|
return -1;
|
|
|
|
YUVBuffer *buf = (YUVBuffer*)m_VideoBuffers[source];
|
|
diff --git a/xbmc/cores/VideoRenderers/WinRenderer.h b/xbmc/cores/VideoRenderers/WinRenderer.h
|
|
index 2ab5684..f493ba7 100644
|
|
--- a/xbmc/cores/VideoRenderers/WinRenderer.h
|
|
+++ b/xbmc/cores/VideoRenderers/WinRenderer.h
|
|
@@ -157,7 +157,7 @@ class CWinRenderer : public CBaseRenderer
|
|
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 bool AddVideoPicture(DVDVideoPicture* picture);
|
|
+ virtual bool AddVideoPicture(DVDVideoPicture* picture, int index);
|
|
virtual void FlipPage(int source);
|
|
virtual unsigned int PreInit();
|
|
virtual void UnInit();
|
|
diff --git a/xbmc/cores/dvdplayer/DVDPlayer.cpp b/xbmc/cores/dvdplayer/DVDPlayer.cpp
|
|
index 0cd2510..315d64a 100644
|
|
--- a/xbmc/cores/dvdplayer/DVDPlayer.cpp
|
|
+++ b/xbmc/cores/dvdplayer/DVDPlayer.cpp
|
|
@@ -463,7 +463,7 @@ bool CDVDPlayer::OpenFile(const CFileItem& file, const CPlayerOptions &options)
|
|
m_ready.Reset();
|
|
|
|
#if defined(HAS_VIDEO_PLAYBACK)
|
|
- g_renderManager.PreInit();
|
|
+ g_renderManager.PreInit(&m_clock);
|
|
#endif
|
|
|
|
Create();
|
|
diff --git a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp
|
|
index 3008c25..a4bb1ba 100644
|
|
--- a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp
|
|
+++ b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp
|
|
@@ -261,6 +261,7 @@ void CDVDPlayerVideo::OpenStream(CDVDStreamInfo &hint, CDVDVideoCodec* codec)
|
|
m_stalled = m_messageQueue.GetPacketCount(CDVDMsg::DEMUXER_PACKET) == 0;
|
|
m_started = false;
|
|
m_codecname = m_pVideoCodec->GetName();
|
|
+ g_renderManager.EnableBuffering(false);
|
|
}
|
|
|
|
void CDVDPlayerVideo::CloseStream(bool bWaitForBuffers)
|
|
@@ -436,6 +437,7 @@ void CDVDPlayerVideo::Process()
|
|
picture.iFlags &= ~DVP_FLAG_ALLOCATED;
|
|
m_packets.clear();
|
|
m_started = false;
|
|
+ g_renderManager.EnableBuffering(false);
|
|
}
|
|
else if (pMsg->IsType(CDVDMsg::GENERAL_FLUSH)) // private message sent by (CDVDPlayerVideo::Flush())
|
|
{
|
|
@@ -448,6 +450,7 @@ void CDVDPlayerVideo::Process()
|
|
//we need to recalculate the framerate
|
|
//TODO: this needs to be set on a streamchange instead
|
|
ResetFrameRateCalc();
|
|
+ g_renderManager.EnableBuffering(false);
|
|
|
|
m_stalled = true;
|
|
m_started = false;
|
|
@@ -586,6 +589,8 @@ void CDVDPlayerVideo::Process()
|
|
|
|
m_pVideoCodec->Reset();
|
|
m_packets.clear();
|
|
+ picture.iFlags &= ~DVP_FLAG_ALLOCATED;
|
|
+ g_renderManager.DiscardBuffer();
|
|
break;
|
|
}
|
|
|
|
@@ -700,6 +705,7 @@ void CDVDPlayerVideo::Process()
|
|
m_codecname = m_pVideoCodec->GetName();
|
|
m_started = true;
|
|
m_messageParent.Put(new CDVDMsgInt(CDVDMsg::PLAYER_STARTED, DVDPLAYER_VIDEO));
|
|
+ g_renderManager.EnableBuffering(true);
|
|
}
|
|
|
|
// guess next frame pts. iDuration is always valid
|
|
@@ -1317,6 +1323,16 @@ int CDVDPlayerVideo::OutputPicture(const DVDVideoPicture* src, double pts)
|
|
mDisplayField = FS_BOT;
|
|
}
|
|
|
|
+ int buffer = g_renderManager.WaitForBuffer(m_bStop);
|
|
+ while (buffer < 0 && !CThread::m_bStop &&
|
|
+ CDVDClock::GetAbsoluteClock(false) < iCurrentClock + iSleepTime + DVD_MSEC_TO_TIME(500) )
|
|
+ {
|
|
+ Sleep(1);
|
|
+ buffer = g_renderManager.WaitForBuffer(m_bStop);
|
|
+ }
|
|
+ if (buffer < 0)
|
|
+ return EOS_DROPPED;
|
|
+
|
|
ProcessOverlays(pPicture, pts);
|
|
AutoCrop(pPicture);
|
|
|
|
@@ -1333,7 +1349,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, pts, -1, mDisplayField, m_speed);
|
|
|
|
return result;
|
|
#else
|
|
--
|
|
1.7.10
|
|
|
|
|
|
From dacc0167c993efa6ac884fd3c439fc5f0c823934 Mon Sep 17 00:00:00 2001
|
|
From: xbmc <fernetmenta@online.de>
|
|
Date: Tue, 2 Oct 2012 10:49:09 +0200
|
|
Subject: [PATCH 03/72] linuxrenderer: delete all textures on reconfigure
|
|
|
|
---
|
|
xbmc/cores/VideoRenderers/LinuxRendererGL.cpp | 2 +-
|
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
|
|
|
diff --git a/xbmc/cores/VideoRenderers/LinuxRendererGL.cpp b/xbmc/cores/VideoRenderers/LinuxRendererGL.cpp
|
|
index b32a7ea..a2dc2be 100644
|
|
--- a/xbmc/cores/VideoRenderers/LinuxRendererGL.cpp
|
|
+++ b/xbmc/cores/VideoRenderers/LinuxRendererGL.cpp
|
|
@@ -251,7 +251,7 @@ bool CLinuxRendererGL::ValidateRenderTarget()
|
|
// function pointer for texture might change in
|
|
// call to LoadShaders
|
|
glFinish();
|
|
- for (int i = 0 ; i < m_NumYV12Buffers ; i++)
|
|
+ for (int i = 0 ; i < NUM_BUFFERS ; i++)
|
|
(this->*m_textureDelete)(i);
|
|
|
|
// trigger update of video filters
|
|
--
|
|
1.7.10
|
|
|
|
|
|
From 226539d21ba940ea8add89417df7102302c7ba79 Mon Sep 17 00:00:00 2001
|
|
From: xbmc <fernetmenta@online.de>
|
|
Date: Mon, 28 May 2012 10:17:33 +0200
|
|
Subject: [PATCH 04/72] drop frame counter in application, ask render manager
|
|
instead
|
|
|
|
---
|
|
xbmc/Application.cpp | 50 +++++----------------------
|
|
xbmc/Application.h | 6 ++--
|
|
xbmc/cores/VideoRenderers/RenderManager.cpp | 11 ++++++
|
|
xbmc/cores/VideoRenderers/RenderManager.h | 1 +
|
|
4 files changed, 23 insertions(+), 45 deletions(-)
|
|
|
|
diff --git a/xbmc/Application.cpp b/xbmc/Application.cpp
|
|
index 18e6310..9a7b900 100644
|
|
--- a/xbmc/Application.cpp
|
|
+++ b/xbmc/Application.cpp
|
|
@@ -415,8 +415,6 @@
|
|
#endif
|
|
m_currentStack = new CFileItemList;
|
|
|
|
- m_frameCount = 0;
|
|
-
|
|
m_bPresentFrame = false;
|
|
m_bPlatformDirectories = true;
|
|
|
|
@@ -2227,28 +2225,18 @@ float CApplication::GetDimScreenSaverLevel() const
|
|
|
|
bool CApplication::WaitFrame(unsigned int timeout)
|
|
{
|
|
- bool done = false;
|
|
-
|
|
// Wait for all other frames to be presented
|
|
- CSingleLock lock(m_frameMutex);
|
|
- //wait until event is set, but modify remaining time
|
|
+ m_frameEvent.Reset();
|
|
|
|
- TightConditionVariable<InversePredicate<int&> > cv(m_frameCond, InversePredicate<int&>(m_frameCount));
|
|
- cv.wait(lock,timeout);
|
|
- done = m_frameCount == 0;
|
|
+ if (!g_renderManager.HasFrame() && !m_frameEvent.WaitMSec(timeout))
|
|
+ return false;
|
|
|
|
- return done;
|
|
+ return g_renderManager.HasFrame();
|
|
}
|
|
|
|
void CApplication::NewFrame()
|
|
{
|
|
- // We just posted another frame. Keep track and notify.
|
|
- {
|
|
- CSingleLock lock(m_frameMutex);
|
|
- m_frameCount++;
|
|
- }
|
|
-
|
|
- m_frameCond.notifyAll();
|
|
+ m_frameEvent.Set();
|
|
}
|
|
|
|
void CApplication::Render()
|
|
@@ -2268,7 +2256,6 @@ void CApplication::Render()
|
|
|
|
int vsync_mode = g_guiSettings.GetInt("videoscreen.vsync");
|
|
|
|
- bool decrement = false;
|
|
bool hasRendered = false;
|
|
bool limitFrames = false;
|
|
unsigned int singleFrameTime = 10; // default limit 100 fps
|
|
@@ -2282,13 +2269,10 @@ void CApplication::Render()
|
|
m_bPresentFrame = false;
|
|
if (!extPlayerActive && g_graphicsContext.IsFullScreenVideo() && !IsPaused())
|
|
{
|
|
- CSingleLock lock(m_frameMutex);
|
|
-
|
|
- TightConditionVariable<int&> cv(m_frameCond,m_frameCount);
|
|
- cv.wait(lock,100);
|
|
-
|
|
- m_bPresentFrame = m_frameCount > 0;
|
|
- decrement = m_bPresentFrame;
|
|
+ m_frameEvent.Reset();
|
|
+ m_bPresentFrame = g_renderManager.HasFrame();
|
|
+ if (!m_bPresentFrame && m_frameEvent.WaitMSec(100))
|
|
+ m_bPresentFrame = g_renderManager.HasFrame();
|
|
hasRendered = true;
|
|
}
|
|
else
|
|
@@ -2312,8 +2296,6 @@ void CApplication::Render()
|
|
else if (lowfps)
|
|
singleFrameTime = 200; // 5 fps, <=200 ms latency to wake up
|
|
}
|
|
-
|
|
- decrement = true;
|
|
}
|
|
}
|
|
|
|
@@ -2377,13 +2359,6 @@ void CApplication::Render()
|
|
|
|
g_renderManager.UpdateResolution();
|
|
g_renderManager.ManageCaptures();
|
|
-
|
|
- {
|
|
- CSingleLock lock(m_frameMutex);
|
|
- if(m_frameCount > 0 && decrement)
|
|
- m_frameCount--;
|
|
- }
|
|
- m_frameCond.notifyAll();
|
|
}
|
|
|
|
void CApplication::SetStandAlone(bool value)
|
|
@@ -5638,12 +5613,6 @@ bool CApplication::SwitchToFullScreen()
|
|
// See if we're playing a video, and are in GUI mode
|
|
if ( IsPlayingVideo() && g_windowManager.GetActiveWindow() != WINDOW_FULLSCREEN_VIDEO)
|
|
{
|
|
- // Reset frame count so that timing is FPS will be correct.
|
|
- {
|
|
- CSingleLock lock(m_frameMutex);
|
|
- m_frameCount = 0;
|
|
- }
|
|
-
|
|
// then switch to fullscreen mode
|
|
g_windowManager.ActivateWindow(WINDOW_FULLSCREEN_VIDEO);
|
|
return true;
|
|
@@ -5876,7 +5845,6 @@ bool CApplication::IsCurrentThread() const
|
|
|
|
bool CApplication::IsPresentFrame()
|
|
{
|
|
- CSingleLock lock(m_frameMutex);
|
|
bool ret = m_bPresentFrame;
|
|
|
|
return ret;
|
|
diff --git a/xbmc/Application.h b/xbmc/Application.h
|
|
index 69609fa..6764a60 100644
|
|
--- a/xbmc/Application.h
|
|
+++ b/xbmc/Application.h
|
|
@@ -422,10 +422,8 @@ class CApplication : public CXBApplicationEx, public IPlayerCallback, public IMs
|
|
bool m_bEnableLegacyRes;
|
|
bool m_bTestMode;
|
|
bool m_bSystemScreenSaverEnable;
|
|
-
|
|
- int m_frameCount;
|
|
- CCriticalSection m_frameMutex;
|
|
- XbmcThreads::ConditionVariable m_frameCond;
|
|
+
|
|
+ CEvent m_frameEvent;
|
|
|
|
VIDEO::CVideoInfoScanner *m_videoInfoScanner;
|
|
MUSIC_INFO::CMusicInfoScanner *m_musicInfoScanner;
|
|
diff --git a/xbmc/cores/VideoRenderers/RenderManager.cpp b/xbmc/cores/VideoRenderers/RenderManager.cpp
|
|
index eeb6c6f..4b897da 100644
|
|
--- a/xbmc/cores/VideoRenderers/RenderManager.cpp
|
|
+++ b/xbmc/cores/VideoRenderers/RenderManager.cpp
|
|
@@ -1104,3 +1104,14 @@ void CXBMCRenderManager::NotifyDisplayFlip()
|
|
lock.Leave();
|
|
m_flipEvent.Set();
|
|
}
|
|
+
|
|
+bool CXBMCRenderManager::HasFrame()
|
|
+{
|
|
+ CSharedLock lock(m_sharedSection);
|
|
+ if (m_presentstep == PRESENT_IDLE &&
|
|
+ GetNextRenderBufferIndex() < 0 &&
|
|
+ m_speed > 0)
|
|
+ return false;
|
|
+ else
|
|
+ return true;
|
|
+}
|
|
diff --git a/xbmc/cores/VideoRenderers/RenderManager.h b/xbmc/cores/VideoRenderers/RenderManager.h
|
|
index 34ff8d0..288175e 100644
|
|
--- a/xbmc/cores/VideoRenderers/RenderManager.h
|
|
+++ b/xbmc/cores/VideoRenderers/RenderManager.h
|
|
@@ -134,6 +134,7 @@ class CXBMCRenderManager
|
|
void RegisterRenderUpdateCallBack(const void *ctx, RenderUpdateCallBackFn fn);
|
|
int WaitForBuffer(volatile bool& bStop);
|
|
void NotifyDisplayFlip();
|
|
+ bool HasFrame();
|
|
void EnableBuffering(bool enable);
|
|
void DiscardBuffer();
|
|
|
|
--
|
|
1.7.10
|
|
|
|
|
|
From 0f81843cb7279f3b99607551967354ff30e15e4d Mon Sep 17 00:00:00 2001
|
|
From: xbmc <fernetmenta@online.de>
|
|
Date: Mon, 28 May 2012 10:34:39 +0200
|
|
Subject: [PATCH 05/72] videoplayer: adopt lateness detection and dropping to
|
|
buffering
|
|
|
|
---
|
|
xbmc/cores/VideoRenderers/RenderManager.cpp | 12 ++
|
|
xbmc/cores/VideoRenderers/RenderManager.h | 1 +
|
|
.../dvdplayer/DVDCodecs/Video/DVDVideoCodec.h | 14 ++
|
|
.../DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp | 31 +++
|
|
.../DVDCodecs/Video/DVDVideoCodecFFmpeg.h | 7 +
|
|
xbmc/cores/dvdplayer/DVDPlayerVideo.cpp | 224 ++++++++++++++++----
|
|
xbmc/cores/dvdplayer/DVDPlayerVideo.h | 24 +++
|
|
7 files changed, 268 insertions(+), 45 deletions(-)
|
|
|
|
diff --git a/xbmc/cores/VideoRenderers/RenderManager.cpp b/xbmc/cores/VideoRenderers/RenderManager.cpp
|
|
index 4b897da..f19797c 100644
|
|
--- a/xbmc/cores/VideoRenderers/RenderManager.cpp
|
|
+++ b/xbmc/cores/VideoRenderers/RenderManager.cpp
|
|
@@ -1105,6 +1105,18 @@ void CXBMCRenderManager::NotifyDisplayFlip()
|
|
m_flipEvent.Set();
|
|
}
|
|
|
|
+bool CXBMCRenderManager::GetStats(double &sleeptime, double &pts, int &bufferLevel)
|
|
+{
|
|
+ CSharedLock lock(m_sharedSection);
|
|
+ sleeptime = m_sleeptime;
|
|
+ pts = m_presentPts;
|
|
+ if (m_iNumRenderBuffers < 3)
|
|
+ bufferLevel = -1;
|
|
+ else
|
|
+ bufferLevel = (m_iOutputRenderBuffer - m_iCurrentRenderBuffer + m_iNumRenderBuffers) % m_iNumRenderBuffers;
|
|
+ return true;
|
|
+}
|
|
+
|
|
bool CXBMCRenderManager::HasFrame()
|
|
{
|
|
CSharedLock lock(m_sharedSection);
|
|
diff --git a/xbmc/cores/VideoRenderers/RenderManager.h b/xbmc/cores/VideoRenderers/RenderManager.h
|
|
index 288175e..9342586 100644
|
|
--- a/xbmc/cores/VideoRenderers/RenderManager.h
|
|
+++ b/xbmc/cores/VideoRenderers/RenderManager.h
|
|
@@ -134,6 +134,7 @@ class CXBMCRenderManager
|
|
void RegisterRenderUpdateCallBack(const void *ctx, RenderUpdateCallBackFn fn);
|
|
int WaitForBuffer(volatile bool& bStop);
|
|
void NotifyDisplayFlip();
|
|
+ bool GetStats(double &sleeptime, double &pts, int &bufferLevel);
|
|
bool HasFrame();
|
|
void EnableBuffering(bool enable);
|
|
void DiscardBuffer();
|
|
diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h
|
|
index 1d8bad3..5001aac 100644
|
|
--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h
|
|
+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h
|
|
@@ -110,6 +110,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 DVP_FLAG_DROPDEINT 0x00000040 // indicate that this picture was requested to have been dropped in deint stage
|
|
+#define DVP_FLAG_NO_POSTPROC 0x00000100
|
|
+#define DVP_FLAG_DRAIN 0x00000200
|
|
+
|
|
// DVP_FLAG 0x00000100 - 0x00000f00 is in use by libmpeg2!
|
|
|
|
#define DVP_QSCALE_UNKNOWN 0
|
|
@@ -127,6 +131,9 @@ struct DVDVideoUserData
|
|
#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
|
|
+#define VC_HURRY 0x00000040
|
|
+
|
|
class CDVDVideoCodec
|
|
{
|
|
public:
|
|
@@ -237,4 +244,11 @@ class CDVDVideoCodec
|
|
{
|
|
return 0;
|
|
}
|
|
+
|
|
+ virtual bool GetPts(double &pts, int &skippedDeint, int &interlaced)
|
|
+ {
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ virtual void SetCodecControl(int flags) {}
|
|
};
|
|
diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp
|
|
index 8f81637..af706bd 100644
|
|
--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp
|
|
+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp
|
|
@@ -142,6 +142,7 @@ enum PixelFormat CDVDVideoCodecFFmpeg::GetFormat( struct AVCodecContext * avctx
|
|
m_iLastKeyframe = 0;
|
|
m_dts = DVD_NOPTS_VALUE;
|
|
m_started = false;
|
|
+ m_decoderPts = DVD_NOPTS_VALUE;
|
|
}
|
|
|
|
CDVDVideoCodecFFmpeg::~CDVDVideoCodecFFmpeg()
|
|
@@ -340,6 +341,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
|
|
@@ -541,6 +550,7 @@ int CDVDVideoCodecFFmpeg::Decode(BYTE* pData, int iSize, double dts, double pts)
|
|
void CDVDVideoCodecFFmpeg::Reset()
|
|
{
|
|
m_started = false;
|
|
+ m_decoderPts = DVD_NOPTS_VALUE;
|
|
m_iLastKeyframe = m_pCodecContext->has_b_frames;
|
|
m_dllAvCodec.avcodec_flush_buffers(m_pCodecContext);
|
|
|
|
@@ -639,6 +649,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 |= DVP_FLAG_DROPDEINT;
|
|
+ m_skippedDeint = 1;
|
|
+ }
|
|
+ else
|
|
+ m_skippedDeint = 0;
|
|
+
|
|
+ m_requestSkipDeint = false;
|
|
+ pDvdVideoPicture->iFlags |= m_codecControlFlags;
|
|
+
|
|
if(!m_started)
|
|
pDvdVideoPicture->iFlags |= DVP_FLAG_DROPPED;
|
|
|
|
@@ -861,3 +887,8 @@ unsigned CDVDVideoCodecFFmpeg::GetConvergeCount()
|
|
else
|
|
return 0;
|
|
}
|
|
+
|
|
+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 61d0305..52e1113 100644
|
|
--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.h
|
|
+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.h
|
|
@@ -44,6 +44,7 @@ class CDVDVideoCodecFFmpeg : public CDVDVideoCodec
|
|
virtual bool GetPicture(AVCodecContext* avctx, AVFrame* frame, DVDVideoPicture* picture) = 0;
|
|
virtual int Check (AVCodecContext* avctx) = 0;
|
|
virtual void Reset () {}
|
|
+ virtual bool CanSkipDeint() {return false; }
|
|
virtual const std::string Name() = 0;
|
|
virtual CCriticalSection* Section() { return NULL; }
|
|
};
|
|
@@ -60,6 +61,8 @@ class CDVDVideoCodecFFmpeg : public CDVDVideoCodec
|
|
virtual unsigned int SetFilters(unsigned int filters);
|
|
virtual const char* GetName() { return m_name.c_str(); }; // m_name is never changed after open
|
|
virtual unsigned GetConvergeCount();
|
|
+ virtual bool GetPts(double &pts, int &skippedDeint, int &interlaced) {pts=m_decoderPts; skippedDeint=m_skippedDeint; if (m_pFrame) interlaced = m_pFrame->interlaced_frame; return true;}
|
|
+ virtual void SetCodecControl(int flags);
|
|
|
|
bool IsHardwareAllowed() { return !m_bSoftware; }
|
|
IHardwareDecoder * GetHardware() { return m_pHardware; };
|
|
@@ -119,4 +122,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 a4bb1ba..93908a7 100644
|
|
--- a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp
|
|
+++ b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp
|
|
@@ -326,8 +326,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)
|
|
{
|
|
@@ -437,6 +439,7 @@ void CDVDPlayerVideo::Process()
|
|
picture.iFlags &= ~DVP_FLAG_ALLOCATED;
|
|
m_packets.clear();
|
|
m_started = false;
|
|
+ m_droppingStats.Reset();
|
|
g_renderManager.EnableBuffering(false);
|
|
}
|
|
else if (pMsg->IsType(CDVDMsg::GENERAL_FLUSH)) // private message sent by (CDVDPlayerVideo::Flush())
|
|
@@ -450,6 +453,7 @@ void CDVDPlayerVideo::Process()
|
|
//we need to recalculate the framerate
|
|
//TODO: this needs to be set on a streamchange instead
|
|
ResetFrameRateCalc();
|
|
+ m_droppingStats.Reset();
|
|
g_renderManager.EnableBuffering(false);
|
|
|
|
m_stalled = true;
|
|
@@ -468,6 +472,7 @@ void CDVDPlayerVideo::Process()
|
|
m_speed = static_cast<CDVDMsgInt*>(pMsg)->m_value;
|
|
if(m_speed == DVD_PLAYSPEED_PAUSE)
|
|
m_iNrOfPicturesNotToSkip = 0;
|
|
+ m_droppingStats.Reset();
|
|
}
|
|
else if (pMsg->IsType(CDVDMsg::PLAYER_STARTED))
|
|
{
|
|
@@ -502,6 +507,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 |= DVP_FLAG_DRAIN;
|
|
+ if (m_speed > DVD_PLAYSPEED_NORMAL)
|
|
+ codecControl |= DVP_FLAG_NO_POSTPROC;
|
|
+ m_pVideoCodec->SetCodecControl(codecControl);
|
|
+ if (iDropDirective & EOS_DROPPED)
|
|
+ {
|
|
+ m_iDroppedFrames++;
|
|
+ iDropped++;
|
|
+ }
|
|
+
|
|
#ifdef PROFILE
|
|
bRequestDrop = false;
|
|
#else
|
|
@@ -511,6 +538,7 @@ void CDVDPlayerVideo::Process()
|
|
bRequestDrop = false;
|
|
m_iDroppedRequest = 0;
|
|
m_iLateFrames = 0;
|
|
+ m_droppingStats.m_requestOutputDrop = false;
|
|
}
|
|
#endif
|
|
|
|
@@ -558,15 +586,8 @@ 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++;
|
|
- }
|
|
+
|
|
+ bRequestDrop = false;
|
|
|
|
// loop while no error
|
|
while (!m_bStop)
|
|
@@ -1244,50 +1265,30 @@ int CDVDPlayerVideo::OutputPicture(const DVDVideoPicture* src, double pts)
|
|
m_FlipTimeStamp += max(0.0, iSleepTime);
|
|
m_FlipTimeStamp += iFrameDuration;
|
|
|
|
- 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_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
|
|
- }
|
|
-
|
|
- //if we requested 5 drops in a row and we're still late, drop on output
|
|
- //this keeps a/v sync if the decoder can't drop, or we're still calculating the framerate
|
|
- if (m_iDroppedRequest > 5)
|
|
- {
|
|
- m_iDroppedRequest--; //decrease so we only drop half the frames
|
|
- return result | EOS_DROPPED;
|
|
- }
|
|
- m_iDroppedRequest++;
|
|
- }
|
|
- }
|
|
- else
|
|
+ if ((m_droppingStats.m_requestOutputDrop && !(pPicture->iFlags & DVP_FLAG_NOSKIP))
|
|
+ || (pPicture->iFlags & DVP_FLAG_DROPPED))
|
|
{
|
|
- m_iDroppedRequest = 0;
|
|
+ m_droppingStats.AddOutputDropGain(pts, 1/m_fFrameRate);
|
|
+ m_droppingStats.m_requestOutputDrop = false;
|
|
+ CLog::Log(LOGDEBUG,"%s - dropped in output", __FUNCTION__);
|
|
+ return result | EOS_DROPPED;
|
|
}
|
|
|
|
if( m_speed < 0 )
|
|
{
|
|
- if( iClockSleep < -DVD_MSEC_TO_TIME(200)
|
|
- && !(pPicture->iFlags & DVP_FLAG_NOSKIP) )
|
|
+ double decoderPts = m_droppingStats.m_lastDecoderPts;
|
|
+ double renderPts = m_droppingStats.m_lastRenderPts;
|
|
+ if (pts > renderPts)
|
|
+ {
|
|
+ if (decoderPts >= renderPts)
|
|
+ {
|
|
+ Sleep(200);
|
|
+ }
|
|
return result | EOS_DROPPED;
|
|
+ }
|
|
}
|
|
|
|
- if( (pPicture->iFlags & DVP_FLAG_DROPPED) )
|
|
- return result | EOS_DROPPED;
|
|
-
|
|
- if( m_speed != DVD_PLAYSPEED_NORMAL && limited )
|
|
+ if( m_speed != DVD_PLAYSPEED_NORMAL && m_speed >= 0 && limited )
|
|
{
|
|
// calculate frame dropping pattern to render at this speed
|
|
// we do that by deciding if this or next frame is closest
|
|
@@ -1648,3 +1649,136 @@ void CDVDPlayerVideo::CalcFrameRate()
|
|
m_iFrameRateCount = 0;
|
|
}
|
|
}
|
|
+
|
|
+int CDVDPlayerVideo::CalcDropRequirement(double pts)
|
|
+{
|
|
+ int result = 0;
|
|
+ double iSleepTime;
|
|
+ double iDecoderPts, iRenderPts;
|
|
+ double iInterval;
|
|
+ int interlaced;
|
|
+ double iGain;
|
|
+ double iLateness;
|
|
+ bool bNewFrame;
|
|
+ int iSkippedDeint = 0;
|
|
+ int iBufferLevel;
|
|
+
|
|
+ // get decoder stats
|
|
+ if (!m_pVideoCodec->GetPts(iDecoderPts, iSkippedDeint, interlaced))
|
|
+ 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;
|
|
+
|
|
+ if (interlaced)
|
|
+ iInterval = 2/m_fFrameRate*(double)DVD_TIME_BASE;
|
|
+ else
|
|
+ iInterval = 1/m_fFrameRate*(double)DVD_TIME_BASE;
|
|
+
|
|
+ if (m_droppingStats.m_lastDecoderPts > 0
|
|
+ && bNewFrame
|
|
+ && m_bAllowDrop
|
|
+ && m_droppingStats.m_dropRequests > 0)
|
|
+ {
|
|
+ iGain = (iDecoderPts - m_droppingStats.m_lastDecoderPts - iInterval)/(double)DVD_TIME_BASE;
|
|
+ if (iSkippedDeint)
|
|
+ {
|
|
+ CDroppingStats::CGain gain;
|
|
+ gain.gain = 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 de-interlacing cycle, Sleeptime: %f, Bufferlevel: %d", iSleepTime, iBufferLevel);
|
|
+ }
|
|
+ else if (iGain > 1/m_fFrameRate)
|
|
+ {
|
|
+ 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)
|
|
+ {
|
|
+ result |= EOS_VERYLATE;
|
|
+
|
|
+ // drop in output
|
|
+ if (m_droppingStats.m_dropRequests > 7 && g_graphicsContext.IsFullScreenVideo())
|
|
+ {
|
|
+ m_droppingStats.m_dropRequests--; //decrease so we only drop half the frames
|
|
+ m_droppingStats.m_requestOutputDrop = true;
|
|
+ }
|
|
+ else if (bNewFrame)
|
|
+ m_droppingStats.m_dropRequests++;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ m_droppingStats.m_dropRequests = 0;
|
|
+ m_droppingStats.m_lateFrames = 0;
|
|
+ m_droppingStats.m_requestOutputDrop = false;
|
|
+ }
|
|
+ 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;
|
|
+ m_requestOutputDrop = false;
|
|
+}
|
|
+
|
|
+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 fe7e12c..4913712 100644
|
|
--- a/xbmc/cores/dvdplayer/DVDPlayerVideo.h
|
|
+++ b/xbmc/cores/dvdplayer/DVDPlayerVideo.h
|
|
@@ -37,6 +37,26 @@
|
|
|
|
#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;
|
|
+ bool m_requestOutputDrop;
|
|
+};
|
|
+
|
|
+
|
|
class CDVDPlayerVideo : public CThread
|
|
{
|
|
public:
|
|
@@ -110,6 +130,7 @@ class CDVDPlayerVideo : public CThread
|
|
#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);
|
|
@@ -135,6 +156,7 @@ class CDVDPlayerVideo : public CThread
|
|
|
|
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
|
|
@@ -195,5 +217,7 @@ class CDVDPlayerVideo : public CThread
|
|
CPullupCorrection m_pullupCorrection;
|
|
|
|
std::list<DVDMessageListItem> m_packets;
|
|
+
|
|
+ CDroppingStats m_droppingStats;
|
|
};
|
|
|
|
--
|
|
1.7.10
|
|
|
|
|
|
From 4bc6ff77b121468020578f9d393e8aaae1a419f6 Mon Sep 17 00:00:00 2001
|
|
From: xbmc <fernetmenta@online.de>
|
|
Date: Mon, 28 May 2012 10:41:31 +0200
|
|
Subject: [PATCH 06/72] 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 93908a7..4675556 100644
|
|
--- a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp
|
|
+++ b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp
|
|
@@ -721,6 +721,8 @@ void CDVDPlayerVideo::Process()
|
|
CDVDCodecUtils::FreePicture(pTempYUVPackedPicture);
|
|
#endif
|
|
|
|
+ frametime = (double)DVD_TIME_BASE/m_fFrameRate;
|
|
+
|
|
if(m_started == false)
|
|
{
|
|
m_codecname = m_pVideoCodec->GetName();
|
|
--
|
|
1.7.10
|
|
|
|
|
|
From 723a731d68b9360f9804e8711255afa62c4ce34d Mon Sep 17 00:00:00 2001
|
|
From: xbmc <fernetmenta@online.de>
|
|
Date: Mon, 28 May 2012 10:43:06 +0200
|
|
Subject: [PATCH 07/72] videoplayer: give streams with invalid fps a chance
|
|
for fps detection
|
|
|
|
---
|
|
xbmc/cores/dvdplayer/DVDPlayerVideo.cpp | 2 +-
|
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
|
|
|
diff --git a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp
|
|
index 4675556..2ef6358 100644
|
|
--- a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp
|
|
+++ b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp
|
|
@@ -1595,7 +1595,7 @@ void CDVDPlayerVideo::CalcFrameRate()
|
|
double frameduration = m_pullupCorrection.GetFrameDuration();
|
|
|
|
if (frameduration == DVD_NOPTS_VALUE ||
|
|
- (g_advancedSettings.m_videoFpsDetect == 1 && m_pullupCorrection.GetPatternLength() > 1))
|
|
+ (g_advancedSettings.m_videoFpsDetect == 1 && (m_pullupCorrection.GetPatternLength() > 1 && !m_bFpsInvalid)))
|
|
{
|
|
//reset the stored framerates if no good framerate was detected
|
|
m_fStableFrameRate = 0.0;
|
|
--
|
|
1.7.10
|
|
|
|
|
|
From 60c955c30cdfcf361396e47fc92a1e1883b085fe Mon Sep 17 00:00:00 2001
|
|
From: xbmc <fernetmenta@online.de>
|
|
Date: Mon, 28 May 2012 10:49:05 +0200
|
|
Subject: [PATCH 08/72] dvdplayer: allow rewinding at end of stream, do a seek
|
|
after rewind
|
|
|
|
---
|
|
xbmc/cores/dvdplayer/DVDPlayer.cpp | 8 +++++++-
|
|
1 file changed, 7 insertions(+), 1 deletion(-)
|
|
|
|
diff --git a/xbmc/cores/dvdplayer/DVDPlayer.cpp b/xbmc/cores/dvdplayer/DVDPlayer.cpp
|
|
index 315d64a..6fcb6b3 100644
|
|
--- a/xbmc/cores/dvdplayer/DVDPlayer.cpp
|
|
+++ b/xbmc/cores/dvdplayer/DVDPlayer.cpp
|
|
@@ -1542,7 +1542,7 @@ void CDVDPlayer::HandlePlaySpeed()
|
|
|
|
}
|
|
else if (m_CurrentVideo.id >= 0
|
|
- && m_CurrentVideo.inited == true
|
|
+ && (m_CurrentVideo.inited == true || GetPlaySpeed() < 0) // allow rewind at end of file
|
|
&& m_SpeedState.lastpts != m_dvdPlayerVideo.GetCurrentPts()
|
|
&& m_SpeedState.lasttime != GetTime())
|
|
{
|
|
@@ -2183,6 +2183,12 @@ void CDVDPlayer::HandleMessages()
|
|
pvrinputstream->Pause( speed == 0 );
|
|
}
|
|
|
|
+ // do a seek after rewind, clock is not in sync with current pts
|
|
+ if (m_playSpeed < 0 && speed >= 0)
|
|
+ {
|
|
+ m_messenger.Put(new CDVDMsgPlayerSeek(GetTime(), true, true, true));
|
|
+ }
|
|
+
|
|
// if playspeed is different then DVD_PLAYSPEED_NORMAL or DVD_PLAYSPEED_PAUSE
|
|
// audioplayer, stops outputing audio to audiorendere, but still tries to
|
|
// sleep an correct amount for each packet
|
|
--
|
|
1.7.10
|
|
|
|
|
|
From 8d237cf023501560fc394679819463034a209413 Mon Sep 17 00:00:00 2001
|
|
From: xbmc <fernetmenta@online.de>
|
|
Date: Sun, 2 Sep 2012 16:05:21 +0200
|
|
Subject: [PATCH 09/72] video player: present correct pts to user for a/v sync
|
|
(after buffering in renderer)
|
|
|
|
---
|
|
xbmc/cores/dvdplayer/DVDPlayerVideo.cpp | 41 +++++++++++++++++++------------
|
|
xbmc/cores/dvdplayer/DVDPlayerVideo.h | 2 +-
|
|
2 files changed, 26 insertions(+), 17 deletions(-)
|
|
|
|
diff --git a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp
|
|
index 2ef6358..10e2225 100644
|
|
--- a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp
|
|
+++ b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp
|
|
@@ -1251,22 +1251,6 @@ int CDVDPlayerVideo::OutputPicture(const DVDVideoPicture* src, double pts)
|
|
else
|
|
iSleepTime = iFrameSleep + (iClockSleep - iFrameSleep) / m_autosync;
|
|
|
|
-#ifdef PROFILE /* during profiling, try to play as fast as possible */
|
|
- iSleepTime = 0;
|
|
-#endif
|
|
-
|
|
- // 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_FlipTimeStamp += iFrameDuration;
|
|
-
|
|
if ((m_droppingStats.m_requestOutputDrop && !(pPicture->iFlags & DVP_FLAG_NOSKIP))
|
|
|| (pPicture->iFlags & DVP_FLAG_DROPPED))
|
|
{
|
|
@@ -1571,6 +1555,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
|
|
|
|
@@ -1689,6 +1689,15 @@ int CDVDPlayerVideo::CalcDropRequirement(double pts)
|
|
else
|
|
iInterval = 1/m_fFrameRate*(double)DVD_TIME_BASE;
|
|
|
|
+
|
|
+ m_FlipTimeStamp = m_pClock->GetAbsoluteClock() + max(0.0, iSleepTime) + iInterval;
|
|
+
|
|
+ if( m_stalled )
|
|
+ m_iCurrentPts = DVD_NOPTS_VALUE;
|
|
+ else
|
|
+ m_iCurrentPts = iRenderPts - max(0.0, iSleepTime);
|
|
+
|
|
+
|
|
if (m_droppingStats.m_lastDecoderPts > 0
|
|
&& bNewFrame
|
|
&& m_bAllowDrop
|
|
diff --git a/xbmc/cores/dvdplayer/DVDPlayerVideo.h b/xbmc/cores/dvdplayer/DVDPlayerVideo.h
|
|
index 4913712..509d5f7 100644
|
|
--- a/xbmc/cores/dvdplayer/DVDPlayerVideo.h
|
|
+++ b/xbmc/cores/dvdplayer/DVDPlayerVideo.h
|
|
@@ -108,7 +108,7 @@ class CDVDPlayerVideo : public CThread
|
|
|
|
bool InitializedOutputDevice();
|
|
|
|
- double GetCurrentPts() { return m_iCurrentPts; }
|
|
+ double GetCurrentPts();
|
|
int GetPullupCorrection() { return m_pullupCorrection.GetPatternLength(); }
|
|
|
|
double GetOutputDelay(); /* returns the expected delay, from that a packet is put in queue */
|
|
--
|
|
1.7.10
|
|
|
|
|
|
From 04a6a8b4ca29c17da6bbb9591685922b2f6f1442 Mon Sep 17 00:00:00 2001
|
|
From: xbmc <fernetmenta@online.de>
|
|
Date: Mon, 28 May 2012 11:02:29 +0200
|
|
Subject: [PATCH 10/72] vaapi: adopt to buffering in renderer
|
|
|
|
---
|
|
xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp | 2 +-
|
|
xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.cpp | 3 ++-
|
|
xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.h | 1 +
|
|
3 files changed, 4 insertions(+), 2 deletions(-)
|
|
|
|
diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp
|
|
index af706bd..dae3b8e 100644
|
|
--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp
|
|
+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp
|
|
@@ -106,7 +106,7 @@ enum PixelFormat CDVDVideoCodecFFmpeg::GetFormat( struct AVCodecContext * avctx
|
|
&& (avctx->codec_id != CODEC_ID_MPEG4 || g_advancedSettings.m_videoAllowMpeg4VAAPI))
|
|
{
|
|
VAAPI::CDecoder* dec = new VAAPI::CDecoder();
|
|
- if(dec->Open(avctx, *cur))
|
|
+ if(dec->Open(avctx, *cur, ctx->m_uSurfacesCount))
|
|
{
|
|
ctx->SetHardware(dec);
|
|
return *cur;
|
|
diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.cpp
|
|
index 9f5a960..a2b9195 100644
|
|
--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.cpp
|
|
+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.cpp
|
|
@@ -357,6 +357,7 @@ bool CDecoder::Open(AVCodecContext *avctx, enum PixelFormat fmt, unsigned int su
|
|
CHECK(vaCreateConfig(m_display->get(), profile, entrypoint, &attrib, 1, &m_hwaccel->config_id))
|
|
m_config = m_hwaccel->config_id;
|
|
|
|
+ m_renderbuffers_count = surfaces;
|
|
if (!EnsureContext(avctx))
|
|
return false;
|
|
|
|
@@ -388,7 +389,7 @@ bool CDecoder::EnsureContext(AVCodecContext *avctx)
|
|
else
|
|
m_refs = 2;
|
|
}
|
|
- return EnsureSurfaces(avctx, m_refs + 3);
|
|
+ return EnsureSurfaces(avctx, m_refs + m_renderbuffers_count + 1);
|
|
}
|
|
|
|
bool CDecoder::EnsureSurfaces(AVCodecContext *avctx, unsigned n_surfaces_count)
|
|
diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.h
|
|
index 863edc4..417cbc0 100644
|
|
--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.h
|
|
+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.h
|
|
@@ -122,6 +122,7 @@ class CDecoder
|
|
static const unsigned m_surfaces_max = 32;
|
|
unsigned m_surfaces_count;
|
|
VASurfaceID m_surfaces[m_surfaces_max];
|
|
+ unsigned m_renderbuffers_count;
|
|
|
|
int m_refs;
|
|
std::list<CSurfacePtr> m_surfaces_used;
|
|
--
|
|
1.7.10
|
|
|
|
|
|
From 4d237410264bbff9c4ac373de498f80ecb15f7a3 Mon Sep 17 00:00:00 2001
|
|
From: xbmc <fernetmenta@online.de>
|
|
Date: Sat, 7 Apr 2012 09:19:00 +0200
|
|
Subject: [PATCH 11/72] vdpau: redesign
|
|
|
|
---
|
|
language/English/strings.po | 12 +-
|
|
system/shaders/yuv2rgb_basic.glsl | 12 +
|
|
xbmc/cores/VideoRenderers/LinuxRendererGL.cpp | 203 +-
|
|
xbmc/cores/VideoRenderers/LinuxRendererGL.h | 13 +-
|
|
xbmc/cores/VideoRenderers/RenderFormats.h | 1 +
|
|
xbmc/cores/VideoRenderers/RenderManager.cpp | 8 +-
|
|
xbmc/cores/VideoRenderers/RenderManager.h | 2 +-
|
|
.../VideoRenderers/VideoShaders/YUV2RGBShader.cpp | 2 +
|
|
.../dvdplayer/DVDCodecs/Video/DVDVideoCodec.h | 4 +-
|
|
.../DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp | 23 +-
|
|
.../DVDCodecs/Video/DVDVideoCodecFFmpeg.h | 1 -
|
|
xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp | 3798 +++++++++++++++-----
|
|
xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.h | 662 +++-
|
|
xbmc/cores/dvdplayer/DVDPlayerVideo.cpp | 3 +
|
|
xbmc/settings/AdvancedSettings.cpp | 8 +-
|
|
xbmc/settings/AdvancedSettings.h | 4 +-
|
|
xbmc/settings/GUISettings.cpp | 2 +
|
|
xbmc/settings/GUIWindowSettingsCategory.cpp | 34 +
|
|
xbmc/utils/ActorProtocol.cpp | 253 ++
|
|
xbmc/utils/ActorProtocol.h | 87 +
|
|
xbmc/utils/Makefile | 1 +
|
|
xbmc/video/dialogs/GUIDialogVideoSettings.cpp | 2 +-
|
|
xbmc/windowing/X11/WinSystemX11.h | 1 +
|
|
23 files changed, 3942 insertions(+), 1194 deletions(-)
|
|
create mode 100644 xbmc/utils/ActorProtocol.cpp
|
|
create mode 100644 xbmc/utils/ActorProtocol.h
|
|
|
|
diff --git a/language/English/strings.po b/language/English/strings.po
|
|
index dff2978..88292d3 100644
|
|
--- a/language/English/strings.po
|
|
+++ b/language/English/strings.po
|
|
@@ -5114,7 +5114,15 @@ msgctxt "#13434"
|
|
msgid "Play only this"
|
|
msgstr ""
|
|
|
|
-#empty strings from id 13435 to 13499
|
|
+msgctxt "#13435"
|
|
+msgid "Allow Vdpau OpenGL interop"
|
|
+msgstr ""
|
|
+
|
|
+msgctxt "#13436"
|
|
+msgid "Allow Vdpau OpenGL interop YUV"
|
|
+msgstr ""
|
|
+
|
|
+#empty strings from id 13437 to 13499
|
|
|
|
msgctxt "#13500"
|
|
msgid "A/V sync method"
|
|
@@ -6333,7 +6341,7 @@ msgid "Software Blend"
|
|
msgstr ""
|
|
|
|
msgctxt "#16325"
|
|
-msgid "Auto - ION Optimized"
|
|
+msgid "VDPAU - Bob"
|
|
msgstr ""
|
|
|
|
#empty strings from id 16326 to 16399
|
|
diff --git a/system/shaders/yuv2rgb_basic.glsl b/system/shaders/yuv2rgb_basic.glsl
|
|
index 88c33b2..aa26174 100644
|
|
--- a/system/shaders/yuv2rgb_basic.glsl
|
|
+++ b/system/shaders/yuv2rgb_basic.glsl
|
|
@@ -70,6 +70,18 @@ void main()
|
|
rgb.a = gl_Color.a;
|
|
gl_FragColor = rgb;
|
|
|
|
+#elif defined(XBMC_VDPAU_NV12)
|
|
+
|
|
+ vec4 yuv, rgb;
|
|
+ yuv.rgba = vec4( texture2D(m_sampY, stretch(m_cordY)).r
|
|
+ , texture2D(m_sampU, stretch(m_cordU)).r
|
|
+ , texture2D(m_sampV, stretch(m_cordV)).g
|
|
+ , 1.0 );
|
|
+
|
|
+ rgb = m_yuvmat * yuv;
|
|
+ rgb.a = gl_Color.a;
|
|
+ gl_FragColor = rgb;
|
|
+
|
|
#elif defined(XBMC_YUY2) || defined(XBMC_UYVY)
|
|
|
|
#if(XBMC_texture_rectangle)
|
|
diff --git a/xbmc/cores/VideoRenderers/LinuxRendererGL.cpp b/xbmc/cores/VideoRenderers/LinuxRendererGL.cpp
|
|
index a2dc2be..4ee50c1 100644
|
|
--- a/xbmc/cores/VideoRenderers/LinuxRendererGL.cpp
|
|
+++ b/xbmc/cores/VideoRenderers/LinuxRendererGL.cpp
|
|
@@ -689,6 +689,18 @@ void CLinuxRendererGL::RenderUpdate(bool clear, DWORD flags, DWORD alpha)
|
|
glDisable(GL_POLYGON_STIPPLE);
|
|
|
|
}
|
|
+ else if(m_format == RENDER_FMT_VDPAU_420
|
|
+ && !(flags & RENDER_FLAG_BOTH))
|
|
+ {
|
|
+ glDisable(GL_BLEND);
|
|
+ glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
|
|
+ Render(flags | RENDER_FLAG_TOP, index);
|
|
+
|
|
+ glEnable(GL_BLEND);
|
|
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|
+ glColor4f(1.0f, 1.0f, 1.0f, 128 / 255.0f);
|
|
+ Render(flags | RENDER_FLAG_BOT , index);
|
|
+ }
|
|
else
|
|
Render(flags, index);
|
|
|
|
@@ -769,11 +781,6 @@ void CLinuxRendererGL::FlipPage(int source)
|
|
|
|
m_buffers[m_iYV12RenderBuffer].flipindex = ++m_flipindex;
|
|
|
|
-#ifdef HAVE_LIBVDPAU
|
|
- if((m_renderMethod & RENDER_VDPAU) && m_buffers[m_iYV12RenderBuffer].vdpau)
|
|
- m_buffers[m_iYV12RenderBuffer].vdpau->Present();
|
|
-#endif
|
|
-
|
|
return;
|
|
}
|
|
|
|
@@ -1100,6 +1107,12 @@ void CLinuxRendererGL::LoadShaders(int field)
|
|
m_textureCreate = &CLinuxRendererGL::CreateVDPAUTexture;
|
|
m_textureDelete = &CLinuxRendererGL::DeleteVDPAUTexture;
|
|
}
|
|
+ else if (m_format == RENDER_FMT_VDPAU_420)
|
|
+ {
|
|
+ m_textureUpload = &CLinuxRendererGL::UploadVDPAUTexture420;
|
|
+ m_textureCreate = &CLinuxRendererGL::CreateVDPAUTexture420;
|
|
+ m_textureDelete = &CLinuxRendererGL::DeleteVDPAUTexture420;
|
|
+ }
|
|
else if (m_format == RENDER_FMT_VAAPI)
|
|
{
|
|
m_textureUpload = &CLinuxRendererGL::UploadVAAPITexture;
|
|
@@ -1175,7 +1188,10 @@ void CLinuxRendererGL::Render(DWORD flags, int renderBuffer)
|
|
m_currentField = FIELD_FULL;
|
|
|
|
// call texture load function
|
|
+ m_skipRender = false;
|
|
(this->*m_textureUpload)(renderBuffer);
|
|
+ if (m_skipRender)
|
|
+ return;
|
|
|
|
if (m_renderMethod & RENDER_GLSL)
|
|
{
|
|
@@ -1541,17 +1557,12 @@ void CLinuxRendererGL::RenderFromFBO()
|
|
void CLinuxRendererGL::RenderVDPAU(int index, int field)
|
|
{
|
|
#ifdef HAVE_LIBVDPAU
|
|
- YUVPLANE &plane = m_buffers[index].fields[field][0];
|
|
- CVDPAU *vdpau = m_buffers[m_iYV12RenderBuffer].vdpau;
|
|
-
|
|
- if (!vdpau)
|
|
- return;
|
|
+ YUVPLANE &plane = m_buffers[index].fields[0][1];
|
|
|
|
glEnable(m_textureTarget);
|
|
glActiveTextureARB(GL_TEXTURE0);
|
|
- glBindTexture(m_textureTarget, plane.id);
|
|
|
|
- vdpau->BindPixmap();
|
|
+ glBindTexture(m_textureTarget, plane.id);
|
|
|
|
// Try some clamping or wrapping
|
|
glTexParameteri(m_textureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
|
@@ -1609,8 +1620,6 @@ void CLinuxRendererGL::RenderVDPAU(int index, int field)
|
|
if (m_pVideoFilterShader)
|
|
m_pVideoFilterShader->Disable();
|
|
|
|
- vdpau->ReleasePixmap();
|
|
-
|
|
glBindTexture (m_textureTarget, 0);
|
|
glDisable(m_textureTarget);
|
|
#endif
|
|
@@ -2295,12 +2304,14 @@ void CLinuxRendererGL::DeleteVDPAUTexture(int index)
|
|
{
|
|
#ifdef HAVE_LIBVDPAU
|
|
YUVPLANE &plane = m_buffers[index].fields[0][0];
|
|
+ YUVFIELDS &fields = m_buffers[index].fields;
|
|
|
|
SAFE_RELEASE(m_buffers[index].vdpau);
|
|
|
|
if(plane.id && glIsTexture(plane.id))
|
|
glDeleteTextures(1, &plane.id);
|
|
plane.id = 0;
|
|
+ fields[0][1].id = 0;
|
|
#endif
|
|
}
|
|
|
|
@@ -2334,11 +2345,152 @@ bool CLinuxRendererGL::CreateVDPAUTexture(int index)
|
|
void CLinuxRendererGL::UploadVDPAUTexture(int index)
|
|
{
|
|
#ifdef HAVE_LIBVDPAU
|
|
+ VDPAU::CVdpauRenderPicture *vdpau = m_buffers[index].vdpau;
|
|
+
|
|
+ unsigned int flipindex = m_buffers[index].flipindex;
|
|
+ YUVFIELDS &fields = m_buffers[index].fields;
|
|
+ YUVPLANE &plane = fields[0][0];
|
|
+
|
|
+ if (!vdpau || !vdpau->valid)
|
|
+ {
|
|
+ m_eventTexturesDone[index]->Set();
|
|
+ m_skipRender = true;
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ fields[0][1].id = vdpau->texture[0];
|
|
+
|
|
+ m_eventTexturesDone[index]->Set();
|
|
+#endif
|
|
+}
|
|
+
|
|
+void CLinuxRendererGL::DeleteVDPAUTexture420(int index)
|
|
+{
|
|
+#ifdef HAVE_LIBVDPAU
|
|
+ YUVPLANE &plane = m_buffers[index].fields[0][0];
|
|
+ YUVFIELDS &fields = m_buffers[index].fields;
|
|
+
|
|
+ SAFE_RELEASE(m_buffers[index].vdpau);
|
|
+
|
|
+ if(plane.id && glIsTexture(plane.id))
|
|
+ glDeleteTextures(1, &plane.id);
|
|
+ plane.id = 0;
|
|
+ fields[1][0].id = 0;
|
|
+ fields[1][1].id = 0;
|
|
+ fields[2][0].id = 0;
|
|
+ fields[2][1].id = 0;
|
|
+
|
|
+#endif
|
|
+}
|
|
+
|
|
+bool CLinuxRendererGL::CreateVDPAUTexture420(int index)
|
|
+{
|
|
+#ifdef HAVE_LIBVDPAU
|
|
+ YV12Image &im = m_buffers[index].image;
|
|
+ YUVFIELDS &fields = m_buffers[index].fields;
|
|
+ YUVPLANE &plane = fields[0][0];
|
|
+ GLuint *pbo = m_buffers[index].pbo;
|
|
+
|
|
+ DeleteVDPAUTexture420(index);
|
|
+
|
|
+ memset(&im , 0, sizeof(im));
|
|
+ memset(&fields, 0, sizeof(fields));
|
|
+
|
|
+ im.cshift_x = 1;
|
|
+ im.cshift_y = 1;
|
|
+
|
|
+ im.plane[0] = NULL;
|
|
+ im.plane[1] = NULL;
|
|
+ im.plane[2] = NULL;
|
|
+
|
|
+ for(int p = 0;p<3;p++)
|
|
+ {
|
|
+ pbo[p] = None;
|
|
+ }
|
|
+
|
|
+ glEnable(m_textureTarget);
|
|
+ glGenTextures(1, &plane.id);
|
|
+ glDisable(m_textureTarget);
|
|
+
|
|
m_eventTexturesDone[index]->Set();
|
|
- glPixelStorei(GL_UNPACK_ALIGNMENT,1); //what's this for?
|
|
#endif
|
|
+ return true;
|
|
}
|
|
|
|
+void CLinuxRendererGL::UploadVDPAUTexture420(int index)
|
|
+{
|
|
+#ifdef HAVE_LIBVDPAU
|
|
+ VDPAU::CVdpauRenderPicture *vdpau = m_buffers[index].vdpau;
|
|
+ YV12Image &im = m_buffers[index].image;
|
|
+
|
|
+ unsigned int flipindex = m_buffers[index].flipindex;
|
|
+ YUVFIELDS &fields = m_buffers[index].fields;
|
|
+ YUVPLANE &plane = fields[0][0];
|
|
+
|
|
+ if (!vdpau || !vdpau->valid)
|
|
+ {
|
|
+ m_eventTexturesDone[index]->Set();
|
|
+ m_skipRender = true;
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ im.height = vdpau->texHeight;
|
|
+ im.width = vdpau->texWidth;
|
|
+
|
|
+ // YUV
|
|
+ for (int f = FIELD_FULL; f<=FIELD_BOT ; f++)
|
|
+ {
|
|
+ int fieldshift = (f==FIELD_FULL) ? 0 : 1;
|
|
+ YUVPLANES &planes = fields[f];
|
|
+
|
|
+ planes[0].texwidth = im.width;
|
|
+ planes[0].texheight = im.height >> fieldshift;
|
|
+
|
|
+ planes[1].texwidth = planes[0].texwidth >> im.cshift_x;
|
|
+ planes[1].texheight = planes[0].texheight >> im.cshift_y;
|
|
+ planes[2].texwidth = planes[1].texwidth;
|
|
+ planes[2].texheight = planes[1].texheight;
|
|
+
|
|
+ for (int p = 0; p < 3; p++)
|
|
+ {
|
|
+ planes[p].pixpertex_x = 1;
|
|
+ planes[p].pixpertex_y = 1;
|
|
+ }
|
|
+ }
|
|
+ // crop
|
|
+// m_sourceRect.x1 += vdpau->crop.x1;
|
|
+// m_sourceRect.x2 -= vdpau->crop.x2;
|
|
+// m_sourceRect.y1 += vdpau->crop.y1;
|
|
+// m_sourceRect.y2 -= vdpau->crop.y2;
|
|
+
|
|
+ // set textures
|
|
+ fields[1][0].id = vdpau->texture[0];
|
|
+ fields[1][1].id = vdpau->texture[2];
|
|
+ fields[2][0].id = vdpau->texture[1];
|
|
+ fields[2][1].id = vdpau->texture[3];
|
|
+
|
|
+ glEnable(m_textureTarget);
|
|
+ for (int f = 1; f < 3; f++)
|
|
+ {
|
|
+ for (int p=0;p<2;p++)
|
|
+ {
|
|
+ glBindTexture(m_textureTarget,fields[f][p].id);
|
|
+ glTexParameteri(m_textureTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
|
+ glTexParameteri(m_textureTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
+ glTexParameteri(m_textureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
|
+ glTexParameteri(m_textureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
|
+
|
|
+ glBindTexture(m_textureTarget,0);
|
|
+ VerifyGLState();
|
|
+ }
|
|
+ fields[f][2].id = fields[f][1].id;
|
|
+ }
|
|
+ CalculateTextureSourceRects(index, 3);
|
|
+ glDisable(m_textureTarget);
|
|
+
|
|
+ m_eventTexturesDone[index]->Set();
|
|
+#endif
|
|
+}
|
|
|
|
void CLinuxRendererGL::DeleteVAAPITexture(int index)
|
|
{
|
|
@@ -3276,12 +3428,13 @@ bool CLinuxRendererGL::Supports(EINTERLACEMETHOD method)
|
|
if(method == VS_INTERLACEMETHOD_AUTO)
|
|
return true;
|
|
|
|
- if(m_renderMethod & RENDER_VDPAU)
|
|
+ if(m_renderMethod & RENDER_VDPAU ||
|
|
+ m_format == RENDER_FMT_VDPAU_420)
|
|
{
|
|
#ifdef HAVE_LIBVDPAU
|
|
- CVDPAU *vdpau = m_buffers[m_iYV12RenderBuffer].vdpau;
|
|
- if(vdpau)
|
|
- return vdpau->Supports(method);
|
|
+ VDPAU::CVdpauRenderPicture *vdpauPic = m_buffers[m_iYV12RenderBuffer].vdpau;
|
|
+ if(vdpauPic && vdpauPic->vdpau)
|
|
+ return vdpauPic->vdpau->Supports(method);
|
|
#endif
|
|
return false;
|
|
}
|
|
@@ -3367,14 +3520,7 @@ EINTERLACEMETHOD CLinuxRendererGL::AutoInterlaceMethod()
|
|
return VS_INTERLACEMETHOD_NONE;
|
|
|
|
if(m_renderMethod & RENDER_VDPAU)
|
|
- {
|
|
-#ifdef HAVE_LIBVDPAU
|
|
- CVDPAU *vdpau = m_buffers[m_iYV12RenderBuffer].vdpau;
|
|
- if(vdpau)
|
|
- return vdpau->AutoInterlaceMethod();
|
|
-#endif
|
|
return VS_INTERLACEMETHOD_NONE;
|
|
- }
|
|
|
|
if(Supports(VS_INTERLACEMETHOD_RENDER_BOB))
|
|
return VS_INTERLACEMETHOD_RENDER_BOB;
|
|
@@ -3417,11 +3563,12 @@ void CLinuxRendererGL::UnBindPbo(YUVBUFFER& buff)
|
|
}
|
|
|
|
#ifdef HAVE_LIBVDPAU
|
|
-void CLinuxRendererGL::AddProcessor(CVDPAU* vdpau, int index)
|
|
+void CLinuxRendererGL::AddProcessor(VDPAU::CVdpauRenderPicture *vdpau, int index)
|
|
{
|
|
YUVBUFFER &buf = m_buffers[index];
|
|
+ VDPAU::CVdpauRenderPicture *pic = vdpau->Acquire();
|
|
SAFE_RELEASE(buf.vdpau);
|
|
- buf.vdpau = (CVDPAU*)vdpau->Acquire();
|
|
+ buf.vdpau = pic;
|
|
}
|
|
#endif
|
|
|
|
diff --git a/xbmc/cores/VideoRenderers/LinuxRendererGL.h b/xbmc/cores/VideoRenderers/LinuxRendererGL.h
|
|
index 9f55fcb..3218cd5 100644
|
|
--- a/xbmc/cores/VideoRenderers/LinuxRendererGL.h
|
|
+++ b/xbmc/cores/VideoRenderers/LinuxRendererGL.h
|
|
@@ -38,15 +38,14 @@
|
|
|
|
class CRenderCapture;
|
|
|
|
-class CVDPAU;
|
|
class CBaseTexture;
|
|
namespace Shaders { class BaseYUV2RGBShader; }
|
|
namespace Shaders { class BaseVideoFilterShader; }
|
|
namespace VAAPI { struct CHolder; }
|
|
+namespace VDPAU { class CVdpauRenderPicture; }
|
|
|
|
#define NUM_BUFFERS 10
|
|
|
|
-
|
|
#undef ALIGN
|
|
#define ALIGN(value, alignment) (((value)+((alignment)-1))&~((alignment)-1))
|
|
#define CLAMP(a, min, max) ((a) > (max) ? (max) : ( (a) < (min) ? (min) : a ))
|
|
@@ -144,7 +143,7 @@ class CLinuxRendererGL : public CBaseRenderer
|
|
virtual unsigned int GetProcessorSize() { return m_NumYV12Buffers; }
|
|
|
|
#ifdef HAVE_LIBVDPAU
|
|
- virtual void AddProcessor(CVDPAU* vdpau, int index);
|
|
+ virtual void AddProcessor(VDPAU::CVdpauRenderPicture* vdpau, int index);
|
|
#endif
|
|
#ifdef HAVE_LIBVA
|
|
virtual void AddProcessor(VAAPI::CHolder& holder, int index);
|
|
@@ -195,6 +194,10 @@ class CLinuxRendererGL : public CBaseRenderer
|
|
void DeleteVDPAUTexture(int index);
|
|
bool CreateVDPAUTexture(int index);
|
|
|
|
+ void UploadVDPAUTexture420(int index);
|
|
+ void DeleteVDPAUTexture420(int index);
|
|
+ bool CreateVDPAUTexture420(int index);
|
|
+
|
|
void UploadVAAPITexture(int index);
|
|
void DeleteVAAPITexture(int index);
|
|
bool CreateVAAPITexture(int index);
|
|
@@ -221,6 +224,7 @@ class CLinuxRendererGL : public CBaseRenderer
|
|
void RenderSinglePass(int renderBuffer, int field); // single pass glsl renderer
|
|
void RenderSoftware(int renderBuffer, int field); // single pass s/w yuv2rgb renderer
|
|
void RenderVDPAU(int renderBuffer, int field); // render using vdpau hardware
|
|
+ void RenderVDPAUYV12(int renderBuffer, int field); // render using vdpau hardware
|
|
void RenderVAAPI(int renderBuffer, int field); // render using vdpau hardware
|
|
|
|
struct
|
|
@@ -281,7 +285,7 @@ class CLinuxRendererGL : public CBaseRenderer
|
|
GLuint pbo[MAX_PLANES];
|
|
|
|
#ifdef HAVE_LIBVDPAU
|
|
- CVDPAU* vdpau;
|
|
+ VDPAU::CVdpauRenderPicture *vdpau;
|
|
#endif
|
|
#ifdef HAVE_LIBVA
|
|
VAAPI::CHolder& vaapi;
|
|
@@ -327,6 +331,7 @@ class CLinuxRendererGL : public CBaseRenderer
|
|
bool m_nonLinStretch;
|
|
bool m_nonLinStretchGui;
|
|
float m_pixelRatio;
|
|
+ bool m_skipRender;
|
|
};
|
|
|
|
|
|
diff --git a/xbmc/cores/VideoRenderers/RenderFormats.h b/xbmc/cores/VideoRenderers/RenderFormats.h
|
|
index 09f8f5d..0262c60 100644
|
|
--- a/xbmc/cores/VideoRenderers/RenderFormats.h
|
|
+++ b/xbmc/cores/VideoRenderers/RenderFormats.h
|
|
@@ -26,6 +26,7 @@ enum ERenderFormat {
|
|
RENDER_FMT_YUV420P10,
|
|
RENDER_FMT_YUV420P16,
|
|
RENDER_FMT_VDPAU,
|
|
+ RENDER_FMT_VDPAU_420,
|
|
RENDER_FMT_NV12,
|
|
RENDER_FMT_UYVY422,
|
|
RENDER_FMT_YUYV422,
|
|
diff --git a/xbmc/cores/VideoRenderers/RenderManager.cpp b/xbmc/cores/VideoRenderers/RenderManager.cpp
|
|
index f19797c..a521680 100644
|
|
--- a/xbmc/cores/VideoRenderers/RenderManager.cpp
|
|
+++ b/xbmc/cores/VideoRenderers/RenderManager.cpp
|
|
@@ -250,8 +250,9 @@ bool CXBMCRenderManager::Configure(unsigned int width, unsigned int height, unsi
|
|
|
|
// check if decoder supports buffering
|
|
m_bCodecSupportsBuffering = false;
|
|
-// if (format == RENDER_FMT_VDPAU)
|
|
-// m_bCodecSupportsBuffering = true;
|
|
+ if (format == RENDER_FMT_VDPAU ||
|
|
+ format == RENDER_FMT_VDPAU_420)
|
|
+ m_bCodecSupportsBuffering = true;
|
|
|
|
bool result = m_pRenderer->Configure(width, height, d_width, d_height, fps, flags, format, extended_format, orientation);
|
|
if(result)
|
|
@@ -856,7 +857,8 @@ int CXBMCRenderManager::AddVideoPicture(DVDVideoPicture& pic)
|
|
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
|
|
diff --git a/xbmc/cores/VideoRenderers/RenderManager.h b/xbmc/cores/VideoRenderers/RenderManager.h
|
|
index 9342586..6746957 100644
|
|
--- a/xbmc/cores/VideoRenderers/RenderManager.h
|
|
+++ b/xbmc/cores/VideoRenderers/RenderManager.h
|
|
@@ -35,7 +35,7 @@
|
|
|
|
namespace DXVA { class CProcessor; }
|
|
namespace VAAPI { class CSurfaceHolder; }
|
|
-class CVDPAU;
|
|
+namespace VDPAU { class CVdpauRenderPicture; }
|
|
struct DVDVideoPicture;
|
|
|
|
#define ERRORBUFFSIZE 30
|
|
diff --git a/xbmc/cores/VideoRenderers/VideoShaders/YUV2RGBShader.cpp b/xbmc/cores/VideoRenderers/VideoShaders/YUV2RGBShader.cpp
|
|
index 58f26b0..50606eb 100644
|
|
--- a/xbmc/cores/VideoRenderers/VideoShaders/YUV2RGBShader.cpp
|
|
+++ b/xbmc/cores/VideoRenderers/VideoShaders/YUV2RGBShader.cpp
|
|
@@ -201,6 +201,8 @@ static void CalculateYUVMatrixGL(GLfloat res[4][4]
|
|
m_defines += "#define XBMC_YUY2\n";
|
|
else if (m_format == RENDER_FMT_UYVY422)
|
|
m_defines += "#define XBMC_UYVY\n";
|
|
+ else if (RENDER_FMT_VDPAU_420)
|
|
+ m_defines += "#define XBMC_VDPAU_NV12\n";
|
|
else
|
|
CLog::Log(LOGERROR, "GL: BaseYUV2RGBGLSLShader - unsupported format %d", m_format);
|
|
|
|
diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h
|
|
index 5001aac..98d8f89 100644
|
|
--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h
|
|
+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h
|
|
@@ -34,7 +34,7 @@
|
|
|
|
namespace DXVA { class CSurfaceContext; }
|
|
namespace VAAPI { struct CHolder; }
|
|
-class CVDPAU;
|
|
+namespace VDPAU { class CVdpauRenderPicture; }
|
|
class COpenMax;
|
|
class COpenMaxVideo;
|
|
struct OpenMaxVideoBuffer;
|
|
@@ -55,7 +55,7 @@ struct DVDVideoPicture
|
|
DXVA::CSurfaceContext* context;
|
|
};
|
|
struct {
|
|
- CVDPAU* vdpau;
|
|
+ VDPAU::CVdpauRenderPicture* vdpau;
|
|
};
|
|
struct {
|
|
VAAPI::CHolder* vaapi;
|
|
diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp
|
|
index dae3b8e..a6e42e5 100644
|
|
--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp
|
|
+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp
|
|
@@ -71,14 +71,14 @@ enum PixelFormat CDVDVideoCodecFFmpeg::GetFormat( struct AVCodecContext * avctx
|
|
while(*cur != PIX_FMT_NONE)
|
|
{
|
|
#ifdef HAVE_LIBVDPAU
|
|
- if(CVDPAU::IsVDPAUFormat(*cur) && g_guiSettings.GetBool("videoplayer.usevdpau"))
|
|
+ if(VDPAU::CDecoder::IsVDPAUFormat(*cur) && g_guiSettings.GetBool("videoplayer.usevdpau"))
|
|
{
|
|
if(ctx->GetHardware())
|
|
return *cur;
|
|
|
|
CLog::Log(LOGNOTICE,"CDVDVideoCodecFFmpeg::GetFormat - Creating VDPAU(%ix%i)", avctx->width, avctx->height);
|
|
- CVDPAU* vdp = new CVDPAU();
|
|
- if(vdp->Open(avctx, *cur))
|
|
+ VDPAU::CDecoder* vdp = new VDPAU::CDecoder();
|
|
+ if(vdp->Open(avctx, *cur, ctx->m_uSurfacesCount))
|
|
{
|
|
ctx->SetHardware(vdp);
|
|
return *cur;
|
|
@@ -205,14 +205,27 @@ bool CDVDVideoCodecFFmpeg::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options
|
|
continue;
|
|
|
|
CLog::Log(LOGNOTICE,"CDVDVideoCodecFFmpeg::Open() Creating VDPAU(%ix%i, %d)",hints.width, hints.height, hints.codec);
|
|
- CVDPAU* vdp = new CVDPAU();
|
|
+
|
|
+ VDPAU::CDecoder* vdp = new VDPAU::CDecoder();
|
|
m_pCodecContext = m_dllAvCodec.avcodec_alloc_context3(pCodec);
|
|
m_pCodecContext->codec_id = hints.codec;
|
|
m_pCodecContext->width = hints.width;
|
|
m_pCodecContext->height = hints.height;
|
|
m_pCodecContext->coded_width = hints.width;
|
|
m_pCodecContext->coded_height = hints.height;
|
|
- if(vdp->Open(m_pCodecContext, pCodec->pix_fmts ? pCodec->pix_fmts[0] : PIX_FMT_NONE))
|
|
+
|
|
+ // check number of surfaces used in renderer
|
|
+ unsigned int surfaces = 0;
|
|
+ for(std::vector<CDVDCodecOption>::iterator it = options.m_keys.begin(); it != options.m_keys.end(); it++)
|
|
+ {
|
|
+ if (it->m_name == "surfaces")
|
|
+ {
|
|
+ surfaces = std::atoi(it->m_value.c_str());
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if(vdp->Open(m_pCodecContext, pCodec->pix_fmts ? pCodec->pix_fmts[0] : PIX_FMT_NONE, surfaces))
|
|
{
|
|
m_pHardware = vdp;
|
|
m_pCodecContext->codec_id = CODEC_ID_NONE; // ffmpeg will complain if this has been set
|
|
diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.h
|
|
index 52e1113..bf4367c 100644
|
|
--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.h
|
|
+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.h
|
|
@@ -28,7 +28,6 @@
|
|
#include "DllSwScale.h"
|
|
#include "DllAvFilter.h"
|
|
|
|
-class CVDPAU;
|
|
class CCriticalSection;
|
|
|
|
class CDVDVideoCodecFFmpeg : public CDVDVideoCodec
|
|
diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp
|
|
index f70a4f9..235f565 100644
|
|
--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp
|
|
+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp
|
|
@@ -32,11 +32,16 @@
|
|
#include "settings/AdvancedSettings.h"
|
|
#include "Application.h"
|
|
#include "utils/MathUtils.h"
|
|
+#include "utils/TimeUtils.h"
|
|
#include "DVDCodecs/DVDCodecUtils.h"
|
|
+#include "cores/VideoRenderers/RenderFlags.h"
|
|
+
|
|
+using namespace VDPAU;
|
|
+#define NUM_RENDER_PICS 9
|
|
|
|
#define ARSIZE(x) (sizeof(x) / sizeof((x)[0]))
|
|
|
|
-CVDPAU::Desc decoder_profiles[] = {
|
|
+CDecoder::Desc decoder_profiles[] = {
|
|
{"MPEG1", VDP_DECODER_PROFILE_MPEG1},
|
|
{"MPEG2_SIMPLE", VDP_DECODER_PROFILE_MPEG2_SIMPLE},
|
|
{"MPEG2_MAIN", VDP_DECODER_PROFILE_MPEG2_MAIN},
|
|
@@ -50,14 +55,16 @@
|
|
{"MPEG4_PART2_ASP", VDP_DECODER_PROFILE_MPEG4_PART2_ASP},
|
|
#endif
|
|
};
|
|
-const size_t decoder_profile_count = sizeof(decoder_profiles)/sizeof(CVDPAU::Desc);
|
|
+const size_t decoder_profile_count = sizeof(decoder_profiles)/sizeof(CDecoder::Desc);
|
|
|
|
-static float studioCSC[3][4] =
|
|
-{
|
|
- { 1.0f, 0.0f, 1.57480000f,-0.78740000f},
|
|
- { 1.0f,-0.18737736f,-0.46813736f, 0.32775736f},
|
|
- { 1.0f, 1.85556000f, 0.0f,-0.92780000f}
|
|
-};
|
|
+//static float studioCSC[3][4] =
|
|
+//{
|
|
+// { 1.0f, 0.0f, 1.57480000f,-0.78740000f},
|
|
+// { 1.0f,-0.18737736f,-0.46813736f, 0.32775736f},
|
|
+// { 1.0f, 1.85556000f, 0.0f,-0.92780000f}
|
|
+//};
|
|
+static float studioCSCKCoeffs601[3] = {0.299, 0.587, 0.114}; //BT601 {Kr, Kg, Kb}
|
|
+static float studioCSCKCoeffs709[3] = {0.2126, 0.7152, 0.0722}; //BT709 {Kr, Kg, Kb}
|
|
|
|
static struct SInterlaceMapping
|
|
{
|
|
@@ -68,88 +75,30 @@
|
|
, {VS_INTERLACEMETHOD_VDPAU_TEMPORAL_HALF , VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL}
|
|
, {VS_INTERLACEMETHOD_VDPAU_TEMPORAL_SPATIAL , VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL_SPATIAL}
|
|
, {VS_INTERLACEMETHOD_VDPAU_TEMPORAL_SPATIAL_HALF, VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL_SPATIAL}
|
|
-, {VS_INTERLACEMETHOD_VDPAU_INVERSE_TELECINE , VDP_VIDEO_MIXER_FEATURE_INVERSE_TELECINE}
|
|
+, {VS_INTERLACEMETHOD_VDPAU_INVERSE_TELECINE , VDP_VIDEO_MIXER_FEATURE_INVERSE_TELECINE}
|
|
, {VS_INTERLACEMETHOD_NONE , (VdpVideoMixerFeature)-1}
|
|
};
|
|
|
|
//since libvdpau 0.4, vdp_device_create_x11() installs a callback on the Display*,
|
|
//if we unload libvdpau with dlclose(), we segfault on XCloseDisplay,
|
|
//so we just keep a static handle to libvdpau around
|
|
-void* CVDPAU::dl_handle;
|
|
+void* CDecoder::dl_handle;
|
|
+
|
|
+//-----------------------------------------------------------------------------
|
|
+// CVDPAU
|
|
+//-----------------------------------------------------------------------------
|
|
|
|
-CVDPAU::CVDPAU()
|
|
+CDecoder::CDecoder() : m_vdpauOutput(&m_inMsgEvent)
|
|
{
|
|
- glXBindTexImageEXT = NULL;
|
|
- glXReleaseTexImageEXT = NULL;
|
|
- vdp_device = VDP_INVALID_HANDLE;
|
|
- surfaceNum = presentSurfaceNum = 0;
|
|
- picAge.b_age = picAge.ip_age[0] = picAge.ip_age[1] = 256*256*256*64;
|
|
- vdpauConfigured = false;
|
|
- m_DisplayState = VDPAU_OPEN;
|
|
- m_mixerfield = VDP_VIDEO_MIXER_PICTURE_STRUCTURE_FRAME;
|
|
- m_mixerstep = 0;
|
|
+ m_vdpauConfig.vdpDevice = VDP_INVALID_HANDLE;
|
|
+ m_vdpauConfig.videoSurfaces = &m_videoSurfaces;
|
|
+ m_vdpauConfig.videoSurfaceSec = &m_videoSurfaceSec;
|
|
|
|
- m_glPixmap = 0;
|
|
- m_Pixmap = 0;
|
|
- if (!glXBindTexImageEXT)
|
|
- glXBindTexImageEXT = (PFNGLXBINDTEXIMAGEEXTPROC)glXGetProcAddress((GLubyte *) "glXBindTexImageEXT");
|
|
- if (!glXReleaseTexImageEXT)
|
|
- glXReleaseTexImageEXT = (PFNGLXRELEASETEXIMAGEEXTPROC)glXGetProcAddress((GLubyte *) "glXReleaseTexImageEXT");
|
|
+ m_vdpauConfigured = false;
|
|
+ m_DisplayState = VDPAU_OPEN;
|
|
+}
|
|
|
|
- totalAvailableOutputSurfaces = 0;
|
|
- outputSurface = presentSurface = VDP_INVALID_HANDLE;
|
|
- vdp_flip_target = VDP_INVALID_HANDLE;
|
|
- vdp_flip_queue = VDP_INVALID_HANDLE;
|
|
- vid_width = vid_height = OutWidth = OutHeight = 0;
|
|
- surface_width = surface_height = 0;
|
|
-
|
|
- memset(&decoder, 0, sizeof(decoder));
|
|
- memset(&outRect, 0, sizeof(outRect));
|
|
- memset(&outRectVid, 0, sizeof(outRectVid));
|
|
-
|
|
- m_Display = NULL;
|
|
-
|
|
- tmpBrightness = 0;
|
|
- tmpContrast = 0;
|
|
- tmpDeintMode = 0;
|
|
- tmpDeintGUI = 0;
|
|
- tmpDeint = 0;
|
|
- max_references = 0;
|
|
-
|
|
- for (int i = 0; i < NUM_OUTPUT_SURFACES; i++)
|
|
- outputSurfaces[i] = VDP_INVALID_HANDLE;
|
|
-
|
|
- videoMixer = VDP_INVALID_HANDLE;
|
|
- m_BlackBar = NULL;
|
|
-
|
|
- memset(m_features, 0, sizeof(m_features));
|
|
- m_feature_count = 0;
|
|
- m_vdpauOutputMethod = OUTPUT_NONE;
|
|
-
|
|
- upScale = g_advancedSettings.m_videoVDPAUScaling;
|
|
-
|
|
- vdp_video_mixer_set_attribute_values = NULL;
|
|
- vdp_generate_csc_matrix = NULL;
|
|
- vdp_presentation_queue_target_destroy = NULL;
|
|
- vdp_presentation_queue_create = NULL;
|
|
- vdp_presentation_queue_destroy = NULL;
|
|
- vdp_presentation_queue_display = NULL;
|
|
- vdp_presentation_queue_block_until_surface_idle = NULL;
|
|
- vdp_presentation_queue_target_create_x11 = NULL;
|
|
- vdp_presentation_queue_query_surface_status = NULL;
|
|
- vdp_presentation_queue_get_time = NULL;
|
|
- vdp_get_error_string = NULL;
|
|
- vdp_decoder_create = NULL;
|
|
- vdp_decoder_destroy = NULL;
|
|
- vdp_decoder_render = NULL;
|
|
- vdp_decoder_query_caps = NULL;
|
|
- vdp_preemption_callback_register = NULL;
|
|
- dl_vdp_device_create_x11 = NULL;
|
|
- dl_vdp_get_proc_address = NULL;
|
|
- dl_vdp_preemption_callback_register = NULL;
|
|
-}
|
|
-
|
|
-bool CVDPAU::Open(AVCodecContext* avctx, const enum PixelFormat, unsigned int surfaces)
|
|
+bool CDecoder::Open(AVCodecContext* avctx, const enum PixelFormat, unsigned int surfaces)
|
|
{
|
|
if(avctx->coded_width == 0
|
|
|| avctx->coded_height == 0)
|
|
@@ -157,6 +106,8 @@ bool CVDPAU::Open(AVCodecContext* avctx, const enum PixelFormat, unsigned int su
|
|
CLog::Log(LOGWARNING,"(VDPAU) no width/height available, can't init");
|
|
return false;
|
|
}
|
|
+ m_vdpauConfig.numRenderBuffers = surfaces;
|
|
+ m_decoderThread = CThread::GetCurrentThreadId();
|
|
|
|
if (!dl_handle)
|
|
{
|
|
@@ -168,8 +119,6 @@ bool CVDPAU::Open(AVCodecContext* avctx, const enum PixelFormat, unsigned int su
|
|
error = "dlerror() returned NULL";
|
|
|
|
CLog::Log(LOGNOTICE,"(VDPAU) Unable to get handle to libvdpau: %s", error);
|
|
- //g_application.m_guiDialogKaiToast.QueueNotification(CGUIDialogKaiToast::Error, "VDPAU", error, 10000);
|
|
-
|
|
return false;
|
|
}
|
|
}
|
|
@@ -178,8 +127,9 @@ bool CVDPAU::Open(AVCodecContext* avctx, const enum PixelFormat, unsigned int su
|
|
return false;
|
|
|
|
InitVDPAUProcs();
|
|
+ m_presentPicture = 0;
|
|
|
|
- if (vdp_device != VDP_INVALID_HANDLE)
|
|
+ if (m_vdpauConfig.vdpDevice != VDP_INVALID_HANDLE)
|
|
{
|
|
SpewHardwareAvailable();
|
|
|
|
@@ -197,25 +147,23 @@ bool CVDPAU::Open(AVCodecContext* avctx, const enum PixelFormat, unsigned int su
|
|
|
|
/* attempt to create a decoder with this width/height, some sizes are not supported by hw */
|
|
VdpStatus vdp_st;
|
|
- vdp_st = vdp_decoder_create(vdp_device, profile, avctx->coded_width, avctx->coded_height, 5, &decoder);
|
|
+ vdp_st = m_vdpauConfig.vdpProcs.vdp_decoder_create(m_vdpauConfig.vdpDevice, profile, avctx->coded_width, avctx->coded_height, 5, &m_vdpauConfig.vdpDecoder);
|
|
|
|
if(vdp_st != VDP_STATUS_OK)
|
|
{
|
|
- CLog::Log(LOGERROR, " (VDPAU) Error: %s(%d) checking for decoder support\n", vdp_get_error_string(vdp_st), vdp_st);
|
|
+ CLog::Log(LOGERROR, " (VDPAU) Error: %s(%d) checking for decoder support\n", m_vdpauConfig.vdpProcs.vdp_get_error_string(vdp_st), vdp_st);
|
|
FiniVDPAUProcs();
|
|
return false;
|
|
}
|
|
|
|
- vdp_decoder_destroy(decoder);
|
|
+ m_vdpauConfig.vdpProcs.vdp_decoder_destroy(m_vdpauConfig.vdpDecoder);
|
|
CheckStatus(vdp_st, __LINE__);
|
|
}
|
|
|
|
- InitCSCMatrix(avctx->coded_height);
|
|
-
|
|
/* finally setup ffmpeg */
|
|
- avctx->get_buffer = CVDPAU::FFGetBuffer;
|
|
- avctx->release_buffer = CVDPAU::FFReleaseBuffer;
|
|
- avctx->draw_horiz_band = CVDPAU::FFDrawSlice;
|
|
+ avctx->get_buffer = CDecoder::FFGetBuffer;
|
|
+ avctx->release_buffer = CDecoder::FFReleaseBuffer;
|
|
+ avctx->draw_horiz_band = CDecoder::FFDrawSlice;
|
|
avctx->slice_flags=SLICE_FLAG_CODED_ORDER|SLICE_FLAG_ALLOW_FIELD;
|
|
|
|
g_Windowing.Register(this);
|
|
@@ -224,17 +172,20 @@ bool CVDPAU::Open(AVCodecContext* avctx, const enum PixelFormat, unsigned int su
|
|
return false;
|
|
}
|
|
|
|
-CVDPAU::~CVDPAU()
|
|
+CDecoder::~CDecoder()
|
|
{
|
|
Close();
|
|
}
|
|
|
|
-void CVDPAU::Close()
|
|
+void CDecoder::Close()
|
|
{
|
|
CLog::Log(LOGNOTICE, " (VDPAU) %s", __FUNCTION__);
|
|
|
|
+ CSingleLock lock(m_DecoderSection);
|
|
+
|
|
FiniVDPAUOutput();
|
|
FiniVDPAUProcs();
|
|
+ m_vdpauOutput.Dispose();
|
|
|
|
while (!m_videoSurfaces.empty())
|
|
{
|
|
@@ -250,188 +201,111 @@ void CVDPAU::Close()
|
|
m_dllAvUtil.Unload();
|
|
}
|
|
|
|
-bool CVDPAU::MakePixmapGL()
|
|
+long CDecoder::Release()
|
|
{
|
|
- int num=0;
|
|
- int fbConfigIndex = 0;
|
|
-
|
|
- int doubleVisAttributes[] = {
|
|
- GLX_RENDER_TYPE, GLX_RGBA_BIT,
|
|
- GLX_RED_SIZE, 8,
|
|
- GLX_GREEN_SIZE, 8,
|
|
- GLX_BLUE_SIZE, 8,
|
|
- GLX_ALPHA_SIZE, 8,
|
|
- GLX_DEPTH_SIZE, 8,
|
|
- GLX_DRAWABLE_TYPE, GLX_PIXMAP_BIT,
|
|
- GLX_BIND_TO_TEXTURE_RGBA_EXT, True,
|
|
- GLX_DOUBLEBUFFER, True,
|
|
- GLX_Y_INVERTED_EXT, True,
|
|
- GLX_X_RENDERABLE, True,
|
|
- None
|
|
- };
|
|
-
|
|
- int pixmapAttribs[] = {
|
|
- GLX_TEXTURE_TARGET_EXT, GLX_TEXTURE_2D_EXT,
|
|
- GLX_TEXTURE_FORMAT_EXT, GLX_TEXTURE_FORMAT_RGBA_EXT,
|
|
- None
|
|
- };
|
|
-
|
|
- GLXFBConfig *fbConfigs;
|
|
- fbConfigs = glXChooseFBConfig(m_Display, DefaultScreen(m_Display), doubleVisAttributes, &num);
|
|
- if (fbConfigs==NULL)
|
|
+ // check if we should do some pre-cleanup here
|
|
+ // a second decoder might need resources
|
|
+ if (m_vdpauConfigured == true)
|
|
{
|
|
- CLog::Log(LOGERROR, "GLX Error: MakePixmap: No compatible framebuffers found");
|
|
- return false;
|
|
- }
|
|
- CLog::Log(LOGDEBUG, "Found %d fbconfigs.", num);
|
|
- fbConfigIndex = 0;
|
|
- CLog::Log(LOGDEBUG, "Using fbconfig index %d.", fbConfigIndex);
|
|
+ CSingleLock lock(m_DecoderSection);
|
|
+ CLog::Log(LOGNOTICE,"CVDPAU::Release pre-cleanup");
|
|
|
|
- m_glPixmap = glXCreatePixmap(m_Display, fbConfigs[fbConfigIndex], m_Pixmap, pixmapAttribs);
|
|
+ Message *reply;
|
|
+ if (m_vdpauOutput.m_controlPort.SendOutMessageSync(COutputControlProtocol::PRECLEANUP,
|
|
+ &reply,
|
|
+ 2000))
|
|
+ {
|
|
+ bool success = reply->signal == COutputControlProtocol::ACC ? true : false;
|
|
+ reply->Release();
|
|
+ if (!success)
|
|
+ {
|
|
+ CLog::Log(LOGERROR, "VDPAU::%s - pre-cleanup returned error", __FUNCTION__);
|
|
+ m_DisplayState = VDPAU_ERROR;
|
|
+ }
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ CLog::Log(LOGERROR, "VDPAU::%s - pre-cleanup timed out", __FUNCTION__);
|
|
+ m_DisplayState = VDPAU_ERROR;
|
|
+ }
|
|
|
|
- if (!m_glPixmap)
|
|
- {
|
|
- CLog::Log(LOGINFO, "GLX Error: Could not create Pixmap");
|
|
- XFree(fbConfigs);
|
|
- return false;
|
|
+ for(unsigned int i = 0; i < m_videoSurfaces.size(); ++i)
|
|
+ {
|
|
+ vdpau_render_state *render = m_videoSurfaces[i];
|
|
+ if (render->surface != VDP_INVALID_HANDLE && !(render->state & FF_VDPAU_STATE_USED_FOR_RENDER))
|
|
+ {
|
|
+ m_vdpauConfig.vdpProcs.vdp_video_surface_destroy(render->surface);
|
|
+ render->surface = VDP_INVALID_HANDLE;
|
|
+ }
|
|
+ }
|
|
}
|
|
- XFree(fbConfigs);
|
|
+ IHardwareDecoder::Release();
|
|
+}
|
|
|
|
- return true;
|
|
+long CDecoder::ReleasePicReference()
|
|
+{
|
|
+ return IHardwareDecoder::Release();
|
|
}
|
|
|
|
-bool CVDPAU::MakePixmap(int width, int height)
|
|
+void CDecoder::SetWidthHeight(int width, int height)
|
|
{
|
|
+ m_vdpauConfig.upscale = g_advancedSettings.m_videoVDPAUScaling;
|
|
+
|
|
//pick the smallest dimensions, so we downscale with vdpau and upscale with opengl when appropriate
|
|
//this requires the least amount of gpu memory bandwidth
|
|
- if (g_graphicsContext.GetWidth() < width || g_graphicsContext.GetHeight() < height || upScale)
|
|
+ if (g_graphicsContext.GetWidth() < width || g_graphicsContext.GetHeight() < height || m_vdpauConfig.upscale >= 0)
|
|
{
|
|
//scale width to desktop size if the aspect ratio is the same or bigger than the desktop
|
|
if ((double)height * g_graphicsContext.GetWidth() / width <= (double)g_graphicsContext.GetHeight())
|
|
{
|
|
- OutWidth = g_graphicsContext.GetWidth();
|
|
- OutHeight = MathUtils::round_int((double)height * g_graphicsContext.GetWidth() / width);
|
|
+ m_vdpauConfig.outWidth = g_graphicsContext.GetWidth();
|
|
+ m_vdpauConfig.outHeight = MathUtils::round_int((double)height * g_graphicsContext.GetWidth() / width);
|
|
}
|
|
else //scale height to the desktop size if the aspect ratio is smaller than the desktop
|
|
{
|
|
- OutHeight = g_graphicsContext.GetHeight();
|
|
- OutWidth = MathUtils::round_int((double)width * g_graphicsContext.GetHeight() / height);
|
|
+ m_vdpauConfig.outHeight = g_graphicsContext.GetHeight();
|
|
+ m_vdpauConfig.outWidth = MathUtils::round_int((double)width * g_graphicsContext.GetHeight() / height);
|
|
}
|
|
}
|
|
else
|
|
{ //let opengl scale
|
|
- OutWidth = width;
|
|
- OutHeight = height;
|
|
- }
|
|
-
|
|
- CLog::Log(LOGNOTICE,"Creating %ix%i pixmap", OutWidth, OutHeight);
|
|
-
|
|
- // Get our window attribs.
|
|
- XWindowAttributes wndattribs;
|
|
- XGetWindowAttributes(m_Display, DefaultRootWindow(m_Display), &wndattribs); // returns a status but I don't know what success is
|
|
-
|
|
- m_Pixmap = XCreatePixmap(m_Display,
|
|
- DefaultRootWindow(m_Display),
|
|
- OutWidth,
|
|
- OutHeight,
|
|
- wndattribs.depth);
|
|
- if (!m_Pixmap)
|
|
- {
|
|
- CLog::Log(LOGERROR, "GLX Error: MakePixmap: Unable to create XPixmap");
|
|
- return false;
|
|
- }
|
|
-
|
|
- XGCValues values = {};
|
|
- GC xgc;
|
|
- values.foreground = BlackPixel (m_Display, DefaultScreen (m_Display));
|
|
- xgc = XCreateGC(m_Display, m_Pixmap, GCForeground, &values);
|
|
- XFillRectangle(m_Display, m_Pixmap, xgc, 0, 0, OutWidth, OutHeight);
|
|
- XFreeGC(m_Display, xgc);
|
|
-
|
|
- if(!MakePixmapGL())
|
|
- return false;
|
|
-
|
|
- return true;
|
|
-}
|
|
-
|
|
-void CVDPAU::BindPixmap()
|
|
-{
|
|
- CSharedLock lock(m_DecoderSection);
|
|
-
|
|
- { CSharedLock dLock(m_DisplaySection);
|
|
- if (m_DisplayState != VDPAU_OPEN)
|
|
- return;
|
|
- }
|
|
-
|
|
- if (m_glPixmap)
|
|
- {
|
|
- if(presentSurface != VDP_INVALID_HANDLE)
|
|
- {
|
|
- VdpPresentationQueueStatus status;
|
|
- VdpTime time;
|
|
- VdpStatus vdp_st;
|
|
- vdp_st = vdp_presentation_queue_query_surface_status(
|
|
- vdp_flip_queue, presentSurface, &status, &time);
|
|
- CheckStatus(vdp_st, __LINE__);
|
|
- while(status != VDP_PRESENTATION_QUEUE_STATUS_VISIBLE && vdp_st == VDP_STATUS_OK)
|
|
- {
|
|
- Sleep(1);
|
|
- vdp_st = vdp_presentation_queue_query_surface_status(
|
|
- vdp_flip_queue, presentSurface, &status, &time);
|
|
- CheckStatus(vdp_st, __LINE__);
|
|
- }
|
|
- }
|
|
-
|
|
- glXBindTexImageEXT(m_Display, m_glPixmap, GLX_FRONT_LEFT_EXT, NULL);
|
|
- }
|
|
- else CLog::Log(LOGERROR,"(VDPAU) BindPixmap called without valid pixmap");
|
|
-}
|
|
-
|
|
-void CVDPAU::ReleasePixmap()
|
|
-{
|
|
- CSharedLock lock(m_DecoderSection);
|
|
-
|
|
- { CSharedLock dLock(m_DisplaySection);
|
|
- if (m_DisplayState != VDPAU_OPEN)
|
|
- return;
|
|
- }
|
|
-
|
|
- if (m_glPixmap)
|
|
- {
|
|
- glXReleaseTexImageEXT(m_Display, m_glPixmap, GLX_FRONT_LEFT_EXT);
|
|
+ m_vdpauConfig.outWidth = width;
|
|
+ m_vdpauConfig.outHeight = height;
|
|
}
|
|
- else CLog::Log(LOGERROR,"(VDPAU) ReleasePixmap called without valid pixmap");
|
|
+ CLog::Log(LOGDEBUG, "CVDPAU::SetWidthHeight Setting OutWidth: %i OutHeight: %i", m_vdpauConfig.outWidth, m_vdpauConfig.outHeight);
|
|
}
|
|
|
|
-void CVDPAU::OnLostDevice()
|
|
+void CDecoder::OnLostDevice()
|
|
{
|
|
CLog::Log(LOGNOTICE,"CVDPAU::OnLostDevice event");
|
|
|
|
- CExclusiveLock lock(m_DecoderSection);
|
|
+ CSingleLock lock(m_DecoderSection);
|
|
FiniVDPAUOutput();
|
|
FiniVDPAUProcs();
|
|
|
|
m_DisplayState = VDPAU_LOST;
|
|
+ lock.Leave();
|
|
m_DisplayEvent.Reset();
|
|
}
|
|
|
|
-void CVDPAU::OnResetDevice()
|
|
+void CDecoder::OnResetDevice()
|
|
{
|
|
CLog::Log(LOGNOTICE,"CVDPAU::OnResetDevice event");
|
|
|
|
- CExclusiveLock lock(m_DisplaySection);
|
|
+ CSingleLock lock(m_DecoderSection);
|
|
if (m_DisplayState == VDPAU_LOST)
|
|
{
|
|
m_DisplayState = VDPAU_RESET;
|
|
+ lock.Leave();
|
|
m_DisplayEvent.Set();
|
|
}
|
|
}
|
|
|
|
-int CVDPAU::Check(AVCodecContext* avctx)
|
|
+int CDecoder::Check(AVCodecContext* avctx)
|
|
{
|
|
EDisplayState state;
|
|
|
|
- { CSharedLock lock(m_DisplaySection);
|
|
+ { CSingleLock lock(m_DecoderSection);
|
|
state = m_DisplayState;
|
|
}
|
|
|
|
@@ -445,16 +319,13 @@ int CVDPAU::Check(AVCodecContext* avctx)
|
|
}
|
|
else
|
|
{
|
|
- CSharedLock lock(m_DisplaySection);
|
|
+ CSingleLock lock(m_DecoderSection);
|
|
state = m_DisplayState;
|
|
}
|
|
}
|
|
if (state == VDPAU_RESET || state == VDPAU_ERROR)
|
|
{
|
|
- CLog::Log(LOGNOTICE,"Attempting recovery");
|
|
-
|
|
- CSingleLock gLock(g_graphicsContext);
|
|
- CExclusiveLock lock(m_DecoderSection);
|
|
+ CSingleLock lock(m_DecoderSection);
|
|
|
|
FiniVDPAUOutput();
|
|
FiniVDPAUProcs();
|
|
@@ -469,7 +340,7 @@ int CVDPAU::Check(AVCodecContext* avctx)
|
|
return 0;
|
|
}
|
|
|
|
-bool CVDPAU::IsVDPAUFormat(PixelFormat format)
|
|
+bool CDecoder::IsVDPAUFormat(PixelFormat format)
|
|
{
|
|
if ((format >= PIX_FMT_VDPAU_H264) && (format <= PIX_FMT_VDPAU_VC1)) return true;
|
|
#if (defined PIX_FMT_VDPAU_MPEG4_IN_AVUTIL)
|
|
@@ -478,91 +349,28 @@ bool CVDPAU::IsVDPAUFormat(PixelFormat format)
|
|
else return false;
|
|
}
|
|
|
|
-void CVDPAU::CheckFeatures()
|
|
-{
|
|
- if (videoMixer == VDP_INVALID_HANDLE)
|
|
- {
|
|
- CLog::Log(LOGNOTICE, " (VDPAU) Creating the video mixer");
|
|
- // Creation of VideoMixer.
|
|
- VdpVideoMixerParameter parameters[] = {
|
|
- VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_WIDTH,
|
|
- VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_HEIGHT,
|
|
- VDP_VIDEO_MIXER_PARAMETER_CHROMA_TYPE
|
|
- };
|
|
-
|
|
- void const * parameter_values[] = {
|
|
- &surface_width,
|
|
- &surface_height,
|
|
- &vdp_chroma_type
|
|
- };
|
|
-
|
|
- tmpBrightness = 0;
|
|
- tmpContrast = 0;
|
|
- tmpNoiseReduction = 0;
|
|
- tmpSharpness = 0;
|
|
-
|
|
- VdpStatus vdp_st = VDP_STATUS_ERROR;
|
|
- vdp_st = vdp_video_mixer_create(vdp_device,
|
|
- m_feature_count,
|
|
- m_features,
|
|
- ARSIZE(parameters),
|
|
- parameters,
|
|
- parameter_values,
|
|
- &videoMixer);
|
|
- CheckStatus(vdp_st, __LINE__);
|
|
-
|
|
- SetHWUpscaling();
|
|
- }
|
|
-
|
|
- if (tmpBrightness != g_settings.m_currentVideoSettings.m_Brightness ||
|
|
- tmpContrast != g_settings.m_currentVideoSettings.m_Contrast)
|
|
- {
|
|
- SetColor();
|
|
- tmpBrightness = g_settings.m_currentVideoSettings.m_Brightness;
|
|
- tmpContrast = g_settings.m_currentVideoSettings.m_Contrast;
|
|
- }
|
|
- if (tmpNoiseReduction != g_settings.m_currentVideoSettings.m_NoiseReduction)
|
|
- {
|
|
- tmpNoiseReduction = g_settings.m_currentVideoSettings.m_NoiseReduction;
|
|
- SetNoiseReduction();
|
|
- }
|
|
- if (tmpSharpness != g_settings.m_currentVideoSettings.m_Sharpness)
|
|
- {
|
|
- tmpSharpness = g_settings.m_currentVideoSettings.m_Sharpness;
|
|
- SetSharpness();
|
|
- }
|
|
- if ( tmpDeintMode != g_settings.m_currentVideoSettings.m_DeinterlaceMode ||
|
|
- tmpDeintGUI != g_settings.m_currentVideoSettings.m_InterlaceMethod ||
|
|
- (tmpDeintGUI == VS_INTERLACEMETHOD_AUTO && tmpDeint != AutoInterlaceMethod()))
|
|
- {
|
|
- tmpDeintMode = g_settings.m_currentVideoSettings.m_DeinterlaceMode;
|
|
- tmpDeintGUI = g_settings.m_currentVideoSettings.m_InterlaceMethod;
|
|
- if (tmpDeintGUI == VS_INTERLACEMETHOD_AUTO)
|
|
- tmpDeint = AutoInterlaceMethod();
|
|
- else
|
|
- tmpDeint = tmpDeintGUI;
|
|
-
|
|
- SetDeinterlacing();
|
|
- }
|
|
-}
|
|
-
|
|
-bool CVDPAU::Supports(VdpVideoMixerFeature feature)
|
|
+bool CDecoder::Supports(VdpVideoMixerFeature feature)
|
|
{
|
|
- for(int i = 0; i < m_feature_count; i++)
|
|
+ for(int i = 0; i < m_vdpauConfig.featureCount; i++)
|
|
{
|
|
- if(m_features[i] == feature)
|
|
+ if(m_vdpauConfig.vdpFeatures[i] == feature)
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
-bool CVDPAU::Supports(EINTERLACEMETHOD method)
|
|
+bool CDecoder::Supports(EINTERLACEMETHOD method)
|
|
{
|
|
if(method == VS_INTERLACEMETHOD_VDPAU_BOB
|
|
- || method == VS_INTERLACEMETHOD_AUTO
|
|
- || method == VS_INTERLACEMETHOD_AUTO_ION)
|
|
+ || method == VS_INTERLACEMETHOD_AUTO)
|
|
return true;
|
|
|
|
+ if (g_guiSettings.GetBool("videoplayer.usevdpauinteropyuv"))
|
|
+ {
|
|
+ if (method == VS_INTERLACEMETHOD_RENDER_BOB)
|
|
+ return true;
|
|
+ }
|
|
+
|
|
for(SInterlaceMapping* p = g_interlace_mapping; p->method != VS_INTERLACEMETHOD_NONE; p++)
|
|
{
|
|
if(p->method == method)
|
|
@@ -571,162 +379,12 @@ bool CVDPAU::Supports(EINTERLACEMETHOD method)
|
|
return false;
|
|
}
|
|
|
|
-EINTERLACEMETHOD CVDPAU::AutoInterlaceMethod()
|
|
-{
|
|
- return VS_INTERLACEMETHOD_VDPAU_TEMPORAL;
|
|
-}
|
|
-
|
|
-void CVDPAU::SetColor()
|
|
-{
|
|
- VdpStatus vdp_st;
|
|
-
|
|
- if (tmpBrightness != g_settings.m_currentVideoSettings.m_Brightness)
|
|
- m_Procamp.brightness = (float)((g_settings.m_currentVideoSettings.m_Brightness)-50) / 100;
|
|
- if (tmpContrast != g_settings.m_currentVideoSettings.m_Contrast)
|
|
- m_Procamp.contrast = (float)((g_settings.m_currentVideoSettings.m_Contrast)+50) / 100;
|
|
-
|
|
- if(vid_height >= 600 || vid_width > 1024)
|
|
- vdp_st = vdp_generate_csc_matrix(&m_Procamp, VDP_COLOR_STANDARD_ITUR_BT_709, &m_CSCMatrix);
|
|
- else
|
|
- vdp_st = vdp_generate_csc_matrix(&m_Procamp, VDP_COLOR_STANDARD_ITUR_BT_601, &m_CSCMatrix);
|
|
-
|
|
- VdpVideoMixerAttribute attributes[] = { VDP_VIDEO_MIXER_ATTRIBUTE_CSC_MATRIX };
|
|
- if (g_guiSettings.GetBool("videoplayer.vdpaustudiolevel"))
|
|
- {
|
|
- void const * pm_CSCMatix[] = { &studioCSC };
|
|
- vdp_st = vdp_video_mixer_set_attribute_values(videoMixer, ARSIZE(attributes), attributes, pm_CSCMatix);
|
|
- }
|
|
- else
|
|
- {
|
|
- void const * pm_CSCMatix[] = { &m_CSCMatrix };
|
|
- vdp_st = vdp_video_mixer_set_attribute_values(videoMixer, ARSIZE(attributes), attributes, pm_CSCMatix);
|
|
- }
|
|
- CheckStatus(vdp_st, __LINE__);
|
|
-}
|
|
-
|
|
-void CVDPAU::SetNoiseReduction()
|
|
-{
|
|
- if(!Supports(VDP_VIDEO_MIXER_FEATURE_NOISE_REDUCTION))
|
|
- return;
|
|
-
|
|
- VdpVideoMixerFeature feature[] = { VDP_VIDEO_MIXER_FEATURE_NOISE_REDUCTION };
|
|
- VdpVideoMixerAttribute attributes[] = { VDP_VIDEO_MIXER_ATTRIBUTE_NOISE_REDUCTION_LEVEL };
|
|
- VdpStatus vdp_st;
|
|
-
|
|
- if (!g_settings.m_currentVideoSettings.m_NoiseReduction)
|
|
- {
|
|
- VdpBool enabled[]= {0};
|
|
- vdp_st = vdp_video_mixer_set_feature_enables(videoMixer, ARSIZE(feature), feature, enabled);
|
|
- CheckStatus(vdp_st, __LINE__);
|
|
- return;
|
|
- }
|
|
- VdpBool enabled[]={1};
|
|
- vdp_st = vdp_video_mixer_set_feature_enables(videoMixer, ARSIZE(feature), feature, enabled);
|
|
- CheckStatus(vdp_st, __LINE__);
|
|
- void* nr[] = { &g_settings.m_currentVideoSettings.m_NoiseReduction };
|
|
- CLog::Log(LOGNOTICE,"Setting Noise Reduction to %f",g_settings.m_currentVideoSettings.m_NoiseReduction);
|
|
- vdp_st = vdp_video_mixer_set_attribute_values(videoMixer, ARSIZE(attributes), attributes, nr);
|
|
- CheckStatus(vdp_st, __LINE__);
|
|
-}
|
|
-
|
|
-void CVDPAU::SetSharpness()
|
|
-{
|
|
- if(!Supports(VDP_VIDEO_MIXER_FEATURE_SHARPNESS))
|
|
- return;
|
|
-
|
|
- VdpVideoMixerFeature feature[] = { VDP_VIDEO_MIXER_FEATURE_SHARPNESS };
|
|
- VdpVideoMixerAttribute attributes[] = { VDP_VIDEO_MIXER_ATTRIBUTE_SHARPNESS_LEVEL };
|
|
- VdpStatus vdp_st;
|
|
-
|
|
- if (!g_settings.m_currentVideoSettings.m_Sharpness)
|
|
- {
|
|
- VdpBool enabled[]={0};
|
|
- vdp_st = vdp_video_mixer_set_feature_enables(videoMixer, ARSIZE(feature), feature, enabled);
|
|
- CheckStatus(vdp_st, __LINE__);
|
|
- return;
|
|
- }
|
|
- VdpBool enabled[]={1};
|
|
- vdp_st = vdp_video_mixer_set_feature_enables(videoMixer, ARSIZE(feature), feature, enabled);
|
|
- CheckStatus(vdp_st, __LINE__);
|
|
- void* sh[] = { &g_settings.m_currentVideoSettings.m_Sharpness };
|
|
- CLog::Log(LOGNOTICE,"Setting Sharpness to %f",g_settings.m_currentVideoSettings.m_Sharpness);
|
|
- vdp_st = vdp_video_mixer_set_attribute_values(videoMixer, ARSIZE(attributes), attributes, sh);
|
|
- CheckStatus(vdp_st, __LINE__);
|
|
-}
|
|
-
|
|
-void CVDPAU::SetHWUpscaling()
|
|
-{
|
|
-#ifdef VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L1
|
|
- if(!Supports(VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L1) || !upScale)
|
|
- return;
|
|
-
|
|
- VdpVideoMixerFeature feature[] = { VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L1 };
|
|
- VdpStatus vdp_st;
|
|
- VdpBool enabled[]={1};
|
|
- vdp_st = vdp_video_mixer_set_feature_enables(videoMixer, ARSIZE(feature), feature, enabled);
|
|
- CheckStatus(vdp_st, __LINE__);
|
|
-#endif
|
|
-}
|
|
-
|
|
-void CVDPAU::SetDeinterlacing()
|
|
+EINTERLACEMETHOD CDecoder::AutoInterlaceMethod()
|
|
{
|
|
- VdpStatus vdp_st;
|
|
- EDEINTERLACEMODE mode = g_settings.m_currentVideoSettings.m_DeinterlaceMode;
|
|
- EINTERLACEMETHOD method = g_settings.m_currentVideoSettings.m_InterlaceMethod;
|
|
- if (method == VS_INTERLACEMETHOD_AUTO)
|
|
- method = AutoInterlaceMethod();
|
|
-
|
|
- VdpVideoMixerFeature feature[] = { VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL,
|
|
- VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL_SPATIAL,
|
|
- VDP_VIDEO_MIXER_FEATURE_INVERSE_TELECINE };
|
|
- if (mode == VS_DEINTERLACEMODE_OFF)
|
|
- {
|
|
- VdpBool enabled[]={0,0,0};
|
|
- vdp_st = vdp_video_mixer_set_feature_enables(videoMixer, ARSIZE(feature), feature, enabled);
|
|
- }
|
|
- else
|
|
- {
|
|
- if (method == VS_INTERLACEMETHOD_AUTO_ION)
|
|
- {
|
|
- if (vid_height <= 576)
|
|
- {
|
|
- VdpBool enabled[]={1,1,0};
|
|
- vdp_st = vdp_video_mixer_set_feature_enables(videoMixer, ARSIZE(feature), feature, enabled);
|
|
- }
|
|
- else if (vid_height > 576)
|
|
- {
|
|
- VdpBool enabled[]={1,0,0};
|
|
- vdp_st = vdp_video_mixer_set_feature_enables(videoMixer, ARSIZE(feature), feature, enabled);
|
|
- }
|
|
- }
|
|
- else if (method == VS_INTERLACEMETHOD_VDPAU_TEMPORAL
|
|
- || method == VS_INTERLACEMETHOD_VDPAU_TEMPORAL_HALF)
|
|
- {
|
|
- VdpBool enabled[]={1,0,0};
|
|
- vdp_st = vdp_video_mixer_set_feature_enables(videoMixer, ARSIZE(feature), feature, enabled);
|
|
- }
|
|
- else if (method == VS_INTERLACEMETHOD_VDPAU_TEMPORAL_SPATIAL
|
|
- || method == VS_INTERLACEMETHOD_VDPAU_TEMPORAL_SPATIAL_HALF)
|
|
- {
|
|
- VdpBool enabled[]={1,1,0};
|
|
- vdp_st = vdp_video_mixer_set_feature_enables(videoMixer, ARSIZE(feature), feature, enabled);
|
|
- }
|
|
- else if (method == VS_INTERLACEMETHOD_VDPAU_INVERSE_TELECINE)
|
|
- {
|
|
- VdpBool enabled[]={1,0,1};
|
|
- vdp_st = vdp_video_mixer_set_feature_enables(videoMixer, ARSIZE(feature), feature, enabled);
|
|
- }
|
|
- else
|
|
- {
|
|
- VdpBool enabled[]={0,0,0};
|
|
- vdp_st = vdp_video_mixer_set_feature_enables(videoMixer, ARSIZE(feature), feature, enabled);
|
|
- }
|
|
- }
|
|
-
|
|
- CheckStatus(vdp_st, __LINE__);
|
|
+ return VS_INTERLACEMETHOD_RENDER_BOB;
|
|
}
|
|
|
|
-void CVDPAU::InitVDPAUProcs()
|
|
+void CDecoder::InitVDPAUProcs()
|
|
{
|
|
char* error;
|
|
|
|
@@ -736,151 +394,115 @@ void CVDPAU::InitVDPAUProcs()
|
|
if (error)
|
|
{
|
|
CLog::Log(LOGERROR,"(VDPAU) - %s in %s",error,__FUNCTION__);
|
|
- vdp_device = VDP_INVALID_HANDLE;
|
|
-
|
|
- //g_application.m_guiDialogKaiToast.QueueNotification(CGUIDialogKaiToast::Error, "VDPAU", error, 10000);
|
|
-
|
|
+ m_vdpauConfig.vdpDevice = VDP_INVALID_HANDLE;
|
|
return;
|
|
}
|
|
|
|
if (dl_vdp_device_create_x11)
|
|
{
|
|
- CSingleLock lock(g_graphicsContext);
|
|
- m_Display = g_Windowing.GetDisplay();
|
|
- }
|
|
- else
|
|
- {
|
|
- CLog::Log(LOGERROR,"(VDPAU) - Unable to get dl_vdp_device_create_x11 in %s", __FUNCTION__);
|
|
- vdp_device = VDP_INVALID_HANDLE;
|
|
- return;
|
|
+ m_Display = XOpenDisplay(NULL);
|
|
}
|
|
|
|
- int mScreen = DefaultScreen(m_Display);
|
|
+ int mScreen = g_Windowing.GetCurrentScreen();
|
|
VdpStatus vdp_st;
|
|
|
|
// Create Device
|
|
- // tested on 64bit Ubuntu 11.10 and it deadlocked without this
|
|
- XLockDisplay(m_Display);
|
|
vdp_st = dl_vdp_device_create_x11(m_Display, //x_display,
|
|
mScreen, //x_screen,
|
|
- &vdp_device,
|
|
- &vdp_get_proc_address);
|
|
- XUnlockDisplay(m_Display);
|
|
+ &m_vdpauConfig.vdpDevice,
|
|
+ &m_vdpauConfig.vdpProcs.vdp_get_proc_address);
|
|
|
|
- CLog::Log(LOGNOTICE,"vdp_device = 0x%08x vdp_st = 0x%08x",vdp_device,vdp_st);
|
|
+ CLog::Log(LOGNOTICE,"vdp_device = 0x%08x vdp_st = 0x%08x",m_vdpauConfig.vdpDevice,vdp_st);
|
|
if (vdp_st != VDP_STATUS_OK)
|
|
{
|
|
CLog::Log(LOGERROR,"(VDPAU) unable to init VDPAU - vdp_st = 0x%x. Falling back.",vdp_st);
|
|
- vdp_device = VDP_INVALID_HANDLE;
|
|
+ m_vdpauConfig.vdpDevice = VDP_INVALID_HANDLE;
|
|
return;
|
|
}
|
|
|
|
#define VDP_PROC(id, proc) \
|
|
do { \
|
|
- vdp_st = vdp_get_proc_address(vdp_device, id, (void**)&proc); \
|
|
+ vdp_st = m_vdpauConfig.vdpProcs.vdp_get_proc_address(m_vdpauConfig.vdpDevice, id, (void**)&proc); \
|
|
CheckStatus(vdp_st, __LINE__); \
|
|
} while(0);
|
|
|
|
- VDP_PROC(VDP_FUNC_ID_GET_ERROR_STRING , vdp_get_error_string);
|
|
- VDP_PROC(VDP_FUNC_ID_DEVICE_DESTROY , vdp_device_destroy);
|
|
- VDP_PROC(VDP_FUNC_ID_GENERATE_CSC_MATRIX , vdp_generate_csc_matrix);
|
|
- VDP_PROC(VDP_FUNC_ID_VIDEO_SURFACE_CREATE , vdp_video_surface_create);
|
|
- VDP_PROC(VDP_FUNC_ID_VIDEO_SURFACE_DESTROY , vdp_video_surface_destroy);
|
|
- VDP_PROC(VDP_FUNC_ID_VIDEO_SURFACE_PUT_BITS_Y_CB_CR , vdp_video_surface_put_bits_y_cb_cr);
|
|
- VDP_PROC(VDP_FUNC_ID_VIDEO_SURFACE_GET_BITS_Y_CB_CR , vdp_video_surface_get_bits_y_cb_cr);
|
|
- VDP_PROC(VDP_FUNC_ID_OUTPUT_SURFACE_PUT_BITS_Y_CB_CR , vdp_output_surface_put_bits_y_cb_cr);
|
|
- VDP_PROC(VDP_FUNC_ID_OUTPUT_SURFACE_PUT_BITS_NATIVE , vdp_output_surface_put_bits_native);
|
|
- VDP_PROC(VDP_FUNC_ID_OUTPUT_SURFACE_CREATE , vdp_output_surface_create);
|
|
- VDP_PROC(VDP_FUNC_ID_OUTPUT_SURFACE_DESTROY , vdp_output_surface_destroy);
|
|
- VDP_PROC(VDP_FUNC_ID_OUTPUT_SURFACE_GET_BITS_NATIVE , vdp_output_surface_get_bits_native);
|
|
- VDP_PROC(VDP_FUNC_ID_OUTPUT_SURFACE_RENDER_OUTPUT_SURFACE, vdp_output_surface_render_output_surface);
|
|
- VDP_PROC(VDP_FUNC_ID_OUTPUT_SURFACE_PUT_BITS_INDEXED , vdp_output_surface_put_bits_indexed);
|
|
- VDP_PROC(VDP_FUNC_ID_VIDEO_MIXER_CREATE , vdp_video_mixer_create);
|
|
- VDP_PROC(VDP_FUNC_ID_VIDEO_MIXER_SET_FEATURE_ENABLES , vdp_video_mixer_set_feature_enables);
|
|
- VDP_PROC(VDP_FUNC_ID_VIDEO_MIXER_DESTROY , vdp_video_mixer_destroy);
|
|
- VDP_PROC(VDP_FUNC_ID_VIDEO_MIXER_RENDER , vdp_video_mixer_render);
|
|
- VDP_PROC(VDP_FUNC_ID_VIDEO_MIXER_SET_ATTRIBUTE_VALUES , vdp_video_mixer_set_attribute_values);
|
|
- VDP_PROC(VDP_FUNC_ID_VIDEO_MIXER_QUERY_PARAMETER_SUPPORT , vdp_video_mixer_query_parameter_support);
|
|
- VDP_PROC(VDP_FUNC_ID_VIDEO_MIXER_QUERY_FEATURE_SUPPORT , vdp_video_mixer_query_feature_support);
|
|
- VDP_PROC(VDP_FUNC_ID_DECODER_CREATE , vdp_decoder_create);
|
|
- VDP_PROC(VDP_FUNC_ID_DECODER_DESTROY , vdp_decoder_destroy);
|
|
- VDP_PROC(VDP_FUNC_ID_DECODER_RENDER , vdp_decoder_render);
|
|
- VDP_PROC(VDP_FUNC_ID_DECODER_QUERY_CAPABILITIES , vdp_decoder_query_caps);
|
|
- VDP_PROC(VDP_FUNC_ID_PREEMPTION_CALLBACK_REGISTER , vdp_preemption_callback_register);
|
|
- VDP_PROC(VDP_FUNC_ID_PRESENTATION_QUEUE_TARGET_DESTROY , vdp_presentation_queue_target_destroy);
|
|
- VDP_PROC(VDP_FUNC_ID_PRESENTATION_QUEUE_CREATE , vdp_presentation_queue_create);
|
|
- VDP_PROC(VDP_FUNC_ID_PRESENTATION_QUEUE_DESTROY , vdp_presentation_queue_destroy);
|
|
- VDP_PROC(VDP_FUNC_ID_PRESENTATION_QUEUE_DISPLAY , vdp_presentation_queue_display);
|
|
- VDP_PROC(VDP_FUNC_ID_PRESENTATION_QUEUE_BLOCK_UNTIL_SURFACE_IDLE, vdp_presentation_queue_block_until_surface_idle);
|
|
- VDP_PROC(VDP_FUNC_ID_PRESENTATION_QUEUE_TARGET_CREATE_X11 , vdp_presentation_queue_target_create_x11);
|
|
- VDP_PROC(VDP_FUNC_ID_PRESENTATION_QUEUE_QUERY_SURFACE_STATUS , vdp_presentation_queue_query_surface_status);
|
|
- VDP_PROC(VDP_FUNC_ID_PRESENTATION_QUEUE_GET_TIME , vdp_presentation_queue_get_time);
|
|
-
|
|
+ VDP_PROC(VDP_FUNC_ID_GET_ERROR_STRING , m_vdpauConfig.vdpProcs.vdp_get_error_string);
|
|
+ VDP_PROC(VDP_FUNC_ID_DEVICE_DESTROY , m_vdpauConfig.vdpProcs.vdp_device_destroy);
|
|
+ VDP_PROC(VDP_FUNC_ID_GENERATE_CSC_MATRIX , m_vdpauConfig.vdpProcs.vdp_generate_csc_matrix);
|
|
+ VDP_PROC(VDP_FUNC_ID_VIDEO_SURFACE_CREATE , m_vdpauConfig.vdpProcs.vdp_video_surface_create);
|
|
+ VDP_PROC(VDP_FUNC_ID_VIDEO_SURFACE_DESTROY , m_vdpauConfig.vdpProcs.vdp_video_surface_destroy);
|
|
+ VDP_PROC(VDP_FUNC_ID_VIDEO_SURFACE_PUT_BITS_Y_CB_CR , m_vdpauConfig.vdpProcs.vdp_video_surface_put_bits_y_cb_cr);
|
|
+ VDP_PROC(VDP_FUNC_ID_VIDEO_SURFACE_GET_BITS_Y_CB_CR , m_vdpauConfig.vdpProcs.vdp_video_surface_get_bits_y_cb_cr);
|
|
+ VDP_PROC(VDP_FUNC_ID_OUTPUT_SURFACE_PUT_BITS_Y_CB_CR , m_vdpauConfig.vdpProcs.vdp_output_surface_put_bits_y_cb_cr);
|
|
+ VDP_PROC(VDP_FUNC_ID_OUTPUT_SURFACE_PUT_BITS_NATIVE , m_vdpauConfig.vdpProcs.vdp_output_surface_put_bits_native);
|
|
+ VDP_PROC(VDP_FUNC_ID_OUTPUT_SURFACE_CREATE , m_vdpauConfig.vdpProcs.vdp_output_surface_create);
|
|
+ VDP_PROC(VDP_FUNC_ID_OUTPUT_SURFACE_DESTROY , m_vdpauConfig.vdpProcs.vdp_output_surface_destroy);
|
|
+ VDP_PROC(VDP_FUNC_ID_OUTPUT_SURFACE_GET_BITS_NATIVE , m_vdpauConfig.vdpProcs.vdp_output_surface_get_bits_native);
|
|
+ VDP_PROC(VDP_FUNC_ID_OUTPUT_SURFACE_RENDER_OUTPUT_SURFACE, m_vdpauConfig.vdpProcs.vdp_output_surface_render_output_surface);
|
|
+ VDP_PROC(VDP_FUNC_ID_OUTPUT_SURFACE_PUT_BITS_INDEXED , m_vdpauConfig.vdpProcs.vdp_output_surface_put_bits_indexed);
|
|
+ VDP_PROC(VDP_FUNC_ID_VIDEO_MIXER_CREATE , m_vdpauConfig.vdpProcs.vdp_video_mixer_create);
|
|
+ VDP_PROC(VDP_FUNC_ID_VIDEO_MIXER_SET_FEATURE_ENABLES , m_vdpauConfig.vdpProcs.vdp_video_mixer_set_feature_enables);
|
|
+ VDP_PROC(VDP_FUNC_ID_VIDEO_MIXER_DESTROY , m_vdpauConfig.vdpProcs.vdp_video_mixer_destroy);
|
|
+ VDP_PROC(VDP_FUNC_ID_VIDEO_MIXER_RENDER , m_vdpauConfig.vdpProcs.vdp_video_mixer_render);
|
|
+ VDP_PROC(VDP_FUNC_ID_VIDEO_MIXER_SET_ATTRIBUTE_VALUES , m_vdpauConfig.vdpProcs.vdp_video_mixer_set_attribute_values);
|
|
+ VDP_PROC(VDP_FUNC_ID_VIDEO_MIXER_QUERY_PARAMETER_SUPPORT , m_vdpauConfig.vdpProcs.vdp_video_mixer_query_parameter_support);
|
|
+ VDP_PROC(VDP_FUNC_ID_VIDEO_MIXER_QUERY_FEATURE_SUPPORT , m_vdpauConfig.vdpProcs.vdp_video_mixer_query_feature_support);
|
|
+ VDP_PROC(VDP_FUNC_ID_DECODER_CREATE , m_vdpauConfig.vdpProcs.vdp_decoder_create);
|
|
+ VDP_PROC(VDP_FUNC_ID_DECODER_DESTROY , m_vdpauConfig.vdpProcs.vdp_decoder_destroy);
|
|
+ VDP_PROC(VDP_FUNC_ID_DECODER_RENDER , m_vdpauConfig.vdpProcs.vdp_decoder_render);
|
|
+ VDP_PROC(VDP_FUNC_ID_DECODER_QUERY_CAPABILITIES , m_vdpauConfig.vdpProcs.vdp_decoder_query_caps);
|
|
+ VDP_PROC(VDP_FUNC_ID_PRESENTATION_QUEUE_TARGET_DESTROY , m_vdpauConfig.vdpProcs.vdp_presentation_queue_target_destroy);
|
|
+ VDP_PROC(VDP_FUNC_ID_PRESENTATION_QUEUE_CREATE , m_vdpauConfig.vdpProcs.vdp_presentation_queue_create);
|
|
+ VDP_PROC(VDP_FUNC_ID_PRESENTATION_QUEUE_DESTROY , m_vdpauConfig.vdpProcs.vdp_presentation_queue_destroy);
|
|
+ VDP_PROC(VDP_FUNC_ID_PRESENTATION_QUEUE_DISPLAY , m_vdpauConfig.vdpProcs.vdp_presentation_queue_display);
|
|
+ VDP_PROC(VDP_FUNC_ID_PRESENTATION_QUEUE_BLOCK_UNTIL_SURFACE_IDLE, m_vdpauConfig.vdpProcs.vdp_presentation_queue_block_until_surface_idle);
|
|
+ VDP_PROC(VDP_FUNC_ID_PRESENTATION_QUEUE_TARGET_CREATE_X11 , m_vdpauConfig.vdpProcs.vdp_presentation_queue_target_create_x11);
|
|
+ VDP_PROC(VDP_FUNC_ID_PRESENTATION_QUEUE_QUERY_SURFACE_STATUS , m_vdpauConfig.vdpProcs.vdp_presentation_queue_query_surface_status);
|
|
+ VDP_PROC(VDP_FUNC_ID_PRESENTATION_QUEUE_GET_TIME , m_vdpauConfig.vdpProcs.vdp_presentation_queue_get_time);
|
|
+
|
|
#undef VDP_PROC
|
|
|
|
// set all vdpau resources to invalid
|
|
- vdp_flip_target = VDP_INVALID_HANDLE;
|
|
- vdp_flip_queue = VDP_INVALID_HANDLE;
|
|
- videoMixer = VDP_INVALID_HANDLE;
|
|
- totalAvailableOutputSurfaces = 0;
|
|
- presentSurface = VDP_INVALID_HANDLE;
|
|
- outputSurface = VDP_INVALID_HANDLE;
|
|
- for (int i = 0; i < NUM_OUTPUT_SURFACES; i++)
|
|
- outputSurfaces[i] = VDP_INVALID_HANDLE;
|
|
-
|
|
- m_vdpauOutputMethod = OUTPUT_NONE;
|
|
-
|
|
- CExclusiveLock lock(m_DisplaySection);
|
|
m_DisplayState = VDPAU_OPEN;
|
|
- vdpauConfigured = false;
|
|
+ m_vdpauConfigured = false;
|
|
}
|
|
|
|
-void CVDPAU::FiniVDPAUProcs()
|
|
+void CDecoder::FiniVDPAUProcs()
|
|
{
|
|
- if (vdp_device == VDP_INVALID_HANDLE) return;
|
|
+ if (m_vdpauConfig.vdpDevice == VDP_INVALID_HANDLE) return;
|
|
|
|
VdpStatus vdp_st;
|
|
- vdp_st = vdp_device_destroy(vdp_device);
|
|
+ vdp_st = m_vdpauConfig.vdpProcs.vdp_device_destroy(m_vdpauConfig.vdpDevice);
|
|
CheckStatus(vdp_st, __LINE__);
|
|
- vdp_device = VDP_INVALID_HANDLE;
|
|
- vdpauConfigured = false;
|
|
+ m_vdpauConfig.vdpDevice = VDP_INVALID_HANDLE;
|
|
}
|
|
|
|
-void CVDPAU::InitCSCMatrix(int Height)
|
|
+void CDecoder::FiniVDPAUOutput()
|
|
{
|
|
+ if (m_vdpauConfig.vdpDevice == VDP_INVALID_HANDLE || !m_vdpauConfigured) return;
|
|
+
|
|
+ CLog::Log(LOGNOTICE, " (VDPAU) %s", __FUNCTION__);
|
|
+
|
|
+ // uninit output
|
|
+ m_vdpauOutput.Dispose();
|
|
+ m_vdpauConfigured = false;
|
|
+
|
|
VdpStatus vdp_st;
|
|
- m_Procamp.struct_version = VDP_PROCAMP_VERSION;
|
|
- m_Procamp.brightness = 0.0;
|
|
- m_Procamp.contrast = 1.0;
|
|
- m_Procamp.saturation = 1.0;
|
|
- m_Procamp.hue = 0;
|
|
- vdp_st = vdp_generate_csc_matrix(&m_Procamp,
|
|
- (Height < 720)? VDP_COLOR_STANDARD_ITUR_BT_601 : VDP_COLOR_STANDARD_ITUR_BT_709,
|
|
- &m_CSCMatrix);
|
|
- CheckStatus(vdp_st, __LINE__);
|
|
-}
|
|
-
|
|
-void CVDPAU::FiniVDPAUOutput()
|
|
-{
|
|
- FiniOutputMethod();
|
|
|
|
- if (vdp_device == VDP_INVALID_HANDLE || !vdpauConfigured) return;
|
|
-
|
|
- CLog::Log(LOGNOTICE, " (VDPAU) %s", __FUNCTION__);
|
|
-
|
|
- VdpStatus vdp_st;
|
|
-
|
|
- vdp_st = vdp_decoder_destroy(decoder);
|
|
+ vdp_st = m_vdpauConfig.vdpProcs.vdp_decoder_destroy(m_vdpauConfig.vdpDecoder);
|
|
if (CheckStatus(vdp_st, __LINE__))
|
|
return;
|
|
- decoder = VDP_INVALID_HANDLE;
|
|
+ m_vdpauConfig.vdpDecoder = VDP_INVALID_HANDLE;
|
|
+
|
|
+ CSingleLock lock(m_videoSurfaceSec);
|
|
+ CLog::Log(LOGDEBUG, "CVDPAU::FiniVDPAUOutput destroying %d video surfaces", (int)m_videoSurfaces.size());
|
|
|
|
- for (unsigned int i = 0; i < m_videoSurfaces.size(); ++i)
|
|
+ for(unsigned int i = 0; i < m_videoSurfaces.size(); ++i)
|
|
{
|
|
vdpau_render_state *render = m_videoSurfaces[i];
|
|
if (render->surface != VDP_INVALID_HANDLE)
|
|
{
|
|
- vdp_st = vdp_video_surface_destroy(render->surface);
|
|
+ vdp_st = m_vdpauConfig.vdpProcs.vdp_video_surface_destroy(render->surface);
|
|
render->surface = VDP_INVALID_HANDLE;
|
|
}
|
|
if (CheckStatus(vdp_st, __LINE__))
|
|
@@ -888,8 +510,7 @@ void CVDPAU::FiniVDPAUOutput()
|
|
}
|
|
}
|
|
|
|
-
|
|
-void CVDPAU::ReadFormatOf( PixelFormat fmt
|
|
+void CDecoder::ReadFormatOf( PixelFormat fmt
|
|
, VdpDecoderProfile &vdp_decoder_profile
|
|
, VdpChromaType &vdp_chroma_type)
|
|
{
|
|
@@ -916,9 +537,9 @@ void CVDPAU::ReadFormatOf( PixelFormat fmt
|
|
vdp_chroma_type = VDP_CHROMA_TYPE_420;
|
|
break;
|
|
#if (defined PIX_FMT_VDPAU_MPEG4_IN_AVUTIL) && \
|
|
- (defined VDP_DECODER_PROFILE_MPEG4_PART2_ASP)
|
|
+ (defined VDP_DECODER_PROFILE_MP)
|
|
case PIX_FMT_VDPAU_MPEG4:
|
|
- vdp_decoder_profile = VDP_DECODER_PROFILE_MPEG4_PART2_ASP;
|
|
+ vdp_decoder_profile = VDP_DECOPEG4_PART2_ASP;
|
|
vdp_chroma_type = VDP_CHROMA_TYPE_420;
|
|
break;
|
|
#endif
|
|
@@ -929,170 +550,78 @@ void CVDPAU::ReadFormatOf( PixelFormat fmt
|
|
}
|
|
}
|
|
|
|
-
|
|
-bool CVDPAU::ConfigVDPAU(AVCodecContext* avctx, int ref_frames)
|
|
+bool CDecoder::ConfigVDPAU(AVCodecContext* avctx, int ref_frames)
|
|
{
|
|
FiniVDPAUOutput();
|
|
|
|
VdpStatus vdp_st;
|
|
VdpDecoderProfile vdp_decoder_profile;
|
|
- vid_width = avctx->width;
|
|
- vid_height = avctx->height;
|
|
- surface_width = avctx->coded_width;
|
|
- surface_height = avctx->coded_height;
|
|
|
|
- past[1] = past[0] = current = future = NULL;
|
|
- CLog::Log(LOGNOTICE, " (VDPAU) screenWidth:%i vidWidth:%i surfaceWidth:%i",OutWidth,vid_width,surface_width);
|
|
- CLog::Log(LOGNOTICE, " (VDPAU) screenHeight:%i vidHeight:%i surfaceHeight:%i",OutHeight,vid_height,surface_height);
|
|
- ReadFormatOf(avctx->pix_fmt, vdp_decoder_profile, vdp_chroma_type);
|
|
+ m_vdpauConfig.vidWidth = avctx->width;
|
|
+ m_vdpauConfig.vidHeight = avctx->height;
|
|
+ m_vdpauConfig.surfaceWidth = avctx->coded_width;
|
|
+ m_vdpauConfig.surfaceHeight = avctx->coded_height;
|
|
+
|
|
+ SetWidthHeight(avctx->width,avctx->height);
|
|
+
|
|
+ CLog::Log(LOGNOTICE, " (VDPAU) screenWidth:%i vidWidth:%i surfaceWidth:%i",m_vdpauConfig.outWidth,m_vdpauConfig.vidWidth,m_vdpauConfig.surfaceWidth);
|
|
+ CLog::Log(LOGNOTICE, " (VDPAU) screenHeight:%i vidHeight:%i surfaceHeight:%i",m_vdpauConfig.outHeight,m_vdpauConfig.vidHeight,m_vdpauConfig.surfaceHeight);
|
|
+
|
|
+ ReadFormatOf(avctx->pix_fmt, vdp_decoder_profile, m_vdpauConfig.vdpChromaType);
|
|
|
|
if(avctx->pix_fmt == PIX_FMT_VDPAU_H264)
|
|
{
|
|
- max_references = ref_frames;
|
|
- if (max_references > 16) max_references = 16;
|
|
- if (max_references < 5) max_references = 5;
|
|
+ m_vdpauConfig.maxReferences = ref_frames;
|
|
+ if (m_vdpauConfig.maxReferences > 16) m_vdpauConfig.maxReferences = 16;
|
|
+ if (m_vdpauConfig.maxReferences < 5) m_vdpauConfig.maxReferences = 5;
|
|
}
|
|
else
|
|
- max_references = 2;
|
|
+ m_vdpauConfig.maxReferences = 2;
|
|
|
|
- vdp_st = vdp_decoder_create(vdp_device,
|
|
+ vdp_st = m_vdpauConfig.vdpProcs.vdp_decoder_create(m_vdpauConfig.vdpDevice,
|
|
vdp_decoder_profile,
|
|
- surface_width,
|
|
- surface_height,
|
|
- max_references,
|
|
- &decoder);
|
|
- if (CheckStatus(vdp_st, __LINE__))
|
|
- return false;
|
|
-
|
|
- m_vdpauOutputMethod = OUTPUT_NONE;
|
|
-
|
|
- vdpauConfigured = true;
|
|
- return true;
|
|
-}
|
|
-
|
|
-bool CVDPAU::ConfigOutputMethod(AVCodecContext *avctx, AVFrame *pFrame)
|
|
-{
|
|
- VdpStatus vdp_st;
|
|
-
|
|
- if (m_vdpauOutputMethod == OUTPUT_PIXMAP)
|
|
- return true;
|
|
-
|
|
- FiniOutputMethod();
|
|
-
|
|
- MakePixmap(avctx->width,avctx->height);
|
|
-
|
|
- vdp_st = vdp_presentation_queue_target_create_x11(vdp_device,
|
|
- m_Pixmap, //x_window,
|
|
- &vdp_flip_target);
|
|
- if (CheckStatus(vdp_st, __LINE__))
|
|
- return false;
|
|
-
|
|
- vdp_st = vdp_presentation_queue_create(vdp_device,
|
|
- vdp_flip_target,
|
|
- &vdp_flip_queue);
|
|
+ m_vdpauConfig.surfaceWidth,
|
|
+ m_vdpauConfig.surfaceHeight,
|
|
+ m_vdpauConfig.maxReferences,
|
|
+ &m_vdpauConfig.vdpDecoder);
|
|
if (CheckStatus(vdp_st, __LINE__))
|
|
return false;
|
|
|
|
- totalAvailableOutputSurfaces = 0;
|
|
-
|
|
- int tmpMaxOutputSurfaces = NUM_OUTPUT_SURFACES;
|
|
- if (vid_width == FULLHD_WIDTH)
|
|
- tmpMaxOutputSurfaces = NUM_OUTPUT_SURFACES_FOR_FULLHD;
|
|
-
|
|
- // Creation of outputSurfaces
|
|
- for (int i = 0; i < NUM_OUTPUT_SURFACES && i < tmpMaxOutputSurfaces; i++)
|
|
- {
|
|
- vdp_st = vdp_output_surface_create(vdp_device,
|
|
- VDP_RGBA_FORMAT_B8G8R8A8,
|
|
- OutWidth,
|
|
- OutHeight,
|
|
- &outputSurfaces[i]);
|
|
- if (CheckStatus(vdp_st, __LINE__))
|
|
+ // initialize output
|
|
+ CSingleLock lock(g_graphicsContext);
|
|
+ m_vdpauConfig.stats = &m_bufferStats;
|
|
+ m_vdpauConfig.vdpau = this;
|
|
+ m_bufferStats.Reset();
|
|
+ m_vdpauOutput.Start();
|
|
+ Message *reply;
|
|
+ if (m_vdpauOutput.m_controlPort.SendOutMessageSync(COutputControlProtocol::INIT,
|
|
+ &reply,
|
|
+ 2000,
|
|
+ &m_vdpauConfig,
|
|
+ sizeof(m_vdpauConfig)))
|
|
+ {
|
|
+ bool success = reply->signal == COutputControlProtocol::ACC ? true : false;
|
|
+ reply->Release();
|
|
+ if (!success)
|
|
+ {
|
|
+ CLog::Log(LOGERROR, "VDPAU::%s - vdpau output returned error", __FUNCTION__);
|
|
+ m_vdpauOutput.Dispose();
|
|
return false;
|
|
- totalAvailableOutputSurfaces++;
|
|
- }
|
|
- CLog::Log(LOGNOTICE, " (VDPAU) Total Output Surfaces Available: %i of a max (tmp: %i const: %i)",
|
|
- totalAvailableOutputSurfaces,
|
|
- tmpMaxOutputSurfaces,
|
|
- NUM_OUTPUT_SURFACES);
|
|
-
|
|
- // create 3 pitches of black lines needed for clipping top
|
|
- // and bottom lines when de-interlacing
|
|
- m_BlackBar = new uint32_t[3*OutWidth];
|
|
- memset(m_BlackBar, 0, 3*OutWidth*sizeof(uint32_t));
|
|
-
|
|
- surfaceNum = presentSurfaceNum = 0;
|
|
- outputSurface = presentSurface = VDP_INVALID_HANDLE;
|
|
- videoMixer = VDP_INVALID_HANDLE;
|
|
-
|
|
- m_vdpauOutputMethod = OUTPUT_PIXMAP;
|
|
-
|
|
- return true;
|
|
-}
|
|
-
|
|
-bool CVDPAU::FiniOutputMethod()
|
|
-{
|
|
- VdpStatus vdp_st;
|
|
-
|
|
- if (vdp_flip_queue != VDP_INVALID_HANDLE)
|
|
- {
|
|
- vdp_st = vdp_presentation_queue_destroy(vdp_flip_queue);
|
|
- vdp_flip_queue = VDP_INVALID_HANDLE;
|
|
- CheckStatus(vdp_st, __LINE__);
|
|
- }
|
|
-
|
|
- if (vdp_flip_target != VDP_INVALID_HANDLE)
|
|
- {
|
|
- vdp_st = vdp_presentation_queue_target_destroy(vdp_flip_target);
|
|
- vdp_flip_target = VDP_INVALID_HANDLE;
|
|
- CheckStatus(vdp_st, __LINE__);
|
|
- }
|
|
-
|
|
- if (m_glPixmap)
|
|
- {
|
|
- CLog::Log(LOGDEBUG, "GLX: Destroying glPixmap");
|
|
- glXDestroyPixmap(m_Display, m_glPixmap);
|
|
- m_glPixmap = None;
|
|
- }
|
|
-
|
|
- if (m_Pixmap)
|
|
- {
|
|
- CLog::Log(LOGDEBUG, "GLX: Destroying XPixmap");
|
|
- XFreePixmap(m_Display, m_Pixmap);
|
|
- m_Pixmap = None;
|
|
- }
|
|
-
|
|
- outputSurface = presentSurface = VDP_INVALID_HANDLE;
|
|
-
|
|
- for (int i = 0; i < totalAvailableOutputSurfaces; i++)
|
|
- {
|
|
- if (outputSurfaces[i] == VDP_INVALID_HANDLE)
|
|
- continue;
|
|
- vdp_st = vdp_output_surface_destroy(outputSurfaces[i]);
|
|
- outputSurfaces[i] = VDP_INVALID_HANDLE;
|
|
- CheckStatus(vdp_st, __LINE__);
|
|
- }
|
|
-
|
|
- if (videoMixer != VDP_INVALID_HANDLE)
|
|
- {
|
|
- vdp_st = vdp_video_mixer_destroy(videoMixer);
|
|
- videoMixer = VDP_INVALID_HANDLE;
|
|
- CheckStatus(vdp_st, __LINE__);
|
|
+ }
|
|
}
|
|
-
|
|
- if (m_BlackBar)
|
|
+ else
|
|
{
|
|
- delete [] m_BlackBar;
|
|
- m_BlackBar = NULL;
|
|
+ CLog::Log(LOGERROR, "VDPAU::%s - failed to init output", __FUNCTION__);
|
|
+ m_vdpauOutput.Dispose();
|
|
+ return false;
|
|
}
|
|
|
|
- while (!m_DVDVideoPics.empty())
|
|
- m_DVDVideoPics.pop();
|
|
-
|
|
+ m_inMsgEvent.Reset();
|
|
+ m_vdpauConfigured = true;
|
|
return true;
|
|
}
|
|
|
|
-void CVDPAU::SpewHardwareAvailable() //Copyright (c) 2008 Wladimir J. van der Laan -- VDPInfo
|
|
+void CDecoder::SpewHardwareAvailable() //CopyrighVDPAUt (c) 2008 Wladimir J. van der Laan -- VDPInfo
|
|
{
|
|
VdpStatus rv;
|
|
CLog::Log(LOGNOTICE,"VDPAU Decoder capabilities:");
|
|
@@ -1102,7 +631,7 @@ void CVDPAU::SpewHardwareAvailable() //Copyright (c) 2008 Wladimir J. van der L
|
|
{
|
|
VdpBool is_supported = false;
|
|
uint32_t max_level, max_macroblocks, max_width, max_height;
|
|
- rv = vdp_decoder_query_caps(vdp_device, decoder_profiles[x].id,
|
|
+ rv = m_vdpauConfig.vdpProcs.vdp_decoder_query_caps(m_vdpauConfig.vdpDevice, decoder_profiles[x].id,
|
|
&is_supported, &max_level, &max_macroblocks, &max_width, &max_height);
|
|
if(rv == VDP_STATUS_OK && is_supported)
|
|
{
|
|
@@ -1111,13 +640,13 @@ void CVDPAU::SpewHardwareAvailable() //Copyright (c) 2008 Wladimir J. van der L
|
|
}
|
|
}
|
|
CLog::Log(LOGNOTICE,"------------------------------------");
|
|
- m_feature_count = 0;
|
|
+ m_vdpauConfig.featureCount = 0;
|
|
#define CHECK_SUPPORT(feature) \
|
|
do { \
|
|
VdpBool supported; \
|
|
- if(vdp_video_mixer_query_feature_support(vdp_device, feature, &supported) == VDP_STATUS_OK && supported) { \
|
|
+ if(m_vdpauConfig.vdpProcs.vdp_video_mixer_query_feature_support(m_vdpauConfig.vdpDevice, feature, &supported) == VDP_STATUS_OK && supported) { \
|
|
CLog::Log(LOGNOTICE, "Mixer feature: "#feature); \
|
|
- m_features[m_feature_count++] = feature; \
|
|
+ m_vdpauConfig.vdpFeatures[m_vdpauConfig.featureCount++] = feature; \
|
|
} \
|
|
} while(false)
|
|
|
|
@@ -1141,7 +670,7 @@ void CVDPAU::SpewHardwareAvailable() //Copyright (c) 2008 Wladimir J. van der L
|
|
|
|
}
|
|
|
|
-bool CVDPAU::IsSurfaceValid(vdpau_render_state *render)
|
|
+bool CDecoder::IsSurfaceValid(vdpau_render_state *render)
|
|
{
|
|
// find render state in queue
|
|
bool found(false);
|
|
@@ -1168,34 +697,33 @@ bool CVDPAU::IsSurfaceValid(vdpau_render_state *render)
|
|
return true;
|
|
}
|
|
|
|
-int CVDPAU::FFGetBuffer(AVCodecContext *avctx, AVFrame *pic)
|
|
+int CDecoder::FFGetBuffer(AVCodecContext *avctx, AVFrame *pic)
|
|
{
|
|
//CLog::Log(LOGNOTICE,"%s",__FUNCTION__);
|
|
CDVDVideoCodecFFmpeg* ctx = (CDVDVideoCodecFFmpeg*)avctx->opaque;
|
|
- CVDPAU* vdp = (CVDPAU*)ctx->GetHardware();
|
|
- struct pictureAge* pA = &vdp->picAge;
|
|
+ CDecoder* vdp = (CDecoder*)ctx->GetHardware();
|
|
|
|
// while we are waiting to recover we can't do anything
|
|
- CSharedLock lock(vdp->m_DecoderSection);
|
|
+ CSingleLock lock(vdp->m_DecoderSection);
|
|
|
|
- { CSharedLock dLock(vdp->m_DisplaySection);
|
|
- if(vdp->m_DisplayState != VDPAU_OPEN)
|
|
- {
|
|
- CLog::Log(LOGWARNING, "CVDPAU::FFGetBuffer - returning due to awaiting recovery");
|
|
- return -1;
|
|
- }
|
|
+ if(vdp->m_DisplayState != VDPAU_OPEN)
|
|
+ {
|
|
+ CLog::Log(LOGWARNING, "CVDPAU::FFGetBuffer - returning due to awaiting recovery");
|
|
+ return -1;
|
|
}
|
|
|
|
vdpau_render_state * render = NULL;
|
|
|
|
// find unused surface
|
|
- for(unsigned int i = 0; i < vdp->m_videoSurfaces.size(); i++)
|
|
- {
|
|
- if(!(vdp->m_videoSurfaces[i]->state & (FF_VDPAU_STATE_USED_FOR_REFERENCE | FF_VDPAU_STATE_USED_FOR_RENDER)))
|
|
+ { CSingleLock lock(vdp->m_videoSurfaceSec);
|
|
+ for(unsigned int i = 0; i < vdp->m_videoSurfaces.size(); i++)
|
|
{
|
|
- render = vdp->m_videoSurfaces[i];
|
|
- render->state = 0;
|
|
- break;
|
|
+ if(!(vdp->m_videoSurfaces[i]->state & (FF_VDPAU_STATE_USED_FOR_REFERENCE | FF_VDPAU_STATE_USED_FOR_RENDER)))
|
|
+ {
|
|
+ render = vdp->m_videoSurfaces[i];
|
|
+ render->state = 0;
|
|
+ break;
|
|
+ }
|
|
}
|
|
}
|
|
|
|
@@ -1204,21 +732,22 @@ int CVDPAU::FFGetBuffer(AVCodecContext *avctx, AVFrame *pic)
|
|
{
|
|
// create a new surface
|
|
VdpDecoderProfile profile;
|
|
- ReadFormatOf(avctx->pix_fmt, profile, vdp->vdp_chroma_type);
|
|
+ ReadFormatOf(avctx->pix_fmt, profile, vdp->m_vdpauConfig.vdpChromaType);
|
|
render = (vdpau_render_state*)calloc(sizeof(vdpau_render_state), 1);
|
|
if (render == NULL)
|
|
{
|
|
CLog::Log(LOGWARNING, "CVDPAU::FFGetBuffer - calloc failed");
|
|
return -1;
|
|
}
|
|
+ CSingleLock lock(vdp->m_videoSurfaceSec);
|
|
render->surface = VDP_INVALID_HANDLE;
|
|
vdp->m_videoSurfaces.push_back(render);
|
|
}
|
|
|
|
if (render->surface == VDP_INVALID_HANDLE)
|
|
{
|
|
- vdp_st = vdp->vdp_video_surface_create(vdp->vdp_device,
|
|
- vdp->vdp_chroma_type,
|
|
+ vdp_st = vdp->m_vdpauConfig.vdpProcs.vdp_video_surface_create(vdp->m_vdpauConfig.vdpDevice,
|
|
+ vdp->m_vdpauConfig.vdpChromaType,
|
|
avctx->coded_width,
|
|
avctx->coded_height,
|
|
&render->surface);
|
|
@@ -1239,18 +768,6 @@ int CVDPAU::FFGetBuffer(AVCodecContext *avctx, AVFrame *pic)
|
|
|
|
pic->linesize[0] = pic->linesize[1] = pic->linesize[2] = 0;
|
|
|
|
- if(pic->reference)
|
|
- {
|
|
- pA->ip_age[0]= pA->ip_age[1]+1;
|
|
- pA->ip_age[1]= 1;
|
|
- pA->b_age++;
|
|
- }
|
|
- else
|
|
- {
|
|
- pA->ip_age[0]++;
|
|
- pA->ip_age[1]++;
|
|
- pA->b_age = 1;
|
|
- }
|
|
pic->type= FF_BUFFER_TYPE_USER;
|
|
|
|
render->state |= FF_VDPAU_STATE_USED_FOR_REFERENCE;
|
|
@@ -1258,15 +775,16 @@ int CVDPAU::FFGetBuffer(AVCodecContext *avctx, AVFrame *pic)
|
|
return 0;
|
|
}
|
|
|
|
-void CVDPAU::FFReleaseBuffer(AVCodecContext *avctx, AVFrame *pic)
|
|
+void CDecoder::FFReleaseBuffer(AVCodecContext *avctx, AVFrame *pic)
|
|
{
|
|
//CLog::Log(LOGNOTICE,"%s",__FUNCTION__);
|
|
CDVDVideoCodecFFmpeg* ctx = (CDVDVideoCodecFFmpeg*)avctx->opaque;
|
|
- CVDPAU* vdp = (CVDPAU*)ctx->GetHardware();
|
|
+ CDecoder* vdp = (CDecoder*)ctx->GetHardware();
|
|
+
|
|
vdpau_render_state * render;
|
|
unsigned int i;
|
|
|
|
- CSharedLock lock(vdp->m_DecoderSection);
|
|
+ CSingleLock lock(vdp->m_DecoderSection);
|
|
|
|
render=(vdpau_render_state*)pic->data[0];
|
|
if(!render)
|
|
@@ -1275,6 +793,8 @@ void CVDPAU::FFReleaseBuffer(AVCodecContext *avctx, AVFrame *pic)
|
|
return;
|
|
}
|
|
|
|
+ CSingleLock vLock(vdp->m_videoSurfaceSec);
|
|
+ render->state &= ~FF_VDPAU_STATE_USED_FOR_REFERENCE;
|
|
for(i=0; i<4; i++)
|
|
pic->data[i]= NULL;
|
|
|
|
@@ -1289,21 +809,18 @@ void CVDPAU::FFReleaseBuffer(AVCodecContext *avctx, AVFrame *pic)
|
|
}
|
|
|
|
|
|
-void CVDPAU::FFDrawSlice(struct AVCodecContext *s,
|
|
+void CDecoder::FFDrawSlice(struct AVCodecContext *s,
|
|
const AVFrame *src, int offset[4],
|
|
int y, int type, int height)
|
|
{
|
|
CDVDVideoCodecFFmpeg* ctx = (CDVDVideoCodecFFmpeg*)s->opaque;
|
|
- CVDPAU* vdp = (CVDPAU*)ctx->GetHardware();
|
|
+ CDecoder* vdp = (CDecoder*)ctx->GetHardware();
|
|
|
|
// while we are waiting to recover we can't do anything
|
|
- CSharedLock lock(vdp->m_DecoderSection);
|
|
-
|
|
- { CSharedLock dLock(vdp->m_DisplaySection);
|
|
- if(vdp->m_DisplayState != VDPAU_OPEN)
|
|
- return;
|
|
- }
|
|
+ CSingleLock lock(vdp->m_DecoderSection);
|
|
|
|
+ if(vdp->m_DisplayState != VDPAU_OPEN)
|
|
+ return;
|
|
|
|
if(src->linesize[0] || src->linesize[1] || src->linesize[2]
|
|
|| offset[0] || offset[1] || offset[2])
|
|
@@ -1333,59 +850,41 @@ void CVDPAU::FFDrawSlice(struct AVCodecContext *s,
|
|
if(s->pix_fmt == PIX_FMT_VDPAU_H264)
|
|
max_refs = render->info.h264.num_ref_frames;
|
|
|
|
- if(vdp->decoder == VDP_INVALID_HANDLE
|
|
- || vdp->vdpauConfigured == false
|
|
- || vdp->max_references < max_refs)
|
|
+ if(vdp->m_vdpauConfig.vdpDecoder == VDP_INVALID_HANDLE
|
|
+ || vdp->m_vdpauConfigured == false
|
|
+ || vdp->m_vdpauConfig.maxReferences < max_refs)
|
|
{
|
|
if(!vdp->ConfigVDPAU(s, max_refs))
|
|
return;
|
|
}
|
|
|
|
- vdp_st = vdp->vdp_decoder_render(vdp->decoder,
|
|
+ uint64_t startTime = CurrentHostCounter();
|
|
+ uint16_t decoded, processed, rend;
|
|
+ vdp->m_bufferStats.Get(decoded, processed, rend);
|
|
+ vdp_st = vdp->m_vdpauConfig.vdpProcs.vdp_decoder_render(vdp->m_vdpauConfig.vdpDecoder,
|
|
render->surface,
|
|
(VdpPictureInfo const *)&(render->info),
|
|
render->bitstream_buffers_used,
|
|
render->bitstream_buffers);
|
|
vdp->CheckStatus(vdp_st, __LINE__);
|
|
+ uint64_t diff = CurrentHostCounter() - startTime;
|
|
+ if (diff*1000/CurrentHostFrequency() > 30)
|
|
+ CLog::Log(LOGWARNING,"CVDPAU::DrawSlice - VdpDecoderRender long decoding: %d ms, dec: %d, proc: %d, rend: %d", (int)((diff*1000)/CurrentHostFrequency()), decoded, processed, rend);
|
|
+
|
|
}
|
|
|
|
-int CVDPAU::Decode(AVCodecContext *avctx, AVFrame *pFrame)
|
|
-{
|
|
- //CLog::Log(LOGNOTICE,"%s",__FUNCTION__);
|
|
- VdpStatus vdp_st;
|
|
- VdpTime time;
|
|
|
|
+int CDecoder::Decode(AVCodecContext *avctx, AVFrame *pFrame)
|
|
+{
|
|
int result = Check(avctx);
|
|
if (result)
|
|
return result;
|
|
|
|
- CSharedLock lock(m_DecoderSection);
|
|
+ CSingleLock lock(m_DecoderSection);
|
|
|
|
- if (!vdpauConfigured)
|
|
+ if (!m_vdpauConfigured)
|
|
return VC_ERROR;
|
|
|
|
- // configure vdpau output
|
|
- if (!ConfigOutputMethod(avctx, pFrame))
|
|
- return VC_FLUSHED;
|
|
-
|
|
- outputSurface = outputSurfaces[surfaceNum];
|
|
-
|
|
- CheckFeatures();
|
|
-
|
|
- if (( (int)outRectVid.x1 != OutWidth ) ||
|
|
- ( (int)outRectVid.y1 != OutHeight ))
|
|
- {
|
|
- outRectVid.x0 = 0;
|
|
- outRectVid.y0 = 0;
|
|
- outRectVid.x1 = OutWidth;
|
|
- outRectVid.y1 = OutHeight;
|
|
- }
|
|
-
|
|
- EDEINTERLACEMODE mode = g_settings.m_currentVideoSettings.m_DeinterlaceMode;
|
|
- EINTERLACEMETHOD method = g_settings.m_currentVideoSettings.m_InterlaceMethod;
|
|
- if (method == VS_INTERLACEMETHOD_AUTO)
|
|
- method = AutoInterlaceMethod();
|
|
-
|
|
if(pFrame)
|
|
{ // we have a new frame from decoder
|
|
|
|
@@ -1393,7 +892,10 @@ int CVDPAU::Decode(AVCodecContext *avctx, AVFrame *pFrame)
|
|
if(!render) // old style ffmpeg gave data on plane 0
|
|
render = (vdpau_render_state*)pFrame->data[0];
|
|
if(!render)
|
|
+ {
|
|
+ CLog::Log(LOGERROR, "CVDPAU::Decode: no valid frame");
|
|
return VC_ERROR;
|
|
+ }
|
|
|
|
// ffmpeg vc-1 decoder does not flush, make sure the data buffer is still valid
|
|
if (!IsSurfaceValid(render))
|
|
@@ -1402,258 +904,166 @@ int CVDPAU::Decode(AVCodecContext *avctx, AVFrame *pFrame)
|
|
return VC_BUFFER;
|
|
}
|
|
|
|
+ CSingleLock lock(m_videoSurfaceSec);
|
|
render->state |= FF_VDPAU_STATE_USED_FOR_RENDER;
|
|
+ lock.Leave();
|
|
|
|
- ClearUsedForRender(&past[0]);
|
|
- past[0] = past[1];
|
|
- past[1] = current;
|
|
- current = future;
|
|
- future = render;
|
|
+ // send frame to output for processing
|
|
+ CVdpauDecodedPicture pic;
|
|
+ memset(&pic.DVDPic, 0, sizeof(pic.DVDPic));
|
|
+ ((CDVDVideoCodecFFmpeg*)avctx->opaque)->GetPictureCommon(&pic.DVDPic);
|
|
+ pic.render = render;
|
|
+ m_bufferStats.IncDecoded();
|
|
+ m_vdpauOutput.m_dataPort.SendOutMessage(COutputDataProtocol::NEWFRAME, &pic, sizeof(pic));
|
|
|
|
- DVDVideoPicture DVDPic;
|
|
- memset(&DVDPic, 0, sizeof(DVDVideoPicture));
|
|
- ((CDVDVideoCodecFFmpeg*)avctx->opaque)->GetPictureCommon(&DVDPic);
|
|
- m_DVDVideoPics.push(DVDPic);
|
|
+ m_codecControl = pic.DVDPic.iFlags & (DVP_FLAG_DRAIN | DVP_FLAG_NO_POSTPROC);
|
|
+ }
|
|
|
|
- int pics = m_DVDVideoPics.size();
|
|
- if (pics < 2)
|
|
- return VC_BUFFER;
|
|
- else if (pics > 2)
|
|
+ int retval = 0;
|
|
+ uint16_t decoded, processed, render;
|
|
+ Message *msg;
|
|
+ while (m_vdpauOutput.m_controlPort.ReceiveInMessage(&msg))
|
|
+ {
|
|
+ if (msg->signal == COutputControlProtocol::ERROR)
|
|
{
|
|
- // this should not normally happen
|
|
- CLog::Log(LOGERROR, "CVDPAU::Decode - invalid number of pictures in queue");
|
|
- while (pics-- != 2)
|
|
- m_DVDVideoPics.pop();
|
|
+ m_DisplayState = VDPAU_ERROR;
|
|
+ retval |= VC_ERROR;
|
|
}
|
|
+ msg->Release();
|
|
+ }
|
|
|
|
- if (mode == VS_DEINTERLACEMODE_FORCE
|
|
- || (mode == VS_DEINTERLACEMODE_AUTO && m_DVDVideoPics.front().iFlags & DVP_FLAG_INTERLACED))
|
|
+ m_bufferStats.Get(decoded, processed, render);
|
|
+
|
|
+ uint64_t startTime = CurrentHostCounter();
|
|
+ while (!retval)
|
|
+ {
|
|
+ if (m_vdpauOutput.m_dataPort.ReceiveInMessage(&msg))
|
|
{
|
|
- if((method == VS_INTERLACEMETHOD_AUTO_ION
|
|
- || method == VS_INTERLACEMETHOD_VDPAU_BOB
|
|
- || method == VS_INTERLACEMETHOD_VDPAU_TEMPORAL
|
|
- || method == VS_INTERLACEMETHOD_VDPAU_TEMPORAL_HALF
|
|
- || method == VS_INTERLACEMETHOD_VDPAU_TEMPORAL_SPATIAL
|
|
- || method == VS_INTERLACEMETHOD_VDPAU_TEMPORAL_SPATIAL_HALF
|
|
- || method == VS_INTERLACEMETHOD_VDPAU_INVERSE_TELECINE ))
|
|
+ if (msg->signal == COutputDataProtocol::PICTURE)
|
|
{
|
|
- if((method == VS_INTERLACEMETHOD_AUTO_ION && vid_height > 576)
|
|
- || method == VS_INTERLACEMETHOD_VDPAU_TEMPORAL_HALF
|
|
- || method == VS_INTERLACEMETHOD_VDPAU_TEMPORAL_SPATIAL_HALF
|
|
- || avctx->skip_frame == AVDISCARD_NONREF)
|
|
- m_mixerstep = 0;
|
|
- else
|
|
- m_mixerstep = 1;
|
|
-
|
|
- if(m_DVDVideoPics.front().iFlags & DVP_FLAG_TOP_FIELD_FIRST)
|
|
- m_mixerfield = VDP_VIDEO_MIXER_PICTURE_STRUCTURE_TOP_FIELD;
|
|
- else
|
|
- m_mixerfield = VDP_VIDEO_MIXER_PICTURE_STRUCTURE_BOTTOM_FIELD;
|
|
+ if (m_presentPicture)
|
|
+ {
|
|
+ m_presentPicture->ReturnUnused();
|
|
+ m_presentPicture = 0;
|
|
+ }
|
|
+
|
|
+ m_presentPicture = *(CVdpauRenderPicture**)msg->data;
|
|
+ m_presentPicture->vdpau = this;
|
|
+ m_bufferStats.DecRender();
|
|
+ m_bufferStats.Get(decoded, processed, render);
|
|
+ retval |= VC_PICTURE;
|
|
+ msg->Release();
|
|
+ break;
|
|
+ }
|
|
+ msg->Release();
|
|
+ }
|
|
+ else if (m_vdpauOutput.m_controlPort.ReceiveInMessage(&msg))
|
|
+ {
|
|
+ if (msg->signal == COutputControlProtocol::STATS)
|
|
+ {
|
|
+ m_bufferStats.Get(decoded, processed, render);
|
|
}
|
|
else
|
|
{
|
|
- m_mixerstep = 0;
|
|
- m_mixerfield = VDP_VIDEO_MIXER_PICTURE_STRUCTURE_FRAME;
|
|
+ m_DisplayState = VDPAU_ERROR;
|
|
+ retval |= VC_ERROR;
|
|
}
|
|
+ msg->Release();
|
|
}
|
|
- else
|
|
+
|
|
+ if ((m_codecControl & DVP_FLAG_DRAIN))
|
|
{
|
|
- m_mixerstep = 0;
|
|
- m_mixerfield = VDP_VIDEO_MIXER_PICTURE_STRUCTURE_FRAME;
|
|
+ if (decoded + processed + render < 4)
|
|
+ {
|
|
+ retval |= VC_BUFFER;
|
|
+ }
|
|
}
|
|
-
|
|
- }
|
|
- else if(m_mixerstep == 1)
|
|
- { // no new frame given, output second field of old frame
|
|
-
|
|
- if(avctx->skip_frame == AVDISCARD_NONREF)
|
|
+ else
|
|
{
|
|
- ClearUsedForRender(&past[1]);
|
|
- m_DVDVideoPics.pop();
|
|
- return VC_BUFFER;
|
|
+ if (decoded < 4 && (processed + render) < 3)
|
|
+ {
|
|
+ retval |= VC_BUFFER;
|
|
+ }
|
|
}
|
|
|
|
- m_mixerstep = 2;
|
|
- if(m_mixerfield == VDP_VIDEO_MIXER_PICTURE_STRUCTURE_TOP_FIELD)
|
|
- m_mixerfield = VDP_VIDEO_MIXER_PICTURE_STRUCTURE_BOTTOM_FIELD;
|
|
- else
|
|
- m_mixerfield = VDP_VIDEO_MIXER_PICTURE_STRUCTURE_TOP_FIELD;
|
|
+ if (!retval && !m_inMsgEvent.WaitMSec(2000))
|
|
+ break;
|
|
}
|
|
- else
|
|
+ uint64_t diff = CurrentHostCounter() - startTime;
|
|
+ if (retval & VC_PICTURE)
|
|
{
|
|
- CLog::Log(LOGERROR, "CVDPAU::Decode - invalid mixer state reached");
|
|
- return VC_BUFFER;
|
|
+ m_bufferStats.SetParams(diff, m_codecControl);
|
|
}
|
|
+ if (diff*1000/CurrentHostFrequency() > 50)
|
|
+ CLog::Log(LOGDEBUG,"CVDPAU::Decode long wait: %d", (int)((diff*1000)/CurrentHostFrequency()));
|
|
|
|
- VdpVideoSurface past_surfaces[2] = { VDP_INVALID_HANDLE, VDP_INVALID_HANDLE };
|
|
- VdpVideoSurface futu_surfaces[1] = { VDP_INVALID_HANDLE };
|
|
-
|
|
- if(m_mixerfield == VDP_VIDEO_MIXER_PICTURE_STRUCTURE_FRAME)
|
|
+ if (!retval)
|
|
{
|
|
- if (past[0])
|
|
- past_surfaces[1] = past[0]->surface;
|
|
- if (past[1])
|
|
- past_surfaces[0] = past[1]->surface;
|
|
- futu_surfaces[0] = future->surface;
|
|
+ CLog::Log(LOGERROR, "VDPAU::%s - timed out waiting for output message", __FUNCTION__);
|
|
+ m_DisplayState = VDPAU_ERROR;
|
|
+ retval |= VC_ERROR;
|
|
}
|
|
- else
|
|
- {
|
|
- if(m_mixerstep == 1)
|
|
- { // first field
|
|
- if (past[1])
|
|
- {
|
|
- past_surfaces[1] = past[1]->surface;
|
|
- past_surfaces[0] = past[1]->surface;
|
|
- }
|
|
- futu_surfaces[0] = current->surface;
|
|
- }
|
|
- else
|
|
- { // second field
|
|
- if (past[1])
|
|
- past_surfaces[1] = past[1]->surface;
|
|
- past_surfaces[0] = current->surface;
|
|
- futu_surfaces[0] = future->surface;
|
|
- }
|
|
- }
|
|
-
|
|
- vdp_st = vdp_presentation_queue_block_until_surface_idle(vdp_flip_queue,outputSurface,&time);
|
|
-
|
|
- VdpRect sourceRect = {0,0,vid_width, vid_height};
|
|
-
|
|
- vdp_st = vdp_video_mixer_render(videoMixer,
|
|
- VDP_INVALID_HANDLE,
|
|
- 0,
|
|
- m_mixerfield,
|
|
- 2,
|
|
- past_surfaces,
|
|
- current->surface,
|
|
- 1,
|
|
- futu_surfaces,
|
|
- &sourceRect,
|
|
- outputSurface,
|
|
- &(outRectVid),
|
|
- &(outRectVid),
|
|
- 0,
|
|
- NULL);
|
|
- CheckStatus(vdp_st, __LINE__);
|
|
|
|
- surfaceNum++;
|
|
- if (surfaceNum >= totalAvailableOutputSurfaces) surfaceNum = 0;
|
|
+ return retval;
|
|
+}
|
|
|
|
- if(m_mixerfield == VDP_VIDEO_MIXER_PICTURE_STRUCTURE_FRAME)
|
|
- {
|
|
- ClearUsedForRender(&past[0]);
|
|
- return VC_BUFFER | VC_PICTURE;
|
|
- }
|
|
- else
|
|
- {
|
|
- // in order to clip top and bottom lines when de-interlacing
|
|
- // we black those lines as a work around for not working
|
|
- // background colour using the mixer
|
|
- // pixel perfect is preferred over overscanning or zooming
|
|
+bool CDecoder::GetPicture(AVCodecContext* avctx, AVFrame* frame, DVDVideoPicture* picture)
|
|
+{
|
|
+ CSingleLock lock(m_DecoderSection);
|
|
|
|
- VdpRect clipRect = outRectVid;
|
|
- clipRect.y1 = clipRect.y0 + 2;
|
|
- uint32_t *data[] = {m_BlackBar};
|
|
- uint32_t pitches[] = {outRectVid.x1};
|
|
- vdp_st = vdp_output_surface_put_bits_native(outputSurface,
|
|
- (void**)data,
|
|
- pitches,
|
|
- &clipRect);
|
|
- CheckStatus(vdp_st, __LINE__);
|
|
+ if (m_DisplayState != VDPAU_OPEN)
|
|
+ return false;
|
|
|
|
- clipRect = outRectVid;
|
|
- clipRect.y0 = clipRect.y1 - 2;
|
|
- vdp_st = vdp_output_surface_put_bits_native(outputSurface,
|
|
- (void**)data,
|
|
- pitches,
|
|
- &clipRect);
|
|
- CheckStatus(vdp_st, __LINE__);
|
|
+ *picture = m_presentPicture->DVDPic;
|
|
+ picture->vdpau = m_presentPicture;
|
|
|
|
- if(m_mixerstep == 1)
|
|
- return VC_PICTURE;
|
|
- else
|
|
- {
|
|
- ClearUsedForRender(&past[1]);
|
|
- return VC_BUFFER | VC_PICTURE;
|
|
- }
|
|
- }
|
|
+ return true;
|
|
}
|
|
|
|
-bool CVDPAU::GetPicture(AVCodecContext* avctx, AVFrame* frame, DVDVideoPicture* picture)
|
|
+void CDecoder::Reset()
|
|
{
|
|
- CSharedLock lock(m_DecoderSection);
|
|
-
|
|
- { CSharedLock dLock(m_DisplaySection);
|
|
- if (m_DisplayState != VDPAU_OPEN)
|
|
- return false;
|
|
- }
|
|
-
|
|
- *picture = m_DVDVideoPics.front();
|
|
- // if this is the first field of an interlaced frame, we'll need
|
|
- // this same picture for the second field later
|
|
- if (m_mixerstep != 1)
|
|
- m_DVDVideoPics.pop();
|
|
+ CSingleLock lock(m_DecoderSection);
|
|
|
|
- picture->format = RENDER_FMT_VDPAU;
|
|
- picture->iFlags &= DVP_FLAG_DROPPED;
|
|
- picture->iWidth = OutWidth;
|
|
- picture->iHeight = OutHeight;
|
|
- picture->vdpau = this;
|
|
+ if (!m_vdpauConfigured)
|
|
+ return;
|
|
|
|
- if(m_mixerstep)
|
|
+ Message *reply;
|
|
+ if (m_vdpauOutput.m_controlPort.SendOutMessageSync(COutputControlProtocol::FLUSH,
|
|
+ &reply,
|
|
+ 2000))
|
|
{
|
|
- picture->iRepeatPicture = -0.5;
|
|
- if(m_mixerstep > 1)
|
|
+ bool success = reply->signal == COutputControlProtocol::ACC ? true : false;
|
|
+ reply->Release();
|
|
+ if (!success)
|
|
{
|
|
- picture->dts = DVD_NOPTS_VALUE;
|
|
- picture->pts = DVD_NOPTS_VALUE;
|
|
+ CLog::Log(LOGERROR, "VDPAU::%s - flush returned error", __FUNCTION__);
|
|
+ m_DisplayState = VDPAU_ERROR;
|
|
}
|
|
+ else
|
|
+ m_bufferStats.Reset();
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ CLog::Log(LOGERROR, "VDPAU::%s - flush timed out", __FUNCTION__);
|
|
+ m_DisplayState = VDPAU_ERROR;
|
|
}
|
|
- return true;
|
|
}
|
|
|
|
-void CVDPAU::Reset()
|
|
+bool CDecoder::CanSkipDeint()
|
|
{
|
|
- // invalidate surfaces and picture queue when seeking
|
|
- ClearUsedForRender(&past[0]);
|
|
- ClearUsedForRender(&past[1]);
|
|
- ClearUsedForRender(¤t);
|
|
- ClearUsedForRender(&future);
|
|
-
|
|
- while (!m_DVDVideoPics.empty())
|
|
- m_DVDVideoPics.pop();
|
|
+ return m_bufferStats.CanSkipDeint();
|
|
}
|
|
|
|
-void CVDPAU::Present()
|
|
+void CDecoder::ReturnRenderPicture(CVdpauRenderPicture *renderPic)
|
|
{
|
|
- //CLog::Log(LOGNOTICE,"%s",__FUNCTION__);
|
|
- VdpStatus vdp_st;
|
|
-
|
|
- CSharedLock lock(m_DecoderSection);
|
|
-
|
|
- { CSharedLock dLock(m_DisplaySection);
|
|
- if (m_DisplayState != VDPAU_OPEN)
|
|
- return;
|
|
- }
|
|
-
|
|
- presentSurface = outputSurface;
|
|
-
|
|
- vdp_st = vdp_presentation_queue_display(vdp_flip_queue,
|
|
- presentSurface,
|
|
- 0,
|
|
- 0,
|
|
- 0);
|
|
- CheckStatus(vdp_st, __LINE__);
|
|
+ m_vdpauOutput.m_dataPort.SendOutMessage(COutputDataProtocol::RETURNPIC, &renderPic, sizeof(renderPic));
|
|
}
|
|
|
|
-bool CVDPAU::CheckStatus(VdpStatus vdp_st, int line)
|
|
+bool CDecoder::CheckStatus(VdpStatus vdp_st, int line)
|
|
{
|
|
if (vdp_st != VDP_STATUS_OK)
|
|
{
|
|
- CLog::Log(LOGERROR, " (VDPAU) Error: %s(%d) at %s:%d\n", vdp_get_error_string(vdp_st), vdp_st, __FILE__, line);
|
|
-
|
|
- CExclusiveLock lock(m_DisplaySection);
|
|
+ CLog::Log(LOGERROR, " (VDPAU) Error: %s(%d) at %s:%d\n", m_vdpauConfig.vdpProcs.vdp_get_error_string(vdp_st), vdp_st, __FILE__, line);
|
|
|
|
if(m_DisplayState == VDPAU_OPEN)
|
|
{
|
|
@@ -1671,4 +1081,2422 @@ bool CVDPAU::CheckStatus(VdpStatus vdp_st, int line)
|
|
return false;
|
|
}
|
|
|
|
+//-----------------------------------------------------------------------------
|
|
+// RenderPicture
|
|
+//-----------------------------------------------------------------------------
|
|
+
|
|
+CVdpauRenderPicture* CVdpauRenderPicture::Acquire()
|
|
+{
|
|
+ CSingleLock lock(*renderPicSection);
|
|
+
|
|
+ if (refCount == 0)
|
|
+ vdpau->Acquire();
|
|
+
|
|
+ refCount++;
|
|
+ return this;
|
|
+}
|
|
+
|
|
+long CVdpauRenderPicture::Release()
|
|
+{
|
|
+ CSingleLock lock(*renderPicSection);
|
|
+
|
|
+ refCount--;
|
|
+ if (refCount > 0)
|
|
+ return refCount;
|
|
+
|
|
+ lock.Leave();
|
|
+ vdpau->ReturnRenderPicture(this);
|
|
+ vdpau->ReleasePicReference();
|
|
+
|
|
+ return refCount;
|
|
+}
|
|
+
|
|
+void CVdpauRenderPicture::ReturnUnused()
|
|
+{
|
|
+ { CSingleLock lock(*renderPicSection);
|
|
+ if (refCount > 0)
|
|
+ return;
|
|
+ }
|
|
+ if (vdpau)
|
|
+ vdpau->ReturnRenderPicture(this);
|
|
+}
|
|
+//-----------------------------------------------------------------------------
|
|
+// Mixer
|
|
+//-----------------------------------------------------------------------------
|
|
+CMixer::CMixer(CEvent *inMsgEvent) :
|
|
+ CThread("Vdpau Mixer Thread"),
|
|
+ m_controlPort("ControlPort", inMsgEvent, &m_outMsgEvent),
|
|
+ m_dataPort("DataPort", inMsgEvent, &m_outMsgEvent)
|
|
+{
|
|
+ m_inMsgEvent = inMsgEvent;
|
|
+}
|
|
+
|
|
+CMixer::~CMixer()
|
|
+{
|
|
+ Dispose();
|
|
+}
|
|
+
|
|
+void CMixer::Start()
|
|
+{
|
|
+ Create();
|
|
+}
|
|
+
|
|
+void CMixer::Dispose()
|
|
+{
|
|
+ m_bStop = true;
|
|
+ m_outMsgEvent.Set();
|
|
+ StopThread();
|
|
+
|
|
+ m_controlPort.Purge();
|
|
+ m_dataPort.Purge();
|
|
+}
|
|
+
|
|
+void CMixer::OnStartup()
|
|
+{
|
|
+ CLog::Log(LOGNOTICE, "CMixer::OnStartup: Output Thread created");
|
|
+}
|
|
+
|
|
+void CMixer::OnExit()
|
|
+{
|
|
+ CLog::Log(LOGNOTICE, "CMixer::OnExit: Output Thread terminated");
|
|
+}
|
|
+
|
|
+enum MIXER_STATES
|
|
+{
|
|
+ M_TOP = 0, // 0
|
|
+ M_TOP_ERROR, // 1
|
|
+ M_TOP_UNCONFIGURED, // 2
|
|
+ M_TOP_CONFIGURED, // 3
|
|
+ M_TOP_CONFIGURED_WAIT1, // 4
|
|
+ M_TOP_CONFIGURED_STEP1, // 5
|
|
+ M_TOP_CONFIGURED_WAIT2, // 6
|
|
+ M_TOP_CONFIGURED_STEP2, // 7
|
|
+};
|
|
+
|
|
+int MIXER_parentStates[] = {
|
|
+ -1,
|
|
+ 0, //TOP_ERROR
|
|
+ 0, //TOP_UNCONFIGURED
|
|
+ 0, //TOP_CONFIGURED
|
|
+ 3, //TOP_CONFIGURED_WAIT1
|
|
+ 3, //TOP_CONFIGURED_STEP1
|
|
+ 3, //TOP_CONFIGURED_WAIT2
|
|
+ 3, //TOP_CONFIGURED_STEP2
|
|
+};
|
|
+
|
|
+void CMixer::StateMachine(int signal, Protocol *port, Message *msg)
|
|
+{
|
|
+ for (int state = m_state; ; state = MIXER_parentStates[state])
|
|
+ {
|
|
+ switch (state)
|
|
+ {
|
|
+ case M_TOP: // TOP
|
|
+ if (port == &m_controlPort)
|
|
+ {
|
|
+ switch (signal)
|
|
+ {
|
|
+ case CMixerControlProtocol::FLUSH:
|
|
+ Flush();
|
|
+ msg->Reply(CMixerControlProtocol::ACC);
|
|
+ return;
|
|
+ default:
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ {
|
|
+ std::string portName = port == NULL ? "timer" : port->portName;
|
|
+ CLog::Log(LOGWARNING, "CMixer::%s - signal: %d form port: %s not handled for state: %d", __FUNCTION__, signal, portName.c_str(), m_state);
|
|
+ }
|
|
+ return;
|
|
+
|
|
+ case M_TOP_ERROR: // TOP
|
|
+ break;
|
|
+
|
|
+ case M_TOP_UNCONFIGURED:
|
|
+ if (port == &m_controlPort)
|
|
+ {
|
|
+ switch (signal)
|
|
+ {
|
|
+ case CMixerControlProtocol::INIT:
|
|
+ CVdpauConfig *data;
|
|
+ data = (CVdpauConfig*)msg->data;
|
|
+ if (data)
|
|
+ {
|
|
+ m_config = *data;
|
|
+ }
|
|
+ Init();
|
|
+ if (!m_vdpError)
|
|
+ {
|
|
+ m_state = M_TOP_CONFIGURED_WAIT1;
|
|
+ msg->Reply(CMixerControlProtocol::ACC);
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ msg->Reply(CMixerControlProtocol::ERROR);
|
|
+ }
|
|
+ return;
|
|
+ default:
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ case M_TOP_CONFIGURED:
|
|
+ if (port == &m_dataPort)
|
|
+ {
|
|
+ switch (signal)
|
|
+ {
|
|
+ case CMixerDataProtocol::FRAME:
|
|
+ CVdpauDecodedPicture *frame;
|
|
+ frame = (CVdpauDecodedPicture*)msg->data;
|
|
+ if (frame)
|
|
+ {
|
|
+ m_decodedPics.push(*frame);
|
|
+ }
|
|
+ m_extTimeout = 0;
|
|
+ return;
|
|
+ case CMixerDataProtocol::BUFFER:
|
|
+ VdpOutputSurface *surf;
|
|
+ surf = (VdpOutputSurface*)msg->data;
|
|
+ if (surf)
|
|
+ {
|
|
+ m_outputSurfaces.push(*surf);
|
|
+ }
|
|
+ m_extTimeout = 0;
|
|
+ return;
|
|
+ default:
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ case M_TOP_CONFIGURED_WAIT1:
|
|
+ if (port == NULL) // timeout
|
|
+ {
|
|
+ switch (signal)
|
|
+ {
|
|
+ case CMixerControlProtocol::TIMEOUT:
|
|
+ if (!m_decodedPics.empty() && !m_outputSurfaces.empty())
|
|
+ {
|
|
+ m_state = M_TOP_CONFIGURED_STEP1;
|
|
+ m_bStateMachineSelfTrigger = true;
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+// if (m_extTimeout != 0)
|
|
+// {
|
|
+// SetPostProcFeatures(false);
|
|
+// CLog::Log(LOGWARNING,"CVDPAU::Mixer timeout - decoded: %d, outputSurf: %d", (int)m_decodedPics.size(), (int)m_outputSurfaces.size());
|
|
+// }
|
|
+ m_extTimeout = 100;
|
|
+ }
|
|
+ return;
|
|
+ default:
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ case M_TOP_CONFIGURED_STEP1:
|
|
+ if (port == NULL) // timeout
|
|
+ {
|
|
+ switch (signal)
|
|
+ {
|
|
+ case CMixerControlProtocol::TIMEOUT:
|
|
+ m_mixerInput.push_front(m_decodedPics.front());
|
|
+ m_decodedPics.pop();
|
|
+ if (m_mixerInput.size() < 2)
|
|
+ {
|
|
+ m_state = M_TOP_CONFIGURED_WAIT1;
|
|
+ m_extTimeout = 0;
|
|
+ return;
|
|
+ }
|
|
+ InitCycle();
|
|
+ ProcessPicture();
|
|
+ if (m_vdpError)
|
|
+ {
|
|
+ m_state = M_TOP_CONFIGURED_WAIT1;
|
|
+ m_extTimeout = 1000;
|
|
+ return;
|
|
+ }
|
|
+ if (m_processPicture.DVDPic.format != RENDER_FMT_VDPAU_420)
|
|
+ m_outputSurfaces.pop();
|
|
+ m_config.stats->IncProcessed();
|
|
+ m_config.stats->DecDecoded();
|
|
+ m_dataPort.SendInMessage(CMixerDataProtocol::PICTURE,&m_processPicture,sizeof(m_processPicture));
|
|
+ if (m_mixersteps > 1)
|
|
+ {
|
|
+ m_state = M_TOP_CONFIGURED_WAIT2;
|
|
+ m_extTimeout = 0;
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ FiniCycle();
|
|
+ m_state = M_TOP_CONFIGURED_WAIT1;
|
|
+ m_extTimeout = 0;
|
|
+ }
|
|
+ return;
|
|
+ default:
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ case M_TOP_CONFIGURED_WAIT2:
|
|
+ if (port == NULL) // timeout
|
|
+ {
|
|
+ switch (signal)
|
|
+ {
|
|
+ case CMixerControlProtocol::TIMEOUT:
|
|
+ if (!m_outputSurfaces.empty())
|
|
+ {
|
|
+ m_state = M_TOP_CONFIGURED_STEP2;
|
|
+ m_bStateMachineSelfTrigger = true;
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+// if (m_extTimeout != 0)
|
|
+// {
|
|
+// SetPostProcFeatures(false);
|
|
+// CLog::Log(LOGNOTICE,"---mixer wait2 decoded: %d, outputSurf: %d", (int)m_decodedPics.size(), (int)m_outputSurfaces.size());
|
|
+// }
|
|
+ m_extTimeout = 100;
|
|
+ }
|
|
+ return;
|
|
+ default:
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ case M_TOP_CONFIGURED_STEP2:
|
|
+ if (port == NULL) // timeout
|
|
+ {
|
|
+ switch (signal)
|
|
+ {
|
|
+ case CMixerControlProtocol::TIMEOUT:
|
|
+ m_processPicture.outputSurface = m_outputSurfaces.front();
|
|
+ m_mixerstep = 1;
|
|
+ ProcessPicture();
|
|
+ if (m_vdpError)
|
|
+ {
|
|
+ m_state = M_TOP_CONFIGURED_WAIT1;
|
|
+ m_extTimeout = 1000;
|
|
+ return;
|
|
+ }
|
|
+ if (m_processPicture.DVDPic.format != RENDER_FMT_VDPAU_420)
|
|
+ m_outputSurfaces.pop();
|
|
+ m_config.stats->IncProcessed();
|
|
+ m_dataPort.SendInMessage(CMixerDataProtocol::PICTURE,&m_processPicture,sizeof(m_processPicture));
|
|
+ FiniCycle();
|
|
+ m_state = M_TOP_CONFIGURED_WAIT1;
|
|
+ m_extTimeout = 0;
|
|
+ return;
|
|
+ default:
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ default: // we are in no state, should not happen
|
|
+ CLog::Log(LOGERROR, "CMixer::%s - no valid state: %d", __FUNCTION__, m_state);
|
|
+ return;
|
|
+ }
|
|
+ } // for
|
|
+}
|
|
+
|
|
+void CMixer::Process()
|
|
+{
|
|
+ Message *msg;
|
|
+ Protocol *port;
|
|
+ bool gotMsg;
|
|
+
|
|
+ m_state = M_TOP_UNCONFIGURED;
|
|
+ m_extTimeout = 1000;
|
|
+ m_bStateMachineSelfTrigger = false;
|
|
+
|
|
+ while (!m_bStop)
|
|
+ {
|
|
+ gotMsg = false;
|
|
+
|
|
+ if (m_bStateMachineSelfTrigger)
|
|
+ {
|
|
+ m_bStateMachineSelfTrigger = false;
|
|
+ // self trigger state machine
|
|
+ StateMachine(msg->signal, port, msg);
|
|
+ if (!m_bStateMachineSelfTrigger)
|
|
+ {
|
|
+ msg->Release();
|
|
+ msg = NULL;
|
|
+ }
|
|
+ continue;
|
|
+ }
|
|
+ // check control port
|
|
+ else if (m_controlPort.ReceiveOutMessage(&msg))
|
|
+ {
|
|
+ gotMsg = true;
|
|
+ port = &m_controlPort;
|
|
+ }
|
|
+ // check data port
|
|
+ else if (m_dataPort.ReceiveOutMessage(&msg))
|
|
+ {
|
|
+ gotMsg = true;
|
|
+ port = &m_dataPort;
|
|
+ }
|
|
+
|
|
+ if (gotMsg)
|
|
+ {
|
|
+ StateMachine(msg->signal, port, msg);
|
|
+ if (!m_bStateMachineSelfTrigger)
|
|
+ {
|
|
+ msg->Release();
|
|
+ msg = NULL;
|
|
+ }
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ // wait for message
|
|
+ else if (m_outMsgEvent.WaitMSec(m_extTimeout))
|
|
+ {
|
|
+ continue;
|
|
+ }
|
|
+ // time out
|
|
+ else
|
|
+ {
|
|
+ msg = m_controlPort.GetMessage();
|
|
+ msg->signal = CMixerControlProtocol::TIMEOUT;
|
|
+ port = 0;
|
|
+ // signal timeout to state machine
|
|
+ StateMachine(msg->signal, port, msg);
|
|
+ if (!m_bStateMachineSelfTrigger)
|
|
+ {
|
|
+ msg->Release();
|
|
+ msg = NULL;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ Uninit();
|
|
+}
|
|
+
|
|
+void CMixer::CreateVdpauMixer()
|
|
+{
|
|
+ CLog::Log(LOGNOTICE, " (VDPAU) Creating the video mixer");
|
|
+
|
|
+ InitCSCMatrix(m_config.vidWidth);
|
|
+
|
|
+ VdpVideoMixerParameter parameters[] = {
|
|
+ VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_WIDTH,
|
|
+ VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_HEIGHT,
|
|
+ VDP_VIDEO_MIXER_PARAMETER_CHROMA_TYPE};
|
|
+
|
|
+ void const * parameter_values[] = {
|
|
+ &m_config.surfaceWidth,
|
|
+ &m_config.surfaceHeight,
|
|
+ &m_config.vdpChromaType};
|
|
+
|
|
+ VdpStatus vdp_st = VDP_STATUS_ERROR;
|
|
+ vdp_st = m_config.vdpProcs.vdp_video_mixer_create(m_config.vdpDevice,
|
|
+ m_config.featureCount,
|
|
+ m_config.vdpFeatures,
|
|
+ ARSIZE(parameters),
|
|
+ parameters,
|
|
+ parameter_values,
|
|
+ &m_videoMixer);
|
|
+ CheckStatus(vdp_st, __LINE__);
|
|
+
|
|
+ // create 3 pitches of black lines needed for clipping top
|
|
+ // and bottom lines when de-interlacing
|
|
+ m_BlackBar = new uint32_t[3*m_config.outWidth];
|
|
+ memset(m_BlackBar, 0, 3*m_config.outWidth*sizeof(uint32_t));
|
|
+
|
|
+}
|
|
+
|
|
+void CMixer::InitCSCMatrix(int Width)
|
|
+{
|
|
+ VdpStatus vdp_st;
|
|
+ m_Procamp.struct_version = VDP_PROCAMP_VERSION;
|
|
+ m_Procamp.brightness = 0.0;
|
|
+ m_Procamp.contrast = 1.0;
|
|
+ m_Procamp.saturation = 1.0;
|
|
+ m_Procamp.hue = 0;
|
|
+ vdp_st = m_config.vdpProcs.vdp_generate_csc_matrix(&m_Procamp,
|
|
+ (Width < 1000)? VDP_COLOR_STANDARD_ITUR_BT_601 : VDP_COLOR_STANDARD_ITUR_BT_709,
|
|
+ &m_CSCMatrix);
|
|
+ CheckStatus(vdp_st, __LINE__);
|
|
+}
|
|
+
|
|
+void CMixer::CheckFeatures()
|
|
+{
|
|
+ if (m_Upscale != m_config.upscale)
|
|
+ {
|
|
+ SetHWUpscaling();
|
|
+ m_Upscale = m_config.upscale;
|
|
+ }
|
|
+ if (m_Brightness != g_settings.m_currentVideoSettings.m_Brightness ||
|
|
+ m_Contrast != g_settings.m_currentVideoSettings.m_Contrast)
|
|
+ {
|
|
+ SetColor();
|
|
+ m_Brightness = g_settings.m_currentVideoSettings.m_Brightness;
|
|
+ m_Contrast = g_settings.m_currentVideoSettings.m_Contrast;
|
|
+ }
|
|
+ if (m_NoiseReduction != g_settings.m_currentVideoSettings.m_NoiseReduction)
|
|
+ {
|
|
+ m_NoiseReduction = g_settings.m_currentVideoSettings.m_NoiseReduction;
|
|
+ SetNoiseReduction();
|
|
+ }
|
|
+ if (m_Sharpness != g_settings.m_currentVideoSettings.m_Sharpness)
|
|
+ {
|
|
+ m_Sharpness = g_settings.m_currentVideoSettings.m_Sharpness;
|
|
+ SetSharpness();
|
|
+ }
|
|
+ if (m_DeintMode != g_settings.m_currentVideoSettings.m_DeinterlaceMode ||
|
|
+ m_Deint != g_settings.m_currentVideoSettings.m_InterlaceMethod)
|
|
+ {
|
|
+ m_DeintMode = g_settings.m_currentVideoSettings.m_DeinterlaceMode;
|
|
+ m_Deint = g_settings.m_currentVideoSettings.m_InterlaceMethod;
|
|
+ SetDeinterlacing();
|
|
+ }
|
|
+}
|
|
+
|
|
+void CMixer::SetPostProcFeatures(bool postProcEnabled)
|
|
+{
|
|
+ if (m_PostProc != postProcEnabled)
|
|
+ {
|
|
+ if (postProcEnabled)
|
|
+ {
|
|
+ SetNoiseReduction();
|
|
+ SetSharpness();
|
|
+ SetDeinterlacing();
|
|
+ SetHWUpscaling();
|
|
+ }
|
|
+ else
|
|
+ PostProcOff();
|
|
+ m_PostProc = postProcEnabled;
|
|
+ }
|
|
+}
|
|
+
|
|
+void CMixer::PostProcOff()
|
|
+{
|
|
+ VdpStatus vdp_st;
|
|
+
|
|
+ if (m_videoMixer == VDP_INVALID_HANDLE)
|
|
+ return;
|
|
+
|
|
+ VdpVideoMixerFeature feature[] = { VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL,
|
|
+ VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL_SPATIAL,
|
|
+ VDP_VIDEO_MIXER_FEATURE_INVERSE_TELECINE};
|
|
+
|
|
+ VdpBool enabled[]={0,0,0};
|
|
+ vdp_st = m_config.vdpProcs.vdp_video_mixer_set_feature_enables(m_videoMixer, ARSIZE(feature), feature, enabled);
|
|
+ CheckStatus(vdp_st, __LINE__);
|
|
+
|
|
+ if(m_config.vdpau->Supports(VDP_VIDEO_MIXER_FEATURE_NOISE_REDUCTION))
|
|
+ {
|
|
+ VdpVideoMixerFeature feature[] = { VDP_VIDEO_MIXER_FEATURE_NOISE_REDUCTION};
|
|
+
|
|
+ VdpBool enabled[]={0};
|
|
+ vdp_st = m_config.vdpProcs.vdp_video_mixer_set_feature_enables(m_videoMixer, ARSIZE(feature), feature, enabled);
|
|
+ CheckStatus(vdp_st, __LINE__);
|
|
+ }
|
|
+
|
|
+ if(m_config.vdpau->Supports(VDP_VIDEO_MIXER_FEATURE_SHARPNESS))
|
|
+ {
|
|
+ VdpVideoMixerFeature feature[] = { VDP_VIDEO_MIXER_FEATURE_SHARPNESS};
|
|
+
|
|
+ VdpBool enabled[]={0};
|
|
+ vdp_st = m_config.vdpProcs.vdp_video_mixer_set_feature_enables(m_videoMixer, ARSIZE(feature), feature, enabled);
|
|
+ CheckStatus(vdp_st, __LINE__);
|
|
+ }
|
|
+
|
|
+ DisableHQScaling();
|
|
+}
|
|
+
|
|
+
|
|
+bool CMixer::GenerateStudioCSCMatrix(VdpColorStandard colorStandard, VdpCSCMatrix &studioCSCMatrix)
|
|
+{
|
|
+ // instead use studioCSCKCoeffs601[3], studioCSCKCoeffs709[3] to generate float[3][4] matrix (float studioCSC[3][4])
|
|
+ // m00 = mRY = red: luma factor (contrast factor) (1.0)
|
|
+ // m10 = mGY = green: luma factor (contrast factor) (1.0)
|
|
+ // m20 = mBY = blue: luma factor (contrast factor) (1.0)
|
|
+ //
|
|
+ // m01 = mRB = red: blue color diff coeff (0.0)
|
|
+ // m11 = mGB = green: blue color diff coeff (-2Kb(1-Kb)/(Kg))
|
|
+ // m21 = mBB = blue: blue color diff coeff ((1-Kb)/0.5)
|
|
+ //
|
|
+ // m02 = mRR = red: red color diff coeff ((1-Kr)/0.5)
|
|
+ // m12 = mGR = green: red color diff coeff (-2Kr(1-Kr)/(Kg))
|
|
+ // m22 = mBR = blue: red color diff coeff (0.0)
|
|
+ //
|
|
+ // m03 = mRC = red: colour zero offset (brightness factor) (-(1-Kr)/0.5 * (128/255))
|
|
+ // m13 = mGC = green: colour zero offset (brightness factor) ((256/255) * (Kb(1-Kb) + Kr(1-Kr)) / Kg)
|
|
+ // m23 = mBC = blue: colour zero offset (brightness factor) (-(1-Kb)/0.5 * (128/255))
|
|
+
|
|
+ // columns
|
|
+ int Y = 0;
|
|
+ int Cb = 1;
|
|
+ int Cr = 2;
|
|
+ int C = 3;
|
|
+ // rows
|
|
+ int R = 0;
|
|
+ int G = 1;
|
|
+ int B = 2;
|
|
+ // colour standard coefficients for red, geen, blue
|
|
+ double Kr, Kg, Kb;
|
|
+ // colour diff zero position (use standard 8-bit coding precision)
|
|
+ double CDZ = 128; //256*0.5
|
|
+ // range excursion (use standard 8-bit coding precision)
|
|
+ double EXC = 255; //256-1
|
|
+
|
|
+ if (colorStandard == VDP_COLOR_STANDARD_ITUR_BT_601)
|
|
+ {
|
|
+ Kr = studioCSCKCoeffs601[0];
|
|
+ Kg = studioCSCKCoeffs601[1];
|
|
+ Kb = studioCSCKCoeffs601[2];
|
|
+ }
|
|
+ else // assume VDP_COLOR_STANDARD_ITUR_BT_709
|
|
+ {
|
|
+ Kr = studioCSCKCoeffs709[0];
|
|
+ Kg = studioCSCKCoeffs709[1];
|
|
+ Kb = studioCSCKCoeffs709[2];
|
|
+ }
|
|
+ // we keep luma unscaled to retain the levels present in source so that 16-235 luma is converted to RGB 16-235
|
|
+ studioCSCMatrix[R][Y] = 1.0;
|
|
+ studioCSCMatrix[G][Y] = 1.0;
|
|
+ studioCSCMatrix[B][Y] = 1.0;
|
|
+
|
|
+ studioCSCMatrix[R][Cb] = 0.0;
|
|
+ studioCSCMatrix[G][Cb] = (double)-2 * Kb * (1 - Kb) / Kg;
|
|
+ studioCSCMatrix[B][Cb] = (double)(1 - Kb) / 0.5;
|
|
+
|
|
+ studioCSCMatrix[R][Cr] = (double)(1 - Kr) / 0.5;
|
|
+ studioCSCMatrix[G][Cr] = (double)-2 * Kr * (1 - Kr) / Kg;
|
|
+ studioCSCMatrix[B][Cr] = 0.0;
|
|
+
|
|
+ studioCSCMatrix[R][C] = (double)-1 * studioCSCMatrix[R][Cr] * CDZ/EXC;
|
|
+ studioCSCMatrix[G][C] = (double)-1 * (studioCSCMatrix[G][Cb] + studioCSCMatrix[G][Cr]) * CDZ/EXC;
|
|
+ studioCSCMatrix[B][C] = (double)-1 * studioCSCMatrix[B][Cb] * CDZ/EXC;
|
|
+
|
|
+ return true;
|
|
+}
|
|
+
|
|
+void CMixer::SetColor()
|
|
+{
|
|
+ VdpStatus vdp_st;
|
|
+
|
|
+ if (m_Brightness != g_settings.m_currentVideoSettings.m_Brightness)
|
|
+ m_Procamp.brightness = (float)((g_settings.m_currentVideoSettings.m_Brightness)-50) / 100;
|
|
+ if (m_Contrast != g_settings.m_currentVideoSettings.m_Contrast)
|
|
+ m_Procamp.contrast = (float)((g_settings.m_currentVideoSettings.m_Contrast)+50) / 100;
|
|
+
|
|
+ VdpColorStandard colorStandard;
|
|
+// if(vid_height >= 600 || vid_width > 1024)
|
|
+ if(m_config.surfaceWidth > 1000)
|
|
+ colorStandard = VDP_COLOR_STANDARD_ITUR_BT_709;
|
|
+ //vdp_st = vdp_generate_csc_matrix(&m_Procamp, VDP_COLOR_STANDARD_ITUR_BT_709, &m_CSCMatrix);
|
|
+ else
|
|
+ colorStandard = VDP_COLOR_STANDARD_ITUR_BT_601;
|
|
+ //vdp_st = vdp_generate_csc_matrix(&m_Procamp, VDP_COLOR_STANDARD_ITUR_BT_601, &m_CSCMatrix);
|
|
+
|
|
+ VdpVideoMixerAttribute attributes[] = { VDP_VIDEO_MIXER_ATTRIBUTE_CSC_MATRIX };
|
|
+ if (g_guiSettings.GetBool("videoplayer.vdpaustudiolevel"))
|
|
+ {
|
|
+ float studioCSC[3][4];
|
|
+ GenerateStudioCSCMatrix(colorStandard, studioCSC);
|
|
+ void const * pm_CSCMatix[] = { &studioCSC };
|
|
+ vdp_st = m_config.vdpProcs.vdp_video_mixer_set_attribute_values(m_videoMixer, ARSIZE(attributes), attributes, pm_CSCMatix);
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ vdp_st = m_config.vdpProcs.vdp_generate_csc_matrix(&m_Procamp, colorStandard, &m_CSCMatrix);
|
|
+ void const * pm_CSCMatix[] = { &m_CSCMatrix };
|
|
+ vdp_st = m_config.vdpProcs.vdp_video_mixer_set_attribute_values(m_videoMixer, ARSIZE(attributes), attributes, pm_CSCMatix);
|
|
+ }
|
|
+ CheckStatus(vdp_st, __LINE__);
|
|
+}
|
|
+
|
|
+void CMixer::SetNoiseReduction()
|
|
+{
|
|
+ if(!m_config.vdpau->Supports(VDP_VIDEO_MIXER_FEATURE_NOISE_REDUCTION))
|
|
+ return;
|
|
+
|
|
+ VdpVideoMixerFeature feature[] = { VDP_VIDEO_MIXER_FEATURE_NOISE_REDUCTION };
|
|
+ VdpVideoMixerAttribute attributes[] = { VDP_VIDEO_MIXER_ATTRIBUTE_NOISE_REDUCTION_LEVEL };
|
|
+ VdpStatus vdp_st;
|
|
+
|
|
+ if (!g_settings.m_currentVideoSettings.m_NoiseReduction)
|
|
+ {
|
|
+ VdpBool enabled[]= {0};
|
|
+ vdp_st = m_config.vdpProcs.vdp_video_mixer_set_feature_enables(m_videoMixer, ARSIZE(feature), feature, enabled);
|
|
+ CheckStatus(vdp_st, __LINE__);
|
|
+ return;
|
|
+ }
|
|
+ VdpBool enabled[]={1};
|
|
+ vdp_st = m_config.vdpProcs.vdp_video_mixer_set_feature_enables(m_videoMixer, ARSIZE(feature), feature, enabled);
|
|
+ CheckStatus(vdp_st, __LINE__);
|
|
+ void* nr[] = { &g_settings.m_currentVideoSettings.m_NoiseReduction };
|
|
+ CLog::Log(LOGNOTICE,"Setting Noise Reduction to %f",g_settings.m_currentVideoSettings.m_NoiseReduction);
|
|
+ vdp_st = m_config.vdpProcs.vdp_video_mixer_set_attribute_values(m_videoMixer, ARSIZE(attributes), attributes, nr);
|
|
+ CheckStatus(vdp_st, __LINE__);
|
|
+}
|
|
+
|
|
+void CMixer::SetSharpness()
|
|
+{
|
|
+ if(!m_config.vdpau->Supports(VDP_VIDEO_MIXER_FEATURE_SHARPNESS))
|
|
+ return;
|
|
+
|
|
+ VdpVideoMixerFeature feature[] = { VDP_VIDEO_MIXER_FEATURE_SHARPNESS };
|
|
+ VdpVideoMixerAttribute attributes[] = { VDP_VIDEO_MIXER_ATTRIBUTE_SHARPNESS_LEVEL };
|
|
+ VdpStatus vdp_st;
|
|
+
|
|
+ if (!g_settings.m_currentVideoSettings.m_Sharpness)
|
|
+ {
|
|
+ VdpBool enabled[]={0};
|
|
+ vdp_st = m_config.vdpProcs.vdp_video_mixer_set_feature_enables(m_videoMixer, ARSIZE(feature), feature, enabled);
|
|
+ CheckStatus(vdp_st, __LINE__);
|
|
+ return;
|
|
+ }
|
|
+ VdpBool enabled[]={1};
|
|
+ vdp_st = m_config.vdpProcs.vdp_video_mixer_set_feature_enables(m_videoMixer, ARSIZE(feature), feature, enabled);
|
|
+ CheckStatus(vdp_st, __LINE__);
|
|
+ void* sh[] = { &g_settings.m_currentVideoSettings.m_Sharpness };
|
|
+ CLog::Log(LOGNOTICE,"Setting Sharpness to %f",g_settings.m_currentVideoSettings.m_Sharpness);
|
|
+ vdp_st = m_config.vdpProcs.vdp_video_mixer_set_attribute_values(m_videoMixer, ARSIZE(attributes), attributes, sh);
|
|
+ CheckStatus(vdp_st, __LINE__);
|
|
+}
|
|
+
|
|
+EINTERLACEMETHOD CMixer::GetDeinterlacingMethod(bool log /* = false */)
|
|
+{
|
|
+ EINTERLACEMETHOD method = g_settings.m_currentVideoSettings.m_InterlaceMethod;
|
|
+ if (method == VS_INTERLACEMETHOD_AUTO)
|
|
+ {
|
|
+ int deint = -1;
|
|
+// if (m_config.outHeight >= 720)
|
|
+// deint = g_advancedSettings.m_videoVDPAUdeintHD;
|
|
+// else
|
|
+// deint = g_advancedSettings.m_videoVDPAUdeintSD;
|
|
+
|
|
+ if (deint != -1)
|
|
+ {
|
|
+ if (m_config.vdpau->Supports(EINTERLACEMETHOD(deint)))
|
|
+ {
|
|
+ method = EINTERLACEMETHOD(deint);
|
|
+ if (log)
|
|
+ CLog::Log(LOGNOTICE, "CVDPAU::GetDeinterlacingMethod: set de-interlacing to %d", deint);
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ if (log)
|
|
+ CLog::Log(LOGWARNING, "CVDPAU::GetDeinterlacingMethod: method for de-interlacing (advanced settings) not supported");
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ return method;
|
|
+}
|
|
+
|
|
+void CMixer::SetDeinterlacing()
|
|
+{
|
|
+ VdpStatus vdp_st;
|
|
+
|
|
+ if (m_videoMixer == VDP_INVALID_HANDLE)
|
|
+ return;
|
|
+
|
|
+ EDEINTERLACEMODE mode = g_settings.m_currentVideoSettings.m_DeinterlaceMode;
|
|
+ EINTERLACEMETHOD method = GetDeinterlacingMethod(true);
|
|
+
|
|
+ VdpVideoMixerFeature feature[] = { VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL,
|
|
+ VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL_SPATIAL,
|
|
+ VDP_VIDEO_MIXER_FEATURE_INVERSE_TELECINE };
|
|
+
|
|
+ if (mode == VS_DEINTERLACEMODE_OFF)
|
|
+ {
|
|
+ VdpBool enabled[] = {0,0,0};
|
|
+ vdp_st = m_config.vdpProcs.vdp_video_mixer_set_feature_enables(m_videoMixer, ARSIZE(feature), feature, enabled);
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ if (method == VS_INTERLACEMETHOD_AUTO)
|
|
+ {
|
|
+ VdpBool enabled[] = {1,0,0};
|
|
+ if (g_advancedSettings.m_videoVDPAUtelecine)
|
|
+ enabled[2] = 1;
|
|
+ vdp_st = m_config.vdpProcs.vdp_video_mixer_set_feature_enables(m_videoMixer, ARSIZE(feature), feature, enabled);
|
|
+ }
|
|
+ else if (method == VS_INTERLACEMETHOD_VDPAU_TEMPORAL
|
|
+ || method == VS_INTERLACEMETHOD_VDPAU_TEMPORAL_HALF)
|
|
+ {
|
|
+ VdpBool enabled[] = {1,0,0};
|
|
+ if (g_advancedSettings.m_videoVDPAUtelecine)
|
|
+ enabled[2] = 1;
|
|
+ vdp_st = m_config.vdpProcs.vdp_video_mixer_set_feature_enables(m_videoMixer, ARSIZE(feature), feature, enabled);
|
|
+ }
|
|
+ else if (method == VS_INTERLACEMETHOD_VDPAU_TEMPORAL_SPATIAL
|
|
+ || method == VS_INTERLACEMETHOD_VDPAU_TEMPORAL_SPATIAL_HALF)
|
|
+ {
|
|
+ VdpBool enabled[] = {1,1,0};
|
|
+ if (g_advancedSettings.m_videoVDPAUtelecine)
|
|
+ enabled[2] = 1;
|
|
+ vdp_st = m_config.vdpProcs.vdp_video_mixer_set_feature_enables(m_videoMixer, ARSIZE(feature), feature, enabled);
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ VdpBool enabled[]={0,0,0};
|
|
+ vdp_st = m_config.vdpProcs.vdp_video_mixer_set_feature_enables(m_videoMixer, ARSIZE(feature), feature, enabled);
|
|
+ }
|
|
+ }
|
|
+ CheckStatus(vdp_st, __LINE__);
|
|
+
|
|
+ SetDeintSkipChroma();
|
|
+
|
|
+ m_config.useInteropYuv = g_guiSettings.GetBool("videoplayer.usevdpauinteropyuv");
|
|
+}
|
|
+
|
|
+void CMixer::SetDeintSkipChroma()
|
|
+{
|
|
+ VdpVideoMixerAttribute attribute[] = { VDP_VIDEO_MIXER_ATTRIBUTE_SKIP_CHROMA_DEINTERLACE};
|
|
+ VdpStatus vdp_st;
|
|
+
|
|
+ uint8_t val;
|
|
+ if (g_advancedSettings.m_videoVDPAUdeintSkipChromaHD && m_config.outHeight >= 720)
|
|
+ val = 1;
|
|
+ else
|
|
+ val = 0;
|
|
+
|
|
+ void const *values[]={&val};
|
|
+ vdp_st = m_config.vdpProcs.vdp_video_mixer_set_attribute_values(m_videoMixer, ARSIZE(attribute), attribute, values);
|
|
+
|
|
+ CheckStatus(vdp_st, __LINE__);
|
|
+}
|
|
+
|
|
+void CMixer::SetHWUpscaling()
|
|
+{
|
|
+#ifdef VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L1
|
|
+
|
|
+ VdpStatus vdp_st;
|
|
+ VdpBool enabled[]={1};
|
|
+ switch (m_config.upscale)
|
|
+ {
|
|
+ case 9:
|
|
+ if (m_config.vdpau->Supports(VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L9))
|
|
+ {
|
|
+ VdpVideoMixerFeature feature[] = { VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L9 };
|
|
+ vdp_st = m_config.vdpProcs.vdp_video_mixer_set_feature_enables(m_videoMixer, ARSIZE(feature), feature, enabled);
|
|
+ break;
|
|
+ }
|
|
+ case 8:
|
|
+ if (m_config.vdpau->Supports(VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L8))
|
|
+ {
|
|
+ VdpVideoMixerFeature feature[] = { VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L8 };
|
|
+ vdp_st = m_config.vdpProcs.vdp_video_mixer_set_feature_enables(m_videoMixer, ARSIZE(feature), feature, enabled);
|
|
+ break;
|
|
+ }
|
|
+ case 7:
|
|
+ if (m_config.vdpau->Supports(VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L7))
|
|
+ {
|
|
+ VdpVideoMixerFeature feature[] = { VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L7 };
|
|
+ vdp_st = m_config.vdpProcs.vdp_video_mixer_set_feature_enables(m_videoMixer, ARSIZE(feature), feature, enabled);
|
|
+ break;
|
|
+ }
|
|
+ case 6:
|
|
+ if (m_config.vdpau->Supports(VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L6))
|
|
+ {
|
|
+ VdpVideoMixerFeature feature[] = { VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L6 };
|
|
+ vdp_st = m_config.vdpProcs.vdp_video_mixer_set_feature_enables(m_videoMixer, ARSIZE(feature), feature, enabled);
|
|
+ break;
|
|
+ }
|
|
+ case 5:
|
|
+ if (m_config.vdpau->Supports(VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L5))
|
|
+ {
|
|
+ VdpVideoMixerFeature feature[] = { VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L5 };
|
|
+ vdp_st = m_config.vdpProcs.vdp_video_mixer_set_feature_enables(m_videoMixer, ARSIZE(feature), feature, enabled);
|
|
+ break;
|
|
+ }
|
|
+ case 4:
|
|
+ if (m_config.vdpau->Supports(VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L4))
|
|
+ {
|
|
+ VdpVideoMixerFeature feature[] = { VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L4 };
|
|
+ vdp_st = m_config.vdpProcs.vdp_video_mixer_set_feature_enables(m_videoMixer, ARSIZE(feature), feature, enabled);
|
|
+ break;
|
|
+ }
|
|
+ case 3:
|
|
+ if (m_config.vdpau->Supports(VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L3))
|
|
+ {
|
|
+ VdpVideoMixerFeature feature[] = { VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L3 };
|
|
+ vdp_st = m_config.vdpProcs.vdp_video_mixer_set_feature_enables(m_videoMixer, ARSIZE(feature), feature, enabled);
|
|
+ break;
|
|
+ }
|
|
+ case 2:
|
|
+ if (m_config.vdpau->Supports(VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L2))
|
|
+ {
|
|
+ VdpVideoMixerFeature feature[] = { VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L2 };
|
|
+ vdp_st = m_config.vdpProcs.vdp_video_mixer_set_feature_enables(m_videoMixer, ARSIZE(feature), feature, enabled);
|
|
+ break;
|
|
+ }
|
|
+ case 1:
|
|
+ if (m_config.vdpau->Supports(VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L1))
|
|
+ {
|
|
+ VdpVideoMixerFeature feature[] = { VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L1 };
|
|
+ vdp_st = m_config.vdpProcs.vdp_video_mixer_set_feature_enables(m_videoMixer, ARSIZE(feature), feature, enabled);
|
|
+ break;
|
|
+ }
|
|
+ default:
|
|
+ DisableHQScaling();
|
|
+ return;
|
|
+ }
|
|
+ CheckStatus(vdp_st, __LINE__);
|
|
+#endif
|
|
+}
|
|
+
|
|
+void CMixer::DisableHQScaling()
|
|
+{
|
|
+ VdpStatus vdp_st;
|
|
+
|
|
+ if (m_videoMixer == VDP_INVALID_HANDLE)
|
|
+ return;
|
|
+
|
|
+ if(m_config.vdpau->Supports(VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L1))
|
|
+ {
|
|
+ VdpVideoMixerFeature feature[] = { VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L1 };
|
|
+ VdpBool enabled[]={0};
|
|
+ vdp_st = m_config.vdpProcs.vdp_video_mixer_set_feature_enables(m_videoMixer, ARSIZE(feature), feature, enabled);
|
|
+ CheckStatus(vdp_st, __LINE__);
|
|
+ }
|
|
+
|
|
+ if(m_config.vdpau->Supports(VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L2))
|
|
+ {
|
|
+ VdpVideoMixerFeature feature[] = { VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L2 };
|
|
+ VdpBool enabled[]={0};
|
|
+ vdp_st = m_config.vdpProcs.vdp_video_mixer_set_feature_enables(m_videoMixer, ARSIZE(feature), feature, enabled);
|
|
+ CheckStatus(vdp_st, __LINE__);
|
|
+ }
|
|
+
|
|
+ if(m_config.vdpau->Supports(VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L3))
|
|
+ {
|
|
+ VdpVideoMixerFeature feature[] = { VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L3 };
|
|
+ VdpBool enabled[]={0};
|
|
+ vdp_st = m_config.vdpProcs.vdp_video_mixer_set_feature_enables(m_videoMixer, ARSIZE(feature), feature, enabled);
|
|
+ CheckStatus(vdp_st, __LINE__);
|
|
+ }
|
|
+
|
|
+ if(m_config.vdpau->Supports(VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L4))
|
|
+ {
|
|
+ VdpVideoMixerFeature feature[] = { VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L4 };
|
|
+ VdpBool enabled[]={0};
|
|
+ vdp_st = m_config.vdpProcs.vdp_video_mixer_set_feature_enables(m_videoMixer, ARSIZE(feature), feature, enabled);
|
|
+ CheckStatus(vdp_st, __LINE__);
|
|
+ }
|
|
+
|
|
+ if(m_config.vdpau->Supports(VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L5))
|
|
+ {
|
|
+ VdpVideoMixerFeature feature[] = { VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L5 };
|
|
+ VdpBool enabled[]={0};
|
|
+ vdp_st = m_config.vdpProcs.vdp_video_mixer_set_feature_enables(m_videoMixer, ARSIZE(feature), feature, enabled);
|
|
+ CheckStatus(vdp_st, __LINE__);
|
|
+ }
|
|
+
|
|
+ if(m_config.vdpau->Supports(VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L6))
|
|
+ {
|
|
+ VdpVideoMixerFeature feature[] = { VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L6 };
|
|
+ VdpBool enabled[]={0};
|
|
+ vdp_st = m_config.vdpProcs.vdp_video_mixer_set_feature_enables(m_videoMixer, ARSIZE(feature), feature, enabled);
|
|
+ CheckStatus(vdp_st, __LINE__);
|
|
+ }
|
|
+
|
|
+ if(m_config.vdpau->Supports(VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L7))
|
|
+ {
|
|
+ VdpVideoMixerFeature feature[] = { VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L7 };
|
|
+ VdpBool enabled[]={0};
|
|
+ vdp_st = m_config.vdpProcs.vdp_video_mixer_set_feature_enables(m_videoMixer, ARSIZE(feature), feature, enabled);
|
|
+ CheckStatus(vdp_st, __LINE__);
|
|
+ }
|
|
+
|
|
+ if(m_config.vdpau->Supports(VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L8))
|
|
+ {
|
|
+ VdpVideoMixerFeature feature[] = { VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L8 };
|
|
+ VdpBool enabled[]={0};
|
|
+ vdp_st = m_config.vdpProcs.vdp_video_mixer_set_feature_enables(m_videoMixer, ARSIZE(feature), feature, enabled);
|
|
+ CheckStatus(vdp_st, __LINE__);
|
|
+ }
|
|
+
|
|
+ if(m_config.vdpau->Supports(VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L9))
|
|
+ {
|
|
+ VdpVideoMixerFeature feature[] = { VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L9 };
|
|
+ VdpBool enabled[]={0};
|
|
+ vdp_st = m_config.vdpProcs.vdp_video_mixer_set_feature_enables(m_videoMixer, ARSIZE(feature), feature, enabled);
|
|
+ CheckStatus(vdp_st, __LINE__);
|
|
+ }
|
|
+}
|
|
+
|
|
+
|
|
+void CMixer::Init()
|
|
+{
|
|
+ m_Brightness = 0.0;
|
|
+ m_Contrast = 0.0;
|
|
+ m_NoiseReduction = 0.0;
|
|
+ m_Sharpness = 0.0;
|
|
+ m_DeintMode = 0;
|
|
+ m_Deint = 0;
|
|
+ m_PostProc = false;
|
|
+ m_vdpError = false;
|
|
+
|
|
+ m_config.upscale = g_advancedSettings.m_videoVDPAUScaling;
|
|
+ m_config.useInteropYuv = g_guiSettings.GetBool("videoplayer.usevdpauinteropyuv");
|
|
+
|
|
+ CreateVdpauMixer();
|
|
+}
|
|
+
|
|
+void CMixer::Uninit()
|
|
+{
|
|
+ Flush();
|
|
+ while (!m_outputSurfaces.empty())
|
|
+ {
|
|
+ m_outputSurfaces.pop();
|
|
+ }
|
|
+ m_config.vdpProcs.vdp_video_mixer_destroy(m_videoMixer);
|
|
+}
|
|
+
|
|
+void CMixer::Flush()
|
|
+{
|
|
+ while (!m_mixerInput.empty())
|
|
+ {
|
|
+ CVdpauDecodedPicture pic = m_mixerInput.back();
|
|
+ m_mixerInput.pop_back();
|
|
+ CSingleLock lock(*m_config.videoSurfaceSec);
|
|
+ if (pic.render)
|
|
+ pic.render->state &= ~FF_VDPAU_STATE_USED_FOR_RENDER;
|
|
+ }
|
|
+ while (!m_decodedPics.empty())
|
|
+ {
|
|
+ CVdpauDecodedPicture pic = m_decodedPics.front();
|
|
+ m_decodedPics.pop();
|
|
+ CSingleLock lock(*m_config.videoSurfaceSec);
|
|
+ if (pic.render)
|
|
+ pic.render->state &= ~FF_VDPAU_STATE_USED_FOR_RENDER;
|
|
+ }
|
|
+ Message *msg;
|
|
+ while (m_dataPort.ReceiveOutMessage(&msg))
|
|
+ {
|
|
+ if (msg->signal == CMixerDataProtocol::FRAME)
|
|
+ {
|
|
+ CVdpauDecodedPicture pic = *(CVdpauDecodedPicture*)msg->data;
|
|
+ CSingleLock lock(*m_config.videoSurfaceSec);
|
|
+ if (pic.render)
|
|
+ pic.render->state &= ~FF_VDPAU_STATE_USED_FOR_RENDER;
|
|
+ }
|
|
+ else if (msg->signal == CMixerDataProtocol::BUFFER)
|
|
+ {
|
|
+ VdpOutputSurface *surf;
|
|
+ surf = (VdpOutputSurface*)msg->data;
|
|
+ m_outputSurfaces.push(*surf);
|
|
+ }
|
|
+ msg->Release();
|
|
+ }
|
|
+}
|
|
+
|
|
+void CMixer::InitCycle()
|
|
+{
|
|
+ CheckFeatures();
|
|
+ uint64_t latency;
|
|
+ int flags;
|
|
+ m_config.stats->GetParams(latency, flags);
|
|
+ latency = (latency*1000)/CurrentHostFrequency();
|
|
+ if (flags & DVP_FLAG_NO_POSTPROC)
|
|
+ SetPostProcFeatures(false);
|
|
+ else
|
|
+ SetPostProcFeatures(true);
|
|
+
|
|
+ m_config.stats->SetCanSkipDeint(false);
|
|
+
|
|
+ EDEINTERLACEMODE mode = g_settings.m_currentVideoSettings.m_DeinterlaceMode;
|
|
+ EINTERLACEMETHOD method = GetDeinterlacingMethod();
|
|
+ bool interlaced = m_mixerInput[1].DVDPic.iFlags & DVP_FLAG_INTERLACED;
|
|
+
|
|
+ if (mode == VS_DEINTERLACEMODE_FORCE ||
|
|
+ (mode == VS_DEINTERLACEMODE_AUTO && interlaced))
|
|
+ {
|
|
+ if((method == VS_INTERLACEMETHOD_AUTO && interlaced)
|
|
+ || method == VS_INTERLACEMETHOD_VDPAU_BOB
|
|
+ || method == VS_INTERLACEMETHOD_VDPAU_TEMPORAL
|
|
+ || method == VS_INTERLACEMETHOD_VDPAU_TEMPORAL_HALF
|
|
+ || method == VS_INTERLACEMETHOD_VDPAU_TEMPORAL_SPATIAL
|
|
+ || method == VS_INTERLACEMETHOD_VDPAU_TEMPORAL_SPATIAL_HALF
|
|
+ || method == VS_INTERLACEMETHOD_VDPAU_INVERSE_TELECINE )
|
|
+ {
|
|
+ if(method == VS_INTERLACEMETHOD_VDPAU_TEMPORAL_HALF
|
|
+ || method == VS_INTERLACEMETHOD_VDPAU_TEMPORAL_SPATIAL_HALF
|
|
+ || !g_graphicsContext.IsFullScreenVideo())
|
|
+ m_mixersteps = 1;
|
|
+ else
|
|
+ {
|
|
+ m_mixersteps = 2;
|
|
+ m_config.stats->SetCanSkipDeint(true);
|
|
+ }
|
|
+
|
|
+ if (m_mixerInput[1].DVDPic.iFlags & DVP_FLAG_DROPDEINT)
|
|
+ {
|
|
+ m_mixersteps = 1;
|
|
+ }
|
|
+
|
|
+ if(m_mixerInput[1].DVDPic.iFlags & DVP_FLAG_TOP_FIELD_FIRST)
|
|
+ m_mixerfield = VDP_VIDEO_MIXER_PICTURE_STRUCTURE_TOP_FIELD;
|
|
+ else
|
|
+ m_mixerfield = VDP_VIDEO_MIXER_PICTURE_STRUCTURE_BOTTOM_FIELD;
|
|
+
|
|
+ m_mixerInput[1].DVDPic.format = RENDER_FMT_VDPAU;
|
|
+ m_mixerInput[1].DVDPic.iFlags &= ~(DVP_FLAG_TOP_FIELD_FIRST |
|
|
+ DVP_FLAG_REPEAT_TOP_FIELD |
|
|
+ DVP_FLAG_INTERLACED);
|
|
+ m_config.useInteropYuv = false;
|
|
+ }
|
|
+ else if (method == VS_INTERLACEMETHOD_RENDER_BOB && m_config.useInteropYuv)
|
|
+ {
|
|
+ m_mixersteps = 1;
|
|
+ m_mixerfield = VDP_VIDEO_MIXER_PICTURE_STRUCTURE_FRAME;
|
|
+ m_mixerInput[1].DVDPic.format = RENDER_FMT_VDPAU_420;
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ CLog::Log(LOGERROR, "CMixer::%s - interlace method not supported", __FUNCTION__);
|
|
+ m_mixersteps = 1;
|
|
+ m_mixerfield = VDP_VIDEO_MIXER_PICTURE_STRUCTURE_FRAME;
|
|
+ m_mixerInput[1].DVDPic.format = RENDER_FMT_VDPAU;
|
|
+ m_mixerInput[1].DVDPic.iFlags &= ~(DVP_FLAG_TOP_FIELD_FIRST |
|
|
+ DVP_FLAG_REPEAT_TOP_FIELD |
|
|
+ DVP_FLAG_INTERLACED);
|
|
+ }
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ m_mixersteps = 1;
|
|
+ m_mixerfield = VDP_VIDEO_MIXER_PICTURE_STRUCTURE_FRAME;
|
|
+
|
|
+ if (m_config.useInteropYuv)
|
|
+ m_mixerInput[1].DVDPic.format = RENDER_FMT_VDPAU_420;
|
|
+ else
|
|
+ {
|
|
+ m_mixerInput[1].DVDPic.format = RENDER_FMT_VDPAU;
|
|
+ m_mixerInput[1].DVDPic.iFlags &= ~(DVP_FLAG_TOP_FIELD_FIRST |
|
|
+ DVP_FLAG_REPEAT_TOP_FIELD |
|
|
+ DVP_FLAG_INTERLACED);
|
|
+ }
|
|
+ }
|
|
+ m_mixerstep = 0;
|
|
+
|
|
+ if (m_mixerInput[1].DVDPic.format == RENDER_FMT_VDPAU)
|
|
+ {
|
|
+ m_processPicture.outputSurface = m_outputSurfaces.front();
|
|
+ m_mixerInput[1].DVDPic.iWidth = m_config.outWidth;
|
|
+ m_mixerInput[1].DVDPic.iHeight = m_config.outHeight;
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ m_mixerInput[1].DVDPic.iWidth = m_config.vidWidth;
|
|
+ m_mixerInput[1].DVDPic.iHeight = m_config.vidHeight;
|
|
+ }
|
|
+
|
|
+ m_processPicture.DVDPic = m_mixerInput[1].DVDPic;
|
|
+ m_processPicture.render = m_mixerInput[1].render;
|
|
+}
|
|
+
|
|
+void CMixer::FiniCycle()
|
|
+{
|
|
+ while (m_mixerInput.size() > 3)
|
|
+ {
|
|
+ CVdpauDecodedPicture &tmp = m_mixerInput.back();
|
|
+ if (tmp.render && m_processPicture.DVDPic.format != RENDER_FMT_VDPAU_420)
|
|
+ {
|
|
+ CSingleLock lock(*m_config.videoSurfaceSec);
|
|
+ tmp.render->state &= ~FF_VDPAU_STATE_USED_FOR_RENDER;
|
|
+ }
|
|
+ m_mixerInput.pop_back();
|
|
+// m_config.stats->DecDecoded();
|
|
+ }
|
|
+}
|
|
+
|
|
+void CMixer::ProcessPicture()
|
|
+{
|
|
+ if (m_processPicture.DVDPic.format == RENDER_FMT_VDPAU_420)
|
|
+ return;
|
|
+
|
|
+ VdpStatus vdp_st;
|
|
+
|
|
+ if (m_mixerstep == 1)
|
|
+ {
|
|
+ if(m_mixerfield == VDP_VIDEO_MIXER_PICTURE_STRUCTURE_TOP_FIELD)
|
|
+ m_mixerfield = VDP_VIDEO_MIXER_PICTURE_STRUCTURE_BOTTOM_FIELD;
|
|
+ else
|
|
+ m_mixerfield = VDP_VIDEO_MIXER_PICTURE_STRUCTURE_TOP_FIELD;
|
|
+ }
|
|
+
|
|
+ VdpVideoSurface past_surfaces[4] = { VDP_INVALID_HANDLE, VDP_INVALID_HANDLE, VDP_INVALID_HANDLE, VDP_INVALID_HANDLE };
|
|
+ VdpVideoSurface futu_surfaces[2] = { VDP_INVALID_HANDLE, VDP_INVALID_HANDLE };
|
|
+ uint32_t pastCount = 4;
|
|
+ uint32_t futuCount = 2;
|
|
+
|
|
+ if(m_mixerfield == VDP_VIDEO_MIXER_PICTURE_STRUCTURE_FRAME)
|
|
+ {
|
|
+ // use only 2 past 1 future for progressive/weave
|
|
+ // (only used for postproc anyway eg noise reduction)
|
|
+ if (m_mixerInput.size() > 3)
|
|
+ past_surfaces[1] = m_mixerInput[3].render->surface;
|
|
+ if (m_mixerInput.size() > 2)
|
|
+ past_surfaces[0] = m_mixerInput[2].render->surface;
|
|
+ futu_surfaces[0] = m_mixerInput[0].render->surface;
|
|
+ pastCount = 2;
|
|
+ futuCount = 1;
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ if(m_mixerstep == 0)
|
|
+ { // first field
|
|
+ if (m_mixerInput.size() > 3)
|
|
+ {
|
|
+ past_surfaces[3] = m_mixerInput[3].render->surface;
|
|
+ past_surfaces[2] = m_mixerInput[3].render->surface;
|
|
+ }
|
|
+ if (m_mixerInput.size() > 2)
|
|
+ {
|
|
+ past_surfaces[1] = m_mixerInput[2].render->surface;
|
|
+ past_surfaces[0] = m_mixerInput[2].render->surface;
|
|
+ }
|
|
+ futu_surfaces[0] = m_mixerInput[1].render->surface;
|
|
+ futu_surfaces[1] = m_mixerInput[0].render->surface;;
|
|
+ }
|
|
+ else
|
|
+ { // second field
|
|
+ if (m_mixerInput.size() > 3)
|
|
+ {
|
|
+ past_surfaces[3] = m_mixerInput[3].render->surface;
|
|
+ }
|
|
+ if (m_mixerInput.size() > 2)
|
|
+ {
|
|
+ past_surfaces[2] = m_mixerInput[2].render->surface;
|
|
+ past_surfaces[1] = m_mixerInput[2].render->surface;
|
|
+ }
|
|
+ past_surfaces[0] = m_mixerInput[1].render->surface;
|
|
+ futu_surfaces[0] = m_mixerInput[1].render->surface;
|
|
+ futu_surfaces[1] = m_mixerInput[1].render->surface;
|
|
+
|
|
+ m_processPicture.DVDPic.pts = DVD_NOPTS_VALUE;
|
|
+ m_processPicture.DVDPic.dts = DVD_NOPTS_VALUE;
|
|
+ }
|
|
+ m_processPicture.DVDPic.iRepeatPicture = 0.0;
|
|
+ } // interlaced
|
|
+
|
|
+ VdpRect sourceRect;
|
|
+ sourceRect.x0 = 0;
|
|
+ sourceRect.y0 = 0;
|
|
+ sourceRect.x1 = m_config.vidWidth;
|
|
+ sourceRect.y1 = m_config.vidHeight;
|
|
+
|
|
+ VdpRect destRect;
|
|
+ destRect.x0 = 0;
|
|
+ destRect.y0 = 0;
|
|
+ destRect.x1 = m_config.outWidth;
|
|
+ destRect.y1 = m_config.outHeight;
|
|
+
|
|
+ // start vdpau video mixer
|
|
+ vdp_st = m_config.vdpProcs.vdp_video_mixer_render(m_videoMixer,
|
|
+ VDP_INVALID_HANDLE,
|
|
+ 0,
|
|
+ m_mixerfield,
|
|
+ pastCount,
|
|
+ past_surfaces,
|
|
+ m_mixerInput[1].render->surface,
|
|
+ futuCount,
|
|
+ futu_surfaces,
|
|
+ &sourceRect,
|
|
+ m_processPicture.outputSurface,
|
|
+ &destRect,
|
|
+ &destRect,
|
|
+ 0,
|
|
+ NULL);
|
|
+ CheckStatus(vdp_st, __LINE__);
|
|
+
|
|
+ if (m_mixerfield != VDP_VIDEO_MIXER_PICTURE_STRUCTURE_FRAME)
|
|
+ {
|
|
+ // in order to clip top and bottom lines when de-interlacing
|
|
+ // we black those lines as a work around for not working
|
|
+ // background colour using the mixer
|
|
+ // pixel perfect is preferred over overscanning or zooming
|
|
+
|
|
+ VdpRect clipRect = destRect;
|
|
+ clipRect.y1 = clipRect.y0 + 2;
|
|
+ uint32_t *data[] = {m_BlackBar};
|
|
+ uint32_t pitches[] = {destRect.x1};
|
|
+ vdp_st = m_config.vdpProcs.vdp_output_surface_put_bits_native(m_processPicture.outputSurface,
|
|
+ (void**)data,
|
|
+ pitches,
|
|
+ &clipRect);
|
|
+ CheckStatus(vdp_st, __LINE__);
|
|
+
|
|
+ clipRect = destRect;
|
|
+ clipRect.y0 = clipRect.y1 - 2;
|
|
+ vdp_st = m_config.vdpProcs.vdp_output_surface_put_bits_native(m_processPicture.outputSurface,
|
|
+ (void**)data,
|
|
+ pitches,
|
|
+ &clipRect);
|
|
+ CheckStatus(vdp_st, __LINE__);
|
|
+ }
|
|
+}
|
|
+
|
|
+
|
|
+bool CMixer::CheckStatus(VdpStatus vdp_st, int line)
|
|
+{
|
|
+ if (vdp_st != VDP_STATUS_OK)
|
|
+ {
|
|
+ CLog::Log(LOGERROR, " (VDPAU) Error: %s(%d) at %s:%d\n", m_config.vdpProcs.vdp_get_error_string(vdp_st), vdp_st, __FILE__, line);
|
|
+ m_vdpError = true;
|
|
+ return true;
|
|
+ }
|
|
+ return false;
|
|
+}
|
|
+
|
|
+//-----------------------------------------------------------------------------
|
|
+// Output
|
|
+//-----------------------------------------------------------------------------
|
|
+COutput::COutput(CEvent *inMsgEvent) :
|
|
+ CThread("Vdpau Output Thread"),
|
|
+ m_controlPort("OutputControlPort", inMsgEvent, &m_outMsgEvent),
|
|
+ m_dataPort("OutputDataPort", inMsgEvent, &m_outMsgEvent),
|
|
+ m_mixer(&m_outMsgEvent)
|
|
+{
|
|
+ m_inMsgEvent = inMsgEvent;
|
|
+
|
|
+ CVdpauRenderPicture pic;
|
|
+ pic.renderPicSection = &m_bufferPool.renderPicSec;
|
|
+ pic.refCount = 0;
|
|
+ for (unsigned int i = 0; i < NUM_RENDER_PICS; i++)
|
|
+ {
|
|
+ m_bufferPool.allRenderPics.push_back(pic);
|
|
+ }
|
|
+ for (unsigned int i = 0; i < m_bufferPool.allRenderPics.size(); ++i)
|
|
+ {
|
|
+ m_bufferPool.freeRenderPics.push_back(&m_bufferPool.allRenderPics[i]);
|
|
+ }
|
|
+}
|
|
+
|
|
+void COutput::Start()
|
|
+{
|
|
+ Create();
|
|
+}
|
|
+
|
|
+COutput::~COutput()
|
|
+{
|
|
+ Dispose();
|
|
+
|
|
+ m_bufferPool.freeRenderPics.clear();
|
|
+ m_bufferPool.usedRenderPics.clear();
|
|
+ m_bufferPool.allRenderPics.clear();
|
|
+}
|
|
+
|
|
+void COutput::Dispose()
|
|
+{
|
|
+ CSingleLock lock(g_graphicsContext);
|
|
+ m_bStop = true;
|
|
+ m_outMsgEvent.Set();
|
|
+ StopThread();
|
|
+ m_controlPort.Purge();
|
|
+ m_dataPort.Purge();
|
|
+}
|
|
+
|
|
+void COutput::OnStartup()
|
|
+{
|
|
+ CLog::Log(LOGNOTICE, "COutput::OnStartup: Output Thread created");
|
|
+}
|
|
+
|
|
+void COutput::OnExit()
|
|
+{
|
|
+ CLog::Log(LOGNOTICE, "COutput::OnExit: Output Thread terminated");
|
|
+}
|
|
+
|
|
+enum OUTPUT_STATES
|
|
+{
|
|
+ O_TOP = 0, // 0
|
|
+ O_TOP_ERROR, // 1
|
|
+ O_TOP_UNCONFIGURED, // 2
|
|
+ O_TOP_CONFIGURED, // 3
|
|
+ O_TOP_CONFIGURED_IDLE, // 4
|
|
+ O_TOP_CONFIGURED_WORK, // 5
|
|
+};
|
|
+
|
|
+int VDPAU_OUTPUT_parentStates[] = {
|
|
+ -1,
|
|
+ 0, //TOP_ERROR
|
|
+ 0, //TOP_UNCONFIGURED
|
|
+ 0, //TOP_CONFIGURED
|
|
+ 3, //TOP_CONFIGURED_IDLE
|
|
+ 3, //TOP_CONFIGURED_WORK
|
|
+};
|
|
+
|
|
+void COutput::StateMachine(int signal, Protocol *port, Message *msg)
|
|
+{
|
|
+ for (int state = m_state; ; state = VDPAU_OUTPUT_parentStates[state])
|
|
+ {
|
|
+ switch (state)
|
|
+ {
|
|
+ case O_TOP: // TOP
|
|
+ if (port == &m_controlPort)
|
|
+ {
|
|
+ switch (signal)
|
|
+ {
|
|
+ case COutputControlProtocol::FLUSH:
|
|
+ msg->Reply(COutputControlProtocol::ACC);
|
|
+ return;
|
|
+ case COutputControlProtocol::PRECLEANUP:
|
|
+ msg->Reply(COutputControlProtocol::ACC);
|
|
+ return;
|
|
+ default:
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ else if (port == &m_dataPort)
|
|
+ {
|
|
+ switch (signal)
|
|
+ {
|
|
+ case COutputDataProtocol::RETURNPIC:
|
|
+ CVdpauRenderPicture *pic;
|
|
+ pic = *((CVdpauRenderPicture**)msg->data);
|
|
+ ProcessReturnPicture(pic);
|
|
+ return;
|
|
+ default:
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ {
|
|
+ std::string portName = port == NULL ? "timer" : port->portName;
|
|
+ CLog::Log(LOGWARNING, "COutput::%s - signal: %d form port: %s not handled for state: %d", __FUNCTION__, signal, portName.c_str(), m_state);
|
|
+ }
|
|
+ return;
|
|
+
|
|
+ case O_TOP_ERROR:
|
|
+ break;
|
|
+
|
|
+ case O_TOP_UNCONFIGURED:
|
|
+ if (port == &m_controlPort)
|
|
+ {
|
|
+ switch (signal)
|
|
+ {
|
|
+ case COutputControlProtocol::INIT:
|
|
+ CVdpauConfig *data;
|
|
+ data = (CVdpauConfig*)msg->data;
|
|
+ if (data)
|
|
+ {
|
|
+ m_config = *data;
|
|
+ }
|
|
+ Init();
|
|
+ Message *reply;
|
|
+ if (m_mixer.m_controlPort.SendOutMessageSync(CMixerControlProtocol::INIT,
|
|
+ &reply, 1000, &m_config, sizeof(m_config)))
|
|
+ {
|
|
+ if (reply->signal != CMixerControlProtocol::ACC)
|
|
+ m_vdpError = true;
|
|
+ reply->Release();
|
|
+ }
|
|
+
|
|
+ // set initial number of
|
|
+ m_bufferPool.numOutputSurfaces = 4;
|
|
+ EnsureBufferPool();
|
|
+ if (!m_vdpError)
|
|
+ {
|
|
+ m_state = O_TOP_CONFIGURED_IDLE;
|
|
+ msg->Reply(COutputControlProtocol::ACC);
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ m_state = O_TOP_ERROR;
|
|
+ msg->Reply(COutputControlProtocol::ERROR);
|
|
+ }
|
|
+ return;
|
|
+ default:
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ case O_TOP_CONFIGURED:
|
|
+ if (port == &m_controlPort)
|
|
+ {
|
|
+ switch (signal)
|
|
+ {
|
|
+ case COutputControlProtocol::FLUSH:
|
|
+ Flush();
|
|
+ msg->Reply(COutputControlProtocol::ACC);
|
|
+ return;
|
|
+ case COutputControlProtocol::PRECLEANUP:
|
|
+ Flush();
|
|
+ msg->Reply(COutputControlProtocol::ACC);
|
|
+ return;
|
|
+ default:
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ else if (port == &m_dataPort)
|
|
+ {
|
|
+ switch (signal)
|
|
+ {
|
|
+ case COutputDataProtocol::NEWFRAME:
|
|
+ CVdpauDecodedPicture *frame;
|
|
+ frame = (CVdpauDecodedPicture*)msg->data;
|
|
+ if (frame)
|
|
+ {
|
|
+ m_mixer.m_dataPort.SendOutMessage(CMixerDataProtocol::FRAME,
|
|
+ frame,sizeof(CVdpauDecodedPicture));
|
|
+ }
|
|
+ return;
|
|
+ case COutputDataProtocol::RETURNPIC:
|
|
+ CVdpauRenderPicture *pic;
|
|
+ pic = *((CVdpauRenderPicture**)msg->data);
|
|
+ ProcessReturnPicture(pic);
|
|
+ m_controlPort.SendInMessage(COutputControlProtocol::STATS);
|
|
+ m_state = O_TOP_CONFIGURED_WORK;
|
|
+ m_extTimeout = 0;
|
|
+ return;
|
|
+ default:
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ else if (port == &m_mixer.m_dataPort)
|
|
+ {
|
|
+ switch (signal)
|
|
+ {
|
|
+ case CMixerDataProtocol::PICTURE:
|
|
+ CVdpauProcessedPicture *pic;
|
|
+ pic = (CVdpauProcessedPicture*)msg->data;
|
|
+ m_bufferPool.processedPics.push(*pic);
|
|
+ m_state = O_TOP_CONFIGURED_WORK;
|
|
+ m_extTimeout = 0;
|
|
+ return;
|
|
+ default:
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ case O_TOP_CONFIGURED_IDLE:
|
|
+ if (port == NULL) // timeout
|
|
+ {
|
|
+ switch (signal)
|
|
+ {
|
|
+ case COutputControlProtocol::TIMEOUT:
|
|
+// uint16_t decoded, processed, render;
|
|
+// m_config.stats->Get(decoded, processed, render);
|
|
+// CLog::Log(LOGDEBUG, "CVDPAU::COutput - timeout idle: decoded: %d, proc: %d, render: %d", decoded, processed, render);
|
|
+ return;
|
|
+ default:
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ case O_TOP_CONFIGURED_WORK:
|
|
+ if (port == NULL) // timeout
|
|
+ {
|
|
+ switch (signal)
|
|
+ {
|
|
+ case COutputControlProtocol::TIMEOUT:
|
|
+ if (HasWork())
|
|
+ {
|
|
+ CVdpauRenderPicture *pic;
|
|
+ pic = ProcessMixerPicture();
|
|
+ if (pic)
|
|
+ {
|
|
+ m_config.stats->DecProcessed();
|
|
+ m_config.stats->IncRender();
|
|
+ m_dataPort.SendInMessage(COutputDataProtocol::PICTURE, &pic, sizeof(pic));
|
|
+ }
|
|
+ m_extTimeout = 1;
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ m_state = O_TOP_CONFIGURED_IDLE;
|
|
+ m_extTimeout = 100;
|
|
+ }
|
|
+ return;
|
|
+ default:
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ default: // we are in no state, should not happen
|
|
+ CLog::Log(LOGERROR, "COutput::%s - no valid state: %d", __FUNCTION__, m_state);
|
|
+ return;
|
|
+ }
|
|
+ } // for
|
|
+}
|
|
+
|
|
+void COutput::Process()
|
|
+{
|
|
+ Message *msg;
|
|
+ Protocol *port;
|
|
+ bool gotMsg;
|
|
+
|
|
+ m_state = O_TOP_UNCONFIGURED;
|
|
+ m_extTimeout = 1000;
|
|
+ m_bStateMachineSelfTrigger = false;
|
|
+
|
|
+ while (!m_bStop)
|
|
+ {
|
|
+ gotMsg = false;
|
|
+
|
|
+ if (m_bStateMachineSelfTrigger)
|
|
+ {
|
|
+ m_bStateMachineSelfTrigger = false;
|
|
+ // self trigger state machine
|
|
+ StateMachine(msg->signal, port, msg);
|
|
+ if (!m_bStateMachineSelfTrigger)
|
|
+ {
|
|
+ msg->Release();
|
|
+ msg = NULL;
|
|
+ }
|
|
+ continue;
|
|
+ }
|
|
+ // check control port
|
|
+ else if (m_controlPort.ReceiveOutMessage(&msg))
|
|
+ {
|
|
+ gotMsg = true;
|
|
+ port = &m_controlPort;
|
|
+ }
|
|
+ // check data port
|
|
+ else if (m_dataPort.ReceiveOutMessage(&msg))
|
|
+ {
|
|
+ gotMsg = true;
|
|
+ port = &m_dataPort;
|
|
+ }
|
|
+ // check mixer data port
|
|
+ else if (m_mixer.m_dataPort.ReceiveInMessage(&msg))
|
|
+ {
|
|
+ gotMsg = true;
|
|
+ port = &m_mixer.m_dataPort;
|
|
+ }
|
|
+ if (gotMsg)
|
|
+ {
|
|
+ StateMachine(msg->signal, port, msg);
|
|
+ if (!m_bStateMachineSelfTrigger)
|
|
+ {
|
|
+ msg->Release();
|
|
+ msg = NULL;
|
|
+ }
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ // wait for message
|
|
+ else if (m_outMsgEvent.WaitMSec(m_extTimeout))
|
|
+ {
|
|
+ continue;
|
|
+ }
|
|
+ // time out
|
|
+ else
|
|
+ {
|
|
+ msg = m_controlPort.GetMessage();
|
|
+ msg->signal = COutputControlProtocol::TIMEOUT;
|
|
+ port = 0;
|
|
+ // signal timeout to state machine
|
|
+ StateMachine(msg->signal, port, msg);
|
|
+ if (!m_bStateMachineSelfTrigger)
|
|
+ {
|
|
+ msg->Release();
|
|
+ msg = NULL;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ Flush();
|
|
+ Uninit();
|
|
+}
|
|
+
|
|
+bool COutput::Init()
|
|
+{
|
|
+ if (!CreateGlxContext())
|
|
+ return false;
|
|
+
|
|
+ if (!GLInit())
|
|
+ return false;
|
|
+
|
|
+ m_mixer.Start();
|
|
+ m_vdpError = false;
|
|
+
|
|
+ return true;
|
|
+}
|
|
+
|
|
+bool COutput::Uninit()
|
|
+{
|
|
+ m_mixer.Dispose();
|
|
+ GLUnmapSurfaces();
|
|
+ GLUnbindPixmaps();
|
|
+ ReleaseBufferPool();
|
|
+ DestroyGlxContext();
|
|
+ return true;
|
|
+}
|
|
+
|
|
+void COutput::Flush()
|
|
+{
|
|
+ Message *reply;
|
|
+ if (m_mixer.m_controlPort.SendOutMessageSync(CMixerControlProtocol::FLUSH,
|
|
+ &reply,
|
|
+ 2000))
|
|
+ {
|
|
+ reply->Release();
|
|
+ }
|
|
+ else
|
|
+ CLog::Log(LOGERROR, "Coutput::%s - failed to flush mixer", __FUNCTION__);
|
|
+
|
|
+ Message *msg;
|
|
+ while (m_mixer.m_dataPort.ReceiveInMessage(&msg))
|
|
+ {
|
|
+ if (msg->signal == CMixerDataProtocol::PICTURE)
|
|
+ {
|
|
+ CVdpauProcessedPicture pic = *(CVdpauProcessedPicture*)msg->data;
|
|
+ if (pic.DVDPic.format == RENDER_FMT_VDPAU_420)
|
|
+ {
|
|
+ CSingleLock lock(*m_config.videoSurfaceSec);
|
|
+ if (pic.render)
|
|
+ pic.render->state &= ~FF_VDPAU_STATE_USED_FOR_RENDER;
|
|
+ }
|
|
+ }
|
|
+ msg->Release();
|
|
+ }
|
|
+
|
|
+ while (m_dataPort.ReceiveOutMessage(&msg))
|
|
+ {
|
|
+ if (msg->signal == COutputDataProtocol::NEWFRAME)
|
|
+ {
|
|
+ CVdpauDecodedPicture pic = *(CVdpauDecodedPicture*)msg->data;
|
|
+ CSingleLock lock(*m_config.videoSurfaceSec);
|
|
+ if (pic.render)
|
|
+ pic.render->state &= ~FF_VDPAU_STATE_USED_FOR_RENDER;
|
|
+ }
|
|
+ else if (msg->signal == COutputDataProtocol::RETURNPIC)
|
|
+ {
|
|
+ CVdpauRenderPicture *pic;
|
|
+ pic = *((CVdpauRenderPicture**)msg->data);
|
|
+ ProcessReturnPicture(pic);
|
|
+ }
|
|
+ msg->Release();
|
|
+ }
|
|
+
|
|
+ while (m_dataPort.ReceiveInMessage(&msg))
|
|
+ {
|
|
+ if (msg->signal == COutputDataProtocol::PICTURE)
|
|
+ {
|
|
+ CVdpauRenderPicture *pic;
|
|
+ pic = *((CVdpauRenderPicture**)msg->data);
|
|
+ ProcessReturnPicture(pic);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ // reset used render flag which was cleared on mixer flush
|
|
+ std::deque<CVdpauRenderPicture*>::iterator it;
|
|
+ for (it = m_bufferPool.usedRenderPics.begin(); it != m_bufferPool.usedRenderPics.end(); ++it)
|
|
+ {
|
|
+ if ((*it)->DVDPic.format == RENDER_FMT_VDPAU_420)
|
|
+ {
|
|
+ std::map<VdpVideoSurface, VdpauBufferPool::GLVideoSurface>::iterator it2;
|
|
+ it2 = m_bufferPool.glVideoSurfaceMap.find((*it)->sourceIdx);
|
|
+ if (it2 == m_bufferPool.glVideoSurfaceMap.end())
|
|
+ {
|
|
+ CLog::Log(LOGDEBUG, "COutput::Flush - gl surface not found");
|
|
+ continue;
|
|
+ }
|
|
+ vdpau_render_state *render = it2->second.sourceVuv;
|
|
+ if (render)
|
|
+ render->state |= FF_VDPAU_STATE_USED_FOR_RENDER;
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
+bool COutput::HasWork()
|
|
+{
|
|
+ if (m_config.usePixmaps)
|
|
+ {
|
|
+ if (!m_bufferPool.processedPics.empty() && FindFreePixmap() >= 0)
|
|
+ return true;
|
|
+ if (!m_bufferPool.notVisiblePixmaps.empty() && !m_bufferPool.freeRenderPics.empty())
|
|
+ return true;
|
|
+ return false;
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ if (!m_bufferPool.processedPics.empty() && !m_bufferPool.freeRenderPics.empty())
|
|
+ return true;
|
|
+ return false;
|
|
+ }
|
|
+}
|
|
+
|
|
+CVdpauRenderPicture* COutput::ProcessMixerPicture()
|
|
+{
|
|
+ CVdpauRenderPicture *retPic = 0;
|
|
+
|
|
+ if (m_config.usePixmaps)
|
|
+ {
|
|
+ if (!m_bufferPool.processedPics.empty() && FindFreePixmap() >= 0)
|
|
+ {
|
|
+ unsigned int i = FindFreePixmap();
|
|
+ VdpauBufferPool::Pixmaps *pixmap = &m_bufferPool.pixmaps[i];
|
|
+ pixmap->used = true;
|
|
+ CVdpauProcessedPicture pic = m_bufferPool.processedPics.front();
|
|
+ m_bufferPool.processedPics.pop();
|
|
+ pixmap->surface = pic.outputSurface;
|
|
+ pixmap->DVDPic = pic.DVDPic;
|
|
+ pixmap->id = i;
|
|
+ m_bufferPool.notVisiblePixmaps.push_back(pixmap);
|
|
+ VdpStatus vdp_st;
|
|
+ m_config.vdpProcs.vdp_presentation_queue_display(pixmap->vdp_flip_queue,
|
|
+ pixmap->surface,0,0,0);
|
|
+ }
|
|
+ if (!m_bufferPool.notVisiblePixmaps.empty() && !m_bufferPool.freeRenderPics.empty())
|
|
+ {
|
|
+ VdpStatus vdp_st;
|
|
+ VdpTime time;
|
|
+ VdpPresentationQueueStatus status;
|
|
+ VdpauBufferPool::Pixmaps *pixmap = m_bufferPool.notVisiblePixmaps.front();
|
|
+ vdp_st = m_config.vdpProcs.vdp_presentation_queue_query_surface_status(
|
|
+ pixmap->vdp_flip_queue, pixmap->surface, &status, &time);
|
|
+
|
|
+ if (vdp_st == VDP_STATUS_OK && status == VDP_PRESENTATION_QUEUE_STATUS_VISIBLE)
|
|
+ {
|
|
+ retPic = m_bufferPool.freeRenderPics.front();
|
|
+ m_bufferPool.freeRenderPics.pop_front();
|
|
+ m_bufferPool.usedRenderPics.push_back(retPic);
|
|
+ retPic->sourceIdx = pixmap->id;
|
|
+ retPic->DVDPic = pixmap->DVDPic;
|
|
+ retPic->valid = true;
|
|
+ retPic->texture[0] = pixmap->texture;
|
|
+ retPic->crop = CRect(0,0,0,0);
|
|
+ m_bufferPool.notVisiblePixmaps.pop_front();
|
|
+ m_mixer.m_dataPort.SendOutMessage(CMixerDataProtocol::BUFFER, &pixmap->surface, sizeof(pixmap->surface));
|
|
+ }
|
|
+ }
|
|
+ } // pixmap
|
|
+ else if (!m_bufferPool.processedPics.empty() && !m_bufferPool.freeRenderPics.empty())
|
|
+ {
|
|
+ retPic = m_bufferPool.freeRenderPics.front();
|
|
+ m_bufferPool.freeRenderPics.pop_front();
|
|
+ m_bufferPool.usedRenderPics.push_back(retPic);
|
|
+ CVdpauProcessedPicture procPic = m_bufferPool.processedPics.front();
|
|
+ m_bufferPool.processedPics.pop();
|
|
+
|
|
+ retPic->DVDPic = procPic.DVDPic;
|
|
+ retPic->valid = true;
|
|
+ if (retPic->DVDPic.format == RENDER_FMT_VDPAU)
|
|
+ {
|
|
+ m_config.useInteropYuv = false;
|
|
+ m_bufferPool.numOutputSurfaces = NUM_RENDER_PICS;
|
|
+ EnsureBufferPool();
|
|
+ GLMapSurfaces();
|
|
+ retPic->sourceIdx = procPic.outputSurface;
|
|
+ retPic->texture[0] = m_bufferPool.glOutputSurfaceMap[procPic.outputSurface].texture[0];
|
|
+ retPic->crop = CRect(0,0,0,0);
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ m_config.useInteropYuv = true;
|
|
+ GLMapSurfaces();
|
|
+ retPic->sourceIdx = procPic.render->surface;
|
|
+ for (unsigned int i=0; i<4; ++i)
|
|
+ retPic->texture[i] = m_bufferPool.glVideoSurfaceMap[procPic.render->surface].texture[i];
|
|
+ retPic->texWidth = m_config.surfaceWidth;
|
|
+ retPic->texHeight = m_config.surfaceHeight;
|
|
+ retPic->crop.x1 = 0;
|
|
+ retPic->crop.y1 = 0;
|
|
+ retPic->crop.x2 = m_config.surfaceWidth - m_config.vidWidth;
|
|
+ retPic->crop.y2 = m_config.surfaceHeight - m_config.vidHeight;
|
|
+ }
|
|
+ }
|
|
+ return retPic;
|
|
+}
|
|
+
|
|
+void COutput::ProcessReturnPicture(CVdpauRenderPicture *pic)
|
|
+{
|
|
+ std::deque<CVdpauRenderPicture*>::iterator it;
|
|
+ it = std::find(m_bufferPool.usedRenderPics.begin(), m_bufferPool.usedRenderPics.end(), pic);
|
|
+ if (it == m_bufferPool.usedRenderPics.end())
|
|
+ {
|
|
+ CLog::Log(LOGWARNING, "COutput::ProcessReturnPicture - pic not found");
|
|
+ return;
|
|
+ }
|
|
+ m_bufferPool.usedRenderPics.erase(it);
|
|
+ m_bufferPool.freeRenderPics.push_back(pic);
|
|
+ if (!pic->valid)
|
|
+ {
|
|
+ CLog::Log(LOGDEBUG, "COutput::%s - return of invalid render pic", __FUNCTION__);
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ if (m_config.usePixmaps)
|
|
+ {
|
|
+ m_bufferPool.pixmaps[pic->sourceIdx].used = false;
|
|
+ return;
|
|
+ }
|
|
+ else if (pic->DVDPic.format == RENDER_FMT_VDPAU_420)
|
|
+ {
|
|
+ std::map<VdpVideoSurface, VdpauBufferPool::GLVideoSurface>::iterator it;
|
|
+ it = m_bufferPool.glVideoSurfaceMap.find(pic->sourceIdx);
|
|
+ if (it == m_bufferPool.glVideoSurfaceMap.end())
|
|
+ {
|
|
+ CLog::Log(LOGDEBUG, "COutput::ProcessReturnPicture - gl surface not found");
|
|
+ return;
|
|
+ }
|
|
+ vdpau_render_state *render = it->second.sourceVuv;
|
|
+ CSingleLock lock(*m_config.videoSurfaceSec);
|
|
+ render->state &= ~FF_VDPAU_STATE_USED_FOR_RENDER;
|
|
+ }
|
|
+ else if (pic->DVDPic.format == RENDER_FMT_VDPAU)
|
|
+ {
|
|
+ std::map<VdpOutputSurface, VdpauBufferPool::GLVideoSurface>::iterator it;
|
|
+ it = m_bufferPool.glOutputSurfaceMap.find(pic->sourceIdx);
|
|
+ if (it == m_bufferPool.glOutputSurfaceMap.end())
|
|
+ {
|
|
+ CLog::Log(LOGDEBUG, "COutput::ProcessReturnPicture - gl surface not found");
|
|
+ return;
|
|
+ }
|
|
+ VdpOutputSurface outSurf = it->second.sourceRgb;
|
|
+ m_mixer.m_dataPort.SendOutMessage(CMixerDataProtocol::BUFFER, &outSurf, sizeof(outSurf));
|
|
+ }
|
|
+}
|
|
+
|
|
+int COutput::FindFreePixmap()
|
|
+{
|
|
+ // find free pixmap
|
|
+ unsigned int i;
|
|
+ for (i = 0; i < m_bufferPool.pixmaps.size(); ++i)
|
|
+ {
|
|
+ if (!m_bufferPool.pixmaps[i].used)
|
|
+ break;
|
|
+ }
|
|
+ if (i == m_bufferPool.pixmaps.size())
|
|
+ return -1;
|
|
+ else
|
|
+ return i;
|
|
+}
|
|
+
|
|
+bool COutput::EnsureBufferPool()
|
|
+{
|
|
+ VdpStatus vdp_st;
|
|
+
|
|
+ // Creation of outputSurfaces
|
|
+ VdpOutputSurface outputSurface;
|
|
+ for (int i = m_bufferPool.outputSurfaces.size(); i < m_bufferPool.numOutputSurfaces; i++)
|
|
+ {
|
|
+ vdp_st = m_config.vdpProcs.vdp_output_surface_create(m_config.vdpDevice,
|
|
+ VDP_RGBA_FORMAT_B8G8R8A8,
|
|
+ m_config.outWidth,
|
|
+ m_config.outHeight,
|
|
+ &outputSurface);
|
|
+ if (CheckStatus(vdp_st, __LINE__))
|
|
+ return false;
|
|
+ m_bufferPool.outputSurfaces.push_back(outputSurface);
|
|
+
|
|
+ m_mixer.m_dataPort.SendOutMessage(CMixerDataProtocol::BUFFER,
|
|
+ &outputSurface,
|
|
+ sizeof(VdpOutputSurface));
|
|
+ CLog::Log(LOGNOTICE, "VDPAU::COutput::InitBufferPool - Output Surface created");
|
|
+ }
|
|
+
|
|
+
|
|
+ if (m_config.usePixmaps && m_bufferPool.pixmaps.empty())
|
|
+ {
|
|
+ // create pixmpas
|
|
+ VdpauBufferPool::Pixmaps pixmap;
|
|
+ int numPixmaps = NUM_RENDER_PICS;
|
|
+ for (unsigned int i = 0; i < numPixmaps; i++)
|
|
+ {
|
|
+ pixmap.pixmap = None;
|
|
+ pixmap.glPixmap = None;
|
|
+ pixmap.vdp_flip_queue = VDP_INVALID_HANDLE;
|
|
+ pixmap.vdp_flip_target = VDP_INVALID_HANDLE;
|
|
+ MakePixmap(pixmap);
|
|
+ glXMakeCurrent(m_Display, None, NULL);
|
|
+ vdp_st = m_config.vdpProcs.vdp_presentation_queue_target_create_x11(m_config.vdpDevice,
|
|
+ pixmap.pixmap, //x_window,
|
|
+ &pixmap.vdp_flip_target);
|
|
+
|
|
+ CheckStatus(vdp_st, __LINE__);
|
|
+
|
|
+ vdp_st = m_config.vdpProcs.vdp_presentation_queue_create(m_config.vdpDevice,
|
|
+ pixmap.vdp_flip_target,
|
|
+ &pixmap.vdp_flip_queue);
|
|
+ CheckStatus(vdp_st, __LINE__);
|
|
+ glXMakeCurrent(m_Display, m_glPixmap, m_glContext);
|
|
+
|
|
+ pixmap.id = i;
|
|
+ pixmap.used = false;
|
|
+ m_bufferPool.pixmaps.push_back(pixmap);
|
|
+ }
|
|
+ GLBindPixmaps();
|
|
+ }
|
|
+
|
|
+ return true;
|
|
+}
|
|
+
|
|
+void COutput::ReleaseBufferPool()
|
|
+{
|
|
+ VdpStatus vdp_st;
|
|
+
|
|
+ CSingleLock lock(m_bufferPool.renderPicSec);
|
|
+
|
|
+ if (m_config.usePixmaps)
|
|
+ {
|
|
+ for (unsigned int i = 0; i < m_bufferPool.pixmaps.size(); ++i)
|
|
+ {
|
|
+ if (m_bufferPool.pixmaps[i].vdp_flip_queue != VDP_INVALID_HANDLE)
|
|
+ {
|
|
+ vdp_st = m_config.vdpProcs.vdp_presentation_queue_destroy(m_bufferPool.pixmaps[i].vdp_flip_queue);
|
|
+ CheckStatus(vdp_st, __LINE__);
|
|
+ }
|
|
+ if (m_bufferPool.pixmaps[i].vdp_flip_target != VDP_INVALID_HANDLE)
|
|
+ {
|
|
+ vdp_st = m_config.vdpProcs.vdp_presentation_queue_target_destroy(m_bufferPool.pixmaps[i].vdp_flip_target);
|
|
+ CheckStatus(vdp_st, __LINE__);
|
|
+ }
|
|
+ if (m_bufferPool.pixmaps[i].glPixmap)
|
|
+ {
|
|
+ glXDestroyPixmap(m_Display, m_bufferPool.pixmaps[i].glPixmap);
|
|
+ }
|
|
+ if (m_bufferPool.pixmaps[i].pixmap)
|
|
+ {
|
|
+ XFreePixmap(m_Display, m_bufferPool.pixmaps[i].pixmap);
|
|
+ }
|
|
+ }
|
|
+ m_bufferPool.pixmaps.clear();
|
|
+ }
|
|
+
|
|
+ // release all output surfaces
|
|
+ for (unsigned int i = 0; i < m_bufferPool.outputSurfaces.size(); ++i)
|
|
+ {
|
|
+ if (m_bufferPool.outputSurfaces[i] == VDP_INVALID_HANDLE)
|
|
+ continue;
|
|
+ vdp_st = m_config.vdpProcs.vdp_output_surface_destroy(m_bufferPool.outputSurfaces[i]);
|
|
+ CheckStatus(vdp_st, __LINE__);
|
|
+ }
|
|
+ m_bufferPool.outputSurfaces.clear();
|
|
+
|
|
+ // invalidate all used render pictures
|
|
+ for (unsigned int i = 0; i < m_bufferPool.usedRenderPics.size(); ++i)
|
|
+ {
|
|
+ m_bufferPool.usedRenderPics[i]->valid = false;
|
|
+ }
|
|
+}
|
|
+
|
|
+void COutput::InitMixer()
|
|
+{
|
|
+ for (unsigned int i = 0; i < m_bufferPool.outputSurfaces.size(); ++i)
|
|
+ {
|
|
+ m_mixer.m_dataPort.SendOutMessage(CMixerDataProtocol::BUFFER,
|
|
+ &m_bufferPool.outputSurfaces[i],
|
|
+ sizeof(VdpOutputSurface));
|
|
+ }
|
|
+}
|
|
+
|
|
+bool COutput::MakePixmap(VdpauBufferPool::Pixmaps &pixmap)
|
|
+{
|
|
+ CLog::Log(LOGNOTICE,"Creating %ix%i pixmap", m_config.outWidth, m_config.outHeight);
|
|
+
|
|
+ // Get our window attribs.
|
|
+ XWindowAttributes wndattribs;
|
|
+ XGetWindowAttributes(m_Display, g_Windowing.GetWindow(), &wndattribs);
|
|
+
|
|
+ pixmap.pixmap = XCreatePixmap(m_Display,
|
|
+ g_Windowing.GetWindow(),
|
|
+ m_config.outWidth,
|
|
+ m_config.outHeight,
|
|
+ wndattribs.depth);
|
|
+ if (!pixmap.pixmap)
|
|
+ {
|
|
+ CLog::Log(LOGERROR, "VDPAU::COUtput::MakePixmap - GLX Error: MakePixmap: Unable to create XPixmap");
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+// XGCValues values = {};
|
|
+// GC xgc;
|
|
+// values.foreground = BlackPixel (m_Display, DefaultScreen (m_Display));
|
|
+// xgc = XCreateGC(m_Display, pixmap.pixmap, GCForeground, &values);
|
|
+// XFillRectangle(m_Display, pixmap.pixmap, xgc, 0, 0, m_config.outWidth, m_config.outHeight);
|
|
+// XFreeGC(m_Display, xgc);
|
|
+
|
|
+ if(!MakePixmapGL(pixmap))
|
|
+ return false;
|
|
+
|
|
+ return true;
|
|
+}
|
|
+
|
|
+bool COutput::MakePixmapGL(VdpauBufferPool::Pixmaps &pixmap)
|
|
+{
|
|
+ int num=0;
|
|
+ int fbConfigIndex = 0;
|
|
+
|
|
+ int doubleVisAttributes[] = {
|
|
+ GLX_RENDER_TYPE, GLX_RGBA_BIT,
|
|
+ GLX_RED_SIZE, 8,
|
|
+ GLX_GREEN_SIZE, 8,
|
|
+ GLX_BLUE_SIZE, 8,
|
|
+ GLX_ALPHA_SIZE, 8,
|
|
+ GLX_DEPTH_SIZE, 8,
|
|
+ GLX_DRAWABLE_TYPE, GLX_PIXMAP_BIT,
|
|
+ GLX_BIND_TO_TEXTURE_RGBA_EXT, True,
|
|
+ GLX_DOUBLEBUFFER, False,
|
|
+ GLX_Y_INVERTED_EXT, True,
|
|
+ GLX_X_RENDERABLE, True,
|
|
+ None
|
|
+ };
|
|
+
|
|
+ int pixmapAttribs[] = {
|
|
+ GLX_TEXTURE_TARGET_EXT, GLX_TEXTURE_2D_EXT,
|
|
+ GLX_TEXTURE_FORMAT_EXT, GLX_TEXTURE_FORMAT_RGBA_EXT,
|
|
+ None
|
|
+ };
|
|
+
|
|
+ GLXFBConfig *fbConfigs;
|
|
+ fbConfigs = glXChooseFBConfig(m_Display, g_Windowing.GetCurrentScreen(), doubleVisAttributes, &num);
|
|
+ if (fbConfigs==NULL)
|
|
+ {
|
|
+ CLog::Log(LOGERROR, "VDPAU::COutput::MakPixmapGL - No compatible framebuffers found");
|
|
+ return false;
|
|
+ }
|
|
+ fbConfigIndex = 0;
|
|
+
|
|
+ pixmap.glPixmap = glXCreatePixmap(m_Display, fbConfigs[fbConfigIndex], pixmap.pixmap, pixmapAttribs);
|
|
+
|
|
+ if (!pixmap.glPixmap)
|
|
+ {
|
|
+ CLog::Log(LOGERROR, "VDPAU::COutput::MakPixmapGL - Could not create Pixmap");
|
|
+ XFree(fbConfigs);
|
|
+ return false;
|
|
+ }
|
|
+ XFree(fbConfigs);
|
|
+ return true;
|
|
+}
|
|
+
|
|
+bool COutput::GLInit()
|
|
+{
|
|
+ glXBindTexImageEXT = NULL;
|
|
+ glXReleaseTexImageEXT = NULL;
|
|
+#ifdef GL_NV_vdpau_interop
|
|
+ glVDPAUInitNV = NULL;
|
|
+ glVDPAUFiniNV = NULL;
|
|
+ glVDPAURegisterOutputSurfaceNV = NULL;
|
|
+ glVDPAURegisterVideoSurfaceNV = NULL;
|
|
+ glVDPAUIsSurfaceNV = NULL;
|
|
+ glVDPAUUnregisterSurfaceNV = NULL;
|
|
+ glVDPAUSurfaceAccessNV = NULL;
|
|
+ glVDPAUMapSurfacesNV = NULL;
|
|
+ glVDPAUUnmapSurfacesNV = NULL;
|
|
+ glVDPAUGetSurfaceivNV = NULL;
|
|
+#endif
|
|
+
|
|
+ m_config.usePixmaps = !g_guiSettings.GetBool("videoplayer.usevdpauinterop");
|
|
+
|
|
+#ifdef GL_NV_vdpau_interop
|
|
+ if (glewIsSupported("GL_NV_vdpau_interop"))
|
|
+ {
|
|
+ if (!glVDPAUInitNV)
|
|
+ glVDPAUInitNV = (PFNGLVDPAUINITNVPROC)glXGetProcAddress((GLubyte *) "glVDPAUInitNV");
|
|
+ if (!glVDPAUFiniNV)
|
|
+ glVDPAUFiniNV = (PFNGLVDPAUFININVPROC)glXGetProcAddress((GLubyte *) "glVDPAUFiniNV");
|
|
+ if (!glVDPAURegisterOutputSurfaceNV)
|
|
+ glVDPAURegisterOutputSurfaceNV = (PFNGLVDPAUREGISTEROUTPUTSURFACENVPROC)glXGetProcAddress((GLubyte *) "glVDPAURegisterOutputSurfaceNV");
|
|
+ if (!glVDPAURegisterVideoSurfaceNV)
|
|
+ glVDPAURegisterVideoSurfaceNV = (PFNGLVDPAUREGISTERVIDEOSURFACENVPROC)glXGetProcAddress((GLubyte *) "glVDPAURegisterVideoSurfaceNV");
|
|
+ if (!glVDPAUIsSurfaceNV)
|
|
+ glVDPAUIsSurfaceNV = (PFNGLVDPAUISSURFACENVPROC)glXGetProcAddress((GLubyte *) "glVDPAUIsSurfaceNV");
|
|
+ if (!glVDPAUUnregisterSurfaceNV)
|
|
+ glVDPAUUnregisterSurfaceNV = (PFNGLVDPAUUNREGISTERSURFACENVPROC)glXGetProcAddress((GLubyte *) "glVDPAUUnregisterSurfaceNV");
|
|
+ if (!glVDPAUSurfaceAccessNV)
|
|
+ glVDPAUSurfaceAccessNV = (PFNGLVDPAUSURFACEACCESSNVPROC)glXGetProcAddress((GLubyte *) "glVDPAUSurfaceAccessNV");
|
|
+ if (!glVDPAUMapSurfacesNV)
|
|
+ glVDPAUMapSurfacesNV = (PFNGLVDPAUMAPSURFACESNVPROC)glXGetProcAddress((GLubyte *) "glVDPAUMapSurfacesNV");
|
|
+ if (!glVDPAUUnmapSurfacesNV)
|
|
+ glVDPAUUnmapSurfacesNV = (PFNGLVDPAUUNMAPSURFACESNVPROC)glXGetProcAddress((GLubyte *) "glVDPAUUnmapSurfacesNV");
|
|
+ if (!glVDPAUGetSurfaceivNV)
|
|
+ glVDPAUGetSurfaceivNV = (PFNGLVDPAUGETSURFACEIVNVPROC)glXGetProcAddress((GLubyte *) "glVDPAUGetSurfaceivNV");
|
|
+
|
|
+ CLog::Log(LOGNOTICE, "VDPAU::COutput GL interop supported");
|
|
+ }
|
|
+ else
|
|
+#endif
|
|
+ {
|
|
+ m_config.usePixmaps = true;
|
|
+ g_guiSettings.SetBool("videoplayer.usevdpauinterop",false);
|
|
+ g_guiSettings.SetBool("videoplayer.usevdpauinteropyuv",false);
|
|
+ }
|
|
+ if (!glXBindTexImageEXT)
|
|
+ glXBindTexImageEXT = (PFNGLXBINDTEXIMAGEEXTPROC)glXGetProcAddress((GLubyte *) "glXBindTexImageEXT");
|
|
+ if (!glXReleaseTexImageEXT)
|
|
+ glXReleaseTexImageEXT = (PFNGLXRELEASETEXIMAGEEXTPROC)glXGetProcAddress((GLubyte *) "glXReleaseTexImageEXT");
|
|
+
|
|
+#ifdef GL_NV_vdpau_interop
|
|
+ if (!m_config.usePixmaps)
|
|
+ {
|
|
+ while (glGetError() != GL_NO_ERROR);
|
|
+ glVDPAUInitNV(reinterpret_cast<void*>(m_config.vdpDevice), reinterpret_cast<void*>(m_config.vdpProcs.vdp_get_proc_address));
|
|
+ if (glGetError() != GL_NO_ERROR)
|
|
+ {
|
|
+ CLog::Log(LOGERROR, "VDPAU::COutput - GLInitInterop glVDPAUInitNV failed");
|
|
+ m_vdpError = true;
|
|
+ return false;
|
|
+ }
|
|
+ CLog::Log(LOGNOTICE, "VDPAU::COutput: vdpau gl interop initialized");
|
|
+ }
|
|
+#endif
|
|
+ return true;
|
|
+}
|
|
+
|
|
+void COutput::GLMapSurfaces()
|
|
+{
|
|
+#ifdef GL_NV_vdpau_interop
|
|
+ if (m_config.usePixmaps)
|
|
+ return;
|
|
+
|
|
+ if (m_config.useInteropYuv)
|
|
+ {
|
|
+ VdpauBufferPool::GLVideoSurface glSurface;
|
|
+ if (m_config.videoSurfaces->size() != m_bufferPool.glVideoSurfaceMap.size())
|
|
+ {
|
|
+ CSingleLock lock(*m_config.videoSurfaceSec);
|
|
+ for (int i = 0; i < m_config.videoSurfaces->size(); i++)
|
|
+ {
|
|
+ if ((*m_config.videoSurfaces)[i]->surface == VDP_INVALID_HANDLE)
|
|
+ continue;
|
|
+
|
|
+ if (m_bufferPool.glVideoSurfaceMap.find((*m_config.videoSurfaces)[i]->surface) == m_bufferPool.glVideoSurfaceMap.end())
|
|
+ {
|
|
+ glSurface.sourceVuv = (*m_config.videoSurfaces)[i];
|
|
+ while (glGetError() != GL_NO_ERROR) ;
|
|
+ glGenTextures(4, glSurface.texture);
|
|
+ if (glGetError() != GL_NO_ERROR)
|
|
+ {
|
|
+ CLog::Log(LOGERROR, "VDPAU::COutput error creating texture");
|
|
+ m_vdpError = true;
|
|
+ }
|
|
+ glSurface.glVdpauSurface = glVDPAURegisterVideoSurfaceNV(reinterpret_cast<void*>((*m_config.videoSurfaces)[i]->surface),
|
|
+ GL_TEXTURE_2D, 4, glSurface.texture);
|
|
+
|
|
+ if (glGetError() != GL_NO_ERROR)
|
|
+ {
|
|
+ CLog::Log(LOGERROR, "VDPAU::COutput error register video surface");
|
|
+ m_vdpError = true;
|
|
+ }
|
|
+ glVDPAUSurfaceAccessNV(glSurface.glVdpauSurface, GL_READ_ONLY);
|
|
+ if (glGetError() != GL_NO_ERROR)
|
|
+ {
|
|
+ CLog::Log(LOGERROR, "VDPAU::COutput error setting access");
|
|
+ m_vdpError = true;
|
|
+ }
|
|
+ glVDPAUMapSurfacesNV(1, &glSurface.glVdpauSurface);
|
|
+ if (glGetError() != GL_NO_ERROR)
|
|
+ {
|
|
+ CLog::Log(LOGERROR, "VDPAU::COutput error mapping surface");
|
|
+ m_vdpError = true;
|
|
+ }
|
|
+ m_bufferPool.glVideoSurfaceMap[(*m_config.videoSurfaces)[i]->surface] = glSurface;
|
|
+ if (m_vdpError)
|
|
+ return;
|
|
+ CLog::Log(LOGNOTICE, "VDPAU::COutput registered surface");
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ if (m_bufferPool.glOutputSurfaceMap.size() != m_bufferPool.numOutputSurfaces)
|
|
+ {
|
|
+ VdpauBufferPool::GLVideoSurface glSurface;
|
|
+ for (int i=m_bufferPool.glOutputSurfaceMap.size(); i<m_bufferPool.outputSurfaces.size(); i++)
|
|
+ {
|
|
+ glSurface.sourceRgb = m_bufferPool.outputSurfaces[i];
|
|
+ glGenTextures(1, glSurface.texture);
|
|
+ glSurface.glVdpauSurface = glVDPAURegisterOutputSurfaceNV(reinterpret_cast<void*>(m_bufferPool.outputSurfaces[i]),
|
|
+ GL_TEXTURE_2D, 1, glSurface.texture);
|
|
+ if (glGetError() != GL_NO_ERROR)
|
|
+ {
|
|
+ CLog::Log(LOGERROR, "VDPAU::COutput error register output surface");
|
|
+ m_vdpError = true;
|
|
+ }
|
|
+ glVDPAUSurfaceAccessNV(glSurface.glVdpauSurface, GL_READ_ONLY);
|
|
+ if (glGetError() != GL_NO_ERROR)
|
|
+ {
|
|
+ CLog::Log(LOGERROR, "VDPAU::COutput error setting access");
|
|
+ m_vdpError = true;
|
|
+ }
|
|
+ glVDPAUMapSurfacesNV(1, &glSurface.glVdpauSurface);
|
|
+ if (glGetError() != GL_NO_ERROR)
|
|
+ {
|
|
+ CLog::Log(LOGERROR, "VDPAU::COutput error mapping surface");
|
|
+ m_vdpError = true;
|
|
+ }
|
|
+ m_bufferPool.glOutputSurfaceMap[m_bufferPool.outputSurfaces[i]] = glSurface;
|
|
+ if (m_vdpError)
|
|
+ return;
|
|
+ }
|
|
+ CLog::Log(LOGNOTICE, "VDPAU::COutput registered output surfaces");
|
|
+ }
|
|
+ }
|
|
+#endif
|
|
+}
|
|
+
|
|
+void COutput::GLUnmapSurfaces()
|
|
+{
|
|
+#ifdef GL_NV_vdpau_interop
|
|
+ if (m_config.usePixmaps)
|
|
+ return;
|
|
+
|
|
+ { CSingleLock lock(*m_config.videoSurfaceSec);
|
|
+ std::map<VdpVideoSurface, VdpauBufferPool::GLVideoSurface>::iterator it;
|
|
+ for (it = m_bufferPool.glVideoSurfaceMap.begin(); it != m_bufferPool.glVideoSurfaceMap.end(); ++it)
|
|
+ {
|
|
+ glVDPAUUnregisterSurfaceNV(it->second.glVdpauSurface);
|
|
+ glDeleteTextures(4, it->second.texture);
|
|
+ }
|
|
+ m_bufferPool.glVideoSurfaceMap.clear();
|
|
+ }
|
|
+
|
|
+ std::map<VdpOutputSurface, VdpauBufferPool::GLVideoSurface>::iterator it;
|
|
+ for (it = m_bufferPool.glOutputSurfaceMap.begin(); it != m_bufferPool.glOutputSurfaceMap.end(); ++it)
|
|
+ {
|
|
+ glVDPAUUnregisterSurfaceNV(it->second.glVdpauSurface);
|
|
+ glDeleteTextures(1, it->second.texture);
|
|
+ }
|
|
+ m_bufferPool.glOutputSurfaceMap.clear();
|
|
+
|
|
+ glVDPAUFiniNV();
|
|
+
|
|
+ CLog::Log(LOGNOTICE, "VDPAU::COutput: vdpau gl interop finished");
|
|
+
|
|
+#endif
|
|
+}
|
|
+
|
|
+void COutput::GLBindPixmaps()
|
|
+{
|
|
+ if (!m_config.usePixmaps)
|
|
+ return;
|
|
+
|
|
+ for (unsigned int i = 0; i < m_bufferPool.pixmaps.size(); i++)
|
|
+ {
|
|
+ // create texture
|
|
+ glGenTextures(1, &m_bufferPool.pixmaps[i].texture);
|
|
+
|
|
+ //bind texture
|
|
+ glBindTexture(GL_TEXTURE_2D, m_bufferPool.pixmaps[i].texture);
|
|
+
|
|
+ // bind pixmap
|
|
+ glXBindTexImageEXT(m_Display, m_bufferPool.pixmaps[i].glPixmap, GLX_FRONT_LEFT_EXT, NULL);
|
|
+
|
|
+ glBindTexture(GL_TEXTURE_2D, 0);
|
|
+ }
|
|
+
|
|
+ CLog::Log(LOGNOTICE, "VDPAU::COutput: bound pixmaps");
|
|
+}
|
|
+
|
|
+void COutput::GLUnbindPixmaps()
|
|
+{
|
|
+ if (!m_config.usePixmaps)
|
|
+ return;
|
|
+
|
|
+ for (unsigned int i = 0; i < m_bufferPool.pixmaps.size(); i++)
|
|
+ {
|
|
+ // create texture
|
|
+ if (!glIsTexture(m_bufferPool.pixmaps[i].texture))
|
|
+ continue;
|
|
+
|
|
+ //bind texture
|
|
+ glBindTexture(GL_TEXTURE_2D, m_bufferPool.pixmaps[i].texture);
|
|
+
|
|
+ // release pixmap
|
|
+ glXReleaseTexImageEXT(m_Display, m_bufferPool.pixmaps[i].glPixmap, GLX_FRONT_LEFT_EXT);
|
|
+
|
|
+ glBindTexture(GL_TEXTURE_2D, 0);
|
|
+
|
|
+ glDeleteTextures(1, &m_bufferPool.pixmaps[i].texture);
|
|
+ }
|
|
+ CLog::Log(LOGNOTICE, "VDPAU::COutput: unbound pixmaps");
|
|
+}
|
|
+
|
|
+bool COutput::CheckStatus(VdpStatus vdp_st, int line)
|
|
+{
|
|
+ if (vdp_st != VDP_STATUS_OK)
|
|
+ {
|
|
+ CLog::Log(LOGERROR, " (VDPAU) Error: %s(%d) at %s:%d\n", m_config.vdpProcs.vdp_get_error_string(vdp_st), vdp_st, __FILE__, line);
|
|
+ m_vdpError = true;
|
|
+ return true;
|
|
+ }
|
|
+ return false;
|
|
+}
|
|
+
|
|
+bool COutput::CreateGlxContext()
|
|
+{
|
|
+ GLXContext glContext;
|
|
+ Window window;
|
|
+
|
|
+ m_Display = g_Windowing.GetDisplay();
|
|
+ glContext = g_Windowing.GetGlxContext();
|
|
+ m_Window = g_Windowing.GetWindow();
|
|
+
|
|
+ // Get our window attribs.
|
|
+ XWindowAttributes wndattribs;
|
|
+ XGetWindowAttributes(m_Display, m_Window, &wndattribs);
|
|
+
|
|
+ // Get visual Info
|
|
+ XVisualInfo visInfo;
|
|
+ visInfo.visualid = wndattribs.visual->visualid;
|
|
+ int nvisuals = 0;
|
|
+ XVisualInfo* visuals = XGetVisualInfo(m_Display, VisualIDMask, &visInfo, &nvisuals);
|
|
+ if (nvisuals != 1)
|
|
+ {
|
|
+ CLog::Log(LOGERROR, "VDPAU::COutput::CreateGlxContext - could not find visual");
|
|
+ return false;
|
|
+ }
|
|
+ visInfo = visuals[0];
|
|
+ XFree(visuals);
|
|
+
|
|
+ m_pixmap = XCreatePixmap(m_Display,
|
|
+ m_Window,
|
|
+ 192,
|
|
+ 108,
|
|
+ visInfo.depth);
|
|
+ if (!m_pixmap)
|
|
+ {
|
|
+ CLog::Log(LOGERROR, "VDPAU::COutput::CreateGlxContext - Unable to create XPixmap");
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ // create gl pixmap
|
|
+ m_glPixmap = glXCreateGLXPixmap(m_Display, &visInfo, m_pixmap);
|
|
+
|
|
+ if (!m_glPixmap)
|
|
+ {
|
|
+ CLog::Log(LOGINFO, "VDPAU::COutput::CreateGlxContext - Could not create glPixmap");
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ m_glContext = glXCreateContext(m_Display, &visInfo, glContext, True);
|
|
+
|
|
+ if (!glXMakeCurrent(m_Display, m_glPixmap, m_glContext))
|
|
+ {
|
|
+ CLog::Log(LOGINFO, "VDPAU::COutput::CreateGlxContext - Could not make Pixmap current");
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ CLog::Log(LOGNOTICE, "VDPAU::COutput::CreateGlxContext - created context");
|
|
+ return true;
|
|
+}
|
|
+
|
|
+bool COutput::DestroyGlxContext()
|
|
+{
|
|
+ if (m_glContext)
|
|
+ {
|
|
+ glXMakeCurrent(m_Display, None, NULL);
|
|
+ glXDestroyContext(m_Display, m_glContext);
|
|
+ }
|
|
+ m_glContext = 0;
|
|
+
|
|
+ if (m_glPixmap)
|
|
+ glXDestroyPixmap(m_Display, m_glPixmap);
|
|
+ m_glPixmap = 0;
|
|
+
|
|
+ if (m_pixmap)
|
|
+ XFreePixmap(m_Display, m_pixmap);
|
|
+ m_pixmap = 0;
|
|
+
|
|
+ return true;
|
|
+}
|
|
+
|
|
#endif
|
|
diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.h
|
|
index 2f53edf..4d1559c 100644
|
|
--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.h
|
|
+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.h
|
|
@@ -1,5 +1,3 @@
|
|
-
|
|
-#pragma once
|
|
/*
|
|
* Copyright (C) 2005-2012 Team XBMC
|
|
* http://www.xbmc.org
|
|
@@ -20,9 +18,32 @@
|
|
*
|
|
*/
|
|
|
|
+/**
|
|
+ * design goals:
|
|
+ * - improve performance
|
|
+ * max out hw resources: e.g. make 1080p60 play on ION2
|
|
+ * allow advanced de-interlacing on ION
|
|
+ *
|
|
+ * - add vdpau/opengl interop
|
|
+ *
|
|
+ * - remove tight dependency to render thread
|
|
+ * prior design needed to hijack render thread in order to do
|
|
+ * gl interop functions. In particular this was a problem for
|
|
+ * init and clear down. Introduction of GL_NV_vdpau_interop
|
|
+ * increased the need to be independent from render thread
|
|
+ *
|
|
+ * - move to an actor based design in order to reduce the number
|
|
+ * of locks needed.
|
|
+ */
|
|
+
|
|
+#pragma once
|
|
+
|
|
#include "system_gl.h"
|
|
|
|
-#include <queue>
|
|
+#include "DllAvUtil.h"
|
|
+#include "DVDVideoCodec.h"
|
|
+#include "DVDVideoCodecFFmpeg.h"
|
|
+#include "libavcodec/vdpau.h"
|
|
#include <X11/Xlib.h>
|
|
#include <X11/Xutil.h>
|
|
#define GLX_GLXEXT_PROTOTYPES
|
|
@@ -37,118 +58,31 @@
|
|
#include "settings/VideoSettings.h"
|
|
#include "guilib/DispResource.h"
|
|
#include "threads/Event.h"
|
|
-namespace Surface { class CSurface; }
|
|
-
|
|
-#define NUM_OUTPUT_SURFACES 4
|
|
-#define NUM_VIDEO_SURFACES_MPEG2 10 // (1 frame being decoded, 2 reference)
|
|
-#define NUM_VIDEO_SURFACES_H264 32 // (1 frame being decoded, up to 16 references)
|
|
-#define NUM_VIDEO_SURFACES_VC1 10 // (same as MPEG-2)
|
|
-#define NUM_OUTPUT_SURFACES_FOR_FULLHD 2
|
|
-#define FULLHD_WIDTH 1920
|
|
-
|
|
-class CVDPAU
|
|
- : public CDVDVideoCodecFFmpeg::IHardwareDecoder
|
|
- , public IDispResource
|
|
-{
|
|
-public:
|
|
-
|
|
- struct pictureAge
|
|
- {
|
|
- int b_age;
|
|
- int ip_age[2];
|
|
- };
|
|
-
|
|
- struct Desc
|
|
- {
|
|
- const char *name;
|
|
- uint32_t id;
|
|
- uint32_t aux; /* optional extra parameter... */
|
|
- };
|
|
-
|
|
- CVDPAU();
|
|
- virtual ~CVDPAU();
|
|
-
|
|
- virtual bool Open (AVCodecContext* avctx, const enum PixelFormat, unsigned int surfaces = 0);
|
|
- virtual int Decode (AVCodecContext* avctx, AVFrame* frame);
|
|
- virtual bool GetPicture(AVCodecContext* avctx, AVFrame* frame, DVDVideoPicture* picture);
|
|
- virtual void Reset();
|
|
- virtual void Close();
|
|
-
|
|
- virtual int Check(AVCodecContext* avctx);
|
|
-
|
|
- virtual const std::string Name() { return "vdpau"; }
|
|
-
|
|
- bool MakePixmap(int width, int height);
|
|
- bool MakePixmapGL();
|
|
-
|
|
- void ReleasePixmap();
|
|
- void BindPixmap();
|
|
-
|
|
- PFNGLXBINDTEXIMAGEEXTPROC glXBindTexImageEXT;
|
|
- PFNGLXRELEASETEXIMAGEEXTPROC glXReleaseTexImageEXT;
|
|
- GLXPixmap m_glPixmap;
|
|
- Pixmap m_Pixmap;
|
|
-
|
|
- static void FFReleaseBuffer(AVCodecContext *avctx, AVFrame *pic);
|
|
- static void FFDrawSlice(struct AVCodecContext *s,
|
|
- const AVFrame *src, int offset[4],
|
|
- int y, int type, int height);
|
|
- static int FFGetBuffer(AVCodecContext *avctx, AVFrame *pic);
|
|
-
|
|
- void Present();
|
|
- bool ConfigVDPAU(AVCodecContext *avctx, int ref_frames);
|
|
- void SpewHardwareAvailable();
|
|
- void InitCSCMatrix(int Height);
|
|
- bool CheckStatus(VdpStatus vdp_st, int line);
|
|
- bool IsSurfaceValid(vdpau_render_state *render);
|
|
+#include "threads/Thread.h"
|
|
+#include "utils/ActorProtocol.h"
|
|
|
|
- void CheckFeatures();
|
|
- void SetColor();
|
|
- void SetNoiseReduction();
|
|
- void SetSharpness();
|
|
- void SetDeinterlacing();
|
|
- void SetHWUpscaling();
|
|
+using namespace Actor;
|
|
|
|
- pictureAge picAge;
|
|
- vdpau_render_state *past[2], *current, *future;
|
|
- int tmpDeintMode, tmpDeintGUI, tmpDeint;
|
|
- float tmpNoiseReduction, tmpSharpness;
|
|
- float tmpBrightness, tmpContrast;
|
|
- int OutWidth, OutHeight;
|
|
- bool upScale;
|
|
- std::queue<DVDVideoPicture> m_DVDVideoPics;
|
|
|
|
- static inline void ClearUsedForRender(vdpau_render_state **st)
|
|
- {
|
|
- if (*st) {
|
|
- (*st)->state &= ~FF_VDPAU_STATE_USED_FOR_RENDER;
|
|
- *st = NULL;
|
|
- }
|
|
- }
|
|
-
|
|
- VdpProcamp m_Procamp;
|
|
- VdpCSCMatrix m_CSCMatrix;
|
|
- VdpDevice HasDevice() { return vdp_device != VDP_INVALID_HANDLE; };
|
|
- VdpChromaType vdp_chroma_type;
|
|
+#define FULLHD_WIDTH 1920
|
|
+#define MAX_PIC_Q_LENGTH 20 //for non-interop_yuv this controls the max length of the decoded pic to render completion Q
|
|
|
|
+namespace VDPAU
|
|
+{
|
|
|
|
- // protected:
|
|
- void InitVDPAUProcs();
|
|
- void FiniVDPAUProcs();
|
|
- void FiniVDPAUOutput();
|
|
- bool ConfigOutputMethod(AVCodecContext *avctx, AVFrame *pFrame);
|
|
- bool FiniOutputMethod();
|
|
+/**
|
|
+ * VDPAU interface to driver
|
|
+ */
|
|
|
|
- VdpDevice vdp_device;
|
|
- VdpGetProcAddress * vdp_get_proc_address;
|
|
- VdpPresentationQueueTarget vdp_flip_target;
|
|
- VdpPresentationQueue vdp_flip_queue;
|
|
- VdpDeviceDestroy * vdp_device_destroy;
|
|
+struct VDPAU_procs
|
|
+{
|
|
+ VdpGetProcAddress * vdp_get_proc_address;
|
|
+ VdpDeviceDestroy * vdp_device_destroy;
|
|
|
|
- VdpVideoSurfaceCreate * vdp_video_surface_create;
|
|
- VdpVideoSurfaceDestroy * vdp_video_surface_destroy;
|
|
- VdpVideoSurfacePutBitsYCbCr * vdp_video_surface_put_bits_y_cb_cr;
|
|
- VdpVideoSurfaceGetBitsYCbCr * vdp_video_surface_get_bits_y_cb_cr;
|
|
+ VdpVideoSurfaceCreate * vdp_video_surface_create;
|
|
+ VdpVideoSurfaceDestroy * vdp_video_surface_destroy;
|
|
+ VdpVideoSurfacePutBitsYCbCr * vdp_video_surface_put_bits_y_cb_cr;
|
|
+ VdpVideoSurfaceGetBitsYCbCr * vdp_video_surface_get_bits_y_cb_cr;
|
|
|
|
VdpOutputSurfacePutBitsYCbCr * vdp_output_surface_put_bits_y_cb_cr;
|
|
VdpOutputSurfacePutBitsNative * vdp_output_surface_put_bits_native;
|
|
@@ -158,15 +92,15 @@ class CVDPAU
|
|
VdpOutputSurfaceRenderOutputSurface * vdp_output_surface_render_output_surface;
|
|
VdpOutputSurfacePutBitsIndexed * vdp_output_surface_put_bits_indexed;
|
|
|
|
- VdpVideoMixerCreate * vdp_video_mixer_create;
|
|
- VdpVideoMixerSetFeatureEnables * vdp_video_mixer_set_feature_enables;
|
|
- VdpVideoMixerQueryParameterSupport * vdp_video_mixer_query_parameter_support;
|
|
- VdpVideoMixerQueryFeatureSupport * vdp_video_mixer_query_feature_support;
|
|
- VdpVideoMixerDestroy * vdp_video_mixer_destroy;
|
|
- VdpVideoMixerRender * vdp_video_mixer_render;
|
|
- VdpVideoMixerSetAttributeValues * vdp_video_mixer_set_attribute_values;
|
|
+ VdpVideoMixerCreate * vdp_video_mixer_create;
|
|
+ VdpVideoMixerSetFeatureEnables * vdp_video_mixer_set_feature_enables;
|
|
+ VdpVideoMixerQueryParameterSupport * vdp_video_mixer_query_parameter_support;
|
|
+ VdpVideoMixerQueryFeatureSupport * vdp_video_mixer_query_feature_support;
|
|
+ VdpVideoMixerDestroy * vdp_video_mixer_destroy;
|
|
+ VdpVideoMixerRender * vdp_video_mixer_render;
|
|
+ VdpVideoMixerSetAttributeValues * vdp_video_mixer_set_attribute_values;
|
|
|
|
- VdpGenerateCSCMatrix * vdp_generate_csc_matrix;
|
|
+ VdpGenerateCSCMatrix * vdp_generate_csc_matrix;
|
|
|
|
VdpPresentationQueueTargetDestroy * vdp_presentation_queue_target_destroy;
|
|
VdpPresentationQueueCreate * vdp_presentation_queue_create;
|
|
@@ -179,64 +113,459 @@ class CVDPAU
|
|
|
|
VdpGetErrorString * vdp_get_error_string;
|
|
|
|
- VdpDecoderCreate * vdp_decoder_create;
|
|
- VdpDecoderDestroy * vdp_decoder_destroy;
|
|
- VdpDecoderRender * vdp_decoder_render;
|
|
- VdpDecoderQueryCapabilities * vdp_decoder_query_caps;
|
|
+ VdpDecoderCreate * vdp_decoder_create;
|
|
+ VdpDecoderDestroy * vdp_decoder_destroy;
|
|
+ VdpDecoderRender * vdp_decoder_render;
|
|
+ VdpDecoderQueryCapabilities * vdp_decoder_query_caps;
|
|
|
|
VdpPreemptionCallbackRegister * vdp_preemption_callback_register;
|
|
|
|
- VdpOutputSurface outputSurfaces[NUM_OUTPUT_SURFACES];
|
|
- VdpOutputSurface outputSurface;
|
|
- VdpOutputSurface presentSurface;
|
|
+};
|
|
|
|
- VdpDecoder decoder;
|
|
- VdpVideoMixer videoMixer;
|
|
- VdpRect outRect;
|
|
- VdpRect outRectVid;
|
|
+//-----------------------------------------------------------------------------
|
|
+// VDPAU data structs
|
|
+//-----------------------------------------------------------------------------
|
|
|
|
- static void* dl_handle;
|
|
- VdpStatus (*dl_vdp_device_create_x11)(Display* display, int screen, VdpDevice* device, VdpGetProcAddress **get_proc_address);
|
|
- VdpStatus (*dl_vdp_get_proc_address)(VdpDevice device, VdpFuncId function_id, void** function_pointer);
|
|
- VdpStatus (*dl_vdp_preemption_callback_register)(VdpDevice device, VdpPreemptionCallback callback, void* context);
|
|
+class CDecoder;
|
|
|
|
- int surfaceNum;
|
|
- int presentSurfaceNum;
|
|
- int totalAvailableOutputSurfaces;
|
|
- uint32_t vid_width, vid_height;
|
|
- int surface_width, surface_height;
|
|
- uint32_t max_references;
|
|
- Display* m_Display;
|
|
- bool vdpauConfigured;
|
|
- uint32_t *m_BlackBar;
|
|
+/**
|
|
+ * Buffer statistics used to control number of frames in queue
|
|
+ */
|
|
|
|
+class CVdpauBufferStats
|
|
+{
|
|
+public:
|
|
+ uint16_t decodedPics;
|
|
+ uint16_t processedPics;
|
|
+ uint16_t renderPics;
|
|
+ uint64_t latency; // time decoder has waited for a frame, ideally there is no latency
|
|
+ int playSpeed;
|
|
+ bool canSkipDeint;
|
|
+ int processCmd;
|
|
+
|
|
+ void IncDecoded() { CSingleLock l(m_sec); decodedPics++;}
|
|
+ void DecDecoded() { CSingleLock l(m_sec); decodedPics--;}
|
|
+ void IncProcessed() { CSingleLock l(m_sec); processedPics++;}
|
|
+ void DecProcessed() { CSingleLock l(m_sec); processedPics--;}
|
|
+ void IncRender() { CSingleLock l(m_sec); renderPics++;}
|
|
+ void DecRender() { CSingleLock l(m_sec); renderPics--;}
|
|
+ void Reset() { CSingleLock l(m_sec); decodedPics=0; processedPics=0;renderPics=0;latency=0;}
|
|
+ void Get(uint16_t &decoded, uint16_t &processed, uint16_t &render) {CSingleLock l(m_sec); decoded = decodedPics, processed=processedPics, render=renderPics;}
|
|
+ void SetParams(uint64_t time, int speed) { CSingleLock l(m_sec); latency = time; playSpeed = speed; }
|
|
+ void GetParams(uint64_t &lat, int &speed) { CSingleLock l(m_sec); lat = latency; speed = playSpeed; }
|
|
+ void SetCmd(int cmd) { CSingleLock l(m_sec); processCmd = cmd; }
|
|
+ void GetCmd(int &cmd) { CSingleLock l(m_sec); cmd = processCmd; processCmd = 0; }
|
|
+ void SetCanSkipDeint(bool canSkip) { CSingleLock l(m_sec); canSkipDeint = canSkip; }
|
|
+ bool CanSkipDeint() { CSingleLock l(m_sec); if (canSkipDeint) return true; else return false;}
|
|
+private:
|
|
+ CCriticalSection m_sec;
|
|
+};
|
|
+
|
|
+/**
|
|
+ * CVdpauConfig holds all configuration parameters needed by vdpau
|
|
+ * The structure is sent to the internal classes CMixer and COutput
|
|
+ * for init.
|
|
+ */
|
|
|
|
+struct CVdpauConfig
|
|
+{
|
|
+ int surfaceWidth;
|
|
+ int surfaceHeight;
|
|
+ int vidWidth;
|
|
+ int vidHeight;
|
|
+ int outWidth;
|
|
+ int outHeight;
|
|
+ VDPAU_procs vdpProcs;
|
|
+ VdpDevice vdpDevice;
|
|
+ VdpDecoder vdpDecoder;
|
|
+ VdpChromaType vdpChromaType;
|
|
+ CVdpauBufferStats *stats;
|
|
+ CDecoder *vdpau;
|
|
+ int featureCount;
|
|
+ int upscale;
|
|
+ VdpVideoMixerFeature vdpFeatures[14];
|
|
+ std::vector<vdpau_render_state*> *videoSurfaces;
|
|
+ CCriticalSection *videoSurfaceSec;
|
|
+ bool usePixmaps;
|
|
+ int numRenderBuffers;
|
|
+ uint32_t maxReferences;
|
|
+ bool useInteropYuv;
|
|
+};
|
|
+
|
|
+/**
|
|
+ * Holds a decoded frame
|
|
+ * Input to COutput for further processing
|
|
+ */
|
|
+struct CVdpauDecodedPicture
|
|
+{
|
|
+ DVDVideoPicture DVDPic;
|
|
+ vdpau_render_state *render;
|
|
+};
|
|
+
|
|
+/**
|
|
+ * Frame after having been processed by vdpau mixer
|
|
+ */
|
|
+struct CVdpauProcessedPicture
|
|
+{
|
|
+ DVDVideoPicture DVDPic;
|
|
+ vdpau_render_state *render;
|
|
+ VdpOutputSurface outputSurface;
|
|
+};
|
|
+
|
|
+/**
|
|
+ * Ready to render textures
|
|
+ * Sent from COutput back to CDecoder
|
|
+ * Objects are referenced by DVDVideoPicture and are sent
|
|
+ * to renderer
|
|
+ */
|
|
+class CVdpauRenderPicture
|
|
+{
|
|
+ friend class CDecoder;
|
|
+ friend class COutput;
|
|
+public:
|
|
+ DVDVideoPicture DVDPic;
|
|
+ int texWidth, texHeight;
|
|
+ CRect crop;
|
|
+ GLuint texture[4];
|
|
+ uint32_t sourceIdx;
|
|
+ bool valid;
|
|
+ CDecoder *vdpau;
|
|
+ CVdpauRenderPicture* Acquire();
|
|
+ long Release();
|
|
+private:
|
|
+ void ReturnUnused();
|
|
+ int refCount;
|
|
+ CCriticalSection *renderPicSection;
|
|
+};
|
|
+
|
|
+//-----------------------------------------------------------------------------
|
|
+// Mixer
|
|
+//-----------------------------------------------------------------------------
|
|
+
|
|
+class CMixerControlProtocol : public Protocol
|
|
+{
|
|
+public:
|
|
+ CMixerControlProtocol(std::string name, CEvent* inEvent, CEvent *outEvent) : Protocol(name, inEvent, outEvent) {};
|
|
+ enum OutSignal
|
|
+ {
|
|
+ INIT = 0,
|
|
+ FLUSH,
|
|
+ TIMEOUT,
|
|
+ };
|
|
+ enum InSignal
|
|
+ {
|
|
+ ACC,
|
|
+ ERROR,
|
|
+ };
|
|
+};
|
|
+
|
|
+class CMixerDataProtocol : public Protocol
|
|
+{
|
|
+public:
|
|
+ CMixerDataProtocol(std::string name, CEvent* inEvent, CEvent *outEvent) : Protocol(name, inEvent, outEvent) {};
|
|
+ enum OutSignal
|
|
+ {
|
|
+ FRAME,
|
|
+ BUFFER,
|
|
+ };
|
|
+ enum InSignal
|
|
+ {
|
|
+ PICTURE,
|
|
+ };
|
|
+};
|
|
+
|
|
+/**
|
|
+ * Embeds the vdpau video mixer
|
|
+ * Embedded by COutput class, gets decoded frames from COutput, processes
|
|
+ * them in mixer ands sends processed frames back to COutput
|
|
+ */
|
|
+class CMixer : private CThread
|
|
+{
|
|
+public:
|
|
+ CMixer(CEvent *inMsgEvent);
|
|
+ virtual ~CMixer();
|
|
+ void Start();
|
|
+ void Dispose();
|
|
+ CMixerControlProtocol m_controlPort;
|
|
+ CMixerDataProtocol m_dataPort;
|
|
+protected:
|
|
+ void OnStartup();
|
|
+ void OnExit();
|
|
+ void Process();
|
|
+ void StateMachine(int signal, Protocol *port, Message *msg);
|
|
+ void Init();
|
|
+ void Uninit();
|
|
+ void Flush();
|
|
+ void CreateVdpauMixer();
|
|
+ void ProcessPicture();
|
|
+ void InitCycle();
|
|
+ void FiniCycle();
|
|
+ void CheckFeatures();
|
|
+ void SetPostProcFeatures(bool postProcEnabled);
|
|
+ void PostProcOff();
|
|
+ void InitCSCMatrix(int Width);
|
|
+ bool GenerateStudioCSCMatrix(VdpColorStandard colorStandard, VdpCSCMatrix &studioCSCMatrix);
|
|
+ void SetColor();
|
|
+ void SetNoiseReduction();
|
|
+ void SetSharpness();
|
|
+ void SetDeintSkipChroma();
|
|
+ void SetDeinterlacing();
|
|
+ void SetHWUpscaling();
|
|
+ void DisableHQScaling();
|
|
+ EINTERLACEMETHOD GetDeinterlacingMethod(bool log = false);
|
|
+ bool CheckStatus(VdpStatus vdp_st, int line);
|
|
+ CEvent m_outMsgEvent;
|
|
+ CEvent *m_inMsgEvent;
|
|
+ int m_state;
|
|
+ bool m_bStateMachineSelfTrigger;
|
|
+
|
|
+ // extended state variables for state machine
|
|
+ int m_extTimeout;
|
|
+ bool m_vdpError;
|
|
+ CVdpauConfig m_config;
|
|
+ VdpVideoMixer m_videoMixer;
|
|
+ VdpProcamp m_Procamp;
|
|
+ VdpCSCMatrix m_CSCMatrix;
|
|
+ bool m_PostProc;
|
|
+ float m_Brightness;
|
|
+ float m_Contrast;
|
|
+ float m_NoiseReduction;
|
|
+ float m_Sharpness;
|
|
+ int m_DeintMode;
|
|
+ int m_Deint;
|
|
+ int m_Upscale;
|
|
+ uint32_t *m_BlackBar;
|
|
VdpVideoMixerPictureStructure m_mixerfield;
|
|
- int m_mixerstep;
|
|
+ int m_mixerstep;
|
|
+ int m_mixersteps;
|
|
+ CVdpauProcessedPicture m_processPicture;
|
|
+ std::queue<VdpOutputSurface> m_outputSurfaces;
|
|
+ std::queue<CVdpauDecodedPicture> m_decodedPics;
|
|
+ std::deque<CVdpauDecodedPicture> m_mixerInput;
|
|
+};
|
|
+
|
|
+//-----------------------------------------------------------------------------
|
|
+// Output
|
|
+//-----------------------------------------------------------------------------
|
|
+
|
|
+/**
|
|
+ * Buffer pool holds allocated vdpau and gl resources
|
|
+ * Embedded in COutput
|
|
+ */
|
|
+struct VdpauBufferPool
|
|
+{
|
|
+ struct Pixmaps
|
|
+ {
|
|
+ unsigned short id;
|
|
+ bool used;
|
|
+ DVDVideoPicture DVDPic;
|
|
+ GLuint texture;
|
|
+ Pixmap pixmap;
|
|
+ GLXPixmap glPixmap;
|
|
+ VdpPresentationQueueTarget vdp_flip_target;
|
|
+ VdpPresentationQueue vdp_flip_queue;
|
|
+ VdpOutputSurface surface;
|
|
+ };
|
|
+ struct GLVideoSurface
|
|
+ {
|
|
+ GLuint texture[4];
|
|
+#ifdef GL_NV_vdpau_interop
|
|
+ GLvdpauSurfaceNV glVdpauSurface;
|
|
+#endif
|
|
+ vdpau_render_state *sourceVuv;
|
|
+ VdpOutputSurface sourceRgb;
|
|
+ };
|
|
+ unsigned short numOutputSurfaces;
|
|
+ std::vector<Pixmaps> pixmaps;
|
|
+ std::vector<VdpOutputSurface> outputSurfaces;
|
|
+ std::deque<Pixmaps*> notVisiblePixmaps;
|
|
+ std::vector<CVdpauRenderPicture> allRenderPics;
|
|
+ std::map<VdpVideoSurface, GLVideoSurface> glVideoSurfaceMap;
|
|
+ std::map<VdpOutputSurface, GLVideoSurface> glOutputSurfaceMap;
|
|
+ std::queue<CVdpauProcessedPicture> processedPics;
|
|
+ std::deque<CVdpauRenderPicture*> usedRenderPics;
|
|
+ std::deque<CVdpauRenderPicture*> freeRenderPics;
|
|
+ CCriticalSection renderPicSec;
|
|
+};
|
|
+
|
|
+class COutputControlProtocol : public Protocol
|
|
+{
|
|
+public:
|
|
+ COutputControlProtocol(std::string name, CEvent* inEvent, CEvent *outEvent) : Protocol(name, inEvent, outEvent) {};
|
|
+ enum OutSignal
|
|
+ {
|
|
+ INIT,
|
|
+ FLUSH,
|
|
+ PRECLEANUP,
|
|
+ TIMEOUT,
|
|
+ };
|
|
+ enum InSignal
|
|
+ {
|
|
+ ACC,
|
|
+ ERROR,
|
|
+ STATS,
|
|
+ };
|
|
+};
|
|
+
|
|
+class COutputDataProtocol : public Protocol
|
|
+{
|
|
+public:
|
|
+ COutputDataProtocol(std::string name, CEvent* inEvent, CEvent *outEvent) : Protocol(name, inEvent, outEvent) {};
|
|
+ enum OutSignal
|
|
+ {
|
|
+ NEWFRAME = 0,
|
|
+ RETURNPIC,
|
|
+ };
|
|
+ enum InSignal
|
|
+ {
|
|
+ PICTURE,
|
|
+ };
|
|
+};
|
|
+
|
|
+/**
|
|
+ * COutput is embedded in CDecoder and embeds CMixer
|
|
+ * The class has its own OpenGl context which is shared with render thread
|
|
+ * COuput generated ready to render textures and passes them back to
|
|
+ * CDecoder
|
|
+ */
|
|
+class COutput : private CThread
|
|
+{
|
|
+public:
|
|
+ COutput(CEvent *inMsgEvent);
|
|
+ virtual ~COutput();
|
|
+ void Start();
|
|
+ void Dispose();
|
|
+ COutputControlProtocol m_controlPort;
|
|
+ COutputDataProtocol m_dataPort;
|
|
+protected:
|
|
+ void OnStartup();
|
|
+ void OnExit();
|
|
+ void Process();
|
|
+ void StateMachine(int signal, Protocol *port, Message *msg);
|
|
+ bool HasWork();
|
|
+ CVdpauRenderPicture *ProcessMixerPicture();
|
|
+ void ProcessReturnPicture(CVdpauRenderPicture *pic);
|
|
+ int FindFreePixmap();
|
|
+ bool Init();
|
|
+ bool Uninit();
|
|
+ void Flush();
|
|
+ bool CreateGlxContext();
|
|
+ bool DestroyGlxContext();
|
|
+ bool EnsureBufferPool();
|
|
+ void ReleaseBufferPool();
|
|
+ void InitMixer();
|
|
+ bool GLInit();
|
|
+ void GLMapSurfaces();
|
|
+ void GLUnmapSurfaces();
|
|
+ void GLBindPixmaps();
|
|
+ void GLUnbindPixmaps();
|
|
+ bool MakePixmap(VdpauBufferPool::Pixmaps &pixmap);
|
|
+ bool MakePixmapGL(VdpauBufferPool::Pixmaps &pixmap);
|
|
+ bool CheckStatus(VdpStatus vdp_st, int line);
|
|
+ CEvent m_outMsgEvent;
|
|
+ CEvent *m_inMsgEvent;
|
|
+ int m_state;
|
|
+ bool m_bStateMachineSelfTrigger;
|
|
+
|
|
+ // extended state variables for state machine
|
|
+ int m_extTimeout;
|
|
+ bool m_vdpError;
|
|
+ CVdpauConfig m_config;
|
|
+ VdpauBufferPool m_bufferPool;
|
|
+ CMixer m_mixer;
|
|
+ Display *m_Display;
|
|
+ Window m_Window;
|
|
+ GLXContext m_glContext;
|
|
+ GLXWindow m_glWindow;
|
|
+ Pixmap m_pixmap;
|
|
+ GLXPixmap m_glPixmap;
|
|
+
|
|
+ // gl functions
|
|
+ PFNGLXBINDTEXIMAGEEXTPROC glXBindTexImageEXT;
|
|
+ PFNGLXRELEASETEXIMAGEEXTPROC glXReleaseTexImageEXT;
|
|
+#ifdef GL_NV_vdpau_interop
|
|
+ PFNGLVDPAUINITNVPROC glVDPAUInitNV;
|
|
+ PFNGLVDPAUFININVPROC glVDPAUFiniNV;
|
|
+ PFNGLVDPAUREGISTEROUTPUTSURFACENVPROC glVDPAURegisterOutputSurfaceNV;
|
|
+ PFNGLVDPAUREGISTERVIDEOSURFACENVPROC glVDPAURegisterVideoSurfaceNV;
|
|
+ PFNGLVDPAUISSURFACENVPROC glVDPAUIsSurfaceNV;
|
|
+ PFNGLVDPAUUNREGISTERSURFACENVPROC glVDPAUUnregisterSurfaceNV;
|
|
+ PFNGLVDPAUSURFACEACCESSNVPROC glVDPAUSurfaceAccessNV;
|
|
+ PFNGLVDPAUMAPSURFACESNVPROC glVDPAUMapSurfacesNV;
|
|
+ PFNGLVDPAUUNMAPSURFACESNVPROC glVDPAUUnmapSurfacesNV;
|
|
+ PFNGLVDPAUGETSURFACEIVNVPROC glVDPAUGetSurfaceivNV;
|
|
+#endif
|
|
+};
|
|
+
|
|
+//-----------------------------------------------------------------------------
|
|
+// VDPAU decoder
|
|
+//-----------------------------------------------------------------------------
|
|
+
|
|
+/**
|
|
+ * VDPAU main class
|
|
+ */
|
|
+class CDecoder
|
|
+ : public CDVDVideoCodecFFmpeg::IHardwareDecoder
|
|
+ , public IDispResource
|
|
+{
|
|
+ friend class CVdpauRenderPicture;
|
|
+
|
|
+public:
|
|
+
|
|
+ struct Desc
|
|
+ {
|
|
+ const char *name;
|
|
+ uint32_t id;
|
|
+ uint32_t aux; /* optional extra parameter... */
|
|
+ };
|
|
+
|
|
+ CDecoder();
|
|
+ virtual ~CDecoder();
|
|
+
|
|
+ virtual bool Open (AVCodecContext* avctx, const enum PixelFormat, unsigned int surfaces = 0);
|
|
+ virtual int Decode (AVCodecContext* avctx, AVFrame* frame);
|
|
+ virtual bool GetPicture(AVCodecContext* avctx, AVFrame* frame, DVDVideoPicture* picture);
|
|
+ virtual void Reset();
|
|
+ virtual void Close();
|
|
+ virtual long Release();
|
|
+ virtual bool CanSkipDeint();
|
|
+
|
|
+ virtual int Check(AVCodecContext* avctx);
|
|
+ virtual const std::string Name() { return "vdpau"; }
|
|
|
|
bool Supports(VdpVideoMixerFeature feature);
|
|
bool Supports(EINTERLACEMETHOD method);
|
|
EINTERLACEMETHOD AutoInterlaceMethod();
|
|
+ static bool IsVDPAUFormat(PixelFormat fmt);
|
|
|
|
- VdpVideoMixerFeature m_features[14];
|
|
- int m_feature_count;
|
|
+ static void FFReleaseBuffer(AVCodecContext *avctx, AVFrame *pic);
|
|
+ static void FFDrawSlice(struct AVCodecContext *s,
|
|
+ const AVFrame *src, int offset[4],
|
|
+ int y, int type, int height);
|
|
+ static int FFGetBuffer(AVCodecContext *avctx, AVFrame *pic);
|
|
+
|
|
+ virtual void OnLostDevice();
|
|
+ virtual void OnResetDevice();
|
|
+
|
|
+protected:
|
|
+ void SetWidthHeight(int width, int height);
|
|
+ bool ConfigVDPAU(AVCodecContext *avctx, int ref_frames);
|
|
+ void SpewHardwareAvailable();
|
|
+ bool CheckStatus(VdpStatus vdp_st, int line);
|
|
+ bool IsSurfaceValid(vdpau_render_state *render);
|
|
+ void InitVDPAUProcs();
|
|
+ void FiniVDPAUProcs();
|
|
+ void FiniVDPAUOutput();
|
|
+ void ReturnRenderPicture(CVdpauRenderPicture *renderPic);
|
|
+ long ReleasePicReference();
|
|
|
|
- static bool IsVDPAUFormat(PixelFormat fmt);
|
|
static void ReadFormatOf( PixelFormat fmt
|
|
, VdpDecoderProfile &decoder_profile
|
|
, VdpChromaType &chroma_type);
|
|
|
|
- std::vector<vdpau_render_state*> m_videoSurfaces;
|
|
- DllAvUtil m_dllAvUtil;
|
|
-
|
|
- enum VDPAUOutputMethod
|
|
- {
|
|
- OUTPUT_NONE,
|
|
- OUTPUT_PIXMAP,
|
|
- OUTPUT_GL_INTEROP_RGB,
|
|
- OUTPUT_GL_INTEROP_YUV
|
|
- };
|
|
- VDPAUOutputMethod m_vdpauOutputMethod;
|
|
+ VdpStatus (*dl_vdp_device_create_x11)(Display* display, int screen, VdpDevice* device, VdpGetProcAddress **get_proc_address);
|
|
+ VdpStatus (*dl_vdp_get_proc_address)(VdpDevice device, VdpFuncId function_id, void** function_pointer);
|
|
+ VdpStatus (*dl_vdp_preemption_callback_register)(VdpDevice device, VdpPreemptionCallback callback, void* context);
|
|
|
|
// OnLostDevice triggers transition from all states to LOST
|
|
// internal errors trigger transition from OPEN to RESET
|
|
@@ -247,9 +576,24 @@ class CVDPAU
|
|
, VDPAU_LOST
|
|
, VDPAU_ERROR
|
|
} m_DisplayState;
|
|
- CSharedSection m_DecoderSection;
|
|
- CSharedSection m_DisplaySection;
|
|
+ CCriticalSection m_DecoderSection;
|
|
CEvent m_DisplayEvent;
|
|
- virtual void OnLostDevice();
|
|
- virtual void OnResetDevice();
|
|
+
|
|
+ static void* dl_handle;
|
|
+ DllAvUtil m_dllAvUtil;
|
|
+ Display* m_Display;
|
|
+ ThreadIdentifier m_decoderThread;
|
|
+ bool m_vdpauConfigured;
|
|
+ CVdpauConfig m_vdpauConfig;
|
|
+ std::vector<vdpau_render_state*> m_videoSurfaces;
|
|
+ CCriticalSection m_videoSurfaceSec;
|
|
+
|
|
+ COutput m_vdpauOutput;
|
|
+ CVdpauBufferStats m_bufferStats;
|
|
+ CEvent m_inMsgEvent;
|
|
+ CVdpauRenderPicture *m_presentPicture;
|
|
+
|
|
+ int m_codecControl;
|
|
};
|
|
+
|
|
+}
|
|
diff --git a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp
|
|
index 10e2225..15a39fa 100644
|
|
--- a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp
|
|
+++ b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp
|
|
@@ -1141,6 +1141,9 @@ int CDVDPlayerVideo::OutputPicture(const DVDVideoPicture* src, double pts)
|
|
case RENDER_FMT_VDPAU:
|
|
formatstr = "VDPAU";
|
|
break;
|
|
+ case RENDER_FMT_VDPAU_420:
|
|
+ formatstr = "VDPAU_420";
|
|
+ break;
|
|
case RENDER_FMT_DXVA:
|
|
formatstr = "DXVA";
|
|
break;
|
|
diff --git a/xbmc/settings/AdvancedSettings.cpp b/xbmc/settings/AdvancedSettings.cpp
|
|
index 16800b7..844f8e8 100644
|
|
--- a/xbmc/settings/AdvancedSettings.cpp
|
|
+++ b/xbmc/settings/AdvancedSettings.cpp
|
|
@@ -98,7 +98,7 @@ void CAdvancedSettings::Initialize()
|
|
m_videoIgnoreSecondsAtStart = 3*60;
|
|
m_videoIgnorePercentAtEnd = 8.0f;
|
|
m_videoPlayCountMinimumPercent = 90.0f;
|
|
- m_videoVDPAUScaling = false;
|
|
+ m_videoVDPAUScaling = -1;
|
|
m_videoNonLinStretchRatio = 0.5f;
|
|
m_videoEnableHighQualityHwScalers = false;
|
|
m_videoAutoScaleMaxFps = 30.0f;
|
|
@@ -106,6 +106,8 @@ void CAdvancedSettings::Initialize()
|
|
m_videoAllowMpeg4VAAPI = false;
|
|
m_videoDisableBackgroundDeinterlace = false;
|
|
m_videoCaptureUseOcclusionQuery = -1; //-1 is auto detect
|
|
+ m_videoVDPAUtelecine = false;
|
|
+ m_videoVDPAUdeintSkipChromaHD = false;
|
|
m_DXVACheckCompatibility = false;
|
|
m_DXVACheckCompatibilityPresent = false;
|
|
m_DXVAForceProcessorRenderer = true;
|
|
@@ -493,7 +495,7 @@ void CAdvancedSettings::ParseSettingsFile(const CStdString &file)
|
|
XMLUtils::GetString(pElement,"cleandatetime", m_videoCleanDateTimeRegExp);
|
|
XMLUtils::GetString(pElement,"ppffmpegdeinterlacing",m_videoPPFFmpegDeint);
|
|
XMLUtils::GetString(pElement,"ppffmpegpostprocessing",m_videoPPFFmpegPostProc);
|
|
- XMLUtils::GetBoolean(pElement,"vdpauscaling",m_videoVDPAUScaling);
|
|
+ XMLUtils::GetInt(pElement,"vdpauscaling",m_videoVDPAUScaling);
|
|
XMLUtils::GetFloat(pElement, "nonlinearstretchratio", m_videoNonLinStretchRatio, 0.01f, 1.0f);
|
|
XMLUtils::GetBoolean(pElement,"enablehighqualityhwscalers", m_videoEnableHighQualityHwScalers);
|
|
XMLUtils::GetFloat(pElement,"autoscalemaxfps",m_videoAutoScaleMaxFps, 0.0f, 1000.0f);
|
|
@@ -501,6 +503,8 @@ void CAdvancedSettings::ParseSettingsFile(const CStdString &file)
|
|
XMLUtils::GetBoolean(pElement,"allowmpeg4vaapi",m_videoAllowMpeg4VAAPI);
|
|
XMLUtils::GetBoolean(pElement, "disablebackgrounddeinterlace", m_videoDisableBackgroundDeinterlace);
|
|
XMLUtils::GetInt(pElement, "useocclusionquery", m_videoCaptureUseOcclusionQuery, -1, 1);
|
|
+ XMLUtils::GetBoolean(pElement,"vdpauInvTelecine",m_videoVDPAUtelecine);
|
|
+ XMLUtils::GetBoolean(pElement,"vdpauHDdeintSkipChroma",m_videoVDPAUdeintSkipChromaHD);
|
|
|
|
TiXmlElement* pAdjustRefreshrate = pElement->FirstChildElement("adjustrefreshrate");
|
|
if (pAdjustRefreshrate)
|
|
diff --git a/xbmc/settings/AdvancedSettings.h b/xbmc/settings/AdvancedSettings.h
|
|
index 27887d4..72718e5 100644
|
|
--- a/xbmc/settings/AdvancedSettings.h
|
|
+++ b/xbmc/settings/AdvancedSettings.h
|
|
@@ -133,6 +133,8 @@ class CAdvancedSettings
|
|
int m_videoPercentSeekBackwardBig;
|
|
CStdString m_videoPPFFmpegDeint;
|
|
CStdString m_videoPPFFmpegPostProc;
|
|
+ bool m_videoVDPAUtelecine;
|
|
+ bool m_videoVDPAUdeintSkipChromaHD;
|
|
bool m_musicUseTimeSeeking;
|
|
int m_musicTimeSeekForward;
|
|
int m_musicTimeSeekBackward;
|
|
@@ -148,7 +150,7 @@ class CAdvancedSettings
|
|
CStdString m_audioHost;
|
|
bool m_audioApplyDrc;
|
|
|
|
- bool m_videoVDPAUScaling;
|
|
+ int m_videoVDPAUScaling;
|
|
float m_videoNonLinStretchRatio;
|
|
bool m_videoEnableHighQualityHwScalers;
|
|
float m_videoAutoScaleMaxFps;
|
|
diff --git a/xbmc/settings/GUISettings.cpp b/xbmc/settings/GUISettings.cpp
|
|
index 76ec0cc..4cdb093 100644
|
|
--- a/xbmc/settings/GUISettings.cpp
|
|
+++ b/xbmc/settings/GUISettings.cpp
|
|
@@ -685,6 +685,8 @@ void CGUISettings::Initialize()
|
|
|
|
#ifdef HAVE_LIBVDPAU
|
|
AddBool(vp, "videoplayer.usevdpau", 13425, true);
|
|
+ AddBool(vp, "videoplayer.usevdpauinterop", 13435, true);
|
|
+ AddBool(vp, "videoplayer.usevdpauinteropyuv", 13436, false);
|
|
#endif
|
|
#ifdef HAVE_LIBVA
|
|
AddBool(vp, "videoplayer.usevaapi", 13426, true);
|
|
diff --git a/xbmc/settings/GUIWindowSettingsCategory.cpp b/xbmc/settings/GUIWindowSettingsCategory.cpp
|
|
index 4ac2663..d988598 100644
|
|
--- a/xbmc/settings/GUIWindowSettingsCategory.cpp
|
|
+++ b/xbmc/settings/GUIWindowSettingsCategory.cpp
|
|
@@ -596,6 +596,40 @@ void CGUIWindowSettingsCategory::UpdateSettings()
|
|
pControl->SetEnabled(true);
|
|
}
|
|
}
|
|
+ else if (strSetting.Equals("videoplayer.usevdpauinteropyuv"))
|
|
+ {
|
|
+ bool hasInterop = g_guiSettings.GetBool("videoplayer.usevdpauinterop");
|
|
+#ifndef GL_NV_vdpau_interop
|
|
+ hasInterop = false;
|
|
+#endif
|
|
+ CGUIControl *pControl = (CGUIControl *)GetControl(pSettingControl->GetID());
|
|
+ if (pControl && hasInterop && glewIsSupported("GL_NV_vdpau_interop"))
|
|
+ {
|
|
+ pControl->SetEnabled(true);
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ pControl->SetEnabled(false);
|
|
+ g_guiSettings.SetBool("videoplayer.usevdpauinteropyuv",false);
|
|
+ }
|
|
+ }
|
|
+ else if (strSetting.Equals("videoplayer.usevdpauinterop"))
|
|
+ {
|
|
+ bool hasInterop = g_guiSettings.GetBool("videoplayer.usevdpau");
|
|
+#ifndef GL_NV_vdpau_interop
|
|
+ hasInterop = false;
|
|
+#endif
|
|
+ CGUIControl *pControl = (CGUIControl *)GetControl(pSettingControl->GetID());
|
|
+ if (pControl && hasInterop && glewIsSupported("GL_NV_vdpau_interop"))
|
|
+ {
|
|
+ pControl->SetEnabled(true);
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ pControl->SetEnabled(false);
|
|
+ g_guiSettings.SetBool("videoplayer.usevdpauinterop",false);
|
|
+ }
|
|
+ }
|
|
else
|
|
#endif
|
|
if (strSetting.Equals("videoscreen.resolution"))
|
|
diff --git a/xbmc/utils/ActorProtocol.cpp b/xbmc/utils/ActorProtocol.cpp
|
|
new file mode 100644
|
|
index 0000000..e0cfd0e
|
|
--- /dev/null
|
|
+++ b/xbmc/utils/ActorProtocol.cpp
|
|
@@ -0,0 +1,253 @@
|
|
+/*
|
|
+ * Copyright (C) 2005-2012 Team XBMC
|
|
+ * http://www.xbmc.org
|
|
+ *
|
|
+ * This Program is free software; you can redistribute it and/or modify
|
|
+ * it under the terms of the GNU General Public License as published by
|
|
+ * the Free Software Foundation; either version 2, or (at your option)
|
|
+ * any later version.
|
|
+ *
|
|
+ * This Program is distributed in the hope that it will be useful,
|
|
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
+ * GNU General Public License for more details.
|
|
+ *
|
|
+ * You should have received a copy of the GNU General Public License
|
|
+ * along with XBMC; see the file COPYING. If not, see
|
|
+ * <http://www.gnu.org/licenses/>.
|
|
+ *
|
|
+ */
|
|
+
|
|
+#include "ActorProtocol.h"
|
|
+
|
|
+using namespace Actor;
|
|
+
|
|
+void Message::Release()
|
|
+{
|
|
+ bool skip;
|
|
+ origin->Lock();
|
|
+ skip = isSync ? !isSyncFini : false;
|
|
+ isSyncFini = true;
|
|
+ origin->Unlock();
|
|
+
|
|
+ if (skip)
|
|
+ return;
|
|
+
|
|
+ // free data buffer
|
|
+ if (data != buffer)
|
|
+ delete [] data;
|
|
+
|
|
+ // delete event in case of sync message
|
|
+ if (event)
|
|
+ delete event;
|
|
+
|
|
+ origin->ReturnMessage(this);
|
|
+}
|
|
+
|
|
+bool Message::Reply(int sig, void *data /* = NULL*/, int size /* = 0 */)
|
|
+{
|
|
+ if (!isSync)
|
|
+ {
|
|
+ if (isOut)
|
|
+ return origin->SendInMessage(sig, data, size);
|
|
+ else
|
|
+ return origin->SendOutMessage(sig, data, size);
|
|
+ }
|
|
+
|
|
+ origin->Lock();
|
|
+
|
|
+ if (!isSyncTimeout)
|
|
+ {
|
|
+ Message *msg = origin->GetMessage();
|
|
+ msg->signal = sig;
|
|
+ msg->isOut = !isOut;
|
|
+ replyMessage = msg;
|
|
+ if (data)
|
|
+ {
|
|
+ if (size > MSG_INTERNAL_BUFFER_SIZE)
|
|
+ msg->data = new uint8_t[size];
|
|
+ else
|
|
+ msg->data = msg->buffer;
|
|
+ memcpy(msg->data, data, size);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ origin->Unlock();
|
|
+
|
|
+ if (event)
|
|
+ event->Set();
|
|
+
|
|
+ return true;
|
|
+}
|
|
+
|
|
+Protocol::~Protocol()
|
|
+{
|
|
+ Message *msg;
|
|
+ Purge();
|
|
+ while (!freeMessageQueue.empty())
|
|
+ {
|
|
+ msg = freeMessageQueue.front();
|
|
+ freeMessageQueue.pop();
|
|
+ delete msg;
|
|
+ }
|
|
+}
|
|
+
|
|
+Message *Protocol::GetMessage()
|
|
+{
|
|
+ Message *msg;
|
|
+
|
|
+ CSingleLock lock(criticalSection);
|
|
+
|
|
+ if (!freeMessageQueue.empty())
|
|
+ {
|
|
+ msg = freeMessageQueue.front();
|
|
+ freeMessageQueue.pop();
|
|
+ }
|
|
+ else
|
|
+ msg = new Message();
|
|
+
|
|
+ msg->isSync = false;
|
|
+ msg->isSyncFini = false;
|
|
+ msg->isSyncTimeout = false;
|
|
+ msg->event = NULL;
|
|
+ msg->data = NULL;
|
|
+ msg->payloadSize = 0;
|
|
+ msg->replyMessage = NULL;
|
|
+ msg->origin = this;
|
|
+
|
|
+ return msg;
|
|
+}
|
|
+
|
|
+void Protocol::ReturnMessage(Message *msg)
|
|
+{
|
|
+ CSingleLock lock(criticalSection);
|
|
+
|
|
+ freeMessageQueue.push(msg);
|
|
+}
|
|
+
|
|
+bool Protocol::SendOutMessage(int signal, void *data /* = NULL */, int size /* = 0 */, Message *outMsg /* = NULL */)
|
|
+{
|
|
+ Message *msg;
|
|
+ if (outMsg)
|
|
+ msg = outMsg;
|
|
+ else
|
|
+ msg = GetMessage();
|
|
+
|
|
+ msg->signal = signal;
|
|
+ msg->isOut = true;
|
|
+
|
|
+ if (data)
|
|
+ {
|
|
+ if (size > MSG_INTERNAL_BUFFER_SIZE)
|
|
+ msg->data = new uint8_t[size];
|
|
+ else
|
|
+ msg->data = msg->buffer;
|
|
+ memcpy(msg->data, data, size);
|
|
+ }
|
|
+
|
|
+ { CSingleLock lock(criticalSection);
|
|
+ outMessages.push(msg);
|
|
+ }
|
|
+ containerOutEvent->Set();
|
|
+
|
|
+ return true;
|
|
+}
|
|
+
|
|
+bool Protocol::SendInMessage(int signal, void *data /* = NULL */, int size /* = 0 */, Message *outMsg /* = NULL */)
|
|
+{
|
|
+ Message *msg;
|
|
+ if (outMsg)
|
|
+ msg = outMsg;
|
|
+ else
|
|
+ msg = GetMessage();
|
|
+
|
|
+ msg->signal = signal;
|
|
+ msg->isOut = false;
|
|
+
|
|
+ if (data)
|
|
+ {
|
|
+ if (size > MSG_INTERNAL_BUFFER_SIZE)
|
|
+ msg->data = new uint8_t[size];
|
|
+ else
|
|
+ msg->data = msg->buffer;
|
|
+ memcpy(msg->data, data, size);
|
|
+ }
|
|
+
|
|
+ { CSingleLock lock(criticalSection);
|
|
+ inMessages.push(msg);
|
|
+ }
|
|
+ containerInEvent->Set();
|
|
+
|
|
+ return true;
|
|
+}
|
|
+
|
|
+
|
|
+bool Protocol::SendOutMessageSync(int signal, Message **retMsg, int timeout, void *data /* = NULL */, int size /* = 0 */)
|
|
+{
|
|
+ Message *msg = GetMessage();
|
|
+ msg->isOut = true;
|
|
+ msg->isSync = true;
|
|
+ msg->event = new CEvent;
|
|
+ msg->event->Reset();
|
|
+ SendOutMessage(signal, data, size, msg);
|
|
+
|
|
+ if (!msg->event->WaitMSec(timeout))
|
|
+ {
|
|
+ msg->origin->Lock();
|
|
+ if (msg->replyMessage)
|
|
+ *retMsg = msg->replyMessage;
|
|
+ else
|
|
+ {
|
|
+ *retMsg = NULL;
|
|
+ msg->isSyncTimeout = true;
|
|
+ }
|
|
+ msg->origin->Unlock();
|
|
+ }
|
|
+ else
|
|
+ *retMsg = msg->replyMessage;
|
|
+
|
|
+ msg->Release();
|
|
+
|
|
+ if (*retMsg)
|
|
+ return true;
|
|
+ else
|
|
+ return false;
|
|
+}
|
|
+
|
|
+bool Protocol::ReceiveOutMessage(Message **msg)
|
|
+{
|
|
+ CSingleLock lock(criticalSection);
|
|
+
|
|
+ if (outMessages.empty() || outDefered)
|
|
+ return false;
|
|
+
|
|
+ *msg = outMessages.front();
|
|
+ outMessages.pop();
|
|
+
|
|
+ return true;
|
|
+}
|
|
+
|
|
+bool Protocol::ReceiveInMessage(Message **msg)
|
|
+{
|
|
+ CSingleLock lock(criticalSection);
|
|
+
|
|
+ if (inMessages.empty() || inDefered)
|
|
+ return false;
|
|
+
|
|
+ *msg = inMessages.front();
|
|
+ inMessages.pop();
|
|
+
|
|
+ return true;
|
|
+}
|
|
+
|
|
+
|
|
+void Protocol::Purge()
|
|
+{
|
|
+ Message *msg;
|
|
+
|
|
+ while (ReceiveInMessage(&msg))
|
|
+ msg->Release();
|
|
+
|
|
+ while (ReceiveOutMessage(&msg))
|
|
+ msg->Release();
|
|
+}
|
|
diff --git a/xbmc/utils/ActorProtocol.h b/xbmc/utils/ActorProtocol.h
|
|
new file mode 100644
|
|
index 0000000..e7108ac
|
|
--- /dev/null
|
|
+++ b/xbmc/utils/ActorProtocol.h
|
|
@@ -0,0 +1,87 @@
|
|
+/*
|
|
+ * Copyright (C) 2005-2012 Team XBMC
|
|
+ * http://www.xbmc.org
|
|
+ *
|
|
+ * This Program is free software; you can redistribute it and/or modify
|
|
+ * it under the terms of the GNU General Public License as published by
|
|
+ * the Free Software Foundation; either version 2, or (at your option)
|
|
+ * any later version.
|
|
+ *
|
|
+ * This Program is distributed in the hope that it will be useful,
|
|
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
+ * GNU General Public License for more details.
|
|
+ *
|
|
+ * You should have received a copy of the GNU General Public License
|
|
+ * along with XBMC; see the file COPYING. If not, see
|
|
+ * <http://www.gnu.org/licenses/>.
|
|
+ *
|
|
+ */
|
|
+
|
|
+#pragma once
|
|
+
|
|
+#include "threads/Thread.h"
|
|
+#include "utils/log.h"
|
|
+#include <queue>
|
|
+#include "memory.h"
|
|
+
|
|
+#define MSG_INTERNAL_BUFFER_SIZE 32
|
|
+
|
|
+namespace Actor
|
|
+{
|
|
+
|
|
+class Protocol;
|
|
+
|
|
+class Message
|
|
+{
|
|
+ friend class Protocol;
|
|
+public:
|
|
+ int signal;
|
|
+ bool isSync;
|
|
+ bool isSyncFini;
|
|
+ bool isOut;
|
|
+ bool isSyncTimeout;
|
|
+ int payloadSize;
|
|
+ uint8_t buffer[MSG_INTERNAL_BUFFER_SIZE];
|
|
+ uint8_t *data;
|
|
+ Message *replyMessage;
|
|
+ Protocol *origin;
|
|
+ CEvent *event;
|
|
+
|
|
+ void Release();
|
|
+ bool Reply(int sig, void *data = NULL, int size = 0);
|
|
+
|
|
+private:
|
|
+ Message() {isSync = false; data = NULL; event = NULL; replyMessage = NULL;};
|
|
+};
|
|
+
|
|
+class Protocol
|
|
+{
|
|
+public:
|
|
+ Protocol(std::string name, CEvent* inEvent, CEvent *outEvent)
|
|
+ : portName(name), inDefered(false), outDefered(false) {containerInEvent = inEvent; containerOutEvent = outEvent;};
|
|
+ virtual ~Protocol();
|
|
+ Message *GetMessage();
|
|
+ void ReturnMessage(Message *msg);
|
|
+ bool SendOutMessage(int signal, void *data = NULL, int size = 0, Message *outMsg = NULL);
|
|
+ bool SendInMessage(int signal, void *data = NULL, int size = 0, Message *outMsg = NULL);
|
|
+ bool SendOutMessageSync(int signal, Message **retMsg, int timeout, void *data = NULL, int size = 0);
|
|
+ bool ReceiveOutMessage(Message **msg);
|
|
+ bool ReceiveInMessage(Message **msg);
|
|
+ void Purge();
|
|
+ void DeferIn(bool value) {inDefered = value;};
|
|
+ void DeferOut(bool value) {outDefered = value;};
|
|
+ void Lock() {criticalSection.lock();};
|
|
+ void Unlock() {criticalSection.unlock();};
|
|
+ std::string portName;
|
|
+
|
|
+protected:
|
|
+ CEvent *containerInEvent, *containerOutEvent;
|
|
+ CCriticalSection criticalSection;
|
|
+ std::queue<Message*> outMessages;
|
|
+ std::queue<Message*> inMessages;
|
|
+ std::queue<Message*> freeMessageQueue;
|
|
+ bool inDefered, outDefered;
|
|
+};
|
|
+
|
|
+}
|
|
diff --git a/xbmc/utils/Makefile b/xbmc/utils/Makefile
|
|
index d201884..7d1f9f0 100644
|
|
--- a/xbmc/utils/Makefile
|
|
+++ b/xbmc/utils/Makefile
|
|
@@ -70,6 +70,7 @@ SRCS=AlarmClock.cpp \
|
|
Weather.cpp \
|
|
XBMCTinyXML.cpp \
|
|
XMLUtils.cpp \
|
|
+ ActorProtocol.cpp \
|
|
|
|
LIB=utils.a
|
|
|
|
diff --git a/xbmc/video/dialogs/GUIDialogVideoSettings.cpp b/xbmc/video/dialogs/GUIDialogVideoSettings.cpp
|
|
index ac5f007..f25d10d 100644
|
|
--- a/xbmc/video/dialogs/GUIDialogVideoSettings.cpp
|
|
+++ b/xbmc/video/dialogs/GUIDialogVideoSettings.cpp
|
|
@@ -103,7 +103,7 @@ void CGUIDialogVideoSettings::CreateSettings()
|
|
entries.push_back(make_pair(VS_INTERLACEMETHOD_INVERSE_TELECINE , 16314));
|
|
entries.push_back(make_pair(VS_INTERLACEMETHOD_VDPAU_TEMPORAL_SPATIAL , 16311));
|
|
entries.push_back(make_pair(VS_INTERLACEMETHOD_VDPAU_TEMPORAL , 16310));
|
|
- entries.push_back(make_pair(VS_INTERLACEMETHOD_VDPAU_BOB , 16021));
|
|
+ entries.push_back(make_pair(VS_INTERLACEMETHOD_VDPAU_BOB , 16325));
|
|
entries.push_back(make_pair(VS_INTERLACEMETHOD_VDPAU_TEMPORAL_SPATIAL_HALF, 16318));
|
|
entries.push_back(make_pair(VS_INTERLACEMETHOD_VDPAU_TEMPORAL_HALF , 16317));
|
|
entries.push_back(make_pair(VS_INTERLACEMETHOD_VDPAU_INVERSE_TELECINE , 16314));
|
|
diff --git a/xbmc/windowing/X11/WinSystemX11.h b/xbmc/windowing/X11/WinSystemX11.h
|
|
index e7af3cb..2dd8a9f 100644
|
|
--- a/xbmc/windowing/X11/WinSystemX11.h
|
|
+++ b/xbmc/windowing/X11/WinSystemX11.h
|
|
@@ -63,6 +63,7 @@ class CWinSystemX11 : public CWinSystemBase
|
|
// Local to WinSystemX11 only
|
|
Display* GetDisplay() { return m_dpy; }
|
|
GLXWindow GetWindow() { return m_glWindow; }
|
|
+ GLXContext GetGlxContext() { return m_glContext; }
|
|
|
|
protected:
|
|
bool RefreshGlxContext();
|
|
--
|
|
1.7.10
|
|
|
|
|
|
From c088467d9d0955051a510dadbddb270ddc3e3c20 Mon Sep 17 00:00:00 2001
|
|
From: xbmc <fernetmenta@online.de>
|
|
Date: Tue, 25 Sep 2012 12:14:15 +0200
|
|
Subject: [PATCH 12/72] linuxrenderer: drop method RenderMultiPass
|
|
|
|
---
|
|
xbmc/cores/VideoRenderers/LinuxRendererGL.cpp | 9 ++-------
|
|
xbmc/cores/VideoRenderers/LinuxRendererGL.h | 1 -
|
|
2 files changed, 2 insertions(+), 8 deletions(-)
|
|
|
|
diff --git a/xbmc/cores/VideoRenderers/LinuxRendererGL.cpp b/xbmc/cores/VideoRenderers/LinuxRendererGL.cpp
|
|
index 4ee50c1..ea58c85 100644
|
|
--- a/xbmc/cores/VideoRenderers/LinuxRendererGL.cpp
|
|
+++ b/xbmc/cores/VideoRenderers/LinuxRendererGL.cpp
|
|
@@ -1205,7 +1205,8 @@ void CLinuxRendererGL::Render(DWORD flags, int renderBuffer)
|
|
break;
|
|
|
|
case RQ_MULTIPASS:
|
|
- RenderMultiPass(renderBuffer, m_currentField);
|
|
+ RenderToFBO(renderBuffer, m_currentField);
|
|
+ RenderFromFBO();
|
|
VerifyGLState();
|
|
break;
|
|
}
|
|
@@ -1328,12 +1329,6 @@ void CLinuxRendererGL::RenderSinglePass(int index, int field)
|
|
VerifyGLState();
|
|
}
|
|
|
|
-void CLinuxRendererGL::RenderMultiPass(int index, int field)
|
|
-{
|
|
- RenderToFBO(index, field);
|
|
- RenderFromFBO();
|
|
-}
|
|
-
|
|
void CLinuxRendererGL::RenderToFBO(int index, int field)
|
|
{
|
|
YUVPLANES &planes = m_buffers[index].fields[field];
|
|
diff --git a/xbmc/cores/VideoRenderers/LinuxRendererGL.h b/xbmc/cores/VideoRenderers/LinuxRendererGL.h
|
|
index 3218cd5..afc78c2 100644
|
|
--- a/xbmc/cores/VideoRenderers/LinuxRendererGL.h
|
|
+++ b/xbmc/cores/VideoRenderers/LinuxRendererGL.h
|
|
@@ -218,7 +218,6 @@ class CLinuxRendererGL : public CBaseRenderer
|
|
void CalculateTextureSourceRects(int source, int num_planes);
|
|
|
|
// renderers
|
|
- void RenderMultiPass(int renderBuffer, int field); // multi pass glsl renderer
|
|
void RenderToFBO(int renderBuffer, int field);
|
|
void RenderFromFBO();
|
|
void RenderSinglePass(int renderBuffer, int field); // single pass glsl renderer
|
|
--
|
|
1.7.10
|
|
|
|
|
|
From 0de3939247a63509e6bfab2e77c298eaa28aa29c Mon Sep 17 00:00:00 2001
|
|
From: xbmc <fernetmenta@online.de>
|
|
Date: Tue, 25 Sep 2012 13:20:47 +0200
|
|
Subject: [PATCH 13/72] linuxrenderer: implement progressive weave for vdpau
|
|
|
|
---
|
|
xbmc/cores/VideoRenderers/LinuxRendererGL.cpp | 55 ++++++++++++++++++-------
|
|
xbmc/cores/VideoRenderers/LinuxRendererGL.h | 4 +-
|
|
2 files changed, 41 insertions(+), 18 deletions(-)
|
|
|
|
diff --git a/xbmc/cores/VideoRenderers/LinuxRendererGL.cpp b/xbmc/cores/VideoRenderers/LinuxRendererGL.cpp
|
|
index ea58c85..b281ca7 100644
|
|
--- a/xbmc/cores/VideoRenderers/LinuxRendererGL.cpp
|
|
+++ b/xbmc/cores/VideoRenderers/LinuxRendererGL.cpp
|
|
@@ -689,18 +689,6 @@ void CLinuxRendererGL::RenderUpdate(bool clear, DWORD flags, DWORD alpha)
|
|
glDisable(GL_POLYGON_STIPPLE);
|
|
|
|
}
|
|
- else if(m_format == RENDER_FMT_VDPAU_420
|
|
- && !(flags & RENDER_FLAG_BOTH))
|
|
- {
|
|
- glDisable(GL_BLEND);
|
|
- glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
|
|
- Render(flags | RENDER_FLAG_TOP, index);
|
|
-
|
|
- glEnable(GL_BLEND);
|
|
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|
- glColor4f(1.0f, 1.0f, 1.0f, 128 / 255.0f);
|
|
- Render(flags | RENDER_FLAG_BOT , index);
|
|
- }
|
|
else
|
|
Render(flags, index);
|
|
|
|
@@ -1200,13 +1188,21 @@ void CLinuxRendererGL::Render(DWORD flags, int renderBuffer)
|
|
{
|
|
case RQ_LOW:
|
|
case RQ_SINGLEPASS:
|
|
- RenderSinglePass(renderBuffer, m_currentField);
|
|
+ if (m_format == RENDER_FMT_VDPAU_420 && m_currentField == FIELD_FULL)
|
|
+ RenderProgressiveWeave(renderBuffer, m_currentField);
|
|
+ else
|
|
+ RenderSinglePass(renderBuffer, m_currentField);
|
|
VerifyGLState();
|
|
break;
|
|
|
|
case RQ_MULTIPASS:
|
|
- RenderToFBO(renderBuffer, m_currentField);
|
|
- RenderFromFBO();
|
|
+ if (m_format == RENDER_FMT_VDPAU_420 && m_currentField == FIELD_FULL)
|
|
+ RenderProgressiveWeave(renderBuffer, m_currentField);
|
|
+ else
|
|
+ {
|
|
+ RenderToFBO(renderBuffer, m_currentField);
|
|
+ RenderFromFBO();
|
|
+ }
|
|
VerifyGLState();
|
|
break;
|
|
}
|
|
@@ -1329,7 +1325,7 @@ void CLinuxRendererGL::RenderSinglePass(int index, int field)
|
|
VerifyGLState();
|
|
}
|
|
|
|
-void CLinuxRendererGL::RenderToFBO(int index, int field)
|
|
+void CLinuxRendererGL::RenderToFBO(int index, int field, bool weave /*= false*/)
|
|
{
|
|
YUVPLANES &planes = m_buffers[index].fields[field];
|
|
|
|
@@ -1431,6 +1427,8 @@ void CLinuxRendererGL::RenderToFBO(int index, int field)
|
|
}
|
|
m_fbo.width *= planes[0].pixpertex_x;
|
|
m_fbo.height *= planes[0].pixpertex_y;
|
|
+ if (weave)
|
|
+ m_fbo.height *= 2;
|
|
|
|
// 1st Pass to video frame size
|
|
glBegin(GL_QUADS);
|
|
@@ -1549,6 +1547,31 @@ void CLinuxRendererGL::RenderFromFBO()
|
|
VerifyGLState();
|
|
}
|
|
|
|
+void CLinuxRendererGL::RenderProgressiveWeave(int index, int field)
|
|
+{
|
|
+ bool scaleUp = (int)m_sourceHeight < g_graphicsContext.GetHeight() || (int)m_sourceWidth < g_graphicsContext.GetWidth();
|
|
+
|
|
+ if (m_fbo.fbo.IsSupported() && (scaleUp || m_renderQuality == RQ_MULTIPASS))
|
|
+ {
|
|
+ glEnable(GL_POLYGON_STIPPLE);
|
|
+ glPolygonStipple(stipple_weave);
|
|
+ RenderToFBO(index, FIELD_TOP, true);
|
|
+ glPolygonStipple(stipple_weave+4);
|
|
+ RenderToFBO(index, FIELD_BOT, true);
|
|
+ glDisable(GL_POLYGON_STIPPLE);
|
|
+ RenderFromFBO();
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ glEnable(GL_POLYGON_STIPPLE);
|
|
+ glPolygonStipple(stipple_weave);
|
|
+ RenderSinglePass(index, FIELD_TOP);
|
|
+ glPolygonStipple(stipple_weave+4);
|
|
+ RenderSinglePass(index, FIELD_BOT);
|
|
+ glDisable(GL_POLYGON_STIPPLE);
|
|
+ }
|
|
+}
|
|
+
|
|
void CLinuxRendererGL::RenderVDPAU(int index, int field)
|
|
{
|
|
#ifdef HAVE_LIBVDPAU
|
|
diff --git a/xbmc/cores/VideoRenderers/LinuxRendererGL.h b/xbmc/cores/VideoRenderers/LinuxRendererGL.h
|
|
index afc78c2..2fc34ae 100644
|
|
--- a/xbmc/cores/VideoRenderers/LinuxRendererGL.h
|
|
+++ b/xbmc/cores/VideoRenderers/LinuxRendererGL.h
|
|
@@ -218,12 +218,12 @@ class CLinuxRendererGL : public CBaseRenderer
|
|
void CalculateTextureSourceRects(int source, int num_planes);
|
|
|
|
// renderers
|
|
- void RenderToFBO(int renderBuffer, int field);
|
|
+ void RenderToFBO(int renderBuffer, int field, bool weave = false);
|
|
void RenderFromFBO();
|
|
void RenderSinglePass(int renderBuffer, int field); // single pass glsl renderer
|
|
void RenderSoftware(int renderBuffer, int field); // single pass s/w yuv2rgb renderer
|
|
void RenderVDPAU(int renderBuffer, int field); // render using vdpau hardware
|
|
- void RenderVDPAUYV12(int renderBuffer, int field); // render using vdpau hardware
|
|
+ void RenderProgressiveWeave(int renderBuffer, int field); // render using vdpau hardware
|
|
void RenderVAAPI(int renderBuffer, int field); // render using vdpau hardware
|
|
|
|
struct
|
|
--
|
|
1.7.10
|
|
|
|
|
|
From c12380f4b9c9c2671bfd1ebd3e29ba7cd83ac95e Mon Sep 17 00:00:00 2001
|
|
From: FernetMenta <fernetmenta@online.de>
|
|
Date: Thu, 5 Jul 2012 15:22:05 +0200
|
|
Subject: [PATCH 14/72] X11: ditch SDL for video and window events
|
|
|
|
---
|
|
xbmc/Application.cpp | 2 +-
|
|
xbmc/system.h | 5 +
|
|
xbmc/windowing/Makefile | 1 +
|
|
xbmc/windowing/WinEvents.h | 4 +
|
|
xbmc/windowing/WinEventsX11.cpp | 765 +++++++++++++++++++++++++++++++++++
|
|
xbmc/windowing/WinEventsX11.h | 57 +++
|
|
xbmc/windowing/X11/WinSystemX11.cpp | 370 ++++++++++++-----
|
|
xbmc/windowing/X11/WinSystemX11.h | 9 +-
|
|
8 files changed, 1112 insertions(+), 101 deletions(-)
|
|
create mode 100644 xbmc/windowing/WinEventsX11.cpp
|
|
create mode 100644 xbmc/windowing/WinEventsX11.h
|
|
|
|
diff --git a/xbmc/Application.cpp b/xbmc/Application.cpp
|
|
index 9a7b900..fc8e721 100644
|
|
--- a/xbmc/Application.cpp
|
|
+++ b/xbmc/Application.cpp
|
|
@@ -790,7 +790,7 @@ bool CApplication::CreateGUI()
|
|
|
|
uint32_t sdlFlags = 0;
|
|
|
|
-#if defined(HAS_SDL_OPENGL) || (HAS_GLES == 2)
|
|
+#if (defined(HAS_SDL_OPENGL) || (HAS_GLES == 2)) && !defined(HAS_GLX)
|
|
sdlFlags |= SDL_INIT_VIDEO;
|
|
#endif
|
|
|
|
diff --git a/xbmc/system.h b/xbmc/system.h
|
|
index 4165c01..32584b1 100644
|
|
--- a/xbmc/system.h
|
|
+++ b/xbmc/system.h
|
|
@@ -162,16 +162,21 @@
|
|
#define HAS_GL
|
|
#ifdef HAVE_X11
|
|
#define HAS_GLX
|
|
+#define HAS_X11_WIN_EVENTS
|
|
#endif
|
|
#ifdef HAVE_SDL
|
|
#define HAS_SDL
|
|
#ifndef HAS_SDL_OPENGL
|
|
#define HAS_SDL_OPENGL
|
|
#endif
|
|
+#ifndef HAVE_X11
|
|
#define HAS_SDL_WIN_EVENTS
|
|
+#endif
|
|
#else
|
|
+#ifndef HAVE_X11
|
|
#define HAS_LINUX_EVENTS
|
|
#endif
|
|
+#endif
|
|
#define HAS_LINUX_NETWORK
|
|
#define HAS_LIRC
|
|
#ifdef HAVE_LIBPULSE
|
|
diff --git a/xbmc/windowing/Makefile b/xbmc/windowing/Makefile
|
|
index f109bec..f981642 100644
|
|
--- a/xbmc/windowing/Makefile
|
|
+++ b/xbmc/windowing/Makefile
|
|
@@ -1,6 +1,7 @@
|
|
SRCS=WinEventsSDL.cpp \
|
|
WinEventsLinux.cpp \
|
|
WinSystem.cpp \
|
|
+ WinEventsX11.cpp \
|
|
|
|
LIB=windowing.a
|
|
|
|
diff --git a/xbmc/windowing/WinEvents.h b/xbmc/windowing/WinEvents.h
|
|
index 6d322a9..5a671cc 100644
|
|
--- a/xbmc/windowing/WinEvents.h
|
|
+++ b/xbmc/windowing/WinEvents.h
|
|
@@ -58,6 +58,10 @@ class CWinEventsBase
|
|
#include "WinEventsSDL.h"
|
|
#define CWinEvents CWinEventsSDL
|
|
|
|
+#elif defined(TARGET_LINUX) && defined(HAS_X11_WIN_EVENTS)
|
|
+#include "WinEventsX11.h"
|
|
+#define CWinEvents CWinEventsX11
|
|
+
|
|
#elif defined(TARGET_LINUX) && defined(HAS_LINUX_EVENTS)
|
|
#include "WinEventsLinux.h"
|
|
#define CWinEvents CWinEventsLinux
|
|
diff --git a/xbmc/windowing/WinEventsX11.cpp b/xbmc/windowing/WinEventsX11.cpp
|
|
new file mode 100644
|
|
index 0000000..24477ae
|
|
--- /dev/null
|
|
+++ b/xbmc/windowing/WinEventsX11.cpp
|
|
@@ -0,0 +1,765 @@
|
|
+/*
|
|
+* Copyright (C) 2005-2012 Team XBMC
|
|
+* http://www.xbmc.org
|
|
+*
|
|
+* This Program is free software; you can redistribute it and/or modify
|
|
+* it under the terms of the GNU General Public License as published by
|
|
+* the Free Software Foundation; either version 2, or (at your option)
|
|
+* any later version.
|
|
+*
|
|
+* This Program is distributed in the hope that it will be useful,
|
|
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
+* GNU General Public License for more details.
|
|
+*
|
|
+* You should have received a copy of the GNU General Public License
|
|
+* along with XBMC; see the file COPYING. If not, write to
|
|
+* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
+* http://www.gnu.org/copyleft/gpl.html
|
|
+*
|
|
+*/
|
|
+
|
|
+#include "system.h"
|
|
+
|
|
+#ifdef HAS_X11_WIN_EVENTS
|
|
+
|
|
+#include "WinEvents.h"
|
|
+#include "WinEventsX11.h"
|
|
+#include "Application.h"
|
|
+#include "ApplicationMessenger.h"
|
|
+#include <X11/Xlib.h>
|
|
+#include "X11/WinSystemX11GL.h"
|
|
+#include "X11/keysymdef.h"
|
|
+#include "X11/XF86keysym.h"
|
|
+#include "utils/log.h"
|
|
+#include "guilib/GUIWindowManager.h"
|
|
+#include "input/MouseStat.h"
|
|
+
|
|
+CWinEventsX11* CWinEventsX11::WinEvents = 0;
|
|
+
|
|
+static uint32_t SymMappingsX11[][2] =
|
|
+{
|
|
+ {XK_BackSpace, XBMCK_BACKSPACE}
|
|
+, {XK_Tab, XBMCK_TAB}
|
|
+, {XK_Clear, XBMCK_CLEAR}
|
|
+, {XK_Return, XBMCK_RETURN}
|
|
+, {XK_Pause, XBMCK_PAUSE}
|
|
+, {XK_Escape, XBMCK_ESCAPE}
|
|
+, {XK_Delete, XBMCK_DELETE}
|
|
+// multi-media keys
|
|
+, {XF86XK_Back, XBMCK_BROWSER_BACK}
|
|
+, {XF86XK_Forward, XBMCK_BROWSER_FORWARD}
|
|
+, {XF86XK_Refresh, XBMCK_BROWSER_REFRESH}
|
|
+, {XF86XK_Stop, XBMCK_BROWSER_STOP}
|
|
+, {XF86XK_Search, XBMCK_BROWSER_SEARCH}
|
|
+, {XF86XK_Favorites, XBMCK_BROWSER_FAVORITES}
|
|
+, {XF86XK_HomePage, XBMCK_BROWSER_HOME}
|
|
+, {XF86XK_AudioMute, XBMCK_VOLUME_MUTE}
|
|
+, {XF86XK_AudioLowerVolume, XBMCK_VOLUME_DOWN}
|
|
+, {XF86XK_AudioRaiseVolume, XBMCK_VOLUME_UP}
|
|
+, {XF86XK_AudioNext, XBMCK_MEDIA_NEXT_TRACK}
|
|
+, {XF86XK_AudioPrev, XBMCK_MEDIA_PREV_TRACK}
|
|
+, {XF86XK_AudioStop, XBMCK_MEDIA_STOP}
|
|
+, {XF86XK_AudioPause, XBMCK_MEDIA_PLAY_PAUSE}
|
|
+, {XF86XK_Mail, XBMCK_LAUNCH_MAIL}
|
|
+, {XF86XK_Select, XBMCK_LAUNCH_MEDIA_SELECT}
|
|
+, {XF86XK_Launch0, XBMCK_LAUNCH_APP1}
|
|
+, {XF86XK_Launch1, XBMCK_LAUNCH_APP2}
|
|
+, {XF86XK_WWW, XBMCK_LAUNCH_FILE_BROWSER}
|
|
+, {XF86XK_AudioMedia, XBMCK_LAUNCH_MEDIA_CENTER }
|
|
+ // Numeric keypad
|
|
+, {XK_KP_0, XBMCK_KP0}
|
|
+, {XK_KP_1, XBMCK_KP1}
|
|
+, {XK_KP_2, XBMCK_KP2}
|
|
+, {XK_KP_3, XBMCK_KP3}
|
|
+, {XK_KP_4, XBMCK_KP4}
|
|
+, {XK_KP_5, XBMCK_KP5}
|
|
+, {XK_KP_6, XBMCK_KP6}
|
|
+, {XK_KP_7, XBMCK_KP7}
|
|
+, {XK_KP_8, XBMCK_KP8}
|
|
+, {XK_KP_9, XBMCK_KP9}
|
|
+, {XK_KP_Separator, XBMCK_KP_PERIOD}
|
|
+, {XK_KP_Divide, XBMCK_KP_DIVIDE}
|
|
+, {XK_KP_Multiply, XBMCK_KP_MULTIPLY}
|
|
+, {XK_KP_Subtract, XBMCK_KP_MINUS}
|
|
+, {XK_KP_Add, XBMCK_KP_PLUS}
|
|
+, {XK_KP_Enter, XBMCK_KP_ENTER}
|
|
+, {XK_KP_Equal, XBMCK_KP_EQUALS}
|
|
+ // Arrows + Home/End pad
|
|
+, {XK_Up, XBMCK_UP}
|
|
+, {XK_Down, XBMCK_DOWN}
|
|
+, {XK_Right, XBMCK_RIGHT}
|
|
+, {XK_Left, XBMCK_LEFT}
|
|
+, {XK_Insert, XBMCK_INSERT}
|
|
+, {XK_Home, XBMCK_HOME}
|
|
+, {XK_End, XBMCK_END}
|
|
+, {XK_Page_Up, XBMCK_PAGEUP}
|
|
+, {XK_Page_Down, XBMCK_PAGEDOWN}
|
|
+ // Function keys
|
|
+, {XK_F1, XBMCK_F1}
|
|
+, {XK_F2, XBMCK_F2}
|
|
+, {XK_F3, XBMCK_F3}
|
|
+, {XK_F4, XBMCK_F4}
|
|
+, {XK_F5, XBMCK_F5}
|
|
+, {XK_F6, XBMCK_F6}
|
|
+, {XK_F7, XBMCK_F7}
|
|
+, {XK_F8, XBMCK_F8}
|
|
+, {XK_F9, XBMCK_F9}
|
|
+, {XK_F10, XBMCK_F10}
|
|
+, {XK_F11, XBMCK_F11}
|
|
+, {XK_F12, XBMCK_F12}
|
|
+, {XK_F13, XBMCK_F13}
|
|
+, {XK_F14, XBMCK_F14}
|
|
+, {XK_F15, XBMCK_F15}
|
|
+ // Key state modifier keys
|
|
+, {XK_Num_Lock, XBMCK_NUMLOCK}
|
|
+, {XK_Caps_Lock, XBMCK_CAPSLOCK}
|
|
+, {XK_Scroll_Lock, XBMCK_SCROLLOCK}
|
|
+, {XK_Shift_R, XBMCK_RSHIFT}
|
|
+, {XK_Shift_L, XBMCK_LSHIFT}
|
|
+, {XK_Control_R, XBMCK_RCTRL}
|
|
+, {XK_Control_L, XBMCK_LCTRL}
|
|
+, {XK_Alt_R, XBMCK_RALT}
|
|
+, {XK_Alt_L, XBMCK_LALT}
|
|
+, {XK_Meta_R, XBMCK_RMETA}
|
|
+, {XK_Meta_L, XBMCK_LMETA}
|
|
+, {XK_Super_L, XBMCK_LSUPER}
|
|
+, {XK_Super_R, XBMCK_RSUPER}
|
|
+, {XK_Mode_switch, XBMCK_MODE}
|
|
+, {XK_Multi_key, XBMCK_COMPOSE}
|
|
+ // Miscellaneous function keys
|
|
+, {XK_Help, XBMCK_HELP}
|
|
+, {XK_Print, XBMCK_PRINT}
|
|
+//, {0, XBMCK_SYSREQ}
|
|
+, {XK_Break, XBMCK_BREAK}
|
|
+, {XK_Menu, XBMCK_MENU}
|
|
+, {XF86XK_PowerOff, XBMCK_POWER}
|
|
+, {XK_EcuSign, XBMCK_EURO}
|
|
+, {XK_Undo, XBMCK_UNDO}
|
|
+ /* Media keys */
|
|
+, {XF86XK_Eject, XBMCK_EJECT}
|
|
+, {XF86XK_Stop, XBMCK_STOP}
|
|
+, {XF86XK_AudioRecord, XBMCK_RECORD}
|
|
+, {XF86XK_AudioRewind, XBMCK_REWIND}
|
|
+, {XF86XK_Phone, XBMCK_PHONE}
|
|
+, {XF86XK_AudioPlay, XBMCK_PLAY}
|
|
+, {XF86XK_AudioRandomPlay, XBMCK_SHUFFLE}
|
|
+, {XF86XK_AudioForward, XBMCK_FASTFORWARD}
|
|
+};
|
|
+
|
|
+
|
|
+CWinEventsX11::CWinEventsX11()
|
|
+{
|
|
+ m_display = 0;
|
|
+ m_window = 0;
|
|
+ m_keybuf = 0;
|
|
+ m_utf16buf = 0;
|
|
+}
|
|
+
|
|
+CWinEventsX11::~CWinEventsX11()
|
|
+{
|
|
+ if (m_keybuf);
|
|
+ {
|
|
+ free(m_keybuf);
|
|
+ m_keybuf = 0;
|
|
+ }
|
|
+
|
|
+ if (m_utf16buf)
|
|
+ {
|
|
+ free(m_utf16buf);
|
|
+ m_utf16buf = 0;
|
|
+ }
|
|
+
|
|
+ if (m_xic)
|
|
+ {
|
|
+ XUnsetICFocus(m_xic);
|
|
+ XDestroyIC(m_xic);
|
|
+ m_xic = 0;
|
|
+ }
|
|
+
|
|
+ if (m_xim)
|
|
+ {
|
|
+ XCloseIM(m_xim);
|
|
+ m_xim = 0;
|
|
+ }
|
|
+
|
|
+ m_symLookupTable.clear();
|
|
+}
|
|
+
|
|
+bool CWinEventsX11::Init(Display *dpy, Window win)
|
|
+{
|
|
+ if (WinEvents)
|
|
+ return true;
|
|
+
|
|
+ WinEvents = new CWinEventsX11();
|
|
+ WinEvents->m_display = dpy;
|
|
+ WinEvents->m_window = win;
|
|
+ WinEvents->m_keybuf = (char*)malloc(32*sizeof(char));
|
|
+ WinEvents->m_utf16buf = (uint16_t*)malloc(32*sizeof(uint16_t));
|
|
+ WinEvents->m_keymodState = 0;
|
|
+ WinEvents->m_wmDeleteMessage = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
|
|
+ WinEvents->m_structureChanged = false;
|
|
+ memset(&(WinEvents->m_lastKey), 0, sizeof(XBMC_Event));
|
|
+
|
|
+ // open input method
|
|
+ char *old_locale = NULL, *old_modifiers = NULL;
|
|
+ char res_name[8];
|
|
+ const char *p;
|
|
+ size_t n;
|
|
+
|
|
+ // set resource name to xbmc, not used
|
|
+ strcpy(res_name, "xbmc");
|
|
+
|
|
+ // save current locale, this should be "C"
|
|
+ p = setlocale(LC_ALL, NULL);
|
|
+ if (p)
|
|
+ {
|
|
+ old_locale = (char*)malloc(strlen(p) +1);
|
|
+ strcpy(old_locale, p);
|
|
+ }
|
|
+ p = XSetLocaleModifiers(NULL);
|
|
+ if (p)
|
|
+ {
|
|
+ old_modifiers = (char*)malloc(strlen(p) +1);
|
|
+ strcpy(old_modifiers, p);
|
|
+ }
|
|
+
|
|
+ // set users preferences and open input method
|
|
+ p = setlocale(LC_ALL, "");
|
|
+ XSetLocaleModifiers("");
|
|
+ WinEvents->m_xim = XOpenIM(WinEvents->m_display, NULL, res_name, res_name);
|
|
+
|
|
+ // restore old locale
|
|
+ if (old_locale)
|
|
+ {
|
|
+ setlocale(LC_ALL, old_locale);
|
|
+ free(old_locale);
|
|
+ }
|
|
+ if (old_modifiers)
|
|
+ {
|
|
+ XSetLocaleModifiers(old_modifiers);
|
|
+ free(old_modifiers);
|
|
+ }
|
|
+
|
|
+ WinEvents->m_xic = NULL;
|
|
+ if (WinEvents->m_xim)
|
|
+ {
|
|
+ WinEvents->m_xic = XCreateIC(WinEvents->m_xim,
|
|
+ XNClientWindow, WinEvents->m_window,
|
|
+ XNFocusWindow, WinEvents->m_window,
|
|
+ XNInputStyle, XIMPreeditNothing | XIMStatusNothing,
|
|
+ XNResourceName, res_name,
|
|
+ XNResourceClass, res_name,
|
|
+ NULL);
|
|
+ }
|
|
+
|
|
+ if (!WinEvents->m_xic)
|
|
+ CLog::Log(LOGWARNING,"CWinEventsX11::Init - no input method found");
|
|
+
|
|
+ // build Keysym lookup table
|
|
+ for (unsigned int i = 0; i < sizeof(SymMappingsX11)/(2*sizeof(uint32_t)); ++i)
|
|
+ {
|
|
+ WinEvents->m_symLookupTable[SymMappingsX11[i][0]] = SymMappingsX11[i][1];
|
|
+ }
|
|
+
|
|
+ return true;
|
|
+}
|
|
+
|
|
+void CWinEventsX11::Quit()
|
|
+{
|
|
+ if (!WinEvents)
|
|
+ return;
|
|
+
|
|
+ delete WinEvents;
|
|
+ WinEvents = 0;
|
|
+}
|
|
+
|
|
+bool CWinEventsX11::HasStructureChanged()
|
|
+{
|
|
+ if (!WinEvents)
|
|
+ return false;
|
|
+
|
|
+ bool ret = WinEvents->m_structureChanged;
|
|
+ WinEvents->m_structureChanged = false;
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+bool CWinEventsX11::MessagePump()
|
|
+{
|
|
+ if (!WinEvents)
|
|
+ return false;
|
|
+
|
|
+ bool ret = false;
|
|
+ XEvent xevent;
|
|
+ unsigned long serial = 0;
|
|
+
|
|
+ while (WinEvents && XPending(WinEvents->m_display))
|
|
+ {
|
|
+ memset(&xevent, 0, sizeof (XEvent));
|
|
+ XNextEvent(WinEvents->m_display, &xevent);
|
|
+
|
|
+ // ignore events generated by auto-repeat
|
|
+ if (xevent.type == KeyRelease && XPending(WinEvents->m_display))
|
|
+ {
|
|
+ XEvent peekevent;
|
|
+ XPeekEvent(WinEvents->m_display, &peekevent);
|
|
+ if ((peekevent.type == KeyPress) &&
|
|
+ (peekevent.xkey.keycode == xevent.xkey.keycode) &&
|
|
+ ((peekevent.xkey.time - xevent.xkey.time) < 2))
|
|
+ {
|
|
+ XNextEvent(WinEvents->m_display, &peekevent);
|
|
+ continue;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (XFilterEvent(&xevent, None))
|
|
+ continue;
|
|
+
|
|
+ switch (xevent.type)
|
|
+ {
|
|
+ case MapNotify:
|
|
+ {
|
|
+ g_application.m_AppActive = true;
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ case UnmapNotify:
|
|
+ {
|
|
+ g_application.m_AppActive = false;
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ case FocusIn:
|
|
+ {
|
|
+ if (WinEvents->m_xic)
|
|
+ XSetICFocus(WinEvents->m_xic);
|
|
+ g_application.m_AppFocused = true;
|
|
+ if (serial == xevent.xfocus.serial)
|
|
+ break;
|
|
+ g_Windowing.NotifyAppFocusChange(g_application.m_AppFocused);
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ case FocusOut:
|
|
+ {
|
|
+ if (WinEvents->m_xic)
|
|
+ XUnsetICFocus(WinEvents->m_xic);
|
|
+ g_application.m_AppFocused = false;
|
|
+ g_Windowing.NotifyAppFocusChange(g_application.m_AppFocused);
|
|
+ serial = xevent.xfocus.serial;
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ case Expose:
|
|
+ {
|
|
+ g_windowManager.MarkDirty();
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ case ConfigureNotify:
|
|
+ {
|
|
+ if (xevent.xconfigure.window != WinEvents->m_window)
|
|
+ break;
|
|
+
|
|
+ WinEvents->m_structureChanged = true;
|
|
+ XBMC_Event newEvent;
|
|
+ memset(&newEvent, 0, sizeof(newEvent));
|
|
+ newEvent.type = XBMC_VIDEORESIZE;
|
|
+ newEvent.resize.w = xevent.xconfigure.width;
|
|
+ newEvent.resize.h = xevent.xconfigure.height;
|
|
+ ret |= g_application.OnEvent(newEvent);
|
|
+ g_windowManager.MarkDirty();
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ case ClientMessage:
|
|
+ {
|
|
+ if (xevent.xclient.data.l[0] == WinEvents->m_wmDeleteMessage)
|
|
+ if (!g_application.m_bStop) CApplicationMessenger::Get().Quit();
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ case KeyPress:
|
|
+ {
|
|
+ XBMC_Event newEvent;
|
|
+ memset(&newEvent, 0, sizeof(newEvent));
|
|
+ newEvent.type = XBMC_KEYDOWN;
|
|
+ KeySym xkeysym;
|
|
+
|
|
+ // fallback if we have no IM
|
|
+ if (!WinEvents->m_xic)
|
|
+ {
|
|
+ static XComposeStatus state;
|
|
+ char keybuf[32];
|
|
+ xkeysym = XLookupKeysym(&xevent.xkey, 0);
|
|
+ newEvent.key.keysym.sym = LookupXbmcKeySym(xkeysym);
|
|
+ newEvent.key.keysym.scancode = xevent.xkey.keycode;
|
|
+ newEvent.key.state = xevent.xkey.state;
|
|
+ newEvent.key.type = xevent.xkey.type;
|
|
+ if (XLookupString(&xevent.xkey, keybuf, sizeof(keybuf), NULL, &state))
|
|
+ {
|
|
+ newEvent.key.keysym.unicode = keybuf[0];
|
|
+ }
|
|
+ ret |= ProcessKey(newEvent, 500);
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ Status status;
|
|
+ int utf16size;
|
|
+ int utf16length;
|
|
+ int len;
|
|
+ len = Xutf8LookupString(WinEvents->m_xic, &xevent.xkey,
|
|
+ WinEvents->m_keybuf, sizeof(WinEvents->m_keybuf),
|
|
+ &xkeysym, &status);
|
|
+ if (status == XBufferOverflow)
|
|
+ {
|
|
+ WinEvents->m_keybuf = (char*)realloc(WinEvents->m_keybuf, len*sizeof(char));
|
|
+ len = Xutf8LookupString(WinEvents->m_xic, &xevent.xkey,
|
|
+ WinEvents->m_keybuf, sizeof(WinEvents->m_keybuf),
|
|
+ &xkeysym, &status);
|
|
+ }
|
|
+ switch (status)
|
|
+ {
|
|
+ case XLookupNone:
|
|
+ break;
|
|
+ case XLookupChars:
|
|
+ case XLookupBoth:
|
|
+ {
|
|
+ if (len == 0)
|
|
+ break;
|
|
+ utf16size = len * sizeof(uint16_t);
|
|
+ if (utf16size > sizeof(WinEvents->m_utf16buf))
|
|
+ {
|
|
+ WinEvents->m_utf16buf = (uint16_t *)realloc(WinEvents->m_utf16buf,utf16size);
|
|
+ if (WinEvents->m_utf16buf == NULL)
|
|
+ {
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ utf16length = Utf8ToUnicode(WinEvents->m_keybuf, len, WinEvents->m_utf16buf, utf16size);
|
|
+ if (utf16length < 0)
|
|
+ {
|
|
+ break;
|
|
+ }
|
|
+ for (unsigned int i = 0; i < utf16length - 1; i++)
|
|
+ {
|
|
+ newEvent.key.keysym.sym = XBMCK_UNKNOWN;
|
|
+ newEvent.key.keysym.unicode = WinEvents->m_utf16buf[i];
|
|
+ newEvent.key.state = xevent.xkey.state;
|
|
+ newEvent.key.type = xevent.xkey.type;
|
|
+ ret |= ProcessKey(newEvent, 500);
|
|
+ }
|
|
+ if (utf16length > 0)
|
|
+ {
|
|
+ newEvent.key.keysym.scancode = xevent.xkey.keycode;
|
|
+ xkeysym = XLookupKeysym(&xevent.xkey, 0);
|
|
+ newEvent.key.keysym.sym = LookupXbmcKeySym(xkeysym);
|
|
+ newEvent.key.keysym.unicode = WinEvents->m_utf16buf[utf16length - 1];
|
|
+ newEvent.key.state = xevent.xkey.state;
|
|
+ newEvent.key.type = xevent.xkey.type;
|
|
+
|
|
+ ret |= ProcessKey(newEvent, 500);
|
|
+ }
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ case XLookupKeySym:
|
|
+ {
|
|
+ newEvent.key.keysym.scancode = xevent.xkey.keycode;
|
|
+ newEvent.key.keysym.sym = LookupXbmcKeySym(xkeysym);
|
|
+ newEvent.key.state = xevent.xkey.state;
|
|
+ newEvent.key.type = xevent.xkey.type;
|
|
+ ret |= ProcessKey(newEvent, 500);
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ }// switch status
|
|
+ break;
|
|
+ } //KeyPress
|
|
+
|
|
+ case KeyRelease:
|
|
+ {
|
|
+ XBMC_Event newEvent;
|
|
+ KeySym xkeysym;
|
|
+ memset(&newEvent, 0, sizeof(newEvent));
|
|
+ newEvent.type = XBMC_KEYUP;
|
|
+ xkeysym = XLookupKeysym(&xevent.xkey, 0);
|
|
+ newEvent.key.keysym.scancode = xevent.xkey.keycode;
|
|
+ newEvent.key.keysym.sym = LookupXbmcKeySym(xkeysym);
|
|
+ newEvent.key.state = xevent.xkey.state;
|
|
+ newEvent.key.type = xevent.xkey.type;
|
|
+ ret |= ProcessKey(newEvent, 0);
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ // lose mouse coverage
|
|
+ case LeaveNotify:
|
|
+ {
|
|
+ g_Mouse.SetActive(false);
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ case MotionNotify:
|
|
+ {
|
|
+ XBMC_Event newEvent;
|
|
+ memset(&newEvent, 0, sizeof(newEvent));
|
|
+ newEvent.type = XBMC_MOUSEMOTION;
|
|
+ newEvent.motion.xrel = (int16_t)xevent.xmotion.x_root;
|
|
+ newEvent.motion.yrel = (int16_t)xevent.xmotion.y_root;
|
|
+ newEvent.motion.x = (int16_t)xevent.xmotion.x;
|
|
+ newEvent.motion.y = (int16_t)xevent.xmotion.y;
|
|
+ ret |= g_application.OnEvent(newEvent);
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ case ButtonPress:
|
|
+ {
|
|
+ XBMC_Event newEvent;
|
|
+ memset(&newEvent, 0, sizeof(newEvent));
|
|
+ newEvent.type = XBMC_MOUSEBUTTONDOWN;
|
|
+ newEvent.button.button = (unsigned char)xevent.xbutton.button;
|
|
+ newEvent.button.state = XBMC_PRESSED;
|
|
+ newEvent.button.x = (int16_t)xevent.xbutton.x;
|
|
+ newEvent.button.y = (int16_t)xevent.xbutton.y;
|
|
+ ret |= g_application.OnEvent(newEvent);
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ case ButtonRelease:
|
|
+ {
|
|
+ XBMC_Event newEvent;
|
|
+ memset(&newEvent, 0, sizeof(newEvent));
|
|
+ newEvent.type = XBMC_MOUSEBUTTONUP;
|
|
+ newEvent.button.button = (unsigned char)xevent.xbutton.button;
|
|
+ newEvent.button.state = XBMC_RELEASED;
|
|
+ newEvent.button.x = (int16_t)xevent.xbutton.x;
|
|
+ newEvent.button.y = (int16_t)xevent.xbutton.y;
|
|
+ ret |= g_application.OnEvent(newEvent);
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ default:
|
|
+ {
|
|
+ break;
|
|
+ }
|
|
+ }// switch event.type
|
|
+ }// while
|
|
+
|
|
+ ret |= ProcessKeyRepeat();
|
|
+
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+bool CWinEventsX11::ProcessKey(XBMC_Event &event, int repeatDelay)
|
|
+{
|
|
+ if (event.type == XBMC_KEYDOWN)
|
|
+ {
|
|
+ // check key modifiers
|
|
+ switch(event.key.keysym.sym)
|
|
+ {
|
|
+ case XBMCK_LSHIFT:
|
|
+ WinEvents->m_keymodState |= XBMCKMOD_LSHIFT;
|
|
+ break;
|
|
+ case XBMCK_RSHIFT:
|
|
+ WinEvents->m_keymodState |= XBMCKMOD_RSHIFT;
|
|
+ break;
|
|
+ case XBMCK_LCTRL:
|
|
+ WinEvents->m_keymodState |= XBMCKMOD_LCTRL;
|
|
+ break;
|
|
+ case XBMCK_RCTRL:
|
|
+ WinEvents->m_keymodState |= XBMCKMOD_RCTRL;
|
|
+ break;
|
|
+ case XBMCK_LALT:
|
|
+ WinEvents->m_keymodState |= XBMCKMOD_LALT;
|
|
+ break;
|
|
+ case XBMCK_RALT:
|
|
+ WinEvents->m_keymodState |= XBMCKMOD_RCTRL;
|
|
+ break;
|
|
+ case XBMCK_LMETA:
|
|
+ WinEvents->m_keymodState |= XBMCKMOD_LMETA;
|
|
+ break;
|
|
+ case XBMCK_RMETA:
|
|
+ WinEvents->m_keymodState |= XBMCKMOD_RMETA;
|
|
+ break;
|
|
+ case XBMCK_MODE:
|
|
+ WinEvents->m_keymodState |= XBMCKMOD_MODE;
|
|
+ break;
|
|
+ default:
|
|
+ break;
|
|
+ }
|
|
+ event.key.keysym.mod = (XBMCMod)WinEvents->m_keymodState;
|
|
+ memcpy(&(WinEvents->m_lastKey), &event, sizeof(event));
|
|
+ WinEvents->m_repeatKeyTimeout.Set(repeatDelay);
|
|
+
|
|
+ bool ret = ProcessShortcuts(event);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+ }
|
|
+ else if (event.type == XBMC_KEYUP)
|
|
+ {
|
|
+ switch(event.key.keysym.sym)
|
|
+ {
|
|
+ case XBMCK_LSHIFT:
|
|
+ WinEvents->m_keymodState &= ~XBMCKMOD_LSHIFT;
|
|
+ break;
|
|
+ case XBMCK_RSHIFT:
|
|
+ WinEvents->m_keymodState &= ~XBMCKMOD_RSHIFT;
|
|
+ break;
|
|
+ case XBMCK_LCTRL:
|
|
+ WinEvents->m_keymodState &= ~XBMCKMOD_LCTRL;
|
|
+ break;
|
|
+ case XBMCK_RCTRL:
|
|
+ WinEvents->m_keymodState &= ~XBMCKMOD_RCTRL;
|
|
+ break;
|
|
+ case XBMCK_LALT:
|
|
+ WinEvents->m_keymodState &= ~XBMCKMOD_LALT;
|
|
+ break;
|
|
+ case XBMCK_RALT:
|
|
+ WinEvents->m_keymodState &= ~XBMCKMOD_RCTRL;
|
|
+ break;
|
|
+ case XBMCK_LMETA:
|
|
+ WinEvents->m_keymodState &= ~XBMCKMOD_LMETA;
|
|
+ break;
|
|
+ case XBMCK_RMETA:
|
|
+ WinEvents->m_keymodState &= ~XBMCKMOD_RMETA;
|
|
+ break;
|
|
+ case XBMCK_MODE:
|
|
+ WinEvents->m_keymodState &= ~XBMCKMOD_MODE;
|
|
+ break;
|
|
+ default:
|
|
+ break;
|
|
+ }
|
|
+ event.key.keysym.mod = (XBMCMod)WinEvents->m_keymodState;
|
|
+ memset(&(WinEvents->m_lastKey), 0, sizeof(event));
|
|
+ }
|
|
+
|
|
+ return g_application.OnEvent(event);
|
|
+}
|
|
+
|
|
+bool CWinEventsX11::ProcessShortcuts(XBMC_Event& event)
|
|
+{
|
|
+ if (event.key.keysym.mod & XBMCKMOD_ALT)
|
|
+ {
|
|
+ switch(event.key.keysym.sym)
|
|
+ {
|
|
+ case XBMCK_TAB: // ALT+TAB to minimize/hide
|
|
+ g_application.Minimize();
|
|
+ return true;
|
|
+
|
|
+ default:
|
|
+ return false;
|
|
+ }
|
|
+ }
|
|
+ return false;
|
|
+}
|
|
+
|
|
+bool CWinEventsX11::ProcessKeyRepeat()
|
|
+{
|
|
+ if (WinEvents && (WinEvents->m_lastKey.type == XBMC_KEYDOWN))
|
|
+ {
|
|
+ if (WinEvents->m_repeatKeyTimeout.IsTimePast())
|
|
+ {
|
|
+ return ProcessKey(WinEvents->m_lastKey, 10);
|
|
+ }
|
|
+ }
|
|
+ return false;
|
|
+}
|
|
+
|
|
+int CWinEventsX11::Utf8ToUnicode(const char *utf8, const int utf8Length, uint16_t *utf16, const int utf16MaxLength)
|
|
+{
|
|
+ // p moves over the output buffer. max_ptr points to the next to the last slot of the buffer.
|
|
+ uint16_t *p = utf16;
|
|
+ uint16_t const *const maxPtr = utf16 + utf16MaxLength;
|
|
+
|
|
+ // end_of_input points to the last byte of input as opposed to the next to the last byte.
|
|
+ char const *const endOfInput = utf8 + utf8Length - 1;
|
|
+
|
|
+ while (utf8 <= endOfInput)
|
|
+ {
|
|
+ unsigned char const c = *utf8;
|
|
+ if (p >= maxPtr)
|
|
+ {
|
|
+ //No more output space.
|
|
+ return -1;
|
|
+ }
|
|
+ if (c < 0x80)
|
|
+ {
|
|
+ //One byte ASCII.
|
|
+ *p++ = c;
|
|
+ utf8 += 1;
|
|
+ }
|
|
+ else if (c < 0xC0)
|
|
+ {
|
|
+ // Follower byte without preceding leader bytes.
|
|
+ return -1;
|
|
+ }
|
|
+ // 11 bits
|
|
+ else if (c < 0xE0)
|
|
+ {
|
|
+ // Two byte sequence. We need one follower byte.
|
|
+ if (endOfInput - utf8 < 1 || (((utf8[1] ^ 0x80)) & 0xC0))
|
|
+ {
|
|
+ return -1;
|
|
+ }
|
|
+ *p++ = (uint16_t)(((c & 0x1F) << 6) + (utf8[1] & 0x3F));
|
|
+ utf8 += 2;
|
|
+ }
|
|
+ // 16 bis
|
|
+ else if (c < 0xF0)
|
|
+ {
|
|
+ // Three byte sequence. We need two follower byte.
|
|
+ if (endOfInput - utf8 < 2 || ((utf8[1] ^ 0x80) & 0xC0) || ((utf8[2] ^ 0x80) & 0xC0))
|
|
+ {
|
|
+ return -1;
|
|
+ }
|
|
+ *p++ = (uint16_t)(((c & 0xF) << 12) + ((utf8[1] & 0x3F) << 6) + (utf8[2] & 0x3F));
|
|
+ utf8 += 3;
|
|
+ }
|
|
+ // 21 bits
|
|
+ else if (c < 0xF8)
|
|
+ {
|
|
+ int plane;
|
|
+ // Four byte sequence. We need three follower bytes.
|
|
+ if (endOfInput - utf8 < 3 || ((utf8[1] ^ 0x80) & 0xC0) ||
|
|
+ ((utf8[2] ^ 0x80) & 0xC0) || ((utf8[3] ^ 0x80) & 0xC0))
|
|
+ {
|
|
+ return -1;
|
|
+ }
|
|
+ uint32_t unicode = ((c & 0x7) << 18) + ((utf8[1] & 0x3F) << 12) +
|
|
+ ((utf8[2] & 0x3F) << 6) + (utf8[3] & 0x3F);
|
|
+ utf8 += 4;
|
|
+ CLog::Log(LOGERROR, "CWinEventsX11::Utf8ToUnicode: 4 byte unicode not supported");
|
|
+ }
|
|
+ // 26 bits
|
|
+ else if (c < 0xFC)
|
|
+ {
|
|
+ CLog::Log(LOGERROR, "CWinEventsX11::Utf8ToUnicode: 4 byte unicode not supported");
|
|
+ utf8 += 5;
|
|
+ }
|
|
+ // 31 bit
|
|
+ else
|
|
+ {
|
|
+ CLog::Log(LOGERROR, "CWinEventsX11::Utf8ToUnicode: 4 byte unicode not supported");
|
|
+ utf8 += 6;
|
|
+ }
|
|
+ }
|
|
+ return p - utf16;
|
|
+}
|
|
+
|
|
+XBMCKey CWinEventsX11::LookupXbmcKeySym(KeySym keysym)
|
|
+{
|
|
+ // try direct mapping first
|
|
+ std::map<uint32_t, uint32_t>::iterator it;
|
|
+ it = WinEvents->m_symLookupTable.find(keysym);
|
|
+ if (it != WinEvents->m_symLookupTable.end())
|
|
+ {
|
|
+ return (XBMCKey)(it->second);
|
|
+ }
|
|
+
|
|
+ // try ascii mappings
|
|
+ if (keysym>>8 == 0x00)
|
|
+ return (XBMCKey)(keysym & 0xFF);
|
|
+
|
|
+ return (XBMCKey)keysym;
|
|
+}
|
|
+#endif
|
|
diff --git a/xbmc/windowing/WinEventsX11.h b/xbmc/windowing/WinEventsX11.h
|
|
new file mode 100644
|
|
index 0000000..e9b7553
|
|
--- /dev/null
|
|
+++ b/xbmc/windowing/WinEventsX11.h
|
|
@@ -0,0 +1,57 @@
|
|
+/*
|
|
+* Copyright (C) 2005-2012 Team XBMC
|
|
+* http://www.xbmc.org
|
|
+*
|
|
+* This Program is free software; you can redistribute it and/or modify
|
|
+* it under the terms of the GNU General Public License as published by
|
|
+* the Free Software Foundation; either version 2, or (at your option)
|
|
+* any later version.
|
|
+*
|
|
+* This Program is distributed in the hope that it will be useful,
|
|
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
+* GNU General Public License for more details.
|
|
+*
|
|
+* You should have received a copy of the GNU General Public License
|
|
+* along with XBMC; see the file COPYING. If not, write to
|
|
+* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
+* http://www.gnu.org/copyleft/gpl.html
|
|
+*
|
|
+*/
|
|
+#pragma once
|
|
+
|
|
+#include "WinEvents.h"
|
|
+#include <X11/Xlib.h>
|
|
+#include "threads/SystemClock.h"
|
|
+#include <map>
|
|
+
|
|
+class CWinEventsX11 : public CWinEventsBase
|
|
+{
|
|
+public:
|
|
+ CWinEventsX11();
|
|
+ virtual ~CWinEventsX11();
|
|
+ static bool Init(Display *dpy, Window win);
|
|
+ static void Quit();
|
|
+ static bool HasStructureChanged();
|
|
+ static bool MessagePump();
|
|
+
|
|
+protected:
|
|
+ static int Utf8ToUnicode(const char *utf8, const int utf8Length, uint16_t *utf16, const int utf16MaxLength);
|
|
+ static XBMCKey LookupXbmcKeySym(KeySym keysym);
|
|
+ static bool ProcessKey(XBMC_Event &event, int repeatDelay);
|
|
+ static bool ProcessKeyRepeat();
|
|
+ static bool ProcessShortcuts(XBMC_Event& event);
|
|
+ static CWinEventsX11 *WinEvents;
|
|
+ Display *m_display;
|
|
+ Window m_window;
|
|
+ Atom m_wmDeleteMessage;
|
|
+ char *m_keybuf;
|
|
+ uint16_t *m_utf16buf;
|
|
+ XIM m_xim;
|
|
+ XIC m_xic;
|
|
+ XBMC_Event m_lastKey;
|
|
+ XbmcThreads::EndTime m_repeatKeyTimeout;
|
|
+ std::map<uint32_t,uint32_t> m_symLookupTable;
|
|
+ int m_keymodState;
|
|
+ bool m_structureChanged;
|
|
+};
|
|
diff --git a/xbmc/windowing/X11/WinSystemX11.cpp b/xbmc/windowing/X11/WinSystemX11.cpp
|
|
index a839709..76ef462 100644
|
|
--- a/xbmc/windowing/X11/WinSystemX11.cpp
|
|
+++ b/xbmc/windowing/X11/WinSystemX11.cpp
|
|
@@ -22,7 +22,6 @@
|
|
|
|
#ifdef HAS_GLX
|
|
|
|
-#include <SDL/SDL_syswm.h>
|
|
#include "WinSystemX11.h"
|
|
#include "settings/Settings.h"
|
|
#include "guilib/Texture.h"
|
|
@@ -31,27 +30,30 @@
|
|
#include "XRandR.h"
|
|
#include <vector>
|
|
#include "threads/SingleLock.h"
|
|
-#include <X11/Xlib.h>
|
|
#include "cores/VideoRenderers/RenderManager.h"
|
|
#include "utils/TimeUtils.h"
|
|
+#include "settings/GUISettings.h"
|
|
|
|
#if defined(HAS_XRANDR)
|
|
#include <X11/extensions/Xrandr.h>
|
|
#endif
|
|
|
|
+#include "../WinEvents.h"
|
|
+#include "input/MouseStat.h"
|
|
+
|
|
using namespace std;
|
|
|
|
CWinSystemX11::CWinSystemX11() : CWinSystemBase()
|
|
{
|
|
m_eWindowSystem = WINDOW_SYSTEM_X11;
|
|
m_glContext = NULL;
|
|
- m_SDLSurface = NULL;
|
|
m_dpy = NULL;
|
|
m_glWindow = 0;
|
|
- m_wmWindow = 0;
|
|
m_bWasFullScreenBeforeMinimize = false;
|
|
m_minimized = false;
|
|
+ m_bIgnoreNextFocusMessage = false;
|
|
m_dpyLostTime = 0;
|
|
+ m_invisibleCursor = 0;
|
|
|
|
XSetErrorHandler(XErrorHandler);
|
|
}
|
|
@@ -64,18 +66,6 @@ bool CWinSystemX11::InitWindowSystem()
|
|
{
|
|
if ((m_dpy = XOpenDisplay(NULL)))
|
|
{
|
|
-
|
|
- SDL_EnableUNICODE(1);
|
|
- // set repeat to 10ms to ensure repeat time < frame time
|
|
- // so that hold times can be reliably detected
|
|
- SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, 10);
|
|
-
|
|
- SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
|
|
- SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
|
|
- SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
|
|
- SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8);
|
|
- SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
|
|
-
|
|
return CWinSystemBase::InitWindowSystem();
|
|
}
|
|
else
|
|
@@ -113,45 +103,37 @@ bool CWinSystemX11::DestroyWindowSystem()
|
|
|
|
bool CWinSystemX11::CreateNewWindow(const CStdString& name, bool fullScreen, RESOLUTION_INFO& res, PHANDLE_EVENT_FUNC userFunction)
|
|
{
|
|
- RESOLUTION_INFO& desktop = g_settings.m_ResInfo[RES_DESKTOP];
|
|
-
|
|
- if (fullScreen &&
|
|
- (res.iWidth != desktop.iWidth || res.iHeight != desktop.iHeight ||
|
|
- res.fRefreshRate != desktop.fRefreshRate || res.iScreen != desktop.iScreen))
|
|
- {
|
|
- //on the first call to SDL_SetVideoMode, SDL stores the current displaymode
|
|
- //SDL restores the displaymode on SDL_QUIT(), if we change the displaymode
|
|
- //before the first call to SDL_SetVideoMode, SDL changes the displaymode back
|
|
- //to the wrong mode on exit
|
|
-
|
|
- CLog::Log(LOGINFO, "CWinSystemX11::CreateNewWindow initializing to desktop resolution first");
|
|
- if (!SetFullScreen(true, desktop, false))
|
|
- return false;
|
|
- }
|
|
-
|
|
if(!SetFullScreen(fullScreen, res, false))
|
|
return false;
|
|
|
|
- CBaseTexture* iconTexture = CTexture::LoadFromFile("special://xbmc/media/icon.png");
|
|
-
|
|
- if (iconTexture)
|
|
- SDL_WM_SetIcon(SDL_CreateRGBSurfaceFrom(iconTexture->GetPixels(), iconTexture->GetWidth(), iconTexture->GetHeight(), 32, iconTexture->GetPitch(), 0xff0000, 0x00ff00, 0x0000ff, 0xff000000L), NULL);
|
|
- SDL_WM_SetCaption("XBMC Media Center", NULL);
|
|
- delete iconTexture;
|
|
-
|
|
- // register XRandR Events
|
|
-#if defined(HAS_XRANDR)
|
|
- int iReturn;
|
|
- XRRQueryExtension(m_dpy, &m_RREventBase, &iReturn);
|
|
- XRRSelectInput(m_dpy, m_wmWindow, RRScreenChangeNotifyMask);
|
|
-#endif
|
|
-
|
|
m_bWindowCreated = true;
|
|
return true;
|
|
}
|
|
|
|
bool CWinSystemX11::DestroyWindow()
|
|
{
|
|
+ if (!m_glWindow)
|
|
+ return true;
|
|
+
|
|
+ if (m_glContext)
|
|
+ glXMakeCurrent(m_dpy, None, NULL);
|
|
+
|
|
+ if (m_invisibleCursor)
|
|
+ {
|
|
+ XUndefineCursor(m_dpy, m_glWindow);
|
|
+ XFreeCursor(m_dpy, m_invisibleCursor);
|
|
+ m_invisibleCursor = 0;
|
|
+ }
|
|
+
|
|
+ CWinEvents::Quit();
|
|
+
|
|
+ XUnmapWindow(m_dpy, m_glWindow);
|
|
+ XSync(m_dpy,TRUE);
|
|
+ XUngrabKeyboard(m_dpy, CurrentTime);
|
|
+ XUngrabPointer(m_dpy, CurrentTime);
|
|
+ XDestroyWindow(m_dpy, m_glWindow);
|
|
+ m_glWindow = 0;
|
|
+
|
|
return true;
|
|
}
|
|
|
|
@@ -161,65 +143,105 @@ bool CWinSystemX11::ResizeWindow(int newWidth, int newHeight, int newLeft, int n
|
|
&& m_nHeight == newHeight)
|
|
return true;
|
|
|
|
+ if (!SetWindow(newWidth, newHeight, false))
|
|
+ {
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ RefreshGlxContext();
|
|
m_nWidth = newWidth;
|
|
m_nHeight = newHeight;
|
|
+ m_bFullScreen = false;
|
|
|
|
- int options = SDL_OPENGL;
|
|
- if (m_bFullScreen)
|
|
- options |= SDL_FULLSCREEN;
|
|
- else
|
|
- options |= SDL_RESIZABLE;
|
|
+ return false;
|
|
+}
|
|
+
|
|
+void CWinSystemX11::RefreshWindow()
|
|
+{
|
|
+ g_xrandr.Query(true);
|
|
+ XOutput out = g_xrandr.GetCurrentOutput();
|
|
+ XMode mode = g_xrandr.GetCurrentMode(out.name);
|
|
|
|
- if ((m_SDLSurface = SDL_SetVideoMode(m_nWidth, m_nHeight, 0, options)))
|
|
+ // only overwrite desktop resolution, if we are not in fullscreen mode
|
|
+ if (!g_graphicsContext.IsFullScreenVideo())
|
|
{
|
|
- RefreshGlxContext();
|
|
- return true;
|
|
+ CLog::Log(LOGDEBUG, "CWinSystemX11::RefreshWindow - store desktop resolution, width: %d, height: %d, hz: %2.2f", mode.w, mode.h, mode.hz);
|
|
+ UpdateDesktopResolution(g_settings.m_ResInfo[RES_DESKTOP], 0, mode.w, mode.h, mode.hz);
|
|
+ g_settings.m_ResInfo[RES_DESKTOP].strId = mode.id;
|
|
+ g_settings.m_ResInfo[RES_DESKTOP].strOutput = out.name;
|
|
}
|
|
|
|
- return false;
|
|
+ RESOLUTION_INFO res;
|
|
+ unsigned int i;
|
|
+ bool found(false);
|
|
+ for (i = RES_DESKTOP; i < g_settings.m_ResInfo.size(); ++i)
|
|
+ {
|
|
+ if (g_settings.m_ResInfo[i].strId == mode.id)
|
|
+ {
|
|
+ found = true;
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (!found)
|
|
+ {
|
|
+ CLog::Log(LOGERROR, "CWinSystemX11::RefreshWindow - could not find resolution");
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ if (g_graphicsContext.IsFullScreenRoot())
|
|
+ g_graphicsContext.SetVideoResolution((RESOLUTION)i, true);
|
|
+ else
|
|
+ g_graphicsContext.SetVideoResolution(RES_WINDOW, true);
|
|
}
|
|
|
|
bool CWinSystemX11::SetFullScreen(bool fullScreen, RESOLUTION_INFO& res, bool blankOtherDisplays)
|
|
{
|
|
- m_nWidth = res.iWidth;
|
|
- m_nHeight = res.iHeight;
|
|
- m_bFullScreen = fullScreen;
|
|
|
|
#if defined(HAS_XRANDR)
|
|
XOutput out;
|
|
XMode mode;
|
|
- out.name = res.strOutput;
|
|
- mode.w = res.iWidth;
|
|
- mode.h = res.iHeight;
|
|
- mode.hz = res.fRefreshRate;
|
|
- mode.id = res.strId;
|
|
+
|
|
+ if (fullScreen)
|
|
+ {
|
|
+ out.name = res.strOutput;
|
|
+ mode.w = res.iWidth;
|
|
+ mode.h = res.iHeight;
|
|
+ mode.hz = res.fRefreshRate;
|
|
+ mode.id = res.strId;
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ out.name = g_settings.m_ResInfo[RES_DESKTOP].strOutput;
|
|
+ mode.w = g_settings.m_ResInfo[RES_DESKTOP].iWidth;
|
|
+ mode.h = g_settings.m_ResInfo[RES_DESKTOP].iHeight;
|
|
+ mode.hz = g_settings.m_ResInfo[RES_DESKTOP].fRefreshRate;
|
|
+ mode.id = g_settings.m_ResInfo[RES_DESKTOP].strId;
|
|
+ }
|
|
|
|
- if(m_bFullScreen)
|
|
+ XOutput currout = g_xrandr.GetCurrentOutput();
|
|
+ XMode currmode = g_xrandr.GetCurrentMode(currout.name);
|
|
+
|
|
+ // only call xrandr if mode changes
|
|
+ if (currout.name != out.name || currmode.w != mode.w || currmode.h != mode.h ||
|
|
+ currmode.hz != mode.hz || currmode.id != mode.id)
|
|
{
|
|
+ CLog::Log(LOGNOTICE, "CWinSystemX11::SetFullScreen - calling xrandr");
|
|
OnLostDevice();
|
|
g_xrandr.SetMode(out, mode);
|
|
}
|
|
- else
|
|
- g_xrandr.RestoreState();
|
|
#endif
|
|
|
|
- int options = SDL_OPENGL;
|
|
- if (m_bFullScreen)
|
|
- options |= SDL_FULLSCREEN;
|
|
- else
|
|
- options |= SDL_RESIZABLE;
|
|
-
|
|
- if ((m_SDLSurface = SDL_SetVideoMode(m_nWidth, m_nHeight, 0, options)))
|
|
- {
|
|
- if ((m_SDLSurface->flags & SDL_OPENGL) != SDL_OPENGL)
|
|
- CLog::Log(LOGERROR, "CWinSystemX11::SetFullScreen SDL_OPENGL not set, SDL_GetError:%s", SDL_GetError());
|
|
+ if (!SetWindow(res.iWidth, res.iHeight, fullScreen))
|
|
+ return false;
|
|
|
|
- RefreshGlxContext();
|
|
+ RefreshGlxContext();
|
|
|
|
- return true;
|
|
- }
|
|
+ m_nWidth = res.iWidth;
|
|
+ m_nHeight = res.iHeight;
|
|
+ m_bFullScreen = fullScreen;
|
|
|
|
- return false;
|
|
+ return true;
|
|
}
|
|
|
|
void CWinSystemX11::UpdateResolutions()
|
|
@@ -321,17 +343,10 @@ bool CWinSystemX11::IsSuitableVisual(XVisualInfo *vInfo)
|
|
bool CWinSystemX11::RefreshGlxContext()
|
|
{
|
|
bool retVal = false;
|
|
- SDL_SysWMinfo info;
|
|
- SDL_VERSION(&info.version);
|
|
- if (SDL_GetWMInfo(&info) <= 0)
|
|
- {
|
|
- CLog::Log(LOGERROR, "Failed to get window manager info from SDL");
|
|
- return false;
|
|
- }
|
|
|
|
- if(m_glWindow == info.info.x11.window && m_glContext)
|
|
+ if (m_glContext)
|
|
{
|
|
- CLog::Log(LOGERROR, "GLX: Same window as before, refreshing context");
|
|
+ CLog::Log(LOGDEBUG, "CWinSystemX11::RefreshGlxContext: refreshing context");
|
|
glXMakeCurrent(m_dpy, None, NULL);
|
|
glXMakeCurrent(m_dpy, m_glWindow, m_glContext);
|
|
return true;
|
|
@@ -343,8 +358,6 @@ bool CWinSystemX11::RefreshGlxContext()
|
|
int availableVisuals = 0;
|
|
vMask.screen = DefaultScreen(m_dpy);
|
|
XWindowAttributes winAttr;
|
|
- m_glWindow = info.info.x11.window;
|
|
- m_wmWindow = info.info.x11.wmwindow;
|
|
|
|
/* Assume a depth of 24 in case the below calls to XGetWindowAttributes()
|
|
or XGetVisualInfo() fail. That shouldn't happen unless something is
|
|
@@ -415,7 +428,10 @@ bool CWinSystemX11::RefreshGlxContext()
|
|
|
|
void CWinSystemX11::ShowOSMouse(bool show)
|
|
{
|
|
- SDL_ShowCursor(show ? 1 : 0);
|
|
+ if (show)
|
|
+ XUndefineCursor(m_dpy,m_glWindow);
|
|
+ else if (m_invisibleCursor)
|
|
+ XDefineCursor(m_dpy,m_glWindow, m_invisibleCursor);
|
|
}
|
|
|
|
void CWinSystemX11::ResetOSScreensaver()
|
|
@@ -429,8 +445,6 @@ void CWinSystemX11::ResetOSScreensaver()
|
|
{
|
|
m_screensaverReset.StartZero();
|
|
XResetScreenSaver(m_dpy);
|
|
- //need to flush the output buffer, since we don't check for events on m_dpy
|
|
- XFlush(m_dpy);
|
|
}
|
|
}
|
|
else
|
|
@@ -446,13 +460,27 @@ void CWinSystemX11::NotifyAppActiveChange(bool bActivated)
|
|
|
|
m_minimized = !bActivated;
|
|
}
|
|
+
|
|
+void CWinSystemX11::NotifyAppFocusChange(bool bGaining)
|
|
+{
|
|
+ if (bGaining && m_bWasFullScreenBeforeMinimize && !m_bIgnoreNextFocusMessage &&
|
|
+ !g_graphicsContext.IsFullScreenRoot())
|
|
+ g_graphicsContext.ToggleFullScreenRoot();
|
|
+ if (!bGaining)
|
|
+ m_bIgnoreNextFocusMessage = false;
|
|
+}
|
|
+
|
|
bool CWinSystemX11::Minimize()
|
|
{
|
|
m_bWasFullScreenBeforeMinimize = g_graphicsContext.IsFullScreenRoot();
|
|
if (m_bWasFullScreenBeforeMinimize)
|
|
+ {
|
|
+ m_bIgnoreNextFocusMessage = true;
|
|
g_graphicsContext.ToggleFullScreenRoot();
|
|
+ }
|
|
+
|
|
+ XIconifyWindow(m_dpy, m_glWindow, DefaultScreen(m_dpy));
|
|
|
|
- SDL_WM_IconifyWindow();
|
|
m_minimized = true;
|
|
return true;
|
|
}
|
|
@@ -462,13 +490,13 @@ bool CWinSystemX11::Restore()
|
|
}
|
|
bool CWinSystemX11::Hide()
|
|
{
|
|
- XUnmapWindow(m_dpy, m_wmWindow);
|
|
+ XUnmapWindow(m_dpy, m_glWindow);
|
|
XSync(m_dpy, False);
|
|
return true;
|
|
}
|
|
bool CWinSystemX11::Show(bool raise)
|
|
{
|
|
- XMapWindow(m_dpy, m_wmWindow);
|
|
+ XMapWindow(m_dpy, m_glWindow);
|
|
XSync(m_dpy, False);
|
|
m_minimized = false;
|
|
return true;
|
|
@@ -500,6 +528,7 @@ void CWinSystemX11::CheckDisplayEvents()
|
|
if (bGotEvent || bTimeout)
|
|
{
|
|
CLog::Log(LOGDEBUG, "%s - notify display reset event", __FUNCTION__);
|
|
+ RefreshWindow();
|
|
|
|
CSingleLock lock(m_resourceSection);
|
|
|
|
@@ -558,4 +587,151 @@ bool CWinSystemX11::EnableFrameLimiter()
|
|
return m_minimized;
|
|
}
|
|
|
|
+bool CWinSystemX11::SetWindow(int width, int height, bool fullscreen)
|
|
+{
|
|
+ bool changeWindow = false;
|
|
+ bool changeSize = false;
|
|
+ bool mouseActive = false;
|
|
+ float mouseX, mouseY;
|
|
+
|
|
+ if (m_glWindow && (m_bFullScreen != fullscreen))
|
|
+ {
|
|
+ mouseActive = g_Mouse.IsActive();
|
|
+ if (mouseActive)
|
|
+ {
|
|
+ Window root_return, child_return;
|
|
+ int root_x_return, root_y_return;
|
|
+ int win_x_return, win_y_return;
|
|
+ unsigned int mask_return;
|
|
+ bool isInWin = XQueryPointer(m_dpy, m_glWindow, &root_return, &child_return,
|
|
+ &root_x_return, &root_y_return,
|
|
+ &win_x_return, &win_y_return,
|
|
+ &mask_return);
|
|
+ if (isInWin)
|
|
+ {
|
|
+ mouseX = (float)win_x_return/m_nWidth;
|
|
+ mouseY = (float)win_y_return/m_nHeight;
|
|
+ g_Mouse.SetActive(false);
|
|
+ }
|
|
+ else
|
|
+ mouseActive = false;
|
|
+ }
|
|
+ DestroyWindow();
|
|
+ }
|
|
+
|
|
+ // create main window
|
|
+ if (!m_glWindow)
|
|
+ {
|
|
+ GLint att[] =
|
|
+ {
|
|
+ GLX_RGBA,
|
|
+ GLX_RED_SIZE, 8,
|
|
+ GLX_GREEN_SIZE, 8,
|
|
+ GLX_BLUE_SIZE, 8,
|
|
+ GLX_ALPHA_SIZE, 8,
|
|
+ GLX_DEPTH_SIZE, 24,
|
|
+ GLX_DOUBLEBUFFER,
|
|
+ None
|
|
+ };
|
|
+ Colormap cmap;
|
|
+ XSetWindowAttributes swa;
|
|
+ XVisualInfo *vi;
|
|
+
|
|
+ vi = glXChooseVisual(m_dpy, DefaultScreen(m_dpy), att);
|
|
+ cmap = XCreateColormap(m_dpy, RootWindow(m_dpy, vi->screen), vi->visual, AllocNone);
|
|
+
|
|
+ int def_vis = (vi->visual == DefaultVisual(m_dpy, vi->screen));
|
|
+ swa.override_redirect = fullscreen ? True : False;
|
|
+ swa.border_pixel = fullscreen ? 0 : 5;
|
|
+ swa.background_pixel = def_vis ? BlackPixel(m_dpy, vi->screen) : 0;
|
|
+ swa.colormap = cmap;
|
|
+ swa.background_pixel = def_vis ? BlackPixel(m_dpy, vi->screen) : 0;
|
|
+ swa.event_mask = FocusChangeMask | KeyPressMask | KeyReleaseMask |
|
|
+ ButtonPressMask | ButtonReleaseMask | PointerMotionMask |
|
|
+ PropertyChangeMask | StructureNotifyMask | KeymapStateMask |
|
|
+ EnterWindowMask | LeaveWindowMask | ExposureMask;
|
|
+ unsigned long mask = CWBackPixel | CWBorderPixel | CWColormap | CWOverrideRedirect | CWEventMask;
|
|
+
|
|
+ m_glWindow = XCreateWindow(m_dpy, RootWindow(m_dpy, vi->screen),
|
|
+ 0, 0, width, height, 0, vi->depth,
|
|
+ InputOutput, vi->visual,
|
|
+ mask, &swa);
|
|
+
|
|
+ // define invisible cursor
|
|
+ Pixmap bitmapNoData;
|
|
+ XColor black;
|
|
+ static char noData[] = { 0,0,0,0,0,0,0,0 };
|
|
+ black.red = black.green = black.blue = 0;
|
|
+
|
|
+ bitmapNoData = XCreateBitmapFromData(m_dpy, m_glWindow, noData, 8, 8);
|
|
+ m_invisibleCursor = XCreatePixmapCursor(m_dpy, bitmapNoData, bitmapNoData,
|
|
+ &black, &black, 0, 0);
|
|
+ XFreePixmap(m_dpy, bitmapNoData);
|
|
+ XDefineCursor(m_dpy,m_glWindow, m_invisibleCursor);
|
|
+
|
|
+ //init X11 events
|
|
+ CWinEvents::Init(m_dpy, m_glWindow);
|
|
+
|
|
+ changeWindow = true;
|
|
+ changeSize = true;
|
|
+ }
|
|
+
|
|
+ if (!CWinEvents::HasStructureChanged() && ((width != m_nWidth) || (height != m_nHeight)))
|
|
+ {
|
|
+ changeSize = true;
|
|
+ }
|
|
+
|
|
+ if (changeSize || changeWindow)
|
|
+ {
|
|
+ XResizeWindow(m_dpy, m_glWindow, width, height);
|
|
+ }
|
|
+
|
|
+ if (changeWindow)
|
|
+ {
|
|
+ if (!fullscreen)
|
|
+ {
|
|
+ XWMHints wm_hints;
|
|
+ XClassHint class_hints;
|
|
+ XTextProperty windowName, iconName;
|
|
+ std::string titleString = "XBMC Media Center";
|
|
+ char *title = (char*)titleString.c_str();
|
|
+
|
|
+ XStringListToTextProperty(&title, 1, &windowName);
|
|
+ XStringListToTextProperty(&title, 1, &iconName);
|
|
+ wm_hints.initial_state = NormalState;
|
|
+ wm_hints.input = True;
|
|
+ wm_hints.icon_pixmap = None;
|
|
+ wm_hints.flags = StateHint | IconPixmapHint | InputHint;
|
|
+
|
|
+ XSetWMProperties(m_dpy, m_glWindow, &windowName, &iconName,
|
|
+ NULL, 0, NULL, &wm_hints,
|
|
+ NULL);
|
|
+
|
|
+ // register interest in the delete window message
|
|
+ Atom wmDeleteMessage = XInternAtom(m_dpy, "WM_DELETE_WINDOW", False);
|
|
+ XSetWMProtocols(m_dpy, m_glWindow, &wmDeleteMessage, 1);
|
|
+ }
|
|
+ XMapRaised(m_dpy, m_glWindow);
|
|
+ XSync(m_dpy,TRUE);
|
|
+
|
|
+ if (changeWindow && mouseActive)
|
|
+ {
|
|
+ XWarpPointer(m_dpy, None, m_glWindow, 0, 0, 0, 0, mouseX*width, mouseY*height);
|
|
+ }
|
|
+
|
|
+ if (fullscreen)
|
|
+ {
|
|
+ int result = -1;
|
|
+ while (result != GrabSuccess)
|
|
+ {
|
|
+ result = XGrabPointer(m_dpy, m_glWindow, True, ButtonPressMask, GrabModeAsync, GrabModeAsync, m_glWindow, None, CurrentTime);
|
|
+ XbmcThreads::ThreadSleep(100);
|
|
+ }
|
|
+ XGrabKeyboard(m_dpy, m_glWindow, True, GrabModeAsync, GrabModeAsync, CurrentTime);
|
|
+
|
|
+ }
|
|
+ }
|
|
+ return true;
|
|
+}
|
|
+
|
|
#endif
|
|
diff --git a/xbmc/windowing/X11/WinSystemX11.h b/xbmc/windowing/X11/WinSystemX11.h
|
|
index 2dd8a9f..9616d17 100644
|
|
--- a/xbmc/windowing/X11/WinSystemX11.h
|
|
+++ b/xbmc/windowing/X11/WinSystemX11.h
|
|
@@ -52,6 +52,7 @@ class CWinSystemX11 : public CWinSystemBase
|
|
virtual bool EnableFrameLimiter();
|
|
|
|
virtual void NotifyAppActiveChange(bool bActivated);
|
|
+ virtual void NotifyAppFocusChange(bool bGaining);
|
|
|
|
virtual bool Minimize();
|
|
virtual bool Restore() ;
|
|
@@ -64,19 +65,21 @@ class CWinSystemX11 : public CWinSystemBase
|
|
Display* GetDisplay() { return m_dpy; }
|
|
GLXWindow GetWindow() { return m_glWindow; }
|
|
GLXContext GetGlxContext() { return m_glContext; }
|
|
+ void RefreshWindow();
|
|
|
|
protected:
|
|
bool RefreshGlxContext();
|
|
void CheckDisplayEvents();
|
|
void OnLostDevice();
|
|
+ bool SetWindow(int width, int height, bool fullscreen);
|
|
|
|
- SDL_Surface* m_SDLSurface;
|
|
+ Window m_glWindow;
|
|
GLXContext m_glContext;
|
|
- GLXWindow m_glWindow;
|
|
- Window m_wmWindow;
|
|
Display* m_dpy;
|
|
+ Cursor m_invisibleCursor;
|
|
bool m_bWasFullScreenBeforeMinimize;
|
|
bool m_minimized;
|
|
+ bool m_bIgnoreNextFocusMessage;
|
|
int m_RREventBase;
|
|
CCriticalSection m_resourceSection;
|
|
std::vector<IDispResource*> m_resources;
|
|
--
|
|
1.7.10
|
|
|
|
|
|
From 58fa894afaffbc990ee1ab87ff55db30e36ab2c2 Mon Sep 17 00:00:00 2001
|
|
From: FernetMenta <fernetmenta@online.de>
|
|
Date: Thu, 5 Jul 2012 15:24:22 +0200
|
|
Subject: [PATCH 15/72] X11: Add xbmc icon
|
|
|
|
---
|
|
xbmc/windowing/X11/WinSystemX11.cpp | 126 ++++++++++++++++++++++++++++++++++-
|
|
xbmc/windowing/X11/WinSystemX11.h | 2 +
|
|
2 files changed, 127 insertions(+), 1 deletion(-)
|
|
|
|
diff --git a/xbmc/windowing/X11/WinSystemX11.cpp b/xbmc/windowing/X11/WinSystemX11.cpp
|
|
index 76ef462..c854598 100644
|
|
--- a/xbmc/windowing/X11/WinSystemX11.cpp
|
|
+++ b/xbmc/windowing/X11/WinSystemX11.cpp
|
|
@@ -134,6 +134,9 @@ bool CWinSystemX11::DestroyWindow()
|
|
XDestroyWindow(m_dpy, m_glWindow);
|
|
m_glWindow = 0;
|
|
|
|
+ if (m_icon)
|
|
+ XFreePixmap(m_dpy, m_icon);
|
|
+
|
|
return true;
|
|
}
|
|
|
|
@@ -688,8 +691,10 @@ bool CWinSystemX11::SetWindow(int width, int height, bool fullscreen)
|
|
|
|
if (changeWindow)
|
|
{
|
|
+ m_icon = None;
|
|
if (!fullscreen)
|
|
{
|
|
+ CreateIconPixmap();
|
|
XWMHints wm_hints;
|
|
XClassHint class_hints;
|
|
XTextProperty windowName, iconName;
|
|
@@ -700,7 +705,7 @@ bool CWinSystemX11::SetWindow(int width, int height, bool fullscreen)
|
|
XStringListToTextProperty(&title, 1, &iconName);
|
|
wm_hints.initial_state = NormalState;
|
|
wm_hints.input = True;
|
|
- wm_hints.icon_pixmap = None;
|
|
+ wm_hints.icon_pixmap = m_icon;
|
|
wm_hints.flags = StateHint | IconPixmapHint | InputHint;
|
|
|
|
XSetWMProperties(m_dpy, m_glWindow, &windowName, &iconName,
|
|
@@ -734,4 +739,123 @@ bool CWinSystemX11::SetWindow(int width, int height, bool fullscreen)
|
|
return true;
|
|
}
|
|
|
|
+bool CWinSystemX11::CreateIconPixmap()
|
|
+{
|
|
+ int depth;
|
|
+ XImage *img = NULL;
|
|
+ Visual *vis;
|
|
+ XWindowAttributes wndattribs;
|
|
+ XVisualInfo visInfo;
|
|
+ double rRatio;
|
|
+ double gRatio;
|
|
+ double bRatio;
|
|
+ int outIndex = 0;
|
|
+ int i,j;
|
|
+ int numBufBytes;
|
|
+ unsigned char *buf;
|
|
+ uint32_t *newBuf = 0;
|
|
+ size_t numNewBufBytes;
|
|
+
|
|
+ // Get visual Info
|
|
+ XGetWindowAttributes(m_dpy, m_glWindow, &wndattribs);
|
|
+ visInfo.visualid = wndattribs.visual->visualid;
|
|
+ int nvisuals = 0;
|
|
+ XVisualInfo* visuals = XGetVisualInfo(m_dpy, VisualIDMask, &visInfo, &nvisuals);
|
|
+ if (nvisuals != 1)
|
|
+ {
|
|
+ CLog::Log(LOGERROR, "CWinSystemX11::CreateIconPixmap - could not find visual");
|
|
+ return false;
|
|
+ }
|
|
+ visInfo = visuals[0];
|
|
+ XFree(visuals);
|
|
+
|
|
+ depth = visInfo.depth;
|
|
+ vis = visInfo.visual;
|
|
+
|
|
+ if (depth < 15)
|
|
+ {
|
|
+ CLog::Log(LOGERROR, "CWinSystemX11::CreateIconPixmap - no suitable depth");
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ rRatio = vis->red_mask / 255.0;
|
|
+ gRatio = vis->green_mask / 255.0;
|
|
+ bRatio = vis->blue_mask / 255.0;
|
|
+
|
|
+ CTexture iconTexture;
|
|
+ iconTexture.LoadFromFile("special://xbmc/media/icon.png");
|
|
+ buf = iconTexture.GetPixels();
|
|
+
|
|
+ numBufBytes = iconTexture.GetWidth() * iconTexture.GetHeight() * 4;
|
|
+
|
|
+ if (depth>=24)
|
|
+ numNewBufBytes = (4 * (iconTexture.GetWidth() * iconTexture.GetHeight()));
|
|
+ else
|
|
+ numNewBufBytes = (2 * (iconTexture.GetWidth() * iconTexture.GetHeight()));
|
|
+
|
|
+ newBuf = (uint32_t*)malloc(numNewBufBytes);
|
|
+ if (!newBuf)
|
|
+ {
|
|
+ CLog::Log(LOGERROR, "CWinSystemX11::CreateIconPixmap - malloc failed");
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ for (i=0; i<iconTexture.GetHeight();++i)
|
|
+ {
|
|
+ for (j=0; j<iconTexture.GetWidth();++j)
|
|
+ {
|
|
+ unsigned int pos = i*iconTexture.GetPitch()+j*4;
|
|
+ unsigned int r, g, b;
|
|
+ r = (buf[pos+2] * rRatio);
|
|
+ g = (buf[pos+1] * gRatio);
|
|
+ b = (buf[pos+0] * bRatio);
|
|
+ r &= vis->red_mask;
|
|
+ g &= vis->green_mask;
|
|
+ b &= vis->blue_mask;
|
|
+ newBuf[outIndex] = r | g | b;
|
|
+ ++outIndex;
|
|
+ }
|
|
+ }
|
|
+ img = XCreateImage(m_dpy, vis, depth,ZPixmap, 0, (char *)newBuf,
|
|
+ iconTexture.GetWidth(), iconTexture.GetHeight(),
|
|
+ (depth>=24)?32:16, 0);
|
|
+ if (!img)
|
|
+ {
|
|
+ CLog::Log(LOGERROR, "CWinSystemX11::CreateIconPixmap - could not create image");
|
|
+ free(newBuf);
|
|
+ return false;
|
|
+ }
|
|
+ if (!XInitImage(img))
|
|
+ {
|
|
+ CLog::Log(LOGERROR, "CWinSystemX11::CreateIconPixmap - init image failed");
|
|
+ XDestroyImage(img);
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ // set byte order
|
|
+ union
|
|
+ {
|
|
+ char c[sizeof(short)];
|
|
+ short s;
|
|
+ } order;
|
|
+ order.s = 1;
|
|
+ if ((1 == order.c[0]))
|
|
+ {
|
|
+ img->byte_order = LSBFirst;
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ img->byte_order = MSBFirst;
|
|
+ }
|
|
+
|
|
+ // create icon pixmap from image
|
|
+ m_icon = XCreatePixmap(m_dpy, m_glWindow, img->width, img->height, depth);
|
|
+ GC gc = XCreateGC(m_dpy, m_glWindow, 0, NULL);
|
|
+ XPutImage(m_dpy, m_icon, gc, img, 0, 0, 0, 0, img->width, img->height);
|
|
+ XFreeGC(m_dpy, gc);
|
|
+ XDestroyImage(img); // this also frees newBuf
|
|
+
|
|
+ return true;
|
|
+}
|
|
+
|
|
#endif
|
|
diff --git a/xbmc/windowing/X11/WinSystemX11.h b/xbmc/windowing/X11/WinSystemX11.h
|
|
index 9616d17..debf714 100644
|
|
--- a/xbmc/windowing/X11/WinSystemX11.h
|
|
+++ b/xbmc/windowing/X11/WinSystemX11.h
|
|
@@ -77,6 +77,7 @@ class CWinSystemX11 : public CWinSystemBase
|
|
GLXContext m_glContext;
|
|
Display* m_dpy;
|
|
Cursor m_invisibleCursor;
|
|
+ Pixmap m_icon;
|
|
bool m_bWasFullScreenBeforeMinimize;
|
|
bool m_minimized;
|
|
bool m_bIgnoreNextFocusMessage;
|
|
@@ -88,6 +89,7 @@ class CWinSystemX11 : public CWinSystemBase
|
|
private:
|
|
bool IsSuitableVisual(XVisualInfo *vInfo);
|
|
static int XErrorHandler(Display* dpy, XErrorEvent* error);
|
|
+ bool CreateIconPixmap();
|
|
|
|
CStopWatch m_screensaverReset;
|
|
};
|
|
--
|
|
1.7.10
|
|
|
|
|
|
From cad2ac7f357906f10f100a038ff28e83a69c68e8 Mon Sep 17 00:00:00 2001
|
|
From: xbmc <fernetmenta@online.de>
|
|
Date: Sun, 20 May 2012 14:11:26 +0200
|
|
Subject: [PATCH 16/72] X11: add SDL joystick until we have a better solution
|
|
|
|
---
|
|
xbmc/windowing/WinEventsX11.cpp | 26 ++++++++++++++++++++++++++
|
|
1 file changed, 26 insertions(+)
|
|
|
|
diff --git a/xbmc/windowing/WinEventsX11.cpp b/xbmc/windowing/WinEventsX11.cpp
|
|
index 24477ae..2ec86a8 100644
|
|
--- a/xbmc/windowing/WinEventsX11.cpp
|
|
+++ b/xbmc/windowing/WinEventsX11.cpp
|
|
@@ -35,6 +35,10 @@
|
|
#include "guilib/GUIWindowManager.h"
|
|
#include "input/MouseStat.h"
|
|
|
|
+#ifdef HAS_SDL_JOYSTICK
|
|
+#include "input/SDLJoystick.h"
|
|
+#endif
|
|
+
|
|
CWinEventsX11* CWinEventsX11::WinEvents = 0;
|
|
|
|
static uint32_t SymMappingsX11[][2] =
|
|
@@ -547,6 +551,28 @@ bool CWinEventsX11::MessagePump()
|
|
|
|
ret |= ProcessKeyRepeat();
|
|
|
|
+#ifdef HAS_SDL_JOYSTICK
|
|
+ SDL_Event event;
|
|
+ while (SDL_PollEvent(&event))
|
|
+ {
|
|
+ switch(event.type)
|
|
+ {
|
|
+ case SDL_JOYBUTTONUP:
|
|
+ case SDL_JOYBUTTONDOWN:
|
|
+ case SDL_JOYAXISMOTION:
|
|
+ case SDL_JOYBALLMOTION:
|
|
+ case SDL_JOYHATMOTION:
|
|
+ g_Joystick.Update(event);
|
|
+ ret = true;
|
|
+ break;
|
|
+
|
|
+ default:
|
|
+ break;
|
|
+ }
|
|
+ memset(&event, 0, sizeof(SDL_Event));
|
|
+ }
|
|
+#endif
|
|
+
|
|
return ret;
|
|
}
|
|
|
|
--
|
|
1.7.10
|
|
|
|
|
|
From fdefd4cf296518f31ad1165268fccd651e08dd3c Mon Sep 17 00:00:00 2001
|
|
From: Joakim Plate <elupus@xbmc.org>
|
|
Date: Thu, 5 Jul 2012 12:35:55 +0200
|
|
Subject: [PATCH 17/72] X11: factor out code handling device reset
|
|
notification
|
|
|
|
---
|
|
xbmc/windowing/X11/WinSystemX11.cpp | 22 ++++++++++++++--------
|
|
xbmc/windowing/X11/WinSystemX11.h | 1 +
|
|
2 files changed, 15 insertions(+), 8 deletions(-)
|
|
|
|
diff --git a/xbmc/windowing/X11/WinSystemX11.cpp b/xbmc/windowing/X11/WinSystemX11.cpp
|
|
index c854598..70557d0 100644
|
|
--- a/xbmc/windowing/X11/WinSystemX11.cpp
|
|
+++ b/xbmc/windowing/X11/WinSystemX11.cpp
|
|
@@ -530,14 +530,7 @@ void CWinSystemX11::CheckDisplayEvents()
|
|
|
|
if (bGotEvent || bTimeout)
|
|
{
|
|
- CLog::Log(LOGDEBUG, "%s - notify display reset event", __FUNCTION__);
|
|
- RefreshWindow();
|
|
-
|
|
- CSingleLock lock(m_resourceSection);
|
|
-
|
|
- // tell any shared resources
|
|
- for (vector<IDispResource *>::iterator i = m_resources.begin(); i != m_resources.end(); i++)
|
|
- (*i)->OnResetDevice();
|
|
+ NotifyXRREvent();
|
|
|
|
// reset fail safe timer
|
|
m_dpyLostTime = 0;
|
|
@@ -545,6 +538,19 @@ void CWinSystemX11::CheckDisplayEvents()
|
|
#endif
|
|
}
|
|
|
|
+void CWinSystemX11::NotifyXRREvent()
|
|
+{
|
|
+ CLog::Log(LOGDEBUG, "%s - notify display reset event", __FUNCTION__);
|
|
+ RefreshWindow();
|
|
+
|
|
+ CSingleLock lock(m_resourceSection);
|
|
+
|
|
+ // tell any shared resources
|
|
+ for (vector<IDispResource *>::iterator i = m_resources.begin(); i != m_resources.end(); i++)
|
|
+ (*i)->OnResetDevice();
|
|
+
|
|
+}
|
|
+
|
|
void CWinSystemX11::OnLostDevice()
|
|
{
|
|
CLog::Log(LOGDEBUG, "%s - notify display change event", __FUNCTION__);
|
|
diff --git a/xbmc/windowing/X11/WinSystemX11.h b/xbmc/windowing/X11/WinSystemX11.h
|
|
index debf714..8c28e3f 100644
|
|
--- a/xbmc/windowing/X11/WinSystemX11.h
|
|
+++ b/xbmc/windowing/X11/WinSystemX11.h
|
|
@@ -66,6 +66,7 @@ class CWinSystemX11 : public CWinSystemBase
|
|
GLXWindow GetWindow() { return m_glWindow; }
|
|
GLXContext GetGlxContext() { return m_glContext; }
|
|
void RefreshWindow();
|
|
+ void NotifyXRREvent();
|
|
|
|
protected:
|
|
bool RefreshGlxContext();
|
|
--
|
|
1.7.10
|
|
|
|
|
|
From 9a409794d1eb8ee0c4b0b1124dea7dd30af32c06 Mon Sep 17 00:00:00 2001
|
|
From: FernetMenta <fernetmenta@online.de>
|
|
Date: Thu, 5 Jul 2012 15:02:00 +0200
|
|
Subject: [PATCH 18/72] X11: move xrandr events to WinEventsX11
|
|
|
|
---
|
|
xbmc/windowing/WinEventsX11.cpp | 42 +++++++++++++++++++++++++++++++++++
|
|
xbmc/windowing/WinEventsX11.h | 5 +++++
|
|
xbmc/windowing/X11/WinSystemX11.cpp | 6 ++++-
|
|
3 files changed, 52 insertions(+), 1 deletion(-)
|
|
|
|
diff --git a/xbmc/windowing/WinEventsX11.cpp b/xbmc/windowing/WinEventsX11.cpp
|
|
index 2ec86a8..5946a33 100644
|
|
--- a/xbmc/windowing/WinEventsX11.cpp
|
|
+++ b/xbmc/windowing/WinEventsX11.cpp
|
|
@@ -35,6 +35,10 @@
|
|
#include "guilib/GUIWindowManager.h"
|
|
#include "input/MouseStat.h"
|
|
|
|
+#if defined(HAS_XRANDR)
|
|
+#include <X11/extensions/Xrandr.h>
|
|
+#endif
|
|
+
|
|
#ifdef HAS_SDL_JOYSTICK
|
|
#include "input/SDLJoystick.h"
|
|
#endif
|
|
@@ -203,6 +207,7 @@ bool CWinEventsX11::Init(Display *dpy, Window win)
|
|
WinEvents->m_keymodState = 0;
|
|
WinEvents->m_wmDeleteMessage = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
|
|
WinEvents->m_structureChanged = false;
|
|
+ WinEvents->m_xrrEventPending = false;
|
|
memset(&(WinEvents->m_lastKey), 0, sizeof(XBMC_Event));
|
|
|
|
// open input method
|
|
@@ -266,6 +271,13 @@ bool CWinEventsX11::Init(Display *dpy, Window win)
|
|
WinEvents->m_symLookupTable[SymMappingsX11[i][0]] = SymMappingsX11[i][1];
|
|
}
|
|
|
|
+ // register for xrandr events
|
|
+#if defined(HAS_XRANDR)
|
|
+ int iReturn;
|
|
+ XRRQueryExtension(WinEvents->m_display, &WinEvents->m_RREventBase, &iReturn);
|
|
+ XRRSelectInput(WinEvents->m_display, WinEvents->m_window, RRScreenChangeNotifyMask);
|
|
+#endif
|
|
+
|
|
return true;
|
|
}
|
|
|
|
@@ -288,6 +300,15 @@ bool CWinEventsX11::HasStructureChanged()
|
|
return ret;
|
|
}
|
|
|
|
+void CWinEventsX11::SetXRRFailSafeTimer(int millis)
|
|
+{
|
|
+ if (!WinEvents)
|
|
+ return;
|
|
+
|
|
+ WinEvents->m_xrrFailSafeTimer.Set(millis);
|
|
+ WinEvents->m_xrrEventPending = true;
|
|
+}
|
|
+
|
|
bool CWinEventsX11::MessagePump()
|
|
{
|
|
if (!WinEvents)
|
|
@@ -547,10 +568,31 @@ bool CWinEventsX11::MessagePump()
|
|
break;
|
|
}
|
|
}// switch event.type
|
|
+
|
|
+#if defined(HAS_XRANDR)
|
|
+ if (WinEvents && (xevent.type == WinEvents->m_RREventBase + RRScreenChangeNotify))
|
|
+ {
|
|
+ XRRUpdateConfiguration(&xevent);
|
|
+ if (xevent.xgeneric.serial != serial)
|
|
+ g_Windowing.NotifyXRREvent();
|
|
+ WinEvents->m_xrrEventPending = false;
|
|
+ serial = xevent.xgeneric.serial;
|
|
+ }
|
|
+#endif
|
|
+
|
|
}// while
|
|
|
|
ret |= ProcessKeyRepeat();
|
|
|
|
+#if defined(HAS_XRANDR)
|
|
+ if (WinEvents && WinEvents->m_xrrEventPending && WinEvents->m_xrrFailSafeTimer.IsTimePast())
|
|
+ {
|
|
+ CLog::Log(LOGERROR,"CWinEventsX11::MessagePump - missed XRR Events");
|
|
+ g_Windowing.NotifyXRREvent();
|
|
+ WinEvents->m_xrrEventPending = false;
|
|
+ }
|
|
+#endif
|
|
+
|
|
#ifdef HAS_SDL_JOYSTICK
|
|
SDL_Event event;
|
|
while (SDL_PollEvent(&event))
|
|
diff --git a/xbmc/windowing/WinEventsX11.h b/xbmc/windowing/WinEventsX11.h
|
|
index e9b7553..6100933 100644
|
|
--- a/xbmc/windowing/WinEventsX11.h
|
|
+++ b/xbmc/windowing/WinEventsX11.h
|
|
@@ -33,6 +33,8 @@ class CWinEventsX11 : public CWinEventsBase
|
|
static bool Init(Display *dpy, Window win);
|
|
static void Quit();
|
|
static bool HasStructureChanged();
|
|
+ static void PendingResize(int width, int height);
|
|
+ static void SetXRRFailSafeTimer(int millis);
|
|
static bool MessagePump();
|
|
|
|
protected:
|
|
@@ -54,4 +56,7 @@ class CWinEventsX11 : public CWinEventsBase
|
|
std::map<uint32_t,uint32_t> m_symLookupTable;
|
|
int m_keymodState;
|
|
bool m_structureChanged;
|
|
+ int m_RREventBase;
|
|
+ XbmcThreads::EndTime m_xrrFailSafeTimer;
|
|
+ bool m_xrrEventPending;
|
|
};
|
|
diff --git a/xbmc/windowing/X11/WinSystemX11.cpp b/xbmc/windowing/X11/WinSystemX11.cpp
|
|
index 70557d0..1cce843 100644
|
|
--- a/xbmc/windowing/X11/WinSystemX11.cpp
|
|
+++ b/xbmc/windowing/X11/WinSystemX11.cpp
|
|
@@ -507,7 +507,7 @@ bool CWinSystemX11::Show(bool raise)
|
|
|
|
void CWinSystemX11::CheckDisplayEvents()
|
|
{
|
|
-#if defined(HAS_XRANDR)
|
|
+#if defined(HAS_XRANDR) && defined(HAS_SDL_VIDEO_X11)
|
|
bool bGotEvent(false);
|
|
bool bTimeout(false);
|
|
XEvent Event;
|
|
@@ -563,8 +563,12 @@ void CWinSystemX11::OnLostDevice()
|
|
(*i)->OnLostDevice();
|
|
}
|
|
|
|
+#if defined(HAS_SDL_VIDEO_X11)
|
|
// fail safe timer
|
|
m_dpyLostTime = CurrentHostCounter();
|
|
+#else
|
|
+ CWinEvents::SetXRRFailSafeTimer(3000);
|
|
+#endif
|
|
}
|
|
|
|
void CWinSystemX11::Register(IDispResource *resource)
|
|
--
|
|
1.7.10
|
|
|
|
|
|
From 1dc579a2d5c608cfd4f799971759d18cbd2957e5 Mon Sep 17 00:00:00 2001
|
|
From: FernetMenta <fernetmenta@online.de>
|
|
Date: Thu, 12 Apr 2012 15:43:56 +0200
|
|
Subject: [PATCH 19/72] xrandr: remove method RestoreState
|
|
|
|
---
|
|
xbmc/windowing/X11/WinSystemX11.cpp | 13 +++++++++++--
|
|
xbmc/windowing/X11/XRandR.cpp | 19 -------------------
|
|
xbmc/windowing/X11/XRandR.h | 1 -
|
|
3 files changed, 11 insertions(+), 22 deletions(-)
|
|
|
|
diff --git a/xbmc/windowing/X11/WinSystemX11.cpp b/xbmc/windowing/X11/WinSystemX11.cpp
|
|
index 1cce843..e13ffa4 100644
|
|
--- a/xbmc/windowing/X11/WinSystemX11.cpp
|
|
+++ b/xbmc/windowing/X11/WinSystemX11.cpp
|
|
@@ -77,9 +77,18 @@ bool CWinSystemX11::InitWindowSystem()
|
|
bool CWinSystemX11::DestroyWindowSystem()
|
|
{
|
|
#if defined(HAS_XRANDR)
|
|
- //restore videomode on exit
|
|
+ //restore desktop resolution on exit
|
|
if (m_bFullScreen)
|
|
- g_xrandr.RestoreState();
|
|
+ {
|
|
+ XOutput out;
|
|
+ XMode mode;
|
|
+ out.name = g_settings.m_ResInfo[RES_DESKTOP].strOutput;
|
|
+ mode.w = g_settings.m_ResInfo[RES_DESKTOP].iWidth;
|
|
+ mode.h = g_settings.m_ResInfo[RES_DESKTOP].iHeight;
|
|
+ mode.hz = g_settings.m_ResInfo[RES_DESKTOP].fRefreshRate;
|
|
+ mode.id = g_settings.m_ResInfo[RES_DESKTOP].strId;
|
|
+ g_xrandr.SetMode(out, mode);
|
|
+ }
|
|
#endif
|
|
|
|
if (m_dpy)
|
|
diff --git a/xbmc/windowing/X11/XRandR.cpp b/xbmc/windowing/X11/XRandR.cpp
|
|
index d8e9161..59755a6 100644
|
|
--- a/xbmc/windowing/X11/XRandR.cpp
|
|
+++ b/xbmc/windowing/X11/XRandR.cpp
|
|
@@ -139,25 +139,6 @@ void CXRandR::SaveState()
|
|
Query(true);
|
|
}
|
|
|
|
-void CXRandR::RestoreState()
|
|
-{
|
|
- vector<XOutput>::iterator outiter;
|
|
- for (outiter=m_current.begin() ; outiter!=m_current.end() ; outiter++)
|
|
- {
|
|
- vector<XMode> modes = (*outiter).modes;
|
|
- vector<XMode>::iterator modeiter;
|
|
- for (modeiter=modes.begin() ; modeiter!=modes.end() ; modeiter++)
|
|
- {
|
|
- XMode mode = *modeiter;
|
|
- if (mode.isCurrent)
|
|
- {
|
|
- SetMode(*outiter, mode);
|
|
- return;
|
|
- }
|
|
- }
|
|
- }
|
|
-}
|
|
-
|
|
bool CXRandR::SetMode(XOutput output, XMode mode)
|
|
{
|
|
if ((output.name == m_currentOutput && mode.id == m_currentMode) || (output.name == "" && mode.id == ""))
|
|
diff --git a/xbmc/windowing/X11/XRandR.h b/xbmc/windowing/X11/XRandR.h
|
|
index 2a269d0..5b64633 100644
|
|
--- a/xbmc/windowing/X11/XRandR.h
|
|
+++ b/xbmc/windowing/X11/XRandR.h
|
|
@@ -99,7 +99,6 @@ class CXRandR
|
|
bool SetMode(XOutput output, XMode mode);
|
|
void LoadCustomModeLinesToAllOutputs(void);
|
|
void SaveState();
|
|
- void RestoreState();
|
|
//bool Has1080i();
|
|
//bool Has1080p();
|
|
//bool Has720p();
|
|
--
|
|
1.7.10
|
|
|
|
|
|
From 4a6f0e986fc27b356041a4b1bb989e0e594c8aa7 Mon Sep 17 00:00:00 2001
|
|
From: xbmc <fernetmenta@online.de>
|
|
Date: Sun, 20 May 2012 13:17:10 +0200
|
|
Subject: [PATCH 20/72] xrandr: observe orientation
|
|
|
|
---
|
|
xbmc/windowing/X11/WinSystemX11.cpp | 61 +++++++++++++++++++++++++++++++++--
|
|
xbmc/windowing/X11/WinSystemX11.h | 2 ++
|
|
xbmc/windowing/X11/XRandR.cpp | 7 ++++
|
|
xbmc/windowing/X11/XRandR.h | 1 +
|
|
4 files changed, 68 insertions(+), 3 deletions(-)
|
|
|
|
diff --git a/xbmc/windowing/X11/WinSystemX11.cpp b/xbmc/windowing/X11/WinSystemX11.cpp
|
|
index e13ffa4..6b0aa92 100644
|
|
--- a/xbmc/windowing/X11/WinSystemX11.cpp
|
|
+++ b/xbmc/windowing/X11/WinSystemX11.cpp
|
|
@@ -170,15 +170,24 @@ bool CWinSystemX11::ResizeWindow(int newWidth, int newHeight, int newLeft, int n
|
|
|
|
void CWinSystemX11::RefreshWindow()
|
|
{
|
|
- g_xrandr.Query(true);
|
|
+ if (!g_xrandr.Query(true))
|
|
+ {
|
|
+ CLog::Log(LOGERROR, "WinSystemX11::RefreshWindow - failed to query xrandr");
|
|
+ return;
|
|
+ }
|
|
XOutput out = g_xrandr.GetCurrentOutput();
|
|
XMode mode = g_xrandr.GetCurrentMode(out.name);
|
|
|
|
+ RotateResolutions();
|
|
+
|
|
// only overwrite desktop resolution, if we are not in fullscreen mode
|
|
if (!g_graphicsContext.IsFullScreenVideo())
|
|
{
|
|
CLog::Log(LOGDEBUG, "CWinSystemX11::RefreshWindow - store desktop resolution, width: %d, height: %d, hz: %2.2f", mode.w, mode.h, mode.hz);
|
|
- UpdateDesktopResolution(g_settings.m_ResInfo[RES_DESKTOP], 0, mode.w, mode.h, mode.hz);
|
|
+ if (!out.isRotated)
|
|
+ UpdateDesktopResolution(g_settings.m_ResInfo[RES_DESKTOP], 0, mode.w, mode.h, mode.hz);
|
|
+ else
|
|
+ UpdateDesktopResolution(g_settings.m_ResInfo[RES_DESKTOP], 0, mode.h, mode.w, mode.hz);
|
|
g_settings.m_ResInfo[RES_DESKTOP].strId = mode.id;
|
|
g_settings.m_ResInfo[RES_DESKTOP].strOutput = out.name;
|
|
}
|
|
@@ -234,6 +243,14 @@ bool CWinSystemX11::SetFullScreen(bool fullScreen, RESOLUTION_INFO& res, bool bl
|
|
XOutput currout = g_xrandr.GetCurrentOutput();
|
|
XMode currmode = g_xrandr.GetCurrentMode(currout.name);
|
|
|
|
+ // flip h/w when rotated
|
|
+ if (m_bIsRotated)
|
|
+ {
|
|
+ int w = mode.w;
|
|
+ mode.w = mode.h;
|
|
+ mode.h = w;
|
|
+ }
|
|
+
|
|
// only call xrandr if mode changes
|
|
if (currout.name != out.name || currmode.w != mode.w || currmode.h != mode.h ||
|
|
currmode.hz != mode.hz || currmode.id != mode.id)
|
|
@@ -266,7 +283,11 @@ void CWinSystemX11::UpdateResolutions()
|
|
{
|
|
XOutput out = g_xrandr.GetCurrentOutput();
|
|
XMode mode = g_xrandr.GetCurrentMode(out.name);
|
|
- UpdateDesktopResolution(g_settings.m_ResInfo[RES_DESKTOP], 0, mode.w, mode.h, mode.hz);
|
|
+ m_bIsRotated = out.isRotated;
|
|
+ if (!m_bIsRotated)
|
|
+ UpdateDesktopResolution(g_settings.m_ResInfo[RES_DESKTOP], 0, mode.w, mode.h, mode.hz);
|
|
+ else
|
|
+ UpdateDesktopResolution(g_settings.m_ResInfo[RES_DESKTOP], 0, mode.h, mode.w, mode.hz);
|
|
g_settings.m_ResInfo[RES_DESKTOP].strId = mode.id;
|
|
g_settings.m_ResInfo[RES_DESKTOP].strOutput = out.name;
|
|
}
|
|
@@ -305,6 +326,16 @@ void CWinSystemX11::UpdateResolutions()
|
|
res.iHeight = mode.h;
|
|
res.iScreenWidth = mode.w;
|
|
res.iScreenHeight = mode.h;
|
|
+ if (!m_bIsRotated)
|
|
+ {
|
|
+ res.iWidth = mode.w;
|
|
+ res.iHeight = mode.h;
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ res.iWidth = mode.h;
|
|
+ res.iHeight = mode.w;
|
|
+ }
|
|
if (mode.h>0 && mode.w>0 && out.hmm>0 && out.wmm>0)
|
|
res.fPixelRatio = ((float)out.wmm/(float)mode.w) / (((float)out.hmm/(float)mode.h));
|
|
else
|
|
@@ -332,6 +363,30 @@ void CWinSystemX11::UpdateResolutions()
|
|
|
|
}
|
|
|
|
+void CWinSystemX11::RotateResolutions()
|
|
+{
|
|
+#if defined(HAS_XRANDR)
|
|
+ XOutput out = g_xrandr.GetCurrentOutput();
|
|
+ if (out.isRotated == m_bIsRotated)
|
|
+ return;
|
|
+
|
|
+ for (unsigned int i = 0; i < g_settings.m_ResInfo.size(); ++i)
|
|
+ {
|
|
+ int width = g_settings.m_ResInfo[i].iWidth;
|
|
+ g_settings.m_ResInfo[i].iWidth = g_settings.m_ResInfo[i].iHeight;
|
|
+ g_settings.m_ResInfo[i].iHeight = width;
|
|
+ }
|
|
+ // update desktop resolution
|
|
+// int h = g_settings.m_ResInfo[RES_DESKTOP].iHeight;
|
|
+// int w = g_settings.m_ResInfo[RES_DESKTOP].iWidth;
|
|
+// float hz = g_settings.m_ResInfo[RES_DESKTOP].fRefreshRate;
|
|
+// UpdateDesktopResolution(g_settings.m_ResInfo[RES_DESKTOP], 0, w, h, hz);
|
|
+
|
|
+ m_bIsRotated = out.isRotated;
|
|
+
|
|
+#endif
|
|
+}
|
|
+
|
|
bool CWinSystemX11::IsSuitableVisual(XVisualInfo *vInfo)
|
|
{
|
|
int value;
|
|
diff --git a/xbmc/windowing/X11/WinSystemX11.h b/xbmc/windowing/X11/WinSystemX11.h
|
|
index 8c28e3f..93cf5db 100644
|
|
--- a/xbmc/windowing/X11/WinSystemX11.h
|
|
+++ b/xbmc/windowing/X11/WinSystemX11.h
|
|
@@ -73,12 +73,14 @@ class CWinSystemX11 : public CWinSystemBase
|
|
void CheckDisplayEvents();
|
|
void OnLostDevice();
|
|
bool SetWindow(int width, int height, bool fullscreen);
|
|
+ void RotateResolutions();
|
|
|
|
Window m_glWindow;
|
|
GLXContext m_glContext;
|
|
Display* m_dpy;
|
|
Cursor m_invisibleCursor;
|
|
Pixmap m_icon;
|
|
+ bool m_bIsRotated;
|
|
bool m_bWasFullScreenBeforeMinimize;
|
|
bool m_minimized;
|
|
bool m_bIgnoreNextFocusMessage;
|
|
diff --git a/xbmc/windowing/X11/XRandR.cpp b/xbmc/windowing/X11/XRandR.cpp
|
|
index 59755a6..45aeb71 100644
|
|
--- a/xbmc/windowing/X11/XRandR.cpp
|
|
+++ b/xbmc/windowing/X11/XRandR.cpp
|
|
@@ -98,6 +98,13 @@ bool CXRandR::Query(bool force)
|
|
xoutput.y = (output->Attribute("y") != NULL ? atoi(output->Attribute("y")) : 0);
|
|
xoutput.wmm = (output->Attribute("wmm") != NULL ? atoi(output->Attribute("wmm")) : 0);
|
|
xoutput.hmm = (output->Attribute("hmm") != NULL ? atoi(output->Attribute("hmm")) : 0);
|
|
+ if (output->Attribute("rotation") != NULL
|
|
+ && (strcasecmp(output->Attribute("rotation"), "left") == 0 || strcasecmp(output->Attribute("rotation"), "right") == 0))
|
|
+ {
|
|
+ xoutput.isRotated = true;
|
|
+ }
|
|
+ else
|
|
+ xoutput.isRotated = false;
|
|
|
|
if (!xoutput.isConnected)
|
|
continue;
|
|
diff --git a/xbmc/windowing/X11/XRandR.h b/xbmc/windowing/X11/XRandR.h
|
|
index 5b64633..618bd68 100644
|
|
--- a/xbmc/windowing/X11/XRandR.h
|
|
+++ b/xbmc/windowing/X11/XRandR.h
|
|
@@ -86,6 +86,7 @@ class XOutput
|
|
int wmm;
|
|
int hmm;
|
|
std::vector<XMode> modes;
|
|
+ bool isRotated;
|
|
};
|
|
|
|
class CXRandR
|
|
--
|
|
1.7.10
|
|
|
|
|
|
From 97e5811e05a4ecde7249b2f76283729ff300fda9 Mon Sep 17 00:00:00 2001
|
|
From: FernetMenta <fernetmenta@online.de>
|
|
Date: Thu, 5 Jul 2012 11:54:15 +0200
|
|
Subject: [PATCH 21/72] xrandr: allow getting info for multiple screen's
|
|
|
|
Refactored by: Joakim Plate <elupus@xbmc.org>
|
|
---
|
|
xbmc/windowing/X11/XRandR.cpp | 65 ++++++++++++++++++++++++++++++++---------
|
|
xbmc/windowing/X11/XRandR.h | 8 +++--
|
|
2 files changed, 57 insertions(+), 16 deletions(-)
|
|
|
|
diff --git a/xbmc/windowing/X11/XRandR.cpp b/xbmc/windowing/X11/XRandR.cpp
|
|
index 45aeb71..cc933b9 100644
|
|
--- a/xbmc/windowing/X11/XRandR.cpp
|
|
+++ b/xbmc/windowing/X11/XRandR.cpp
|
|
@@ -39,6 +39,7 @@
|
|
CXRandR::CXRandR(bool query)
|
|
{
|
|
m_bInit = false;
|
|
+ m_numScreens = 1;
|
|
if (query)
|
|
Query();
|
|
}
|
|
@@ -55,11 +56,21 @@ bool CXRandR::Query(bool force)
|
|
return false;
|
|
|
|
m_outputs.clear();
|
|
- m_current.clear();
|
|
+ // query all screens
|
|
+ for(unsigned int screennum=0; screennum<m_numScreens; ++screennum)
|
|
+ {
|
|
+ if(!Query(force, screennum))
|
|
+ return false;
|
|
+ }
|
|
+ return true;
|
|
+}
|
|
|
|
+bool CXRandR::Query(bool force, int screennum)
|
|
+{
|
|
CStdString cmd;
|
|
cmd = getenv("XBMC_BIN_HOME");
|
|
cmd += "/xbmc-xrandr";
|
|
+ cmd.append("-q --screen %d", screennum);
|
|
|
|
FILE* file = popen(cmd.c_str(),"r");
|
|
if (!file)
|
|
@@ -79,7 +90,7 @@ bool CXRandR::Query(bool force)
|
|
pclose(file);
|
|
|
|
TiXmlElement *pRootElement = xmlDoc.RootElement();
|
|
- if (strcasecmp(pRootElement->Value(), "screen") != 0)
|
|
+ if (strcasecmp(pRootElement->Value(), "screen") != screennum)
|
|
{
|
|
// TODO ERROR
|
|
return false;
|
|
@@ -92,6 +103,7 @@ bool CXRandR::Query(bool force)
|
|
xoutput.name.TrimLeft(" \n\r\t");
|
|
xoutput.name.TrimRight(" \n\r\t");
|
|
xoutput.isConnected = (strcasecmp(output->Attribute("connected"), "true") == 0);
|
|
+ xoutput.screen = screennum;
|
|
xoutput.w = (output->Attribute("w") != NULL ? atoi(output->Attribute("w")) : 0);
|
|
xoutput.h = (output->Attribute("h") != NULL ? atoi(output->Attribute("h")) : 0);
|
|
xoutput.x = (output->Attribute("x") != NULL ? atoi(output->Attribute("x")) : 0);
|
|
@@ -123,7 +135,6 @@ bool CXRandR::Query(bool force)
|
|
xoutput.modes.push_back(xmode);
|
|
if (xmode.isCurrent)
|
|
{
|
|
- m_current.push_back(xoutput);
|
|
hascurrent = true;
|
|
}
|
|
}
|
|
@@ -247,17 +258,6 @@ bool CXRandR::SetMode(XOutput output, XMode mode)
|
|
return true;
|
|
}
|
|
|
|
-XOutput CXRandR::GetCurrentOutput()
|
|
-{
|
|
- Query();
|
|
- for (unsigned int j = 0; j < m_outputs.size(); j++)
|
|
- {
|
|
- if(m_outputs[j].isConnected)
|
|
- return m_outputs[j];
|
|
- }
|
|
- XOutput empty;
|
|
- return empty;
|
|
-}
|
|
XMode CXRandR::GetCurrentMode(CStdString outputName)
|
|
{
|
|
Query();
|
|
@@ -331,6 +331,43 @@ void CXRandR::LoadCustomModeLinesToAllOutputs(void)
|
|
}
|
|
}
|
|
|
|
+void CXRandR::SetNumScreens(unsigned int num)
|
|
+{
|
|
+ m_numScreens = num;
|
|
+ m_bInit = false;
|
|
+}
|
|
+
|
|
+bool CXRandR::IsOutputConnected(CStdString name)
|
|
+{
|
|
+ bool result = false;
|
|
+ Query();
|
|
+
|
|
+ for (unsigned int i = 0; i < m_outputs.size(); ++i)
|
|
+ {
|
|
+ if (m_outputs[i].name == name)
|
|
+ {
|
|
+ result = true;
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ return result;
|
|
+}
|
|
+
|
|
+XOutput* CXRandR::GetOutput(CStdString outputName)
|
|
+{
|
|
+ XOutput *result = 0;
|
|
+ Query();
|
|
+ for (unsigned int i = 0; i < m_outputs.size(); ++i)
|
|
+ {
|
|
+ if (m_outputs[i].name == outputName)
|
|
+ {
|
|
+ result = &m_outputs[i];
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ return result;
|
|
+}
|
|
+
|
|
CXRandR g_xrandr;
|
|
|
|
#endif // HAS_XRANDR
|
|
diff --git a/xbmc/windowing/X11/XRandR.h b/xbmc/windowing/X11/XRandR.h
|
|
index 618bd68..0824af5 100644
|
|
--- a/xbmc/windowing/X11/XRandR.h
|
|
+++ b/xbmc/windowing/X11/XRandR.h
|
|
@@ -79,6 +79,7 @@ class XOutput
|
|
}
|
|
CStdString name;
|
|
bool isConnected;
|
|
+ int screen;
|
|
int w;
|
|
int h;
|
|
int x;
|
|
@@ -94,12 +95,15 @@ class CXRandR
|
|
public:
|
|
CXRandR(bool query=false);
|
|
bool Query(bool force=false);
|
|
+ bool Query(bool force, int screennum);
|
|
std::vector<XOutput> GetModes(void);
|
|
- XOutput GetCurrentOutput();
|
|
XMode GetCurrentMode(CStdString outputName);
|
|
+ XOutput *GetOutput(CStdString outputName);
|
|
bool SetMode(XOutput output, XMode mode);
|
|
void LoadCustomModeLinesToAllOutputs(void);
|
|
void SaveState();
|
|
+ void SetNumScreens(unsigned int num);
|
|
+ bool IsOutputConnected(CStdString name);
|
|
//bool Has1080i();
|
|
//bool Has1080p();
|
|
//bool Has720p();
|
|
@@ -107,10 +111,10 @@ class CXRandR
|
|
|
|
private:
|
|
bool m_bInit;
|
|
- std::vector<XOutput> m_current;
|
|
std::vector<XOutput> m_outputs;
|
|
CStdString m_currentOutput;
|
|
CStdString m_currentMode;
|
|
+ unsigned int m_numScreens;
|
|
};
|
|
|
|
extern CXRandR g_xrandr;
|
|
--
|
|
1.7.10
|
|
|
|
|
|
From 2b379b9ce21b6d61b44b647b79ef3587dbbcf0ec Mon Sep 17 00:00:00 2001
|
|
From: FernetMenta <fernetmenta@online.de>
|
|
Date: Thu, 5 Jul 2012 11:44:00 +0200
|
|
Subject: [PATCH 22/72] X11: fix multi-head setups
|
|
|
|
---
|
|
language/English/strings.po | 4 +-
|
|
xbmc/rendering/gl/RenderSystemGL.h | 1 +
|
|
xbmc/settings/GUISettings.cpp | 5 +
|
|
xbmc/settings/GUIWindowSettingsCategory.cpp | 60 +++++-
|
|
xbmc/settings/GUIWindowSettingsCategory.h | 1 +
|
|
xbmc/windowing/WinEventsX11.cpp | 7 +
|
|
xbmc/windowing/X11/WinSystemX11.cpp | 262 ++++++++++++++++-----------
|
|
xbmc/windowing/X11/WinSystemX11.h | 10 +-
|
|
8 files changed, 235 insertions(+), 115 deletions(-)
|
|
|
|
diff --git a/language/English/strings.po b/language/English/strings.po
|
|
index 88292d3..bba7284 100644
|
|
--- a/language/English/strings.po
|
|
+++ b/language/English/strings.po
|
|
@@ -895,7 +895,9 @@ msgctxt "#245"
|
|
msgid "Sizing: (%i,%i)->(%i,%i) (Zoom x%2.2f) AR:%2.2f:1 (Pixels: %2.2f:1) (VShift: %2.2f)"
|
|
msgstr ""
|
|
|
|
-#empty string with id 246
|
|
+msgctxt "#246"
|
|
+msgid "Monitor"
|
|
+msgstr ""
|
|
|
|
msgctxt "#247"
|
|
msgid "Scripts"
|
|
diff --git a/xbmc/rendering/gl/RenderSystemGL.h b/xbmc/rendering/gl/RenderSystemGL.h
|
|
index efe5493..85d780d 100644
|
|
--- a/xbmc/rendering/gl/RenderSystemGL.h
|
|
+++ b/xbmc/rendering/gl/RenderSystemGL.h
|
|
@@ -44,6 +44,7 @@ class CRenderSystemGL : public CRenderSystemBase
|
|
virtual bool IsExtSupported(const char* extension);
|
|
|
|
virtual void SetVSync(bool vsync);
|
|
+ virtual void ResetVSync() { m_bVsyncInit = false; }
|
|
|
|
virtual void SetViewPort(CRect& viewPort);
|
|
virtual void GetViewPort(CRect& viewPort);
|
|
diff --git a/xbmc/settings/GUISettings.cpp b/xbmc/settings/GUISettings.cpp
|
|
index 4cdb093..0e320e1 100644
|
|
--- a/xbmc/settings/GUISettings.cpp
|
|
+++ b/xbmc/settings/GUISettings.cpp
|
|
@@ -392,11 +392,16 @@ void CGUISettings::Initialize()
|
|
AddGroup(SETTINGS_SYSTEM, 13000);
|
|
CSettingsCategory* vs = AddCategory(SETTINGS_SYSTEM, "videoscreen", 21373);
|
|
|
|
+#if defined(HAS_GLX)
|
|
+ AddString(vs, "videoscreen.monitor", 246, "", SPIN_CONTROL_TEXT);
|
|
+#endif
|
|
+
|
|
// this setting would ideally not be saved, as its value is systematically derived from videoscreen.screenmode.
|
|
// contains a DISPLAYMODE
|
|
#if !defined(TARGET_DARWIN_IOS_ATV2) && !defined(TARGET_RASPBERRY_PI)
|
|
AddInt(vs, "videoscreen.screen", 240, 0, -1, 1, 32, SPIN_CONTROL_TEXT);
|
|
#endif
|
|
+
|
|
// this setting would ideally not be saved, as its value is systematically derived from videoscreen.screenmode.
|
|
// contains an index to the g_settings.m_ResInfo array. the only meaningful fields are iScreen, iWidth, iHeight.
|
|
#if defined(TARGET_DARWIN)
|
|
diff --git a/xbmc/settings/GUIWindowSettingsCategory.cpp b/xbmc/settings/GUIWindowSettingsCategory.cpp
|
|
index d988598..3c19a06 100644
|
|
--- a/xbmc/settings/GUIWindowSettingsCategory.cpp
|
|
+++ b/xbmc/settings/GUIWindowSettingsCategory.cpp
|
|
@@ -528,6 +528,12 @@ void CGUIWindowSettingsCategory::CreateSettings()
|
|
FillInRefreshRates(strSetting, g_guiSettings.GetResolution(), false);
|
|
continue;
|
|
}
|
|
+ else if (strSetting.Equals("videoscreen.monitor"))
|
|
+ {
|
|
+ AddSetting(pSetting, group->GetWidth(), iControlID);
|
|
+ FillInMonitors(strSetting);
|
|
+ continue;
|
|
+ }
|
|
else if (strSetting.Equals("lookandfeel.skintheme"))
|
|
{
|
|
AddSetting(pSetting, group->GetWidth(), iControlID);
|
|
@@ -1494,6 +1500,20 @@ void CGUIWindowSettingsCategory::OnSettingChanged(BaseSettingControlPtr pSetting
|
|
// Cascade
|
|
FillInResolutions("videoscreen.resolution", mode, RES_DESKTOP, true);
|
|
}
|
|
+ else if (strSetting.Equals("videoscreen.monitor"))
|
|
+ {
|
|
+ CSettingString *pSettingString = (CSettingString *)pSettingControl->GetSetting();
|
|
+ CGUISpinControlEx *pControl = (CGUISpinControlEx *)GetControl(pSettingControl->GetID());
|
|
+ CStdString currentMonitor = pControl->GetCurrentLabel();
|
|
+ if (!g_Windowing.IsCurrentOutput(currentMonitor))
|
|
+ {
|
|
+ g_guiSettings.SetString("videoscreen.monitor", currentMonitor);
|
|
+ g_Windowing.UpdateResolutions();
|
|
+ DisplayMode mode = g_guiSettings.GetInt("videoscreen.screen");
|
|
+ // Cascade
|
|
+ FillInResolutions("videoscreen.resolution", mode, RES_DESKTOP, true);
|
|
+ }
|
|
+ }
|
|
else if (strSetting.Equals("videoscreen.resolution"))
|
|
{
|
|
RESOLUTION nextRes = (RESOLUTION) g_guiSettings.GetInt("videoscreen.resolution");
|
|
@@ -2430,11 +2450,15 @@ DisplayMode CGUIWindowSettingsCategory::FillInScreens(CStdString strSetting, RES
|
|
if (g_advancedSettings.m_canWindowed)
|
|
pControl->AddLabel(g_localizeStrings.Get(242), -1);
|
|
|
|
+#if !defined(HAS_GLX)
|
|
for (int idx = 0; idx < g_Windowing.GetNumScreens(); idx++)
|
|
{
|
|
strScreen.Format(g_localizeStrings.Get(241), g_settings.m_ResInfo[RES_DESKTOP + idx].iScreen + 1);
|
|
pControl->AddLabel(strScreen, g_settings.m_ResInfo[RES_DESKTOP + idx].iScreen);
|
|
}
|
|
+#else
|
|
+ pControl->AddLabel(g_localizeStrings.Get(244), 0);
|
|
+#endif
|
|
pControl->SetValue(mode);
|
|
g_guiSettings.SetInt("videoscreen.screen", mode);
|
|
}
|
|
@@ -2442,6 +2466,36 @@ DisplayMode CGUIWindowSettingsCategory::FillInScreens(CStdString strSetting, RES
|
|
return mode;
|
|
}
|
|
|
|
+void CGUIWindowSettingsCategory::FillInMonitors(CStdString strSetting)
|
|
+{
|
|
+ // we expect "videoscreen.monitor" but it might be hidden on some platforms,
|
|
+ // so check that we actually have a visable control.
|
|
+ CBaseSettingControl *control = GetSetting(strSetting);
|
|
+ if (control)
|
|
+ {
|
|
+ control->SetDelayed();
|
|
+ CGUISpinControlEx *pControl = (CGUISpinControlEx *)GetControl(control->GetID());
|
|
+ pControl->Clear();
|
|
+
|
|
+ std::vector<CStdString> monitors;
|
|
+ g_Windowing.GetConnectedOutputs(&monitors);
|
|
+
|
|
+ int currentMonitor = 0;
|
|
+ for (unsigned int i=0; i<monitors.size(); ++i)
|
|
+ {
|
|
+ if(g_settings.m_ResInfo[RES_DESKTOP].strOutput.Equals(monitors[i]))
|
|
+ {
|
|
+ currentMonitor = i;
|
|
+ }
|
|
+ pControl->AddLabel(monitors[i], i);
|
|
+ }
|
|
+
|
|
+ pControl->SetValue(currentMonitor);
|
|
+ g_guiSettings.SetString("videoscreen.monitor", g_settings.m_ResInfo[RES_DESKTOP].strOutput);
|
|
+ }
|
|
+}
|
|
+
|
|
+
|
|
void CGUIWindowSettingsCategory::FillInResolutions(CStdString strSetting, DisplayMode mode, RESOLUTION res, bool UserChange)
|
|
{
|
|
BaseSettingControlPtr control = GetSetting(strSetting);
|
|
@@ -2570,13 +2624,15 @@ void CGUIWindowSettingsCategory::OnRefreshRateChanged(RESOLUTION nextRes)
|
|
RESOLUTION lastRes = g_graphicsContext.GetVideoResolution();
|
|
bool cancelled = false;
|
|
|
|
+ bool outputChanged = !g_Windowing.IsCurrentOutput(g_guiSettings.GetString("videoscreen.monitor"));
|
|
+
|
|
g_guiSettings.SetResolution(nextRes);
|
|
- g_graphicsContext.SetVideoResolution(nextRes);
|
|
+ g_graphicsContext.SetVideoResolution(nextRes, outputChanged);
|
|
|
|
if (!CGUIDialogYesNo::ShowAndGetInput(13110, 13111, 20022, 20022, -1, -1, cancelled, 10000))
|
|
{
|
|
g_guiSettings.SetResolution(lastRes);
|
|
- g_graphicsContext.SetVideoResolution(lastRes);
|
|
+ g_graphicsContext.SetVideoResolution(lastRes, outputChanged);
|
|
|
|
DisplayMode mode = FillInScreens("videoscreen.screen", lastRes);
|
|
FillInResolutions("videoscreen.resolution", mode, lastRes, false);
|
|
diff --git a/xbmc/settings/GUIWindowSettingsCategory.h b/xbmc/settings/GUIWindowSettingsCategory.h
|
|
index 5142c6e..0d4649d 100644
|
|
--- a/xbmc/settings/GUIWindowSettingsCategory.h
|
|
+++ b/xbmc/settings/GUIWindowSettingsCategory.h
|
|
@@ -51,6 +51,7 @@ class CGUIWindowSettingsCategory :
|
|
void FillInSoundSkins(CSetting *pSetting);
|
|
void FillInLanguages(CSetting *pSetting, const std::vector<CStdString> &languages = std::vector<CStdString>(), const std::vector<CStdString> &languageKeys = std::vector<CStdString>());
|
|
DisplayMode FillInScreens(CStdString strSetting, RESOLUTION res);
|
|
+ void FillInMonitors(CStdString strSetting);
|
|
void FillInResolutions(CStdString strSetting, DisplayMode mode, RESOLUTION res, bool UserChange);
|
|
void FillInRefreshRates(CStdString strSetting, RESOLUTION res, bool UserChange);
|
|
void OnRefreshRateChanged(RESOLUTION resolution);
|
|
diff --git a/xbmc/windowing/WinEventsX11.cpp b/xbmc/windowing/WinEventsX11.cpp
|
|
index 5946a33..6c22358 100644
|
|
--- a/xbmc/windowing/WinEventsX11.cpp
|
|
+++ b/xbmc/windowing/WinEventsX11.cpp
|
|
@@ -517,9 +517,16 @@ bool CWinEventsX11::MessagePump()
|
|
break;
|
|
}
|
|
|
|
+ case EnterNotify:
|
|
+ {
|
|
+ g_Windowing.NotifyMouseCoverage(true);
|
|
+ break;
|
|
+ }
|
|
+
|
|
// lose mouse coverage
|
|
case LeaveNotify:
|
|
{
|
|
+ g_Windowing.NotifyMouseCoverage(false);
|
|
g_Mouse.SetActive(false);
|
|
break;
|
|
}
|
|
diff --git a/xbmc/windowing/X11/WinSystemX11.cpp b/xbmc/windowing/X11/WinSystemX11.cpp
|
|
index 6b0aa92..5f913f1 100644
|
|
--- a/xbmc/windowing/X11/WinSystemX11.cpp
|
|
+++ b/xbmc/windowing/X11/WinSystemX11.cpp
|
|
@@ -33,6 +33,7 @@
|
|
#include "cores/VideoRenderers/RenderManager.h"
|
|
#include "utils/TimeUtils.h"
|
|
#include "settings/GUISettings.h"
|
|
+#include "windowing/WindowingFactory.h"
|
|
|
|
#if defined(HAS_XRANDR)
|
|
#include <X11/extensions/Xrandr.h>
|
|
@@ -54,6 +55,7 @@
|
|
m_bIgnoreNextFocusMessage = false;
|
|
m_dpyLostTime = 0;
|
|
m_invisibleCursor = 0;
|
|
+ m_bIsInternalXrr = false;
|
|
|
|
XSetErrorHandler(XErrorHandler);
|
|
}
|
|
@@ -66,7 +68,8 @@ bool CWinSystemX11::InitWindowSystem()
|
|
{
|
|
if ((m_dpy = XOpenDisplay(NULL)))
|
|
{
|
|
- return CWinSystemBase::InitWindowSystem();
|
|
+ bool ret = CWinSystemBase::InitWindowSystem();
|
|
+ return ret;
|
|
}
|
|
else
|
|
CLog::Log(LOGERROR, "GLX Error: No Display found");
|
|
@@ -103,6 +106,8 @@ bool CWinSystemX11::DestroyWindowSystem()
|
|
|
|
//we don't call XCloseDisplay() here, since ati keeps a pointer to our m_dpy
|
|
//so instead we just let m_dpy die on exit
|
|
+ // i have seen core dumps on ATI if the display is not closed here
|
|
+ XCloseDisplay(m_dpy);
|
|
}
|
|
|
|
// m_SDLSurface is free()'d by SDL_Quit().
|
|
@@ -125,7 +130,10 @@ bool CWinSystemX11::DestroyWindow()
|
|
return true;
|
|
|
|
if (m_glContext)
|
|
+ {
|
|
+ glFinish();
|
|
glXMakeCurrent(m_dpy, None, NULL);
|
|
+ }
|
|
|
|
if (m_invisibleCursor)
|
|
{
|
|
@@ -155,7 +163,7 @@ bool CWinSystemX11::ResizeWindow(int newWidth, int newHeight, int newLeft, int n
|
|
&& m_nHeight == newHeight)
|
|
return true;
|
|
|
|
- if (!SetWindow(newWidth, newHeight, false))
|
|
+ if (!SetWindow(newWidth, newHeight, false, g_guiSettings.GetString("videoscreen.monitor")))
|
|
{
|
|
return false;
|
|
}
|
|
@@ -164,58 +172,11 @@ bool CWinSystemX11::ResizeWindow(int newWidth, int newHeight, int newLeft, int n
|
|
m_nWidth = newWidth;
|
|
m_nHeight = newHeight;
|
|
m_bFullScreen = false;
|
|
+ m_currentOutput = g_guiSettings.GetString("videoscreen.monitor");
|
|
|
|
return false;
|
|
}
|
|
|
|
-void CWinSystemX11::RefreshWindow()
|
|
-{
|
|
- if (!g_xrandr.Query(true))
|
|
- {
|
|
- CLog::Log(LOGERROR, "WinSystemX11::RefreshWindow - failed to query xrandr");
|
|
- return;
|
|
- }
|
|
- XOutput out = g_xrandr.GetCurrentOutput();
|
|
- XMode mode = g_xrandr.GetCurrentMode(out.name);
|
|
-
|
|
- RotateResolutions();
|
|
-
|
|
- // only overwrite desktop resolution, if we are not in fullscreen mode
|
|
- if (!g_graphicsContext.IsFullScreenVideo())
|
|
- {
|
|
- CLog::Log(LOGDEBUG, "CWinSystemX11::RefreshWindow - store desktop resolution, width: %d, height: %d, hz: %2.2f", mode.w, mode.h, mode.hz);
|
|
- if (!out.isRotated)
|
|
- UpdateDesktopResolution(g_settings.m_ResInfo[RES_DESKTOP], 0, mode.w, mode.h, mode.hz);
|
|
- else
|
|
- UpdateDesktopResolution(g_settings.m_ResInfo[RES_DESKTOP], 0, mode.h, mode.w, mode.hz);
|
|
- g_settings.m_ResInfo[RES_DESKTOP].strId = mode.id;
|
|
- g_settings.m_ResInfo[RES_DESKTOP].strOutput = out.name;
|
|
- }
|
|
-
|
|
- RESOLUTION_INFO res;
|
|
- unsigned int i;
|
|
- bool found(false);
|
|
- for (i = RES_DESKTOP; i < g_settings.m_ResInfo.size(); ++i)
|
|
- {
|
|
- if (g_settings.m_ResInfo[i].strId == mode.id)
|
|
- {
|
|
- found = true;
|
|
- break;
|
|
- }
|
|
- }
|
|
-
|
|
- if (!found)
|
|
- {
|
|
- CLog::Log(LOGERROR, "CWinSystemX11::RefreshWindow - could not find resolution");
|
|
- return;
|
|
- }
|
|
-
|
|
- if (g_graphicsContext.IsFullScreenRoot())
|
|
- g_graphicsContext.SetVideoResolution((RESOLUTION)i, true);
|
|
- else
|
|
- g_graphicsContext.SetVideoResolution(RES_WINDOW, true);
|
|
-}
|
|
-
|
|
bool CWinSystemX11::SetFullScreen(bool fullScreen, RESOLUTION_INFO& res, bool blankOtherDisplays)
|
|
{
|
|
|
|
@@ -240,8 +201,7 @@ bool CWinSystemX11::SetFullScreen(bool fullScreen, RESOLUTION_INFO& res, bool bl
|
|
mode.id = g_settings.m_ResInfo[RES_DESKTOP].strId;
|
|
}
|
|
|
|
- XOutput currout = g_xrandr.GetCurrentOutput();
|
|
- XMode currmode = g_xrandr.GetCurrentMode(currout.name);
|
|
+ XMode currmode = g_xrandr.GetCurrentMode(out.name);
|
|
|
|
// flip h/w when rotated
|
|
if (m_bIsRotated)
|
|
@@ -252,16 +212,17 @@ bool CWinSystemX11::SetFullScreen(bool fullScreen, RESOLUTION_INFO& res, bool bl
|
|
}
|
|
|
|
// only call xrandr if mode changes
|
|
- if (currout.name != out.name || currmode.w != mode.w || currmode.h != mode.h ||
|
|
+ if (currmode.w != mode.w || currmode.h != mode.h ||
|
|
currmode.hz != mode.hz || currmode.id != mode.id)
|
|
{
|
|
CLog::Log(LOGNOTICE, "CWinSystemX11::SetFullScreen - calling xrandr");
|
|
OnLostDevice();
|
|
+ m_bIsInternalXrr = true;
|
|
g_xrandr.SetMode(out, mode);
|
|
}
|
|
#endif
|
|
|
|
- if (!SetWindow(res.iWidth, res.iHeight, fullScreen))
|
|
+ if (!SetWindow(res.iWidth, res.iHeight, fullScreen, g_guiSettings.GetString("videoscreen.monitor")))
|
|
return false;
|
|
|
|
RefreshGlxContext();
|
|
@@ -269,6 +230,7 @@ bool CWinSystemX11::SetFullScreen(bool fullScreen, RESOLUTION_INFO& res, bool bl
|
|
m_nWidth = res.iWidth;
|
|
m_nHeight = res.iHeight;
|
|
m_bFullScreen = fullScreen;
|
|
+ m_currentOutput = g_guiSettings.GetString("videoscreen.monitor");
|
|
|
|
return true;
|
|
}
|
|
@@ -277,19 +239,30 @@ void CWinSystemX11::UpdateResolutions()
|
|
{
|
|
CWinSystemBase::UpdateResolutions();
|
|
|
|
-
|
|
#if defined(HAS_XRANDR)
|
|
- if(g_xrandr.Query())
|
|
- {
|
|
- XOutput out = g_xrandr.GetCurrentOutput();
|
|
- XMode mode = g_xrandr.GetCurrentMode(out.name);
|
|
- m_bIsRotated = out.isRotated;
|
|
+ CStdString currentMonitor;
|
|
+ int numScreens = XScreenCount(m_dpy);
|
|
+ g_xrandr.SetNumScreens(numScreens);
|
|
+ if(g_xrandr.Query(true))
|
|
+ {
|
|
+ currentMonitor = g_guiSettings.GetString("videoscreen.monitor");
|
|
+ // check if the monitor is connected
|
|
+ XOutput *out = g_xrandr.GetOutput(currentMonitor);
|
|
+ if (!out)
|
|
+ {
|
|
+ // choose first output
|
|
+ currentMonitor = g_xrandr.GetModes()[0].name;
|
|
+ out = g_xrandr.GetOutput(currentMonitor);
|
|
+ g_guiSettings.SetString("videoscreen.monitor", currentMonitor);
|
|
+ }
|
|
+ XMode mode = g_xrandr.GetCurrentMode(currentMonitor);
|
|
+ m_bIsRotated = out->isRotated;
|
|
if (!m_bIsRotated)
|
|
- UpdateDesktopResolution(g_settings.m_ResInfo[RES_DESKTOP], 0, mode.w, mode.h, mode.hz);
|
|
+ UpdateDesktopResolution(g_settings.m_ResInfo[RES_DESKTOP], out->screen, mode.w, mode.h, mode.hz);
|
|
else
|
|
- UpdateDesktopResolution(g_settings.m_ResInfo[RES_DESKTOP], 0, mode.h, mode.w, mode.hz);
|
|
+ UpdateDesktopResolution(g_settings.m_ResInfo[RES_DESKTOP], out->screen, mode.h, mode.w, mode.hz);
|
|
g_settings.m_ResInfo[RES_DESKTOP].strId = mode.id;
|
|
- g_settings.m_ResInfo[RES_DESKTOP].strOutput = out.name;
|
|
+ g_settings.m_ResInfo[RES_DESKTOP].strOutput = currentMonitor;
|
|
}
|
|
else
|
|
#endif
|
|
@@ -300,23 +273,26 @@ void CWinSystemX11::UpdateResolutions()
|
|
UpdateDesktopResolution(g_settings.m_ResInfo[RES_DESKTOP], 0, w, h, 0.0);
|
|
}
|
|
|
|
-
|
|
#if defined(HAS_XRANDR)
|
|
|
|
+ // erase previous stored modes
|
|
+ if (g_settings.m_ResInfo.size() > RES_CUSTOM)
|
|
+ {
|
|
+ std::vector<RESOLUTION_INFO>::iterator firstCustom = g_settings.m_ResInfo.begin()+RES_CUSTOM;
|
|
+ g_settings.m_ResInfo.erase(firstCustom, g_settings.m_ResInfo.end());
|
|
+ }
|
|
+
|
|
CLog::Log(LOGINFO, "Available videomodes (xrandr):");
|
|
- vector<XOutput>::iterator outiter;
|
|
- vector<XOutput> outs;
|
|
- outs = g_xrandr.GetModes();
|
|
- CLog::Log(LOGINFO, "Number of connected outputs: %"PRIdS"", outs.size());
|
|
+
|
|
+ XOutput *out = g_xrandr.GetOutput(currentMonitor);
|
|
string modename = "";
|
|
|
|
- for (outiter = outs.begin() ; outiter != outs.end() ; outiter++)
|
|
+ if (out != NULL)
|
|
{
|
|
- XOutput out = *outiter;
|
|
vector<XMode>::iterator modeiter;
|
|
- CLog::Log(LOGINFO, "Output '%s' has %"PRIdS" modes", out.name.c_str(), out.modes.size());
|
|
+ CLog::Log(LOGINFO, "Output '%s' has %"PRIdS" modes", out->name.c_str(), out->modes.size());
|
|
|
|
- for (modeiter = out.modes.begin() ; modeiter!=out.modes.end() ; modeiter++)
|
|
+ for (modeiter = out->modes.begin() ; modeiter!=out->modes.end() ; modeiter++)
|
|
{
|
|
XMode mode = *modeiter;
|
|
CLog::Log(LOGINFO, "ID:%s Name:%s Refresh:%f Width:%d Height:%d",
|
|
@@ -336,15 +312,15 @@ void CWinSystemX11::UpdateResolutions()
|
|
res.iWidth = mode.h;
|
|
res.iHeight = mode.w;
|
|
}
|
|
- if (mode.h>0 && mode.w>0 && out.hmm>0 && out.wmm>0)
|
|
- res.fPixelRatio = ((float)out.wmm/(float)mode.w) / (((float)out.hmm/(float)mode.h));
|
|
+ if (mode.h>0 && mode.w>0 && out->hmm>0 && out->wmm>0)
|
|
+ res.fPixelRatio = ((float)out->wmm/(float)mode.w) / (((float)out->hmm/(float)mode.h));
|
|
else
|
|
res.fPixelRatio = 1.0f;
|
|
|
|
CLog::Log(LOGINFO, "Pixel Ratio: %f", res.fPixelRatio);
|
|
|
|
- res.strMode.Format("%s: %s @ %.2fHz", out.name.c_str(), mode.name.c_str(), mode.hz);
|
|
- res.strOutput = out.name;
|
|
+ res.strMode.Format("%s: %s @ %.2fHz", out->name.c_str(), mode.name.c_str(), mode.hz);
|
|
+ res.strOutput = out->name;
|
|
res.strId = mode.id;
|
|
res.iSubtitles = (int)(0.95*mode.h);
|
|
res.fRefreshRate = mode.hz;
|
|
@@ -363,28 +339,19 @@ void CWinSystemX11::UpdateResolutions()
|
|
|
|
}
|
|
|
|
-void CWinSystemX11::RotateResolutions()
|
|
+void CWinSystemX11::GetConnectedOutputs(std::vector<CStdString> *outputs)
|
|
{
|
|
-#if defined(HAS_XRANDR)
|
|
- XOutput out = g_xrandr.GetCurrentOutput();
|
|
- if (out.isRotated == m_bIsRotated)
|
|
- return;
|
|
-
|
|
- for (unsigned int i = 0; i < g_settings.m_ResInfo.size(); ++i)
|
|
+ vector<XOutput> outs;
|
|
+ outs = g_xrandr.GetModes();
|
|
+ for(unsigned int i=0; i<outs.size(); ++i)
|
|
{
|
|
- int width = g_settings.m_ResInfo[i].iWidth;
|
|
- g_settings.m_ResInfo[i].iWidth = g_settings.m_ResInfo[i].iHeight;
|
|
- g_settings.m_ResInfo[i].iHeight = width;
|
|
+ outputs->push_back(outs[i].name);
|
|
}
|
|
- // update desktop resolution
|
|
-// int h = g_settings.m_ResInfo[RES_DESKTOP].iHeight;
|
|
-// int w = g_settings.m_ResInfo[RES_DESKTOP].iWidth;
|
|
-// float hz = g_settings.m_ResInfo[RES_DESKTOP].fRefreshRate;
|
|
-// UpdateDesktopResolution(g_settings.m_ResInfo[RES_DESKTOP], 0, w, h, hz);
|
|
-
|
|
- m_bIsRotated = out.isRotated;
|
|
+}
|
|
|
|
-#endif
|
|
+bool CWinSystemX11::IsCurrentOutput(CStdString output)
|
|
+{
|
|
+ return m_currentOutput.Equals(output);
|
|
}
|
|
|
|
bool CWinSystemX11::IsSuitableVisual(XVisualInfo *vInfo)
|
|
@@ -414,8 +381,11 @@ bool CWinSystemX11::RefreshGlxContext()
|
|
if (m_glContext)
|
|
{
|
|
CLog::Log(LOGDEBUG, "CWinSystemX11::RefreshGlxContext: refreshing context");
|
|
+ glFinish();
|
|
glXMakeCurrent(m_dpy, None, NULL);
|
|
glXMakeCurrent(m_dpy, m_glWindow, m_glContext);
|
|
+ XSync(m_dpy, FALSE);
|
|
+ g_Windowing.ResetVSync();
|
|
return true;
|
|
}
|
|
|
|
@@ -481,6 +451,8 @@ bool CWinSystemX11::RefreshGlxContext()
|
|
{
|
|
// make this context current
|
|
glXMakeCurrent(m_dpy, m_glWindow, m_glContext);
|
|
+ g_Windowing.ResetVSync();
|
|
+ XSync(m_dpy, False);
|
|
retVal = true;
|
|
}
|
|
else
|
|
@@ -522,24 +494,53 @@ void CWinSystemX11::ResetOSScreensaver()
|
|
|
|
void CWinSystemX11::NotifyAppActiveChange(bool bActivated)
|
|
{
|
|
- if (bActivated && m_bWasFullScreenBeforeMinimize && !g_graphicsContext.IsFullScreenRoot())
|
|
+ if (bActivated && m_bWasFullScreenBeforeMinimize && !m_bFullScreen)
|
|
+ {
|
|
g_graphicsContext.ToggleFullScreenRoot();
|
|
|
|
+ m_bWasFullScreenBeforeMinimize = false;
|
|
+ }
|
|
m_minimized = !bActivated;
|
|
}
|
|
|
|
void CWinSystemX11::NotifyAppFocusChange(bool bGaining)
|
|
{
|
|
if (bGaining && m_bWasFullScreenBeforeMinimize && !m_bIgnoreNextFocusMessage &&
|
|
- !g_graphicsContext.IsFullScreenRoot())
|
|
+ !m_bFullScreen)
|
|
+ {
|
|
+ m_bWasFullScreenBeforeMinimize = false;
|
|
g_graphicsContext.ToggleFullScreenRoot();
|
|
+ m_minimized = false;
|
|
+ }
|
|
if (!bGaining)
|
|
m_bIgnoreNextFocusMessage = false;
|
|
}
|
|
|
|
+void CWinSystemX11::NotifyMouseCoverage(bool covered)
|
|
+{
|
|
+ if (!m_bFullScreen)
|
|
+ return;
|
|
+
|
|
+ if (covered)
|
|
+ {
|
|
+ int result = -1;
|
|
+ while (result != GrabSuccess && result != AlreadyGrabbed)
|
|
+ {
|
|
+ result = XGrabPointer(m_dpy, m_glWindow, True, ButtonPressMask, GrabModeAsync, GrabModeAsync, None, None, CurrentTime);
|
|
+ XbmcThreads::ThreadSleep(100);
|
|
+ }
|
|
+ XGrabKeyboard(m_dpy, m_glWindow, True, GrabModeAsync, GrabModeAsync, CurrentTime);
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ XUngrabKeyboard(m_dpy, CurrentTime);
|
|
+ XUngrabPointer(m_dpy, CurrentTime);
|
|
+ }
|
|
+}
|
|
+
|
|
bool CWinSystemX11::Minimize()
|
|
{
|
|
- m_bWasFullScreenBeforeMinimize = g_graphicsContext.IsFullScreenRoot();
|
|
+ m_bWasFullScreenBeforeMinimize = m_bFullScreen;
|
|
if (m_bWasFullScreenBeforeMinimize)
|
|
{
|
|
m_bIgnoreNextFocusMessage = true;
|
|
@@ -605,13 +606,46 @@ void CWinSystemX11::CheckDisplayEvents()
|
|
void CWinSystemX11::NotifyXRREvent()
|
|
{
|
|
CLog::Log(LOGDEBUG, "%s - notify display reset event", __FUNCTION__);
|
|
- RefreshWindow();
|
|
+ m_windowDirty = true;
|
|
|
|
- CSingleLock lock(m_resourceSection);
|
|
+ // if external event update resolutions
|
|
+ if (!m_bIsInternalXrr)
|
|
+ {
|
|
+ UpdateResolutions();
|
|
+ }
|
|
+ else if (!g_xrandr.Query(true))
|
|
+ {
|
|
+ CLog::Log(LOGERROR, "WinSystemX11::RefreshWindow - failed to query xrandr");
|
|
+ return;
|
|
+ }
|
|
+ m_bIsInternalXrr = false;
|
|
|
|
- // tell any shared resources
|
|
- for (vector<IDispResource *>::iterator i = m_resources.begin(); i != m_resources.end(); i++)
|
|
- (*i)->OnResetDevice();
|
|
+ CStdString currentOutput = g_guiSettings.GetString("videoscreen.monitor");
|
|
+ XOutput *out = g_xrandr.GetOutput(currentOutput);
|
|
+ XMode mode = g_xrandr.GetCurrentMode(currentOutput);
|
|
+
|
|
+ RESOLUTION_INFO res;
|
|
+ unsigned int i;
|
|
+ bool found(false);
|
|
+ for (i = RES_DESKTOP; i < g_settings.m_ResInfo.size(); ++i)
|
|
+ {
|
|
+ if (g_settings.m_ResInfo[i].strId == mode.id)
|
|
+ {
|
|
+ found = true;
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (!found)
|
|
+ {
|
|
+ CLog::Log(LOGERROR, "CWinSystemX11::RefreshWindow - could not find resolution");
|
|
+ i = RES_DESKTOP;
|
|
+ }
|
|
+
|
|
+ if (g_graphicsContext.IsFullScreenRoot())
|
|
+ g_graphicsContext.SetVideoResolution((RESOLUTION)i, true);
|
|
+ else
|
|
+ g_graphicsContext.SetVideoResolution(RES_WINDOW, true);
|
|
|
|
}
|
|
|
|
@@ -664,14 +698,14 @@ bool CWinSystemX11::EnableFrameLimiter()
|
|
return m_minimized;
|
|
}
|
|
|
|
-bool CWinSystemX11::SetWindow(int width, int height, bool fullscreen)
|
|
+bool CWinSystemX11::SetWindow(int width, int height, bool fullscreen, const CStdString &output)
|
|
{
|
|
bool changeWindow = false;
|
|
bool changeSize = false;
|
|
bool mouseActive = false;
|
|
float mouseX, mouseY;
|
|
|
|
- if (m_glWindow && (m_bFullScreen != fullscreen))
|
|
+ if (m_glWindow && ((m_bFullScreen != fullscreen) || !m_currentOutput.Equals(output) || m_windowDirty))
|
|
{
|
|
mouseActive = g_Mouse.IsActive();
|
|
if (mouseActive)
|
|
@@ -693,6 +727,7 @@ bool CWinSystemX11::SetWindow(int width, int height, bool fullscreen)
|
|
else
|
|
mouseActive = false;
|
|
}
|
|
+ OnLostDevice();
|
|
DestroyWindow();
|
|
}
|
|
|
|
@@ -714,7 +749,11 @@ bool CWinSystemX11::SetWindow(int width, int height, bool fullscreen)
|
|
XSetWindowAttributes swa;
|
|
XVisualInfo *vi;
|
|
|
|
- vi = glXChooseVisual(m_dpy, DefaultScreen(m_dpy), att);
|
|
+ XOutput *out = g_xrandr.GetOutput(output);
|
|
+ if (!out)
|
|
+ out = g_xrandr.GetOutput(m_currentOutput);
|
|
+ m_nScreen = out->screen;
|
|
+ vi = glXChooseVisual(m_dpy, m_nScreen, att);
|
|
cmap = XCreateColormap(m_dpy, RootWindow(m_dpy, vi->screen), vi->visual, AllocNone);
|
|
|
|
int def_vis = (vi->visual == DefaultVisual(m_dpy, vi->screen));
|
|
@@ -730,7 +769,7 @@ bool CWinSystemX11::SetWindow(int width, int height, bool fullscreen)
|
|
unsigned long mask = CWBackPixel | CWBorderPixel | CWColormap | CWOverrideRedirect | CWEventMask;
|
|
|
|
m_glWindow = XCreateWindow(m_dpy, RootWindow(m_dpy, vi->screen),
|
|
- 0, 0, width, height, 0, vi->depth,
|
|
+ out->x, out->y, width, height, 0, vi->depth,
|
|
InputOutput, vi->visual,
|
|
mask, &swa);
|
|
|
|
@@ -801,14 +840,19 @@ bool CWinSystemX11::SetWindow(int width, int height, bool fullscreen)
|
|
if (fullscreen)
|
|
{
|
|
int result = -1;
|
|
- while (result != GrabSuccess)
|
|
+ while (result != GrabSuccess && result != AlreadyGrabbed)
|
|
{
|
|
- result = XGrabPointer(m_dpy, m_glWindow, True, ButtonPressMask, GrabModeAsync, GrabModeAsync, m_glWindow, None, CurrentTime);
|
|
+ result = XGrabPointer(m_dpy, m_glWindow, True, ButtonPressMask, GrabModeAsync, GrabModeAsync, None, None, CurrentTime);
|
|
XbmcThreads::ThreadSleep(100);
|
|
}
|
|
XGrabKeyboard(m_dpy, m_glWindow, True, GrabModeAsync, GrabModeAsync, CurrentTime);
|
|
-
|
|
}
|
|
+ CSingleLock lock(m_resourceSection);
|
|
+ // tell any shared resources
|
|
+ for (vector<IDispResource *>::iterator i = m_resources.begin(); i != m_resources.end(); i++)
|
|
+ (*i)->OnResetDevice();
|
|
+
|
|
+ m_windowDirty = false;
|
|
}
|
|
return true;
|
|
}
|
|
diff --git a/xbmc/windowing/X11/WinSystemX11.h b/xbmc/windowing/X11/WinSystemX11.h
|
|
index 93cf5db..71034fc 100644
|
|
--- a/xbmc/windowing/X11/WinSystemX11.h
|
|
+++ b/xbmc/windowing/X11/WinSystemX11.h
|
|
@@ -65,15 +65,16 @@ class CWinSystemX11 : public CWinSystemBase
|
|
Display* GetDisplay() { return m_dpy; }
|
|
GLXWindow GetWindow() { return m_glWindow; }
|
|
GLXContext GetGlxContext() { return m_glContext; }
|
|
- void RefreshWindow();
|
|
void NotifyXRREvent();
|
|
+ void GetConnectedOutputs(std::vector<CStdString> *outputs);
|
|
+ bool IsCurrentOutput(CStdString output);
|
|
+ void NotifyMouseCoverage(bool covered);
|
|
|
|
protected:
|
|
bool RefreshGlxContext();
|
|
void CheckDisplayEvents();
|
|
void OnLostDevice();
|
|
- bool SetWindow(int width, int height, bool fullscreen);
|
|
- void RotateResolutions();
|
|
+ bool SetWindow(int width, int height, bool fullscreen, const CStdString &output);
|
|
|
|
Window m_glWindow;
|
|
GLXContext m_glContext;
|
|
@@ -88,6 +89,9 @@ class CWinSystemX11 : public CWinSystemBase
|
|
CCriticalSection m_resourceSection;
|
|
std::vector<IDispResource*> m_resources;
|
|
uint64_t m_dpyLostTime;
|
|
+ CStdString m_currentOutput;
|
|
+ bool m_windowDirty;
|
|
+ bool m_bIsInternalXrr;
|
|
|
|
private:
|
|
bool IsSuitableVisual(XVisualInfo *vInfo);
|
|
--
|
|
1.7.10
|
|
|
|
|
|
From 2a747f13a0a50dea0883d0d3c701ef290235a99b Mon Sep 17 00:00:00 2001
|
|
From: FernetMenta <fernetmenta@online.de>
|
|
Date: Thu, 5 Jul 2012 11:36:32 +0200
|
|
Subject: [PATCH 23/72] X11: remove all DefaultScreen and RootWindow macros
|
|
|
|
---
|
|
xbmc/windowing/X11/WinSystemX11.cpp | 6 +++---
|
|
xbmc/windowing/X11/WinSystemX11.h | 1 +
|
|
xbmc/windowing/X11/WinSystemX11GL.cpp | 2 +-
|
|
3 files changed, 5 insertions(+), 4 deletions(-)
|
|
|
|
diff --git a/xbmc/windowing/X11/WinSystemX11.cpp b/xbmc/windowing/X11/WinSystemX11.cpp
|
|
index 5f913f1..af1307c 100644
|
|
--- a/xbmc/windowing/X11/WinSystemX11.cpp
|
|
+++ b/xbmc/windowing/X11/WinSystemX11.cpp
|
|
@@ -267,7 +267,7 @@ void CWinSystemX11::UpdateResolutions()
|
|
else
|
|
#endif
|
|
{
|
|
- int x11screen = DefaultScreen(m_dpy);
|
|
+ int x11screen = m_nScreen;
|
|
int w = DisplayWidth(m_dpy, x11screen);
|
|
int h = DisplayHeight(m_dpy, x11screen);
|
|
UpdateDesktopResolution(g_settings.m_ResInfo[RES_DESKTOP], 0, w, h, 0.0);
|
|
@@ -393,7 +393,7 @@ bool CWinSystemX11::RefreshGlxContext()
|
|
XVisualInfo *visuals;
|
|
XVisualInfo *vInfo = NULL;
|
|
int availableVisuals = 0;
|
|
- vMask.screen = DefaultScreen(m_dpy);
|
|
+ vMask.screen = m_nScreen;
|
|
XWindowAttributes winAttr;
|
|
|
|
/* Assume a depth of 24 in case the below calls to XGetWindowAttributes()
|
|
@@ -547,7 +547,7 @@ bool CWinSystemX11::Minimize()
|
|
g_graphicsContext.ToggleFullScreenRoot();
|
|
}
|
|
|
|
- XIconifyWindow(m_dpy, m_glWindow, DefaultScreen(m_dpy));
|
|
+ XIconifyWindow(m_dpy, m_glWindow, m_nScreen);
|
|
|
|
m_minimized = true;
|
|
return true;
|
|
diff --git a/xbmc/windowing/X11/WinSystemX11.h b/xbmc/windowing/X11/WinSystemX11.h
|
|
index 71034fc..3bb4b8e 100644
|
|
--- a/xbmc/windowing/X11/WinSystemX11.h
|
|
+++ b/xbmc/windowing/X11/WinSystemX11.h
|
|
@@ -47,6 +47,7 @@ class CWinSystemX11 : public CWinSystemBase
|
|
virtual bool SetFullScreen(bool fullScreen, RESOLUTION_INFO& res, bool blankOtherDisplays);
|
|
virtual void UpdateResolutions();
|
|
virtual int GetNumScreens() { return 1; }
|
|
+ virtual int GetCurrentScreen() { return m_nScreen; }
|
|
virtual void ShowOSMouse(bool show);
|
|
virtual void ResetOSScreensaver();
|
|
virtual bool EnableFrameLimiter();
|
|
diff --git a/xbmc/windowing/X11/WinSystemX11GL.cpp b/xbmc/windowing/X11/WinSystemX11GL.cpp
|
|
index f858f88..d192697 100644
|
|
--- a/xbmc/windowing/X11/WinSystemX11GL.cpp
|
|
+++ b/xbmc/windowing/X11/WinSystemX11GL.cpp
|
|
@@ -203,7 +203,7 @@ bool CWinSystemX11GL::CreateNewWindow(const CStdString& name, bool fullScreen, R
|
|
return false;
|
|
|
|
m_glxext = " ";
|
|
- m_glxext += (const char*)glXQueryExtensionsString(m_dpy, DefaultScreen(m_dpy));
|
|
+ m_glxext += (const char*)glXQueryExtensionsString(m_dpy, m_nScreen);
|
|
m_glxext += " ";
|
|
|
|
CLog::Log(LOGDEBUG, "GLX_EXTENSIONS:%s", m_glxext.c_str());
|
|
--
|
|
1.7.10
|
|
|
|
|
|
From cf018ebbf1eae8f5ae2914ef347aac5f963c0d71 Mon Sep 17 00:00:00 2001
|
|
From: FernetMenta <fernetmenta@online.de>
|
|
Date: Thu, 5 Jul 2012 11:45:22 +0200
|
|
Subject: [PATCH 24/72] X11: remove all DefaultScreen and RootWindow macros
|
|
(VideoRefClock)
|
|
|
|
Note this is on a separate display connection.
|
|
---
|
|
xbmc/video/VideoReferenceClock.cpp | 15 ++++++++-------
|
|
1 file changed, 8 insertions(+), 7 deletions(-)
|
|
|
|
diff --git a/xbmc/video/VideoReferenceClock.cpp b/xbmc/video/VideoReferenceClock.cpp
|
|
index 9785fe7..0004e07 100644
|
|
--- a/xbmc/video/VideoReferenceClock.cpp
|
|
+++ b/xbmc/video/VideoReferenceClock.cpp
|
|
@@ -270,7 +270,7 @@ bool CVideoReferenceClock::SetupGLX()
|
|
}
|
|
|
|
bool ExtensionFound = false;
|
|
- istringstream Extensions(glXQueryExtensionsString(m_Dpy, DefaultScreen(m_Dpy)));
|
|
+ istringstream Extensions(glXQueryExtensionsString(m_Dpy, g_Windowing.GetCurrentScreen()));
|
|
string ExtensionStr;
|
|
|
|
while (!ExtensionFound)
|
|
@@ -297,7 +297,7 @@ bool CVideoReferenceClock::SetupGLX()
|
|
m_bIsATI = true;
|
|
}
|
|
|
|
- m_vInfo = glXChooseVisual(m_Dpy, DefaultScreen(m_Dpy), singleBufferAttributes);
|
|
+ m_vInfo = glXChooseVisual(m_Dpy, g_Windowing.GetCurrentScreen(), singleBufferAttributes);
|
|
if (!m_vInfo)
|
|
{
|
|
CLog::Log(LOGDEBUG, "CVideoReferenceClock: glXChooseVisual returned NULL");
|
|
@@ -308,15 +308,16 @@ bool CVideoReferenceClock::SetupGLX()
|
|
{
|
|
Swa.border_pixel = 0;
|
|
Swa.event_mask = StructureNotifyMask;
|
|
- Swa.colormap = XCreateColormap(m_Dpy, RootWindow(m_Dpy, m_vInfo->screen), m_vInfo->visual, AllocNone );
|
|
+ Swa.colormap = XCreateColormap(m_Dpy, g_Windowing.GetWindow(), m_vInfo->visual, AllocNone );
|
|
SwaMask = CWBorderPixel | CWColormap | CWEventMask;
|
|
|
|
- m_Window = XCreateWindow(m_Dpy, RootWindow(m_Dpy, m_vInfo->screen), 0, 0, 256, 256, 0,
|
|
+ m_Window = XCreateWindow(m_Dpy, g_Windowing.GetWindow(), 0, 0, 256, 256, 0,
|
|
m_vInfo->depth, InputOutput, m_vInfo->visual, SwaMask, &Swa);
|
|
}
|
|
else
|
|
{
|
|
- m_pixmap = XCreatePixmap(m_Dpy, DefaultRootWindow(m_Dpy), 256, 256, m_vInfo->depth);
|
|
+ Window window = g_Windowing.GetWindow();
|
|
+ m_pixmap = XCreatePixmap(m_Dpy, window, 256, 256, m_vInfo->depth);
|
|
if (!m_pixmap)
|
|
{
|
|
CLog::Log(LOGDEBUG, "CVideoReferenceClock: unable to create pixmap");
|
|
@@ -383,7 +384,7 @@ bool CVideoReferenceClock::SetupGLX()
|
|
|
|
//set up receiving of RandR events, we'll get one when the refreshrate changes
|
|
XRRQueryExtension(m_Dpy, &m_RREventBase, &ReturnV);
|
|
- XRRSelectInput(m_Dpy, RootWindow(m_Dpy, m_vInfo->screen), RRScreenChangeNotifyMask);
|
|
+ XRRSelectInput(m_Dpy, g_Windowing.GetWindow(), RRScreenChangeNotifyMask);
|
|
|
|
UpdateRefreshrate(true); //forced refreshrate update
|
|
m_MissedVblanks = 0;
|
|
@@ -518,7 +519,7 @@ int CVideoReferenceClock::GetRandRRate()
|
|
int RefreshRate;
|
|
XRRScreenConfiguration *CurrInfo;
|
|
|
|
- CurrInfo = XRRGetScreenInfo(m_Dpy, RootWindow(m_Dpy, m_vInfo->screen));
|
|
+ CurrInfo = XRRGetScreenInfo(m_Dpy, g_Windowing.GetWindow());
|
|
RefreshRate = XRRConfigCurrentRate(CurrInfo);
|
|
XRRFreeScreenConfigInfo(CurrInfo);
|
|
|
|
--
|
|
1.7.10
|
|
|
|
|
|
From 5d8bfcd52e5a189515629c15c73434ef6c6bcc88 Mon Sep 17 00:00:00 2001
|
|
From: xbmc <fernetmenta@online.de>
|
|
Date: Wed, 20 Jun 2012 17:37:11 +0200
|
|
Subject: [PATCH 25/72] X11: recreate gl context after output has changed
|
|
|
|
---
|
|
xbmc/windowing/X11/WinSystemX11.cpp | 24 ++++++++++++++----------
|
|
xbmc/windowing/X11/WinSystemX11.h | 1 +
|
|
xbmc/windowing/X11/WinSystemX11GL.cpp | 9 +++++++++
|
|
3 files changed, 24 insertions(+), 10 deletions(-)
|
|
|
|
diff --git a/xbmc/windowing/X11/WinSystemX11.cpp b/xbmc/windowing/X11/WinSystemX11.cpp
|
|
index af1307c..d3d15e2 100644
|
|
--- a/xbmc/windowing/X11/WinSystemX11.cpp
|
|
+++ b/xbmc/windowing/X11/WinSystemX11.cpp
|
|
@@ -168,7 +168,6 @@ bool CWinSystemX11::ResizeWindow(int newWidth, int newHeight, int newLeft, int n
|
|
return false;
|
|
}
|
|
|
|
- RefreshGlxContext();
|
|
m_nWidth = newWidth;
|
|
m_nHeight = newHeight;
|
|
m_bFullScreen = false;
|
|
@@ -219,14 +218,13 @@ bool CWinSystemX11::SetFullScreen(bool fullScreen, RESOLUTION_INFO& res, bool bl
|
|
OnLostDevice();
|
|
m_bIsInternalXrr = true;
|
|
g_xrandr.SetMode(out, mode);
|
|
+ return true;
|
|
}
|
|
#endif
|
|
|
|
if (!SetWindow(res.iWidth, res.iHeight, fullScreen, g_guiSettings.GetString("videoscreen.monitor")))
|
|
return false;
|
|
|
|
- RefreshGlxContext();
|
|
-
|
|
m_nWidth = res.iWidth;
|
|
m_nHeight = res.iHeight;
|
|
m_bFullScreen = fullScreen;
|
|
@@ -381,11 +379,8 @@ bool CWinSystemX11::RefreshGlxContext()
|
|
if (m_glContext)
|
|
{
|
|
CLog::Log(LOGDEBUG, "CWinSystemX11::RefreshGlxContext: refreshing context");
|
|
- glFinish();
|
|
glXMakeCurrent(m_dpy, None, NULL);
|
|
glXMakeCurrent(m_dpy, m_glWindow, m_glContext);
|
|
- XSync(m_dpy, FALSE);
|
|
- g_Windowing.ResetVSync();
|
|
return true;
|
|
}
|
|
|
|
@@ -445,14 +440,14 @@ bool CWinSystemX11::RefreshGlxContext()
|
|
{
|
|
glXMakeCurrent(m_dpy, None, NULL);
|
|
glXDestroyContext(m_dpy, m_glContext);
|
|
+ XSync(m_dpy, FALSE);
|
|
+ m_newGlContext = true;
|
|
}
|
|
|
|
if ((m_glContext = glXCreateContext(m_dpy, vInfo, NULL, True)))
|
|
{
|
|
// make this context current
|
|
glXMakeCurrent(m_dpy, m_glWindow, m_glContext);
|
|
- g_Windowing.ResetVSync();
|
|
- XSync(m_dpy, False);
|
|
retVal = true;
|
|
}
|
|
else
|
|
@@ -729,6 +724,7 @@ bool CWinSystemX11::SetWindow(int width, int height, bool fullscreen, const CStd
|
|
}
|
|
OnLostDevice();
|
|
DestroyWindow();
|
|
+ m_windowDirty = true;
|
|
}
|
|
|
|
// create main window
|
|
@@ -847,13 +843,21 @@ bool CWinSystemX11::SetWindow(int width, int height, bool fullscreen, const CStd
|
|
}
|
|
XGrabKeyboard(m_dpy, m_glWindow, True, GrabModeAsync, GrabModeAsync, CurrentTime);
|
|
}
|
|
+
|
|
+ CDirtyRegionList dr;
|
|
+ RefreshGlxContext();
|
|
+ XSync(m_dpy, FALSE);
|
|
+ g_graphicsContext.Clear(0);
|
|
+ g_graphicsContext.Flip(dr);
|
|
+ g_Windowing.ResetVSync();
|
|
+ m_windowDirty = false;
|
|
+
|
|
CSingleLock lock(m_resourceSection);
|
|
// tell any shared resources
|
|
for (vector<IDispResource *>::iterator i = m_resources.begin(); i != m_resources.end(); i++)
|
|
(*i)->OnResetDevice();
|
|
-
|
|
- m_windowDirty = false;
|
|
}
|
|
+
|
|
return true;
|
|
}
|
|
|
|
diff --git a/xbmc/windowing/X11/WinSystemX11.h b/xbmc/windowing/X11/WinSystemX11.h
|
|
index 3bb4b8e..cc28f56 100644
|
|
--- a/xbmc/windowing/X11/WinSystemX11.h
|
|
+++ b/xbmc/windowing/X11/WinSystemX11.h
|
|
@@ -93,6 +93,7 @@ class CWinSystemX11 : public CWinSystemBase
|
|
CStdString m_currentOutput;
|
|
bool m_windowDirty;
|
|
bool m_bIsInternalXrr;
|
|
+ bool m_newGlContext;
|
|
|
|
private:
|
|
bool IsSuitableVisual(XVisualInfo *vInfo);
|
|
diff --git a/xbmc/windowing/X11/WinSystemX11GL.cpp b/xbmc/windowing/X11/WinSystemX11GL.cpp
|
|
index d192697..0f2d1d2 100644
|
|
--- a/xbmc/windowing/X11/WinSystemX11GL.cpp
|
|
+++ b/xbmc/windowing/X11/WinSystemX11GL.cpp
|
|
@@ -23,6 +23,7 @@
|
|
|
|
#include "WinSystemX11GL.h"
|
|
#include "utils/log.h"
|
|
+#include "Application.h"
|
|
|
|
CWinSystemX11GL::CWinSystemX11GL()
|
|
{
|
|
@@ -245,17 +246,25 @@ bool CWinSystemX11GL::CreateNewWindow(const CStdString& name, bool fullScreen, R
|
|
|
|
bool CWinSystemX11GL::ResizeWindow(int newWidth, int newHeight, int newLeft, int newTop)
|
|
{
|
|
+ m_newGlContext = false;
|
|
CWinSystemX11::ResizeWindow(newWidth, newHeight, newLeft, newTop);
|
|
CRenderSystemGL::ResetRenderSystem(newWidth, newHeight, false, 0);
|
|
|
|
+ if (m_newGlContext)
|
|
+ g_application.ReloadSkin();
|
|
+
|
|
return true;
|
|
}
|
|
|
|
bool CWinSystemX11GL::SetFullScreen(bool fullScreen, RESOLUTION_INFO& res, bool blankOtherDisplays)
|
|
{
|
|
+ m_newGlContext = false;
|
|
CWinSystemX11::SetFullScreen(fullScreen, res, blankOtherDisplays);
|
|
CRenderSystemGL::ResetRenderSystem(res.iWidth, res.iHeight, fullScreen, res.fRefreshRate);
|
|
|
|
+ if (m_newGlContext)
|
|
+ g_application.ReloadSkin();
|
|
+
|
|
return true;
|
|
}
|
|
|
|
--
|
|
1.7.10
|
|
|
|
|
|
From bd9a29b7661c75152174959f9f269f32c13a658b Mon Sep 17 00:00:00 2001
|
|
From: FernetMenta <fernetmenta@online.de>
|
|
Date: Thu, 5 Jul 2012 12:06:25 +0200
|
|
Subject: [PATCH 26/72] X11: hook video reference clock in windowing
|
|
|
|
---
|
|
xbmc/video/VideoReferenceClock.cpp | 71 ++++++++++++++++++++++++++----------
|
|
xbmc/video/VideoReferenceClock.h | 13 ++++++-
|
|
2 files changed, 63 insertions(+), 21 deletions(-)
|
|
|
|
diff --git a/xbmc/video/VideoReferenceClock.cpp b/xbmc/video/VideoReferenceClock.cpp
|
|
index 0004e07..fa8e35a 100644
|
|
--- a/xbmc/video/VideoReferenceClock.cpp
|
|
+++ b/xbmc/video/VideoReferenceClock.cpp
|
|
@@ -135,12 +135,23 @@
|
|
m_Context = NULL;
|
|
m_pixmap = None;
|
|
m_glPixmap = None;
|
|
- m_RREventBase = 0;
|
|
m_UseNvSettings = true;
|
|
m_bIsATI = false;
|
|
#endif
|
|
}
|
|
|
|
+CVideoReferenceClock::~CVideoReferenceClock()
|
|
+{
|
|
+#if defined(HAS_GLX)
|
|
+ // some ATI voodoo, if we don't close the display, we crash on exit
|
|
+ if (m_Dpy)
|
|
+ {
|
|
+ XCloseDisplay(m_Dpy);
|
|
+ m_Dpy = NULL;
|
|
+ }
|
|
+#endif
|
|
+}
|
|
+
|
|
void CVideoReferenceClock::Process()
|
|
{
|
|
bool SetupSuccess = false;
|
|
@@ -151,6 +162,10 @@ void CVideoReferenceClock::Process()
|
|
m_D3dCallback.Reset();
|
|
g_Windowing.Register(&m_D3dCallback);
|
|
#endif
|
|
+#if defined(HAS_GLX) && defined(HAS_XRANDR)
|
|
+ g_Windowing.Register(this);
|
|
+ m_xrrEvent = false;
|
|
+#endif
|
|
|
|
while(!m_bStop)
|
|
{
|
|
@@ -211,6 +226,16 @@ void CVideoReferenceClock::Process()
|
|
//clean up the vblank clock
|
|
#if defined(HAS_GLX) && defined(HAS_XRANDR)
|
|
CleanupGLX();
|
|
+ if (m_xrrEvent)
|
|
+ {
|
|
+ m_releaseEvent.Set();
|
|
+ while (!m_bStop)
|
|
+ {
|
|
+ if (m_resetEvent.WaitMSec(100))
|
|
+ break;
|
|
+ }
|
|
+ m_xrrEvent = false;
|
|
+ }
|
|
#elif defined(_WIN32) && defined(HAS_DX)
|
|
CleanupD3D();
|
|
#elif defined(TARGET_DARWIN)
|
|
@@ -222,6 +247,9 @@ void CVideoReferenceClock::Process()
|
|
#if defined(_WIN32) && defined(HAS_DX)
|
|
g_Windowing.Unregister(&m_D3dCallback);
|
|
#endif
|
|
+#if defined(HAS_GLX)
|
|
+ g_Windowing.Unregister(this);
|
|
+#endif
|
|
}
|
|
|
|
bool CVideoReferenceClock::WaitStarted(int MSecs)
|
|
@@ -231,6 +259,24 @@ bool CVideoReferenceClock::WaitStarted(int MSecs)
|
|
}
|
|
|
|
#if defined(HAS_GLX) && defined(HAS_XRANDR)
|
|
+
|
|
+void CVideoReferenceClock::OnLostDevice()
|
|
+{
|
|
+ if (!m_xrrEvent)
|
|
+ {
|
|
+ m_releaseEvent.Reset();
|
|
+ m_resetEvent.Reset();
|
|
+ m_xrrEvent = true;
|
|
+ m_releaseEvent.Wait();
|
|
+ }
|
|
+}
|
|
+
|
|
+void CVideoReferenceClock::OnResetDevice()
|
|
+{
|
|
+ m_xrrEvent = false;
|
|
+ m_resetEvent.Set();
|
|
+}
|
|
+
|
|
bool CVideoReferenceClock::SetupGLX()
|
|
{
|
|
int singleBufferAttributes[] = {
|
|
@@ -382,10 +428,6 @@ bool CVideoReferenceClock::SetupGLX()
|
|
return false;
|
|
}
|
|
|
|
- //set up receiving of RandR events, we'll get one when the refreshrate changes
|
|
- XRRQueryExtension(m_Dpy, &m_RREventBase, &ReturnV);
|
|
- XRRSelectInput(m_Dpy, g_Windowing.GetWindow(), RRScreenChangeNotifyMask);
|
|
-
|
|
UpdateRefreshrate(true); //forced refreshrate update
|
|
m_MissedVblanks = 0;
|
|
|
|
@@ -586,6 +628,9 @@ void CVideoReferenceClock::RunGLX()
|
|
|
|
while(!m_bStop)
|
|
{
|
|
+ if (m_xrrEvent)
|
|
+ return;
|
|
+
|
|
//wait for the next vblank
|
|
if (!m_bIsATI)
|
|
{
|
|
@@ -649,7 +694,6 @@ void CVideoReferenceClock::RunGLX()
|
|
UpdateClock((int)(VblankCount - PrevVblankCount), true);
|
|
SingleLock.Leave();
|
|
SendVblankSignal();
|
|
- UpdateRefreshrate();
|
|
IsReset = false;
|
|
}
|
|
else if (!m_bStop)
|
|
@@ -1186,23 +1230,10 @@ bool CVideoReferenceClock::UpdateRefreshrate(bool Forced /*= false*/)
|
|
|
|
#if defined(HAS_GLX) && defined(HAS_XRANDR)
|
|
|
|
- //check for RandR events
|
|
- bool GotEvent = Forced || m_RefreshChanged == 2;
|
|
- XEvent Event;
|
|
- while (XCheckTypedEvent(m_Dpy, m_RREventBase + RRScreenChangeNotify, &Event))
|
|
- {
|
|
- if (Event.type == m_RREventBase + RRScreenChangeNotify)
|
|
- {
|
|
- CLog::Log(LOGDEBUG, "CVideoReferenceClock: Received RandR event %i", Event.type);
|
|
- GotEvent = true;
|
|
- }
|
|
- XRRUpdateConfiguration(&Event);
|
|
- }
|
|
-
|
|
if (!Forced)
|
|
m_RefreshChanged = 0;
|
|
|
|
- if (!GotEvent) //refreshrate did not change
|
|
+ if (!Forced) //refreshrate did not change
|
|
return false;
|
|
|
|
//the refreshrate can be wrong on nvidia drivers, so read it from nvidia-settings when it's available
|
|
diff --git a/xbmc/video/VideoReferenceClock.h b/xbmc/video/VideoReferenceClock.h
|
|
index dcc4f09..7eb6317 100644
|
|
--- a/xbmc/video/VideoReferenceClock.h
|
|
+++ b/xbmc/video/VideoReferenceClock.h
|
|
@@ -30,6 +30,7 @@
|
|
#include <X11/X.h>
|
|
#include <X11/Xlib.h>
|
|
#include <GL/glx.h>
|
|
+ #include "guilib/DispResource.h"
|
|
#elif defined(_WIN32) && defined(HAS_DX)
|
|
#include <d3d9.h>
|
|
#include "guilib/D3DResource.h"
|
|
@@ -56,9 +57,13 @@ class CD3DCallback : public ID3DResource
|
|
#endif
|
|
|
|
class CVideoReferenceClock : public CThread
|
|
+#if defined(HAS_GLX) && defined(HAS_XRANDR)
|
|
+ ,public IDispResource
|
|
+#endif
|
|
{
|
|
public:
|
|
CVideoReferenceClock();
|
|
+ virtual ~CVideoReferenceClock();
|
|
|
|
int64_t GetTime(bool interpolated = true);
|
|
int64_t GetFrequency();
|
|
@@ -75,6 +80,11 @@ class CVideoReferenceClock : public CThread
|
|
void VblankHandler(int64_t nowtime, double fps);
|
|
#endif
|
|
|
|
+#if defined(HAS_GLX) && defined(HAS_XRANDR)
|
|
+ virtual void OnLostDevice();
|
|
+ virtual void OnResetDevice();
|
|
+#endif
|
|
+
|
|
private:
|
|
void Process();
|
|
bool UpdateRefreshrate(bool Forced = false);
|
|
@@ -121,7 +131,8 @@ class CVideoReferenceClock : public CThread
|
|
GLXContext m_Context;
|
|
Pixmap m_pixmap;
|
|
GLXPixmap m_glPixmap;
|
|
- int m_RREventBase;
|
|
+ bool m_xrrEvent;
|
|
+ CEvent m_releaseEvent, m_resetEvent;
|
|
|
|
bool m_UseNvSettings;
|
|
bool m_bIsATI;
|
|
--
|
|
1.7.10
|
|
|
|
|
|
From 702f79eab647ec68030c99d6113976f3c602e87c Mon Sep 17 00:00:00 2001
|
|
From: xbmc <fernetmenta@online.de>
|
|
Date: Thu, 21 Jun 2012 17:26:51 +0200
|
|
Subject: [PATCH 27/72] X11: fix video calibrations
|
|
|
|
---
|
|
xbmc/settings/Settings.cpp | 1 +
|
|
xbmc/windowing/WinSystem.h | 1 +
|
|
xbmc/windowing/X11/WinSystemX11.cpp | 36 ++++++++++++++++++++++++++++++++++-
|
|
xbmc/windowing/X11/WinSystemX11.h | 1 +
|
|
4 files changed, 38 insertions(+), 1 deletion(-)
|
|
|
|
diff --git a/xbmc/settings/Settings.cpp b/xbmc/settings/Settings.cpp
|
|
index 8a430ad..fde6e4e 100644
|
|
--- a/xbmc/settings/Settings.cpp
|
|
+++ b/xbmc/settings/Settings.cpp
|
|
@@ -55,6 +55,7 @@
|
|
#include "filesystem/File.h"
|
|
#include "filesystem/DirectoryCache.h"
|
|
#include "DatabaseManager.h"
|
|
+#include "windowing/WindowingFactory.h"
|
|
|
|
using namespace std;
|
|
using namespace XFILE;
|
|
diff --git a/xbmc/windowing/WinSystem.h b/xbmc/windowing/WinSystem.h
|
|
index 05c5eda..852d085 100644
|
|
--- a/xbmc/windowing/WinSystem.h
|
|
+++ b/xbmc/windowing/WinSystem.h
|
|
@@ -100,6 +100,7 @@ class CWinSystemBase
|
|
std::vector<RESOLUTION_WHR> ScreenResolutions(int screen);
|
|
std::vector<REFRESHRATE> RefreshRates(int screen, int width, int height, uint32_t dwFlags);
|
|
REFRESHRATE DefaultRefreshRate(int screen, std::vector<REFRESHRATE> rates);
|
|
+ virtual bool HasCalibration(const RESOLUTION_INFO &resInfo) { return true; };
|
|
|
|
protected:
|
|
void UpdateDesktopResolution(RESOLUTION_INFO& newRes, int screen, int width, int height, float refreshRate, uint32_t dwFlags = 0);
|
|
diff --git a/xbmc/windowing/X11/WinSystemX11.cpp b/xbmc/windowing/X11/WinSystemX11.cpp
|
|
index d3d15e2..487b324 100644
|
|
--- a/xbmc/windowing/X11/WinSystemX11.cpp
|
|
+++ b/xbmc/windowing/X11/WinSystemX11.cpp
|
|
@@ -320,7 +320,7 @@ void CWinSystemX11::UpdateResolutions()
|
|
res.strMode.Format("%s: %s @ %.2fHz", out->name.c_str(), mode.name.c_str(), mode.hz);
|
|
res.strOutput = out->name;
|
|
res.strId = mode.id;
|
|
- res.iSubtitles = (int)(0.95*mode.h);
|
|
+ res.iSubtitles = (int)(0.965*mode.h);
|
|
res.fRefreshRate = mode.hz;
|
|
res.bFullScreen = true;
|
|
|
|
@@ -333,8 +333,42 @@ void CWinSystemX11::UpdateResolutions()
|
|
g_settings.m_ResInfo.push_back(res);
|
|
}
|
|
}
|
|
+ g_settings.ApplyCalibrations();
|
|
#endif
|
|
+}
|
|
+
|
|
+bool CWinSystemX11::HasCalibration(const RESOLUTION_INFO &resInfo)
|
|
+{
|
|
+ XOutput *out = g_xrandr.GetOutput(m_currentOutput);
|
|
+
|
|
+ // keep calibrations done on a not connected output
|
|
+ if (!out->name.Equals(resInfo.strOutput))
|
|
+ return true;
|
|
+
|
|
+ // keep calibrations not updated with resolution data
|
|
+ if (resInfo.iWidth == 0)
|
|
+ return true;
|
|
+
|
|
+ float fPixRatio;
|
|
+ if (resInfo.iHeight>0 && resInfo.iWidth>0 && out->hmm>0 && out->wmm>0)
|
|
+ fPixRatio = ((float)out->wmm/(float)resInfo.iWidth) / (((float)out->hmm/(float)resInfo.iHeight));
|
|
+ else
|
|
+ fPixRatio = 1.0f;
|
|
|
|
+ if (resInfo.Overscan.left != 0)
|
|
+ return true;
|
|
+ if (resInfo.Overscan.top != 0)
|
|
+ return true;
|
|
+ if (resInfo.Overscan.right != resInfo.iWidth)
|
|
+ return true;
|
|
+ if (resInfo.Overscan.bottom != resInfo.iHeight)
|
|
+ return true;
|
|
+ if (resInfo.fPixelRatio != fPixRatio)
|
|
+ return true;
|
|
+ if (resInfo.iSubtitles != (int)(0.965*resInfo.iHeight))
|
|
+ return true;
|
|
+
|
|
+ return false;
|
|
}
|
|
|
|
void CWinSystemX11::GetConnectedOutputs(std::vector<CStdString> *outputs)
|
|
diff --git a/xbmc/windowing/X11/WinSystemX11.h b/xbmc/windowing/X11/WinSystemX11.h
|
|
index cc28f56..c046c86 100644
|
|
--- a/xbmc/windowing/X11/WinSystemX11.h
|
|
+++ b/xbmc/windowing/X11/WinSystemX11.h
|
|
@@ -61,6 +61,7 @@ class CWinSystemX11 : public CWinSystemBase
|
|
virtual bool Show(bool raise = true);
|
|
virtual void Register(IDispResource *resource);
|
|
virtual void Unregister(IDispResource *resource);
|
|
+ virtual bool HasCalibration(const RESOLUTION_INFO &resInfo);
|
|
|
|
// Local to WinSystemX11 only
|
|
Display* GetDisplay() { return m_dpy; }
|
|
--
|
|
1.7.10
|
|
|
|
|
|
From 07920e322c9770ebb99becd104ebce0789c502fa Mon Sep 17 00:00:00 2001
|
|
From: FernetMenta <fernetmenta@online.de>
|
|
Date: Thu, 5 Jul 2012 12:00:26 +0200
|
|
Subject: [PATCH 28/72] X11: deactivate screen saver on startup
|
|
|
|
---
|
|
xbmc/windowing/X11/WinSystemX11.cpp | 29 +++++++++++++++++++++++++++++
|
|
xbmc/windowing/X11/WinSystemX11.h | 1 +
|
|
2 files changed, 30 insertions(+)
|
|
|
|
diff --git a/xbmc/windowing/X11/WinSystemX11.cpp b/xbmc/windowing/X11/WinSystemX11.cpp
|
|
index 487b324..b3e7ab5 100644
|
|
--- a/xbmc/windowing/X11/WinSystemX11.cpp
|
|
+++ b/xbmc/windowing/X11/WinSystemX11.cpp
|
|
@@ -521,6 +521,33 @@ void CWinSystemX11::ResetOSScreensaver()
|
|
}
|
|
}
|
|
|
|
+void CWinSystemX11::EnableSystemScreenSaver(bool bEnable)
|
|
+{
|
|
+ if (!m_dpy)
|
|
+ return;
|
|
+
|
|
+ if (bEnable)
|
|
+ XForceScreenSaver(m_dpy, ScreenSaverActive);
|
|
+ else
|
|
+ {
|
|
+ Window root_return, child_return;
|
|
+ int root_x_return, root_y_return;
|
|
+ int win_x_return, win_y_return;
|
|
+ unsigned int mask_return;
|
|
+ bool isInWin = XQueryPointer(m_dpy, RootWindow(m_dpy, m_nScreen), &root_return, &child_return,
|
|
+ &root_x_return, &root_y_return,
|
|
+ &win_x_return, &win_y_return,
|
|
+ &mask_return);
|
|
+
|
|
+ XWarpPointer(m_dpy, None, RootWindow(m_dpy, m_nScreen), 0, 0, 0, 0, root_x_return+300, root_y_return+300);
|
|
+ XSync(m_dpy, FALSE);
|
|
+ XWarpPointer(m_dpy, None, RootWindow(m_dpy, m_nScreen), 0, 0, 0, 0, 0, 0);
|
|
+ XSync(m_dpy, FALSE);
|
|
+ XWarpPointer(m_dpy, None, RootWindow(m_dpy, m_nScreen), 0, 0, 0, 0, root_x_return, root_y_return);
|
|
+ XSync(m_dpy, FALSE);
|
|
+ }
|
|
+}
|
|
+
|
|
void CWinSystemX11::NotifyAppActiveChange(bool bActivated)
|
|
{
|
|
if (bActivated && m_bWasFullScreenBeforeMinimize && !m_bFullScreen)
|
|
@@ -764,6 +791,8 @@ bool CWinSystemX11::SetWindow(int width, int height, bool fullscreen, const CStd
|
|
// create main window
|
|
if (!m_glWindow)
|
|
{
|
|
+ EnableSystemScreenSaver(false);
|
|
+
|
|
GLint att[] =
|
|
{
|
|
GLX_RGBA,
|
|
diff --git a/xbmc/windowing/X11/WinSystemX11.h b/xbmc/windowing/X11/WinSystemX11.h
|
|
index c046c86..e953d2d 100644
|
|
--- a/xbmc/windowing/X11/WinSystemX11.h
|
|
+++ b/xbmc/windowing/X11/WinSystemX11.h
|
|
@@ -51,6 +51,7 @@ class CWinSystemX11 : public CWinSystemBase
|
|
virtual void ShowOSMouse(bool show);
|
|
virtual void ResetOSScreensaver();
|
|
virtual bool EnableFrameLimiter();
|
|
+ virtual void EnableSystemScreenSaver(bool bEnable);
|
|
|
|
virtual void NotifyAppActiveChange(bool bActivated);
|
|
virtual void NotifyAppFocusChange(bool bGaining);
|
|
--
|
|
1.7.10
|
|
|
|
|
|
From 835bcc9c7fd477012492ffc4cad2bdd9ce506064 Mon Sep 17 00:00:00 2001
|
|
From: FernetMenta <fernetmenta@online.de>
|
|
Date: Thu, 5 Jul 2012 12:10:09 +0200
|
|
Subject: [PATCH 29/72] X11: change method of going full-screen
|
|
|
|
---
|
|
xbmc/windowing/X11/WinSystemX11.cpp | 9 ++++++++-
|
|
1 file changed, 8 insertions(+), 1 deletion(-)
|
|
|
|
diff --git a/xbmc/windowing/X11/WinSystemX11.cpp b/xbmc/windowing/X11/WinSystemX11.cpp
|
|
index b3e7ab5..91f92c1 100644
|
|
--- a/xbmc/windowing/X11/WinSystemX11.cpp
|
|
+++ b/xbmc/windowing/X11/WinSystemX11.cpp
|
|
@@ -34,6 +34,7 @@
|
|
#include "utils/TimeUtils.h"
|
|
#include "settings/GUISettings.h"
|
|
#include "windowing/WindowingFactory.h"
|
|
+#include <X11/Xatom.h>
|
|
|
|
#if defined(HAS_XRANDR)
|
|
#include <X11/extensions/Xrandr.h>
|
|
@@ -816,7 +817,7 @@ bool CWinSystemX11::SetWindow(int width, int height, bool fullscreen, const CStd
|
|
cmap = XCreateColormap(m_dpy, RootWindow(m_dpy, vi->screen), vi->visual, AllocNone);
|
|
|
|
int def_vis = (vi->visual == DefaultVisual(m_dpy, vi->screen));
|
|
- swa.override_redirect = fullscreen ? True : False;
|
|
+ swa.override_redirect = False;
|
|
swa.border_pixel = fullscreen ? 0 : 5;
|
|
swa.background_pixel = def_vis ? BlackPixel(m_dpy, vi->screen) : 0;
|
|
swa.colormap = cmap;
|
|
@@ -832,6 +833,12 @@ bool CWinSystemX11::SetWindow(int width, int height, bool fullscreen, const CStd
|
|
InputOutput, vi->visual,
|
|
mask, &swa);
|
|
|
|
+ if (fullscreen)
|
|
+ {
|
|
+ Atom fs = XInternAtom(m_dpy, "_NET_WM_STATE_FULLSCREEN", True);
|
|
+ XChangeProperty(m_dpy, m_glWindow, XInternAtom(m_dpy, "_NET_WM_STATE", True), XA_ATOM, 32, PropModeReplace, (unsigned char *) &fs, 1);
|
|
+ }
|
|
+
|
|
// define invisible cursor
|
|
Pixmap bitmapNoData;
|
|
XColor black;
|
|
--
|
|
1.7.10
|
|
|
|
|
|
From e2442797ff82b3ed8053f1a6422863ffce9cbe5f Mon Sep 17 00:00:00 2001
|
|
From: xbmc <fernetmenta@online.de>
|
|
Date: Thu, 28 Jun 2012 19:12:39 +0200
|
|
Subject: [PATCH 30/72] X11: reset key repeat and key modifier on focus lost
|
|
and gain
|
|
|
|
---
|
|
xbmc/windowing/WinEventsX11.cpp | 3 +++
|
|
1 file changed, 3 insertions(+)
|
|
|
|
diff --git a/xbmc/windowing/WinEventsX11.cpp b/xbmc/windowing/WinEventsX11.cpp
|
|
index 6c22358..d86205d 100644
|
|
--- a/xbmc/windowing/WinEventsX11.cpp
|
|
+++ b/xbmc/windowing/WinEventsX11.cpp
|
|
@@ -359,6 +359,8 @@ bool CWinEventsX11::MessagePump()
|
|
if (WinEvents->m_xic)
|
|
XSetICFocus(WinEvents->m_xic);
|
|
g_application.m_AppFocused = true;
|
|
+ memset(&(WinEvents->m_lastKey), 0, sizeof(XBMC_Event));
|
|
+ WinEvents->m_keymodState = 0;
|
|
if (serial == xevent.xfocus.serial)
|
|
break;
|
|
g_Windowing.NotifyAppFocusChange(g_application.m_AppFocused);
|
|
@@ -370,6 +372,7 @@ bool CWinEventsX11::MessagePump()
|
|
if (WinEvents->m_xic)
|
|
XUnsetICFocus(WinEvents->m_xic);
|
|
g_application.m_AppFocused = false;
|
|
+ memset(&(WinEvents->m_lastKey), 0, sizeof(XBMC_Event));
|
|
g_Windowing.NotifyAppFocusChange(g_application.m_AppFocused);
|
|
serial = xevent.xfocus.serial;
|
|
break;
|
|
--
|
|
1.7.10
|
|
|
|
|
|
From 77a22163a7f611e9183b7cd0b817fc51a42d45de Mon Sep 17 00:00:00 2001
|
|
From: Joakim Plate <elupus@xbmc.org>
|
|
Date: Thu, 5 Jul 2012 14:18:46 +0200
|
|
Subject: [PATCH 31/72] X11: replace custom utf8 to unicode with charset
|
|
convertor (squash to x11 events)
|
|
|
|
---
|
|
xbmc/windowing/WinEventsX11.cpp | 119 ++++-----------------------------------
|
|
xbmc/windowing/WinEventsX11.h | 2 -
|
|
2 files changed, 11 insertions(+), 110 deletions(-)
|
|
|
|
diff --git a/xbmc/windowing/WinEventsX11.cpp b/xbmc/windowing/WinEventsX11.cpp
|
|
index d86205d..76702e6 100644
|
|
--- a/xbmc/windowing/WinEventsX11.cpp
|
|
+++ b/xbmc/windowing/WinEventsX11.cpp
|
|
@@ -32,6 +32,7 @@
|
|
#include "X11/keysymdef.h"
|
|
#include "X11/XF86keysym.h"
|
|
#include "utils/log.h"
|
|
+#include "utils/CharsetConverter.h"
|
|
#include "guilib/GUIWindowManager.h"
|
|
#include "input/MouseStat.h"
|
|
|
|
@@ -161,7 +162,6 @@
|
|
m_display = 0;
|
|
m_window = 0;
|
|
m_keybuf = 0;
|
|
- m_utf16buf = 0;
|
|
}
|
|
|
|
CWinEventsX11::~CWinEventsX11()
|
|
@@ -172,12 +172,6 @@
|
|
m_keybuf = 0;
|
|
}
|
|
|
|
- if (m_utf16buf)
|
|
- {
|
|
- free(m_utf16buf);
|
|
- m_utf16buf = 0;
|
|
- }
|
|
-
|
|
if (m_xic)
|
|
{
|
|
XUnsetICFocus(m_xic);
|
|
@@ -203,7 +197,6 @@ bool CWinEventsX11::Init(Display *dpy, Window win)
|
|
WinEvents->m_display = dpy;
|
|
WinEvents->m_window = win;
|
|
WinEvents->m_keybuf = (char*)malloc(32*sizeof(char));
|
|
- WinEvents->m_utf16buf = (uint16_t*)malloc(32*sizeof(uint16_t));
|
|
WinEvents->m_keymodState = 0;
|
|
WinEvents->m_wmDeleteMessage = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
|
|
WinEvents->m_structureChanged = false;
|
|
@@ -433,8 +426,6 @@ bool CWinEventsX11::MessagePump()
|
|
}
|
|
|
|
Status status;
|
|
- int utf16size;
|
|
- int utf16length;
|
|
int len;
|
|
len = Xutf8LookupString(WinEvents->m_xic, &xevent.xkey,
|
|
WinEvents->m_keybuf, sizeof(WinEvents->m_keybuf),
|
|
@@ -453,36 +444,29 @@ bool CWinEventsX11::MessagePump()
|
|
case XLookupChars:
|
|
case XLookupBoth:
|
|
{
|
|
- if (len == 0)
|
|
- break;
|
|
- utf16size = len * sizeof(uint16_t);
|
|
- if (utf16size > sizeof(WinEvents->m_utf16buf))
|
|
- {
|
|
- WinEvents->m_utf16buf = (uint16_t *)realloc(WinEvents->m_utf16buf,utf16size);
|
|
- if (WinEvents->m_utf16buf == NULL)
|
|
- {
|
|
- break;
|
|
- }
|
|
- }
|
|
- utf16length = Utf8ToUnicode(WinEvents->m_keybuf, len, WinEvents->m_utf16buf, utf16size);
|
|
- if (utf16length < 0)
|
|
+ CStdString data(WinEvents->m_keybuf, len);
|
|
+ CStdStringW keys;
|
|
+ g_charsetConverter.utf8ToW(data, keys, false);
|
|
+
|
|
+ if (keys.length() == 0)
|
|
{
|
|
break;
|
|
}
|
|
- for (unsigned int i = 0; i < utf16length - 1; i++)
|
|
+
|
|
+ for (unsigned int i = 0; i < keys.length() - 1; i++)
|
|
{
|
|
newEvent.key.keysym.sym = XBMCK_UNKNOWN;
|
|
- newEvent.key.keysym.unicode = WinEvents->m_utf16buf[i];
|
|
+ newEvent.key.keysym.unicode = keys[i];
|
|
newEvent.key.state = xevent.xkey.state;
|
|
newEvent.key.type = xevent.xkey.type;
|
|
ret |= ProcessKey(newEvent, 500);
|
|
}
|
|
- if (utf16length > 0)
|
|
+ if (keys.length() > 0)
|
|
{
|
|
newEvent.key.keysym.scancode = xevent.xkey.keycode;
|
|
xkeysym = XLookupKeysym(&xevent.xkey, 0);
|
|
newEvent.key.keysym.sym = LookupXbmcKeySym(xkeysym);
|
|
- newEvent.key.keysym.unicode = WinEvents->m_utf16buf[utf16length - 1];
|
|
+ newEvent.key.keysym.unicode = keys[keys.length() - 1];
|
|
newEvent.key.state = xevent.xkey.state;
|
|
newEvent.key.type = xevent.xkey.type;
|
|
|
|
@@ -743,87 +727,6 @@ bool CWinEventsX11::ProcessKeyRepeat()
|
|
return false;
|
|
}
|
|
|
|
-int CWinEventsX11::Utf8ToUnicode(const char *utf8, const int utf8Length, uint16_t *utf16, const int utf16MaxLength)
|
|
-{
|
|
- // p moves over the output buffer. max_ptr points to the next to the last slot of the buffer.
|
|
- uint16_t *p = utf16;
|
|
- uint16_t const *const maxPtr = utf16 + utf16MaxLength;
|
|
-
|
|
- // end_of_input points to the last byte of input as opposed to the next to the last byte.
|
|
- char const *const endOfInput = utf8 + utf8Length - 1;
|
|
-
|
|
- while (utf8 <= endOfInput)
|
|
- {
|
|
- unsigned char const c = *utf8;
|
|
- if (p >= maxPtr)
|
|
- {
|
|
- //No more output space.
|
|
- return -1;
|
|
- }
|
|
- if (c < 0x80)
|
|
- {
|
|
- //One byte ASCII.
|
|
- *p++ = c;
|
|
- utf8 += 1;
|
|
- }
|
|
- else if (c < 0xC0)
|
|
- {
|
|
- // Follower byte without preceding leader bytes.
|
|
- return -1;
|
|
- }
|
|
- // 11 bits
|
|
- else if (c < 0xE0)
|
|
- {
|
|
- // Two byte sequence. We need one follower byte.
|
|
- if (endOfInput - utf8 < 1 || (((utf8[1] ^ 0x80)) & 0xC0))
|
|
- {
|
|
- return -1;
|
|
- }
|
|
- *p++ = (uint16_t)(((c & 0x1F) << 6) + (utf8[1] & 0x3F));
|
|
- utf8 += 2;
|
|
- }
|
|
- // 16 bis
|
|
- else if (c < 0xF0)
|
|
- {
|
|
- // Three byte sequence. We need two follower byte.
|
|
- if (endOfInput - utf8 < 2 || ((utf8[1] ^ 0x80) & 0xC0) || ((utf8[2] ^ 0x80) & 0xC0))
|
|
- {
|
|
- return -1;
|
|
- }
|
|
- *p++ = (uint16_t)(((c & 0xF) << 12) + ((utf8[1] & 0x3F) << 6) + (utf8[2] & 0x3F));
|
|
- utf8 += 3;
|
|
- }
|
|
- // 21 bits
|
|
- else if (c < 0xF8)
|
|
- {
|
|
- int plane;
|
|
- // Four byte sequence. We need three follower bytes.
|
|
- if (endOfInput - utf8 < 3 || ((utf8[1] ^ 0x80) & 0xC0) ||
|
|
- ((utf8[2] ^ 0x80) & 0xC0) || ((utf8[3] ^ 0x80) & 0xC0))
|
|
- {
|
|
- return -1;
|
|
- }
|
|
- uint32_t unicode = ((c & 0x7) << 18) + ((utf8[1] & 0x3F) << 12) +
|
|
- ((utf8[2] & 0x3F) << 6) + (utf8[3] & 0x3F);
|
|
- utf8 += 4;
|
|
- CLog::Log(LOGERROR, "CWinEventsX11::Utf8ToUnicode: 4 byte unicode not supported");
|
|
- }
|
|
- // 26 bits
|
|
- else if (c < 0xFC)
|
|
- {
|
|
- CLog::Log(LOGERROR, "CWinEventsX11::Utf8ToUnicode: 4 byte unicode not supported");
|
|
- utf8 += 5;
|
|
- }
|
|
- // 31 bit
|
|
- else
|
|
- {
|
|
- CLog::Log(LOGERROR, "CWinEventsX11::Utf8ToUnicode: 4 byte unicode not supported");
|
|
- utf8 += 6;
|
|
- }
|
|
- }
|
|
- return p - utf16;
|
|
-}
|
|
-
|
|
XBMCKey CWinEventsX11::LookupXbmcKeySym(KeySym keysym)
|
|
{
|
|
// try direct mapping first
|
|
diff --git a/xbmc/windowing/WinEventsX11.h b/xbmc/windowing/WinEventsX11.h
|
|
index 6100933..72955ad 100644
|
|
--- a/xbmc/windowing/WinEventsX11.h
|
|
+++ b/xbmc/windowing/WinEventsX11.h
|
|
@@ -38,7 +38,6 @@ class CWinEventsX11 : public CWinEventsBase
|
|
static bool MessagePump();
|
|
|
|
protected:
|
|
- static int Utf8ToUnicode(const char *utf8, const int utf8Length, uint16_t *utf16, const int utf16MaxLength);
|
|
static XBMCKey LookupXbmcKeySym(KeySym keysym);
|
|
static bool ProcessKey(XBMC_Event &event, int repeatDelay);
|
|
static bool ProcessKeyRepeat();
|
|
@@ -48,7 +47,6 @@ class CWinEventsX11 : public CWinEventsBase
|
|
Window m_window;
|
|
Atom m_wmDeleteMessage;
|
|
char *m_keybuf;
|
|
- uint16_t *m_utf16buf;
|
|
XIM m_xim;
|
|
XIC m_xic;
|
|
XBMC_Event m_lastKey;
|
|
--
|
|
1.7.10
|
|
|
|
|
|
From e060b3197bbac54b79b604bbbf9a8e86257980f5 Mon Sep 17 00:00:00 2001
|
|
From: Joakim Plate <elupus@xbmc.org>
|
|
Date: Thu, 5 Jul 2012 14:23:54 +0200
|
|
Subject: [PATCH 32/72] X11: fixed invalid usage of sizeof() (squash into x11
|
|
changes)
|
|
|
|
---
|
|
xbmc/windowing/WinEventsX11.cpp | 11 +++++++----
|
|
xbmc/windowing/WinEventsX11.h | 1 +
|
|
2 files changed, 8 insertions(+), 4 deletions(-)
|
|
|
|
diff --git a/xbmc/windowing/WinEventsX11.cpp b/xbmc/windowing/WinEventsX11.cpp
|
|
index 76702e6..c31877e 100644
|
|
--- a/xbmc/windowing/WinEventsX11.cpp
|
|
+++ b/xbmc/windowing/WinEventsX11.cpp
|
|
@@ -162,6 +162,7 @@
|
|
m_display = 0;
|
|
m_window = 0;
|
|
m_keybuf = 0;
|
|
+ m_keybuf_len = 0;
|
|
}
|
|
|
|
CWinEventsX11::~CWinEventsX11()
|
|
@@ -196,7 +197,8 @@ bool CWinEventsX11::Init(Display *dpy, Window win)
|
|
WinEvents = new CWinEventsX11();
|
|
WinEvents->m_display = dpy;
|
|
WinEvents->m_window = win;
|
|
- WinEvents->m_keybuf = (char*)malloc(32*sizeof(char));
|
|
+ WinEvents->m_keybuf_len = 32*sizeof(char);
|
|
+ WinEvents->m_keybuf = (char*)malloc(WinEvents->m_keybuf_len);
|
|
WinEvents->m_keymodState = 0;
|
|
WinEvents->m_wmDeleteMessage = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
|
|
WinEvents->m_structureChanged = false;
|
|
@@ -428,13 +430,14 @@ bool CWinEventsX11::MessagePump()
|
|
Status status;
|
|
int len;
|
|
len = Xutf8LookupString(WinEvents->m_xic, &xevent.xkey,
|
|
- WinEvents->m_keybuf, sizeof(WinEvents->m_keybuf),
|
|
+ WinEvents->m_keybuf, WinEvents->m_keybuf_len,
|
|
&xkeysym, &status);
|
|
if (status == XBufferOverflow)
|
|
{
|
|
- WinEvents->m_keybuf = (char*)realloc(WinEvents->m_keybuf, len*sizeof(char));
|
|
+ WinEvents->m_keybuf_len = len;
|
|
+ WinEvents->m_keybuf = (char*)realloc(WinEvents->m_keybuf, WinEvents->m_keybuf_len);
|
|
len = Xutf8LookupString(WinEvents->m_xic, &xevent.xkey,
|
|
- WinEvents->m_keybuf, sizeof(WinEvents->m_keybuf),
|
|
+ WinEvents->m_keybuf, WinEvents->m_keybuf_len,
|
|
&xkeysym, &status);
|
|
}
|
|
switch (status)
|
|
diff --git a/xbmc/windowing/WinEventsX11.h b/xbmc/windowing/WinEventsX11.h
|
|
index 72955ad..102a076 100644
|
|
--- a/xbmc/windowing/WinEventsX11.h
|
|
+++ b/xbmc/windowing/WinEventsX11.h
|
|
@@ -47,6 +47,7 @@ class CWinEventsX11 : public CWinEventsBase
|
|
Window m_window;
|
|
Atom m_wmDeleteMessage;
|
|
char *m_keybuf;
|
|
+ size_t m_keybuf_len;
|
|
XIM m_xim;
|
|
XIC m_xic;
|
|
XBMC_Event m_lastKey;
|
|
--
|
|
1.7.10
|
|
|
|
|
|
From c52af3ba68292f08331cbbbc940dfcea838a2f44 Mon Sep 17 00:00:00 2001
|
|
From: xbmc <fernetmenta@online.de>
|
|
Date: Sat, 9 Jun 2012 18:23:53 +0200
|
|
Subject: [PATCH 33/72] add missing keys to xbmc keytable
|
|
|
|
---
|
|
xbmc/input/XBMC_keytable.cpp | 2 ++
|
|
1 file changed, 2 insertions(+)
|
|
|
|
diff --git a/xbmc/input/XBMC_keytable.cpp b/xbmc/input/XBMC_keytable.cpp
|
|
index aaf65ba..9d7922f 100644
|
|
--- a/xbmc/input/XBMC_keytable.cpp
|
|
+++ b/xbmc/input/XBMC_keytable.cpp
|
|
@@ -179,6 +179,8 @@
|
|
, { XBMCK_LAUNCH_APP2, 0, 0, XBMCVK_LAUNCH_APP2, "launch_app2_pc_icon" }
|
|
, { XBMCK_LAUNCH_FILE_BROWSER, 0, 0, XBMCVK_LAUNCH_FILE_BROWSER, "launch_file_browser" }
|
|
, { XBMCK_LAUNCH_MEDIA_CENTER, 0, 0, XBMCVK_LAUNCH_MEDIA_CENTER, "launch_media_center" }
|
|
+, { XBMCK_PLAY, 0, 0, XBMCVK_MEDIA_PLAY_PAUSE, "play_pause" }
|
|
+, { XBMCK_STOP, 0, 0, XBMCVK_MEDIA_STOP, "stop" }
|
|
|
|
// Function keys
|
|
, { XBMCK_F1, 0, 0, XBMCVK_F1, "f1"}
|
|
--
|
|
1.7.10
|
|
|
|
|
|
From 25587ee807eca2fc9dde4528e3fc930b337e38b0 Mon Sep 17 00:00:00 2001
|
|
From: xbmc <fernetmenta@online.de>
|
|
Date: Fri, 16 Mar 2012 15:57:51 +0100
|
|
Subject: [PATCH 34/72] videorefclock: temp deactivate of nv settings
|
|
|
|
---
|
|
xbmc/video/VideoReferenceClock.cpp | 2 +-
|
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
|
|
|
diff --git a/xbmc/video/VideoReferenceClock.cpp b/xbmc/video/VideoReferenceClock.cpp
|
|
index fa8e35a..85e36c7 100644
|
|
--- a/xbmc/video/VideoReferenceClock.cpp
|
|
+++ b/xbmc/video/VideoReferenceClock.cpp
|
|
@@ -135,7 +135,7 @@
|
|
m_Context = NULL;
|
|
m_pixmap = None;
|
|
m_glPixmap = None;
|
|
- m_UseNvSettings = true;
|
|
+ m_UseNvSettings = false;
|
|
m_bIsATI = false;
|
|
#endif
|
|
}
|
|
--
|
|
1.7.10
|
|
|
|
|
|
From 4f8a95de09408321e2df3da891536c314fe3b4d2 Mon Sep 17 00:00:00 2001
|
|
From: xbmc <fernetmenta@online.de>
|
|
Date: Mon, 20 Aug 2012 09:09:09 +0200
|
|
Subject: [PATCH 35/72] videorefclock: ask graphics context for refresh rate
|
|
|
|
---
|
|
xbmc/video/VideoReferenceClock.cpp | 3 ++-
|
|
1 file changed, 2 insertions(+), 1 deletion(-)
|
|
|
|
diff --git a/xbmc/video/VideoReferenceClock.cpp b/xbmc/video/VideoReferenceClock.cpp
|
|
index 85e36c7..8209163 100644
|
|
--- a/xbmc/video/VideoReferenceClock.cpp
|
|
+++ b/xbmc/video/VideoReferenceClock.cpp
|
|
@@ -30,6 +30,7 @@
|
|
#include <sstream>
|
|
#include <X11/extensions/Xrandr.h>
|
|
#include "windowing/WindowingFactory.h"
|
|
+ #include "guilib/GraphicContext.h"
|
|
#define NVSETTINGSCMD "nvidia-settings -nt -q RefreshRate3"
|
|
#elif defined(TARGET_DARWIN_OSX)
|
|
#include <QuartzCore/CVDisplayLink.h>
|
|
@@ -1254,7 +1255,7 @@ bool CVideoReferenceClock::UpdateRefreshrate(bool Forced /*= false*/)
|
|
}
|
|
|
|
CSingleLock SingleLock(m_CritSection);
|
|
- m_RefreshRate = GetRandRRate();
|
|
+ m_RefreshRate = MathUtils::round_int(g_graphicsContext.GetFPS());
|
|
|
|
CLog::Log(LOGDEBUG, "CVideoReferenceClock: Detected refreshrate: %i hertz", (int)m_RefreshRate);
|
|
|
|
--
|
|
1.7.10
|
|
|
|
|
|
From 85d81f0c933cb0a75c2c21de86b4065e3db86002 Mon Sep 17 00:00:00 2001
|
|
From: xbmc <fernetmenta@online.de>
|
|
Date: Mon, 9 Jul 2012 14:00:18 +0200
|
|
Subject: [PATCH 36/72] X11: fix icon texture after
|
|
cc5ed3c2474084ebc0373a3046410e6f766e03f4
|
|
|
|
---
|
|
xbmc/windowing/X11/WinSystemX11.cpp | 43 +++++++++++++++++++++--------------
|
|
1 file changed, 26 insertions(+), 17 deletions(-)
|
|
|
|
diff --git a/xbmc/windowing/X11/WinSystemX11.cpp b/xbmc/windowing/X11/WinSystemX11.cpp
|
|
index 91f92c1..174ccef 100644
|
|
--- a/xbmc/windowing/X11/WinSystemX11.cpp
|
|
+++ b/xbmc/windowing/X11/WinSystemX11.cpp
|
|
@@ -874,22 +874,24 @@ bool CWinSystemX11::SetWindow(int width, int height, bool fullscreen, const CStd
|
|
if (!fullscreen)
|
|
{
|
|
CreateIconPixmap();
|
|
- XWMHints wm_hints;
|
|
- XClassHint class_hints;
|
|
+ XWMHints *wm_hints;
|
|
XTextProperty windowName, iconName;
|
|
std::string titleString = "XBMC Media Center";
|
|
char *title = (char*)titleString.c_str();
|
|
|
|
XStringListToTextProperty(&title, 1, &windowName);
|
|
XStringListToTextProperty(&title, 1, &iconName);
|
|
- wm_hints.initial_state = NormalState;
|
|
- wm_hints.input = True;
|
|
- wm_hints.icon_pixmap = m_icon;
|
|
- wm_hints.flags = StateHint | IconPixmapHint | InputHint;
|
|
|
|
+ wm_hints = XAllocWMHints();
|
|
+ wm_hints->initial_state = NormalState;
|
|
+ wm_hints->icon_pixmap = m_icon;
|
|
+ wm_hints->flags = StateHint | IconPixmapHint;
|
|
+
|
|
+ XSync(m_dpy,False);
|
|
XSetWMProperties(m_dpy, m_glWindow, &windowName, &iconName,
|
|
- NULL, 0, NULL, &wm_hints,
|
|
+ NULL, 0, NULL, wm_hints,
|
|
NULL);
|
|
+ XFree(wm_hints);
|
|
|
|
// register interest in the delete window message
|
|
Atom wmDeleteMessage = XInternAtom(m_dpy, "WM_DELETE_WINDOW", False);
|
|
@@ -974,16 +976,21 @@ bool CWinSystemX11::CreateIconPixmap()
|
|
gRatio = vis->green_mask / 255.0;
|
|
bRatio = vis->blue_mask / 255.0;
|
|
|
|
- CTexture iconTexture;
|
|
- iconTexture.LoadFromFile("special://xbmc/media/icon.png");
|
|
- buf = iconTexture.GetPixels();
|
|
+ CBaseTexture *iconTexture = CBaseTexture::LoadFromFile("special://xbmc/media/icon.png");
|
|
+
|
|
+ if (!iconTexture)
|
|
+ return false;
|
|
|
|
- numBufBytes = iconTexture.GetWidth() * iconTexture.GetHeight() * 4;
|
|
+ buf = iconTexture->GetPixels();
|
|
+
|
|
+ numBufBytes = iconTexture->GetWidth() * iconTexture->GetHeight() * 4;
|
|
+ int wid = iconTexture->GetWidth();
|
|
+ int hi = iconTexture->GetHeight();
|
|
|
|
if (depth>=24)
|
|
- numNewBufBytes = (4 * (iconTexture.GetWidth() * iconTexture.GetHeight()));
|
|
+ numNewBufBytes = (4 * (iconTexture->GetWidth() * iconTexture->GetHeight()));
|
|
else
|
|
- numNewBufBytes = (2 * (iconTexture.GetWidth() * iconTexture.GetHeight()));
|
|
+ numNewBufBytes = (2 * (iconTexture->GetWidth() * iconTexture->GetHeight()));
|
|
|
|
newBuf = (uint32_t*)malloc(numNewBufBytes);
|
|
if (!newBuf)
|
|
@@ -992,11 +999,11 @@ bool CWinSystemX11::CreateIconPixmap()
|
|
return false;
|
|
}
|
|
|
|
- for (i=0; i<iconTexture.GetHeight();++i)
|
|
+ for (i=0; i<iconTexture->GetHeight();++i)
|
|
{
|
|
- for (j=0; j<iconTexture.GetWidth();++j)
|
|
+ for (j=0; j<iconTexture->GetWidth();++j)
|
|
{
|
|
- unsigned int pos = i*iconTexture.GetPitch()+j*4;
|
|
+ unsigned int pos = i*iconTexture->GetPitch()+j*4;
|
|
unsigned int r, g, b;
|
|
r = (buf[pos+2] * rRatio);
|
|
g = (buf[pos+1] * gRatio);
|
|
@@ -1009,7 +1016,7 @@ bool CWinSystemX11::CreateIconPixmap()
|
|
}
|
|
}
|
|
img = XCreateImage(m_dpy, vis, depth,ZPixmap, 0, (char *)newBuf,
|
|
- iconTexture.GetWidth(), iconTexture.GetHeight(),
|
|
+ iconTexture->GetWidth(), iconTexture->GetHeight(),
|
|
(depth>=24)?32:16, 0);
|
|
if (!img)
|
|
{
|
|
@@ -1047,6 +1054,8 @@ bool CWinSystemX11::CreateIconPixmap()
|
|
XFreeGC(m_dpy, gc);
|
|
XDestroyImage(img); // this also frees newBuf
|
|
|
|
+ delete iconTexture;
|
|
+
|
|
return true;
|
|
}
|
|
|
|
--
|
|
1.7.10
|
|
|
|
|
|
From 111c2f8fd0f6b698fbff0fda6dc6c17ce3644626 Mon Sep 17 00:00:00 2001
|
|
From: xbmc <fernetmenta@online.de>
|
|
Date: Tue, 10 Jul 2012 11:14:12 +0200
|
|
Subject: [PATCH 37/72] X11: check for window manager
|
|
|
|
---
|
|
xbmc/windowing/X11/WinSystemX11.cpp | 74 ++++++++++++++++++++++++++++++++++-
|
|
xbmc/windowing/X11/WinSystemX11.h | 1 +
|
|
2 files changed, 73 insertions(+), 2 deletions(-)
|
|
|
|
diff --git a/xbmc/windowing/X11/WinSystemX11.cpp b/xbmc/windowing/X11/WinSystemX11.cpp
|
|
index 174ccef..4f1ae26 100644
|
|
--- a/xbmc/windowing/X11/WinSystemX11.cpp
|
|
+++ b/xbmc/windowing/X11/WinSystemX11.cpp
|
|
@@ -816,8 +816,10 @@ bool CWinSystemX11::SetWindow(int width, int height, bool fullscreen, const CStd
|
|
vi = glXChooseVisual(m_dpy, m_nScreen, att);
|
|
cmap = XCreateColormap(m_dpy, RootWindow(m_dpy, vi->screen), vi->visual, AllocNone);
|
|
|
|
+ bool hasWM = HasWindowManager();
|
|
+
|
|
int def_vis = (vi->visual == DefaultVisual(m_dpy, vi->screen));
|
|
- swa.override_redirect = False;
|
|
+ swa.override_redirect = hasWM ? False : True;
|
|
swa.border_pixel = fullscreen ? 0 : 5;
|
|
swa.background_pixel = def_vis ? BlackPixel(m_dpy, vi->screen) : 0;
|
|
swa.colormap = cmap;
|
|
@@ -833,7 +835,7 @@ bool CWinSystemX11::SetWindow(int width, int height, bool fullscreen, const CStd
|
|
InputOutput, vi->visual,
|
|
mask, &swa);
|
|
|
|
- if (fullscreen)
|
|
+ if (fullscreen && hasWM)
|
|
{
|
|
Atom fs = XInternAtom(m_dpy, "_NET_WM_STATE_FULLSCREEN", True);
|
|
XChangeProperty(m_dpy, m_glWindow, XInternAtom(m_dpy, "_NET_WM_STATE", True), XA_ATOM, 32, PropModeReplace, (unsigned char *) &fs, 1);
|
|
@@ -1059,4 +1061,72 @@ bool CWinSystemX11::CreateIconPixmap()
|
|
return true;
|
|
}
|
|
|
|
+bool CWinSystemX11::HasWindowManager()
|
|
+{
|
|
+ Window wm_check;
|
|
+ unsigned char *data;
|
|
+ int status, real_format;
|
|
+ Atom real_type, prop;
|
|
+ unsigned long items_read, items_left, i;
|
|
+ char req = 0;
|
|
+
|
|
+ prop = XInternAtom(m_dpy, "_NET_SUPPORTING_WM_CHECK", True);
|
|
+ if (prop == None)
|
|
+ return false;
|
|
+ status = XGetWindowProperty(m_dpy, DefaultRootWindow(m_dpy), prop,
|
|
+ 0L, 1L, False, XA_WINDOW, &real_type, &real_format,
|
|
+ &items_read, &items_left, &data);
|
|
+ if(status != Success || ! items_read)
|
|
+ {
|
|
+ if(status == Success)
|
|
+ XFree(data);
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ wm_check = ((Window*)data)[0];
|
|
+ XFree(data);
|
|
+
|
|
+ status = XGetWindowProperty(m_dpy, wm_check, prop,
|
|
+ 0L, 1L, False, XA_WINDOW, &real_type, &real_format,
|
|
+ &items_read, &items_left, &data);
|
|
+
|
|
+ if(status != Success || !items_read)
|
|
+ {
|
|
+ if(status == Success)
|
|
+ XFree(data);
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ if(wm_check != ((Window*)data)[0])
|
|
+ {
|
|
+ XFree(data);
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ XFree(data);
|
|
+
|
|
+ prop = XInternAtom(m_dpy, "_NET_WM_NAME", True);
|
|
+ if (prop == None)
|
|
+ {
|
|
+ CLog::Log(LOGDEBUG,"Window Manager Name: ");
|
|
+ return true;
|
|
+ }
|
|
+
|
|
+ status = XGetWindowProperty(m_dpy, wm_check, prop,
|
|
+ 0L, (~0L), False, AnyPropertyType, &real_type, &real_format,
|
|
+ &items_read, &items_left, &data);
|
|
+
|
|
+ if(status == Success && items_read)
|
|
+ {
|
|
+ CLog::Log(LOGDEBUG,"Window Manager Name: %s", data);
|
|
+ }
|
|
+ else
|
|
+ CLog::Log(LOGDEBUG,"Window Manager Name: ");
|
|
+
|
|
+ if(status == Success)
|
|
+ XFree(data);
|
|
+
|
|
+ return true;
|
|
+}
|
|
+
|
|
#endif
|
|
diff --git a/xbmc/windowing/X11/WinSystemX11.h b/xbmc/windowing/X11/WinSystemX11.h
|
|
index e953d2d..0b7c10a 100644
|
|
--- a/xbmc/windowing/X11/WinSystemX11.h
|
|
+++ b/xbmc/windowing/X11/WinSystemX11.h
|
|
@@ -101,6 +101,7 @@ class CWinSystemX11 : public CWinSystemBase
|
|
bool IsSuitableVisual(XVisualInfo *vInfo);
|
|
static int XErrorHandler(Display* dpy, XErrorEvent* error);
|
|
bool CreateIconPixmap();
|
|
+ bool HasWindowManager();
|
|
|
|
CStopWatch m_screensaverReset;
|
|
};
|
|
--
|
|
1.7.10
|
|
|
|
|
|
From f1051e1991e5ef5d83ce428b841ac365082042ec Mon Sep 17 00:00:00 2001
|
|
From: xbmc <fernetmenta@online.de>
|
|
Date: Thu, 12 Jul 2012 11:11:47 +0200
|
|
Subject: [PATCH 38/72] X11: dont set window on xrandr if no mode available
|
|
|
|
---
|
|
xbmc/windowing/X11/WinSystemX11.cpp | 11 ++++++-----
|
|
1 file changed, 6 insertions(+), 5 deletions(-)
|
|
|
|
diff --git a/xbmc/windowing/X11/WinSystemX11.cpp b/xbmc/windowing/X11/WinSystemX11.cpp
|
|
index 4f1ae26..c11ea89 100644
|
|
--- a/xbmc/windowing/X11/WinSystemX11.cpp
|
|
+++ b/xbmc/windowing/X11/WinSystemX11.cpp
|
|
@@ -665,16 +665,17 @@ void CWinSystemX11::NotifyXRREvent()
|
|
CLog::Log(LOGDEBUG, "%s - notify display reset event", __FUNCTION__);
|
|
m_windowDirty = true;
|
|
|
|
+ if (!g_xrandr.Query(true))
|
|
+ {
|
|
+ CLog::Log(LOGERROR, "WinSystemX11::RefreshWindow - failed to query xrandr");
|
|
+ return;
|
|
+ }
|
|
+
|
|
// if external event update resolutions
|
|
if (!m_bIsInternalXrr)
|
|
{
|
|
UpdateResolutions();
|
|
}
|
|
- else if (!g_xrandr.Query(true))
|
|
- {
|
|
- CLog::Log(LOGERROR, "WinSystemX11::RefreshWindow - failed to query xrandr");
|
|
- return;
|
|
- }
|
|
m_bIsInternalXrr = false;
|
|
|
|
CStdString currentOutput = g_guiSettings.GetString("videoscreen.monitor");
|
|
--
|
|
1.7.10
|
|
|
|
|
|
From 83b9c33e88077d957884ee22316c218e570dc3d5 Mon Sep 17 00:00:00 2001
|
|
From: xbmc <fernetmenta@online.de>
|
|
Date: Thu, 26 Jul 2012 09:34:28 +0200
|
|
Subject: [PATCH 39/72] X11: fix crash after a resolution change on startup
|
|
|
|
---
|
|
xbmc/windowing/X11/WinSystemX11.cpp | 3 ++-
|
|
1 file changed, 2 insertions(+), 1 deletion(-)
|
|
|
|
diff --git a/xbmc/windowing/X11/WinSystemX11.cpp b/xbmc/windowing/X11/WinSystemX11.cpp
|
|
index c11ea89..0bd72d4 100644
|
|
--- a/xbmc/windowing/X11/WinSystemX11.cpp
|
|
+++ b/xbmc/windowing/X11/WinSystemX11.cpp
|
|
@@ -219,7 +219,8 @@ bool CWinSystemX11::SetFullScreen(bool fullScreen, RESOLUTION_INFO& res, bool bl
|
|
OnLostDevice();
|
|
m_bIsInternalXrr = true;
|
|
g_xrandr.SetMode(out, mode);
|
|
- return true;
|
|
+ if (m_glWindow)
|
|
+ return true;
|
|
}
|
|
#endif
|
|
|
|
--
|
|
1.7.10
|
|
|
|
|
|
From b8956ed57f1b683ae79d7306c7461a31c894e9a9 Mon Sep 17 00:00:00 2001
|
|
From: xbmc <fernetmenta@online.de>
|
|
Date: Sat, 15 Sep 2012 18:27:29 +0200
|
|
Subject: [PATCH 40/72] X11: lock graphics context in NotifyXRREvent
|
|
|
|
---
|
|
xbmc/windowing/X11/WinSystemX11.cpp | 2 ++
|
|
1 file changed, 2 insertions(+)
|
|
|
|
diff --git a/xbmc/windowing/X11/WinSystemX11.cpp b/xbmc/windowing/X11/WinSystemX11.cpp
|
|
index 0bd72d4..ef83133 100644
|
|
--- a/xbmc/windowing/X11/WinSystemX11.cpp
|
|
+++ b/xbmc/windowing/X11/WinSystemX11.cpp
|
|
@@ -666,6 +666,8 @@ void CWinSystemX11::NotifyXRREvent()
|
|
CLog::Log(LOGDEBUG, "%s - notify display reset event", __FUNCTION__);
|
|
m_windowDirty = true;
|
|
|
|
+ CSingleLock lock(g_graphicsContext);
|
|
+
|
|
if (!g_xrandr.Query(true))
|
|
{
|
|
CLog::Log(LOGERROR, "WinSystemX11::RefreshWindow - failed to query xrandr");
|
|
--
|
|
1.7.10
|
|
|
|
|
|
From aed5d244b81b1a0b171b7fea3b332decafc96c56 Mon Sep 17 00:00:00 2001
|
|
From: Rainer Hochecker <fernetmenta@online.de>
|
|
Date: Sat, 8 Oct 2011 16:45:13 +0200
|
|
Subject: [PATCH 41/72] ffmpeg: add xvba hwaccel
|
|
|
|
---
|
|
lib/ffmpeg/configure | 8 ++
|
|
lib/ffmpeg/libavcodec/Makefile | 7 +-
|
|
lib/ffmpeg/libavcodec/allcodecs.c | 4 +
|
|
lib/ffmpeg/libavcodec/h264.c | 1 +
|
|
lib/ffmpeg/libavcodec/mpegvideo.c | 1 +
|
|
lib/ffmpeg/libavcodec/xvba.c | 66 ++++++++++++
|
|
lib/ffmpeg/libavcodec/xvba.h | 71 ++++++++++++
|
|
lib/ffmpeg/libavcodec/xvba_h264.c | 189 ++++++++++++++++++++++++++++++++
|
|
lib/ffmpeg/libavcodec/xvba_internal.h | 24 +++++
|
|
lib/ffmpeg/libavcodec/xvba_mpeg2.c | 52 +++++++++
|
|
lib/ffmpeg/libavcodec/xvba_vc1.c | 190 +++++++++++++++++++++++++++++++++
|
|
lib/ffmpeg/libavcodec/xvmc_internal.h | 4 +-
|
|
lib/ffmpeg/libavutil/pixdesc.c | 6 ++
|
|
lib/ffmpeg/libavutil/pixfmt.h | 1 +
|
|
14 files changed, 622 insertions(+), 2 deletions(-)
|
|
create mode 100644 lib/ffmpeg/libavcodec/xvba.c
|
|
create mode 100644 lib/ffmpeg/libavcodec/xvba.h
|
|
create mode 100644 lib/ffmpeg/libavcodec/xvba_h264.c
|
|
create mode 100644 lib/ffmpeg/libavcodec/xvba_internal.h
|
|
create mode 100644 lib/ffmpeg/libavcodec/xvba_mpeg2.c
|
|
create mode 100644 lib/ffmpeg/libavcodec/xvba_vc1.c
|
|
|
|
diff --git a/lib/ffmpeg/configure b/lib/ffmpeg/configure
|
|
index c06005b..157cfd3 100755
|
|
--- a/lib/ffmpeg/configure
|
|
+++ b/lib/ffmpeg/configure
|
|
@@ -113,6 +113,7 @@ Configuration options:
|
|
--enable-vdpau enable VDPAU code [autodetect]
|
|
--disable-dxva2 disable DXVA2 code
|
|
--disable-vda disable VDA code
|
|
+ --disable-xvba disable XVBA code
|
|
--enable-runtime-cpudetect detect cpu capabilities at runtime (bigger binary)
|
|
--enable-hardcoded-tables use hardcoded tables instead of runtime generation
|
|
--disable-safe-bitstream-reader
|
|
@@ -1084,6 +1085,7 @@ CONFIG_LIST="
|
|
vaapi
|
|
vda
|
|
vdpau
|
|
+ xvba
|
|
version3
|
|
x11grab
|
|
zlib
|
|
@@ -1423,6 +1425,7 @@ h264_dxva2_hwaccel_select="dxva2 h264_decoder"
|
|
h264_vaapi_hwaccel_select="vaapi h264_decoder"
|
|
h264_vda_hwaccel_deps="VideoDecodeAcceleration_VDADecoder_h pthreads"
|
|
h264_vda_hwaccel_select="vda h264_decoder"
|
|
+h264_xvba_hwaccel_select="xvba h264_decoder"
|
|
h264_vdpau_decoder_select="vdpau h264_decoder"
|
|
imc_decoder_select="fft mdct sinewin"
|
|
jpegls_decoder_select="golomb"
|
|
@@ -1459,6 +1462,7 @@ mpeg4_crystalhd_decoder_select="crystalhd"
|
|
mpeg4_decoder_select="h263_decoder mpeg4video_parser"
|
|
mpeg4_encoder_select="h263_encoder"
|
|
mpeg4_vaapi_hwaccel_select="vaapi mpeg4_decoder"
|
|
+mpeg2_xvba_hwaccel_select="xvba mpeg2video_decoder"
|
|
mpeg4_vdpau_decoder_select="vdpau mpeg4_decoder"
|
|
msmpeg4_crystalhd_decoder_select="crystalhd"
|
|
msmpeg4v1_decoder_select="h263_decoder"
|
|
@@ -1501,6 +1505,7 @@ vc1_decoder_select="h263_decoder h264chroma"
|
|
vc1_dxva2_hwaccel_deps="dxva2api_h"
|
|
vc1_dxva2_hwaccel_select="dxva2 vc1_decoder"
|
|
vc1_vaapi_hwaccel_select="vaapi vc1_decoder"
|
|
+vc1_xvba_hwaccel_select="xvba vc1_decoder"
|
|
vc1_vdpau_decoder_select="vdpau vc1_decoder"
|
|
vc1image_decoder_select="vc1_decoder"
|
|
vorbis_decoder_select="mdct"
|
|
@@ -1525,6 +1530,7 @@ wmv3_dxva2_hwaccel_select="vc1_dxva2_hwaccel"
|
|
wmv3_vaapi_hwaccel_select="vc1_vaapi_hwaccel"
|
|
wmv3_vdpau_decoder_select="vc1_vdpau_decoder"
|
|
wmv3image_decoder_select="wmv3_decoder"
|
|
+wmv3_xvba_hwaccel_select="vc1_xvba_hwaccel"
|
|
zlib_decoder_select="zlib"
|
|
zlib_encoder_select="zlib"
|
|
zmbv_decoder_select="zlib"
|
|
@@ -1533,6 +1539,7 @@ zmbv_encoder_select="zlib"
|
|
crystalhd_deps="libcrystalhd_libcrystalhd_if_h"
|
|
vaapi_deps="va_va_h"
|
|
vda_deps="VideoDecodeAcceleration_VDADecoder_h pthreads"
|
|
+xvba_deps="amd_amdxvba_h"
|
|
vdpau_deps="vdpau_vdpau_h vdpau_vdpau_x11_h"
|
|
|
|
# parsers
|
|
@@ -3062,6 +3069,7 @@ check_header sys/select.h
|
|
check_header termios.h
|
|
check_header vdpau/vdpau.h
|
|
check_header vdpau/vdpau_x11.h
|
|
+check_header amd/amdxvba.h
|
|
check_cpp_condition vdpau/vdpau.h "defined(VDP_DECODER_PROFILE_MPEG4_PART2_SP)" && enable vdpau_mpeg4_support
|
|
|
|
check_header X11/extensions/XvMClib.h
|
|
diff --git a/lib/ffmpeg/libavcodec/Makefile b/lib/ffmpeg/libavcodec/Makefile
|
|
index 972cc59..fc441bf 100644
|
|
--- a/lib/ffmpeg/libavcodec/Makefile
|
|
+++ b/lib/ffmpeg/libavcodec/Makefile
|
|
@@ -3,7 +3,7 @@ include $(SUBDIR)../config.mak
|
|
NAME = avcodec
|
|
FFLIBS = avutil
|
|
|
|
-HEADERS = avcodec.h avfft.h dxva2.h opt.h vaapi.h vda.h vdpau.h version.h xvmc.h
|
|
+HEADERS = avcodec.h avfft.h dxva2.h opt.h vaapi.h vda.h vdpau.h version.h xvmc.h xvba.h
|
|
|
|
OBJS = allcodecs.o \
|
|
audioconvert.o \
|
|
@@ -51,6 +51,7 @@ OBJS-$(CONFIG_SINEWIN) += sinewin.o
|
|
OBJS-$(CONFIG_VAAPI) += vaapi.o
|
|
OBJS-$(CONFIG_VDA) += vda.o
|
|
OBJS-$(CONFIG_VDPAU) += vdpau.o
|
|
+OBJS-$(CONFIG_XVBA) += xvba.o
|
|
|
|
# decoders/encoders/hardware accelerators
|
|
OBJS-$(CONFIG_A64MULTI_ENCODER) += a64multienc.o elbg.o
|
|
@@ -201,6 +202,7 @@ OBJS-$(CONFIG_H264_DECODER) += h264.o \
|
|
OBJS-$(CONFIG_H264_DXVA2_HWACCEL) += dxva2_h264.o
|
|
OBJS-$(CONFIG_H264_VAAPI_HWACCEL) += vaapi_h264.o
|
|
OBJS-$(CONFIG_H264_VDA_HWACCEL) += vda_h264.o
|
|
+OBJS-$(CONFIG_H264_XVBA_HWACCEL) += xvba_h264.o
|
|
OBJS-$(CONFIG_HUFFYUV_DECODER) += huffyuv.o
|
|
OBJS-$(CONFIG_HUFFYUV_ENCODER) += huffyuv.o
|
|
OBJS-$(CONFIG_IDCIN_DECODER) += idcinvideo.o
|
|
@@ -284,6 +286,7 @@ OBJS-$(CONFIG_MPEG1VIDEO_ENCODER) += mpeg12enc.o mpegvideo_enc.o \
|
|
mpegvideo.o error_resilience.o
|
|
OBJS-$(CONFIG_MPEG2_DXVA2_HWACCEL) += dxva2_mpeg2.o
|
|
OBJS-$(CONFIG_MPEG2_VAAPI_HWACCEL) += vaapi_mpeg2.o
|
|
+OBJS-$(CONFIG_MPEG2_XVBA_HWACCEL) += xvba_mpeg2.o
|
|
OBJS-$(CONFIG_MPEG2VIDEO_DECODER) += mpeg12.o mpeg12data.o \
|
|
mpegvideo.o error_resilience.o
|
|
OBJS-$(CONFIG_MPEG2VIDEO_ENCODER) += mpeg12enc.o mpegvideo_enc.o \
|
|
@@ -431,6 +434,7 @@ OBJS-$(CONFIG_VC1_DECODER) += vc1dec.o vc1.o vc1data.o vc1dsp.o \
|
|
intrax8.o intrax8dsp.o
|
|
OBJS-$(CONFIG_VC1_DXVA2_HWACCEL) += dxva2_vc1.o
|
|
OBJS-$(CONFIG_VC1_VAAPI_HWACCEL) += vaapi_vc1.o
|
|
+OBJS-$(CONFIG_VC1_XVBA_HWACCEL) += xvba_vc1.o
|
|
OBJS-$(CONFIG_VCR1_DECODER) += vcr1.o
|
|
OBJS-$(CONFIG_VCR1_ENCODER) += vcr1.o
|
|
OBJS-$(CONFIG_VMDAUDIO_DECODER) += vmdav.o
|
|
@@ -732,6 +736,7 @@ SKIPHEADERS-$(CONFIG_LIBDIRAC) += libdirac.h
|
|
SKIPHEADERS-$(CONFIG_LIBSCHROEDINGER) += libschroedinger.h
|
|
SKIPHEADERS-$(CONFIG_VAAPI) += vaapi_internal.h
|
|
SKIPHEADERS-$(CONFIG_VDA) += vda_internal.h
|
|
+SKIPHEADERS-$(CONFIG_XVBA) += xvba_internal.h
|
|
SKIPHEADERS-$(CONFIG_VDPAU) += vdpau.h
|
|
SKIPHEADERS-$(CONFIG_XVMC) += xvmc.h
|
|
SKIPHEADERS-$(HAVE_W32THREADS) += w32pthreads.h
|
|
diff --git a/lib/ffmpeg/libavcodec/allcodecs.c b/lib/ffmpeg/libavcodec/allcodecs.c
|
|
index 32f3f52..0ff178e 100644
|
|
--- a/lib/ffmpeg/libavcodec/allcodecs.c
|
|
+++ b/lib/ffmpeg/libavcodec/allcodecs.c
|
|
@@ -59,14 +59,18 @@ void avcodec_register_all(void)
|
|
REGISTER_HWACCEL (H264_VAAPI, h264_vaapi);
|
|
REGISTER_HWACCEL (H264_VDA, h264_vda);
|
|
REGISTER_HWACCEL (MPEG1_VDPAU, mpeg1_vdpau);
|
|
+ REGISTER_HWACCEL (H264_XVBA, h264_xvba);
|
|
REGISTER_HWACCEL (MPEG2_DXVA2, mpeg2_dxva2);
|
|
REGISTER_HWACCEL (MPEG2_VAAPI, mpeg2_vaapi);
|
|
REGISTER_HWACCEL (MPEG2_VDPAU, mpeg2_vdpau);
|
|
REGISTER_HWACCEL (MPEG4_VAAPI, mpeg4_vaapi);
|
|
+ REGISTER_HWACCEL (MPEG2_XVBA, mpeg2_xvba);
|
|
REGISTER_HWACCEL (VC1_DXVA2, vc1_dxva2);
|
|
REGISTER_HWACCEL (VC1_VAAPI, vc1_vaapi);
|
|
+ REGISTER_HWACCEL (VC1_XVBA, vc1_xvba);
|
|
REGISTER_HWACCEL (WMV3_DXVA2, wmv3_dxva2);
|
|
REGISTER_HWACCEL (WMV3_VAAPI, wmv3_vaapi);
|
|
+ REGISTER_HWACCEL (WMV3_XVBA, wmv3_xvba);
|
|
|
|
/* video codecs */
|
|
REGISTER_ENCODER (A64MULTI, a64multi);
|
|
diff --git a/lib/ffmpeg/libavcodec/h264.c b/lib/ffmpeg/libavcodec/h264.c
|
|
index c4785db..e9e7546 100644
|
|
--- a/lib/ffmpeg/libavcodec/h264.c
|
|
+++ b/lib/ffmpeg/libavcodec/h264.c
|
|
@@ -60,6 +60,7 @@
|
|
PIX_FMT_DXVA2_VLD,
|
|
PIX_FMT_VAAPI_VLD,
|
|
PIX_FMT_VDA_VLD,
|
|
+ PIX_FMT_XVBA_VLD,
|
|
PIX_FMT_YUVJ420P,
|
|
PIX_FMT_NONE
|
|
};
|
|
diff --git a/lib/ffmpeg/libavcodec/mpegvideo.c b/lib/ffmpeg/libavcodec/mpegvideo.c
|
|
index 04c149a..b22b631 100644
|
|
--- a/lib/ffmpeg/libavcodec/mpegvideo.c
|
|
+++ b/lib/ffmpeg/libavcodec/mpegvideo.c
|
|
@@ -136,6 +136,7 @@ static void dct_unquantize_h263_inter_c(MpegEncContext *s,
|
|
PIX_FMT_DXVA2_VLD,
|
|
PIX_FMT_VAAPI_VLD,
|
|
PIX_FMT_VDA_VLD,
|
|
+ PIX_FMT_XVBA_VLD,
|
|
PIX_FMT_YUV420P,
|
|
PIX_FMT_NONE
|
|
};
|
|
diff --git a/lib/ffmpeg/libavcodec/xvba.c b/lib/ffmpeg/libavcodec/xvba.c
|
|
new file mode 100644
|
|
index 0000000..be29e5d
|
|
--- /dev/null
|
|
+++ b/lib/ffmpeg/libavcodec/xvba.c
|
|
@@ -0,0 +1,66 @@
|
|
+/*
|
|
+ * HW decode acceleration for MPEG-2, H.264 and VC-1
|
|
+ *
|
|
+ * Copyright (C) 2005-2011 Team XBMC
|
|
+ *
|
|
+ * This file is part of FFmpeg.
|
|
+ *
|
|
+ * FFmpeg is free software; you can redistribute it and/or
|
|
+ * modify it under the terms of the GNU Lesser General Public
|
|
+ * License as published by the Free Software Foundation; either
|
|
+ * version 2.1 of the License, or (at your option) any later version.
|
|
+ *
|
|
+ * FFmpeg is distributed in the hope that it will be useful,
|
|
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ * Lesser General Public License for more details.
|
|
+ *
|
|
+ * You should have received a copy of the GNU Lesser General Public
|
|
+ * License along with FFmpeg; if not, write to the Free Software
|
|
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
+ */
|
|
+
|
|
+
|
|
+/**
|
|
+ * \addtogroup XVBA_Decoding
|
|
+ *
|
|
+ * @{
|
|
+ */
|
|
+
|
|
+#include <stdint.h>
|
|
+#include "xvba.h"
|
|
+#include "xvba_internal.h"
|
|
+#include "avcodec.h"
|
|
+
|
|
+int ff_xvba_translate_profile(int profile) {
|
|
+
|
|
+ if (profile == 66)
|
|
+ return 1;
|
|
+ else if (profile == 77)
|
|
+ return 2;
|
|
+ else if (profile == 100)
|
|
+ return 3;
|
|
+ else if (profile == 0)
|
|
+ return 4;
|
|
+ else if (profile == 1)
|
|
+ return 5;
|
|
+ else if (profile == 3)
|
|
+ return 6;
|
|
+ else
|
|
+ return -1;
|
|
+}
|
|
+
|
|
+void ff_xvba_add_slice_data(struct xvba_render_state *render, const uint8_t *buffer, uint32_t size) {
|
|
+
|
|
+ render->buffers = av_fast_realloc(
|
|
+ render->buffers,
|
|
+ &render->buffers_alllocated,
|
|
+ sizeof(struct xvba_bitstream_buffers)*(render->num_slices + 1)
|
|
+ );
|
|
+
|
|
+ render->buffers[render->num_slices].buffer = buffer;
|
|
+ render->buffers[render->num_slices].size = size;
|
|
+
|
|
+ render->num_slices++;
|
|
+}
|
|
+
|
|
diff --git a/lib/ffmpeg/libavcodec/xvba.h b/lib/ffmpeg/libavcodec/xvba.h
|
|
new file mode 100644
|
|
index 0000000..9f9ff0c
|
|
--- /dev/null
|
|
+++ b/lib/ffmpeg/libavcodec/xvba.h
|
|
@@ -0,0 +1,71 @@
|
|
+/*
|
|
+ * HW decode acceleration for MPEG-2, H.264 and VC-1
|
|
+ *
|
|
+ * Copyright (C) 2005-2011 Team XBMC
|
|
+ *
|
|
+ * This file is part of FFmpeg.
|
|
+ *
|
|
+ * FFmpeg is free software; you can redistribute it and/or
|
|
+ * modify it under the terms of the GNU Lesser General Public
|
|
+ * License as published by the Free Software Foundation; either
|
|
+ * version 2.1 of the License, or (at your option) any later version.
|
|
+ *
|
|
+ * FFmpeg is distributed in the hope that it will be useful,
|
|
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ * Lesser General Public License for more details.
|
|
+ *
|
|
+ * You should have received a copy of the GNU Lesser General Public
|
|
+ * License along with FFmpeg; if not, write to the Free Software
|
|
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
+ */
|
|
+
|
|
+#ifndef AVCODEC_XVBA_H
|
|
+#define AVCODEC_XVBA_H
|
|
+
|
|
+#include <stdint.h>
|
|
+#include <X11/Xlib.h>
|
|
+#include <amd/amdxvba.h>
|
|
+
|
|
+
|
|
+/**
|
|
+ * \defgroup XVBA_Decoding VA API Decoding
|
|
+ * \ingroup Decoder
|
|
+ * @{
|
|
+ */
|
|
+
|
|
+/** \brief The videoSurface is used for rendering. */
|
|
+#define FF_XVBA_STATE_USED_FOR_RENDER 1
|
|
+
|
|
+/**
|
|
+ * \brief The videoSurface is needed for reference/prediction.
|
|
+ * The codec manipulates this.
|
|
+ */
|
|
+#define FF_XVBA_STATE_USED_FOR_REFERENCE 2
|
|
+
|
|
+/**
|
|
+ * \brief The videoSurface holds a decoded frame.
|
|
+ * The codec manipulates this.
|
|
+ */
|
|
+#define FF_XVBA_STATE_DECODED 4
|
|
+
|
|
+/* @} */
|
|
+
|
|
+struct xvba_bitstream_buffers
|
|
+{
|
|
+ const void *buffer;
|
|
+ unsigned int size;
|
|
+};
|
|
+
|
|
+struct xvba_render_state {
|
|
+
|
|
+ int state; ///< Holds FF_XVBA_STATE_* values.
|
|
+ void *surface;
|
|
+ XVBAPictureDescriptor *picture_descriptor;
|
|
+ XVBAQuantMatrixAvc *iq_matrix;
|
|
+ unsigned int num_slices;
|
|
+ struct xvba_bitstream_buffers *buffers;
|
|
+ uint32_t buffers_alllocated;
|
|
+};
|
|
+
|
|
+#endif /* AVCODEC_XVBA_H */
|
|
diff --git a/lib/ffmpeg/libavcodec/xvba_h264.c b/lib/ffmpeg/libavcodec/xvba_h264.c
|
|
new file mode 100644
|
|
index 0000000..a077442
|
|
--- /dev/null
|
|
+++ b/lib/ffmpeg/libavcodec/xvba_h264.c
|
|
@@ -0,0 +1,189 @@
|
|
+/*
|
|
+ * H.264 HW decode acceleration through XVBA
|
|
+ *
|
|
+ * Copyright (C) 2005-2011 Team XBMC
|
|
+ *
|
|
+ * This file is part of FFmpeg.
|
|
+ *
|
|
+ * FFmpeg is free software; you can redistribute it and/or
|
|
+ * modify it under the terms of the GNU Lesser General Public
|
|
+ * License as published by the Free Software Foundation; either
|
|
+ * version 2.1 of the License, or (at your option) any later version.
|
|
+ *
|
|
+ * FFmpeg is distributed in the hope that it will be useful,
|
|
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ * Lesser General Public License for more details.
|
|
+ *
|
|
+ * You should have received a copy of the GNU Lesser General Public
|
|
+ * License along with FFmpeg; if not, write to the Free Software
|
|
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
+ */
|
|
+
|
|
+#include "xvba.h"
|
|
+#include "xvba_internal.h"
|
|
+#include "h264.h"
|
|
+#include <assert.h>
|
|
+
|
|
+/** @file
|
|
+ * This file implements the glue code between FFmpeg's and XvBA API's
|
|
+ * structures for H.264 decoding.
|
|
+ */
|
|
+
|
|
+
|
|
+/** Initialize and start decoding a frame with XVBA. */
|
|
+static int start_frame(AVCodecContext *avctx,
|
|
+ av_unused const uint8_t *buffer,
|
|
+ av_unused uint32_t size)
|
|
+{
|
|
+ H264Context * const h = avctx->priv_data;
|
|
+ MpegEncContext * const s = &h->s;
|
|
+ struct xvba_render_state *render;
|
|
+ XVBAPictureDescriptor *pic_descriptor;
|
|
+ int i;
|
|
+
|
|
+ render = (struct xvba_render_state *)s->current_picture_ptr->f.data[0];
|
|
+ assert(render);
|
|
+
|
|
+ if (render->picture_descriptor == 0)
|
|
+ return -1;
|
|
+
|
|
+ pic_descriptor = render->picture_descriptor;
|
|
+
|
|
+ for (i = 0; i < 2; ++i) {
|
|
+ int foc = s->current_picture_ptr->field_poc[i];
|
|
+ if (foc == INT_MAX)
|
|
+ foc = 0;
|
|
+ pic_descriptor->avc_curr_field_order_cnt_list[i] = foc;
|
|
+ }
|
|
+
|
|
+ pic_descriptor->avc_frame_num = h->frame_num;
|
|
+
|
|
+ render->num_slices = 0;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+/** End a hardware decoding based frame. */
|
|
+static int end_frame(AVCodecContext *avctx)
|
|
+{
|
|
+ H264Context * const h = avctx->priv_data;
|
|
+ MpegEncContext * const s = &h->s;
|
|
+ struct xvba_render_state *render;
|
|
+ XVBAPictureDescriptor *pic_descriptor;
|
|
+ XVBAQuantMatrixAvc *iq_matrix;
|
|
+
|
|
+ render = (struct xvba_render_state *)s->current_picture_ptr->f.data[0];
|
|
+ assert(render);
|
|
+
|
|
+ if (render->picture_descriptor == 0 || render->iq_matrix == 0)
|
|
+ return -1;
|
|
+
|
|
+ pic_descriptor = render->picture_descriptor;
|
|
+ iq_matrix = render->iq_matrix;
|
|
+
|
|
+ av_dlog(avctx, "end_frame()\n");
|
|
+
|
|
+ /* Fill in Picture Parameters*/
|
|
+ pic_descriptor->profile = ff_xvba_translate_profile(avctx->profile);
|
|
+ pic_descriptor->level = avctx->level;
|
|
+ pic_descriptor->width_in_mb = s->mb_width;
|
|
+ pic_descriptor->height_in_mb = s->mb_height;
|
|
+ pic_descriptor->picture_structure = s->picture_structure;
|
|
+ pic_descriptor->chroma_format = s->chroma_format ? s->chroma_format : 1;
|
|
+ pic_descriptor->avc_intra_flag = (h->slice_type == AV_PICTURE_TYPE_I) ? 1 : 0;
|
|
+ pic_descriptor->avc_reference = (s->current_picture_ptr->f.reference & 3) ? 1 : 0;
|
|
+
|
|
+ pic_descriptor->avc_bit_depth_luma_minus8 = h->sps.bit_depth_luma - 8;
|
|
+ pic_descriptor->avc_bit_depth_chroma_minus8 = h->sps.bit_depth_chroma - 8;
|
|
+ pic_descriptor->avc_log2_max_frame_num_minus4 = h->sps.log2_max_frame_num -4;
|
|
+ pic_descriptor->avc_pic_order_cnt_type = h->sps.poc_type;
|
|
+ pic_descriptor->avc_log2_max_pic_order_cnt_lsb_minus4 = h->sps.log2_max_poc_lsb - 4;
|
|
+ pic_descriptor->avc_num_ref_frames = h->sps.ref_frame_count;
|
|
+ pic_descriptor->avc_reserved_8bit = 0;
|
|
+
|
|
+ /* Set correct level */
|
|
+ if (pic_descriptor->level == 41) {
|
|
+ const unsigned int mbw = pic_descriptor->width_in_mb;
|
|
+ const unsigned int mbh = pic_descriptor->height_in_mb;
|
|
+ const unsigned int max_ref_frames = 12288 * 1024 / (mbw * mbh * 384);
|
|
+ const unsigned int num_ref_frames = pic_descriptor->avc_num_ref_frames;
|
|
+ if (max_ref_frames < num_ref_frames)
|
|
+ pic_descriptor->level = 51;
|
|
+ }
|
|
+
|
|
+ pic_descriptor->avc_num_slice_groups_minus1 = h->pps.slice_group_count - 1;
|
|
+ pic_descriptor->avc_num_ref_idx_l0_active_minus1 = h->pps.ref_count[0] - 1;
|
|
+ pic_descriptor->avc_num_ref_idx_l1_active_minus1 = h->pps.ref_count[1] - 1;
|
|
+
|
|
+ pic_descriptor->avc_pic_init_qp_minus26 = h->pps.init_qp - 26;
|
|
+ pic_descriptor->avc_pic_init_qs_minus26 = h->pps.init_qs - 26;
|
|
+ pic_descriptor->avc_chroma_qp_index_offset = h->pps.chroma_qp_index_offset[0];
|
|
+ pic_descriptor->avc_second_chroma_qp_index_offset = h->pps.chroma_qp_index_offset[1];
|
|
+ pic_descriptor->avc_slice_group_change_rate_minus1 = 0; // not implemented in ffmpeg
|
|
+ pic_descriptor->avc_reserved_16bit = 0; // must be 0
|
|
+ memset(pic_descriptor->avc_field_order_cnt_list,0,sizeof(pic_descriptor->avc_field_order_cnt_list)); // must be 0
|
|
+ memset(pic_descriptor->avc_slice_group_map,0,sizeof(pic_descriptor->avc_slice_group_map)); // must be 0
|
|
+
|
|
+ // sps
|
|
+ pic_descriptor->sps_info.avc.delta_pic_always_zero_flag = h->sps.delta_pic_order_always_zero_flag;
|
|
+ pic_descriptor->sps_info.avc.direct_8x8_inference_flag = h->sps.direct_8x8_inference_flag;
|
|
+ pic_descriptor->sps_info.avc.frame_mbs_only_flag = h->sps.frame_mbs_only_flag;
|
|
+ pic_descriptor->sps_info.avc.gaps_in_frame_num_value_allowed_flag = h->sps.gaps_in_frame_num_allowed_flag;
|
|
+ pic_descriptor->sps_info.avc.mb_adaptive_frame_field_flag = h->sps.mb_aff;
|
|
+ pic_descriptor->sps_info.avc.residual_colour_transform_flag = h->sps.residual_color_transform_flag;
|
|
+ pic_descriptor->sps_info.avc.xvba_avc_sps_reserved = 0;
|
|
+
|
|
+ // pps
|
|
+ pic_descriptor->pps_info.avc.entropy_coding_mode_flag = h->pps.cabac;
|
|
+ pic_descriptor->pps_info.avc.pic_order_present_flag = h->pps.pic_order_present;
|
|
+ pic_descriptor->pps_info.avc.weighted_pred_flag = h->pps.weighted_pred;
|
|
+ pic_descriptor->pps_info.avc.weighted_bipred_idc = h->pps.weighted_bipred_idc;
|
|
+ pic_descriptor->pps_info.avc.deblocking_filter_control_present_flag = h->pps.deblocking_filter_parameters_present;
|
|
+ pic_descriptor->pps_info.avc.constrained_intra_pred_flag = h->pps.constrained_intra_pred;
|
|
+ pic_descriptor->pps_info.avc.redundant_pic_cnt_present_flag = h->pps.redundant_pic_cnt_present;
|
|
+ pic_descriptor->pps_info.avc.transform_8x8_mode_flag = h->pps.transform_8x8_mode;
|
|
+ pic_descriptor->pps_info.avc.xvba_avc_pps_reserved = 0; // must be 0
|
|
+
|
|
+ memcpy(iq_matrix->bScalingLists4x4, h->pps.scaling_matrix4, sizeof(iq_matrix->bScalingLists4x4));
|
|
+ memcpy(iq_matrix->bScalingLists8x8[0], h->pps.scaling_matrix8[0], sizeof(iq_matrix->bScalingLists8x8[0]));
|
|
+ memcpy(iq_matrix->bScalingLists8x8[1], h->pps.scaling_matrix8[3], sizeof(iq_matrix->bScalingLists8x8[0]));
|
|
+
|
|
+ // Wait for an I-frame before start decoding. Workaround for ATI UVD and UVD+ GPUs
|
|
+ if (!h->got_first_iframe) {
|
|
+ if (h->slice_type != AV_PICTURE_TYPE_I && h->slice_type != AV_PICTURE_TYPE_SI)
|
|
+ return -1;
|
|
+ h->got_first_iframe = 1;
|
|
+ }
|
|
+
|
|
+ ff_draw_horiz_band(s, 0, s->avctx->height);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+/** Decode the given H.264 slice with XVBA. */
|
|
+static int decode_slice(AVCodecContext *avctx,
|
|
+ const uint8_t *buffer,
|
|
+ uint32_t size)
|
|
+{
|
|
+ H264Context * const h = avctx->priv_data;
|
|
+ MpegEncContext * const s = &h->s;
|
|
+ struct xvba_render_state *render;
|
|
+
|
|
+ render = (struct xvba_render_state *)s->current_picture_ptr->f.data[0];
|
|
+ assert(render);
|
|
+
|
|
+ ff_xvba_add_slice_data(render, buffer, size);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+AVHWAccel ff_h264_xvba_hwaccel = {
|
|
+ .name = "h264_xvba",
|
|
+ .type = AVMEDIA_TYPE_VIDEO,
|
|
+ .id = CODEC_ID_H264,
|
|
+ .pix_fmt = PIX_FMT_XVBA_VLD,
|
|
+ .start_frame = start_frame,
|
|
+ .end_frame = end_frame,
|
|
+ .decode_slice = decode_slice,
|
|
+};
|
|
diff --git a/lib/ffmpeg/libavcodec/xvba_internal.h b/lib/ffmpeg/libavcodec/xvba_internal.h
|
|
new file mode 100644
|
|
index 0000000..9653f85
|
|
--- /dev/null
|
|
+++ b/lib/ffmpeg/libavcodec/xvba_internal.h
|
|
@@ -0,0 +1,24 @@
|
|
+/*
|
|
+ * HW decode acceleration for MPEG-2, H.264 and VC-1
|
|
+ *
|
|
+ * Copyright (C) 2005-2011 Team XBMC
|
|
+ *
|
|
+ * This file is part of FFmpeg.
|
|
+ *
|
|
+ * FFmpeg is free software; you can redistribute it and/or
|
|
+ * modify it under the terms of the GNU Lesser General Public
|
|
+ * License as published by the Free Software Foundation; either
|
|
+ * version 2.1 of the License, or (at your option) any later version.
|
|
+ *
|
|
+ * FFmpeg is distributed in the hope that it will be useful,
|
|
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ * Lesser General Public License for more details.
|
|
+ *
|
|
+ * You should have received a copy of the GNU Lesser General Public
|
|
+ * License along with FFmpeg; if not, write to the Free Software
|
|
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
+ */
|
|
+
|
|
+int ff_xvba_translate_profile(int profile);
|
|
+void ff_xvba_add_slice_data(struct xvba_render_state *render, const uint8_t *buffer, uint32_t size);
|
|
diff --git a/lib/ffmpeg/libavcodec/xvba_mpeg2.c b/lib/ffmpeg/libavcodec/xvba_mpeg2.c
|
|
new file mode 100644
|
|
index 0000000..552ef95
|
|
--- /dev/null
|
|
+++ b/lib/ffmpeg/libavcodec/xvba_mpeg2.c
|
|
@@ -0,0 +1,52 @@
|
|
+/*
|
|
+ * MPEG-2 HW decode acceleration through XVBA
|
|
+ *
|
|
+ * Copyright (C) 2005-2011 Team XBMC
|
|
+ *
|
|
+ * This file is part of FFmpeg.
|
|
+ *
|
|
+ * FFmpeg is free software; you can redistribute it and/or
|
|
+ * modify it under the terms of the GNU Lesser General Public
|
|
+ * License as published by the Free Software Foundation; either
|
|
+ * version 2.1 of the License, or (at your option) any later version.
|
|
+ *
|
|
+ * FFmpeg is distributed in the hope that it will be useful,
|
|
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ * Lesser General Public License for more details.
|
|
+ *
|
|
+ * You should have received a copy of the GNU Lesser General Public
|
|
+ * License along with FFmpeg; if not, write to the Free Software
|
|
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
+ */
|
|
+
|
|
+#include "dsputil.h"
|
|
+
|
|
+static int start_frame(AVCodecContext *avctx, av_unused const uint8_t *buffer, av_unused uint32_t size)
|
|
+{
|
|
+ struct MpegEncContext * const s = avctx->priv_data;
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int end_frame(AVCodecContext *avctx)
|
|
+{
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int decode_slice(AVCodecContext *avctx, const uint8_t *buffer, uint32_t size)
|
|
+{
|
|
+ struct MpegEncContext * const s = avctx->priv_data;
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+AVHWAccel ff_mpeg2_xvba_hwaccel = {
|
|
+ .name = "mpeg2_xvba",
|
|
+ .type = AVMEDIA_TYPE_VIDEO,
|
|
+ .id = CODEC_ID_MPEG2VIDEO,
|
|
+ .pix_fmt = PIX_FMT_XVBA_VLD,
|
|
+ .capabilities = 0,
|
|
+ .start_frame = start_frame,
|
|
+ .end_frame = end_frame,
|
|
+ .decode_slice = decode_slice,
|
|
+ .priv_data_size = 0,
|
|
+};
|
|
diff --git a/lib/ffmpeg/libavcodec/xvba_vc1.c b/lib/ffmpeg/libavcodec/xvba_vc1.c
|
|
new file mode 100644
|
|
index 0000000..7315b62
|
|
--- /dev/null
|
|
+++ b/lib/ffmpeg/libavcodec/xvba_vc1.c
|
|
@@ -0,0 +1,190 @@
|
|
+/*
|
|
+ * VC-1 HW decode acceleration through XVBA
|
|
+ *
|
|
+ * Copyright (C) 2005-2011 Team XBMC
|
|
+ *
|
|
+ * This file is part of FFmpeg.
|
|
+ *
|
|
+ * FFmpeg is free software; you can redistribute it and/or
|
|
+ * modify it under the terms of the GNU Lesser General Public
|
|
+ * License as published by the Free Software Foundation; either
|
|
+ * version 2.1 of the License, or (at your option) any later version.
|
|
+ *
|
|
+ * FFmpeg is distributed in the hope that it will be useful,
|
|
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ * Lesser General Public License for more details.
|
|
+ *
|
|
+ * You should have received a copy of the GNU Lesser General Public
|
|
+ * License along with FFmpeg; if not, write to the Free Software
|
|
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
+ */
|
|
+
|
|
+#include "xvba.h"
|
|
+#include "xvba_internal.h"
|
|
+#include "vc1.h"
|
|
+#include "vc1data.h"
|
|
+#include <assert.h>
|
|
+
|
|
+
|
|
+/** @file
|
|
+ * Implement structures of ffmpeg <-> XvBA
|
|
+ */
|
|
+
|
|
+/* Initialize and start decoding a frame with XvBA */
|
|
+static int start_frame(AVCodecContext *avctx,
|
|
+ av_unused const uint8_t *buffer,
|
|
+ av_unused uint32_t size)
|
|
+{
|
|
+ VC1Context * const v = avctx->priv_data;
|
|
+ MpegEncContext * const s = &v->s;
|
|
+ struct xvba_render_state *render;
|
|
+
|
|
+ render = (struct xvba_render_state *)s->current_picture_ptr->f.data[0];
|
|
+ assert(render);
|
|
+
|
|
+ render->num_slices = 0;
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+/* End a hardware decoding based frame */
|
|
+static int end_frame(AVCodecContext *avctx)
|
|
+{
|
|
+ VC1Context* const v = avctx->priv_data;
|
|
+ MpegEncContext* const s = &v->s;
|
|
+ struct xvba_render_state *render, *last, *next;
|
|
+ XVBAPictureDescriptor *pic_descriptor;
|
|
+
|
|
+ render = (struct xvba_render_state *)s->current_picture_ptr->f.data[0];
|
|
+ assert(render);
|
|
+
|
|
+ if (render->picture_descriptor == 0)
|
|
+ return -1;
|
|
+
|
|
+ pic_descriptor = render->picture_descriptor;
|
|
+
|
|
+ av_dlog(avctx, "xvba_vc1_end_frame()\n");
|
|
+
|
|
+ memset(pic_descriptor, 0, sizeof(*pic_descriptor));
|
|
+
|
|
+ /* Fill in Parameters - for reference see AMD sdk documentation */
|
|
+ pic_descriptor->profile = ff_xvba_translate_profile(v->profile);
|
|
+ pic_descriptor->level = v->level;
|
|
+ //done like in va-driver and vaapi
|
|
+ if (v->profile == PROFILE_ADVANCED) {
|
|
+ pic_descriptor->width_in_mb = s->avctx->coded_width;
|
|
+ pic_descriptor->height_in_mb = s->avctx->coded_height;
|
|
+ } else {
|
|
+ pic_descriptor->width_in_mb = s->mb_width;
|
|
+ pic_descriptor->height_in_mb = s->mb_height;
|
|
+ }
|
|
+ pic_descriptor->picture_structure = s->picture_structure;
|
|
+ // xvba-video set this to 1 only 4:2:0 supported
|
|
+ // doc says: if not set, choose 1 - we try this
|
|
+ pic_descriptor->chroma_format = 1;
|
|
+ pic_descriptor->avc_intra_flag = s->pict_type == AV_PICTURE_TYPE_I || v->bi_type == 1;
|
|
+ pic_descriptor->avc_reference = (s->current_picture_ptr->f.reference & 3) ? 1 : 0;
|
|
+
|
|
+ // VC-1 explicit parameters see page 30 of sdk
|
|
+ // sps_info
|
|
+ pic_descriptor->sps_info.vc1.postprocflag = v->postprocflag;
|
|
+
|
|
+ // done as in vaapi
|
|
+ pic_descriptor->sps_info.vc1.pulldown = v->broadcast;
|
|
+ pic_descriptor->sps_info.vc1.interlace = v->interlace;
|
|
+ pic_descriptor->sps_info.vc1.tfcntrflag = v->tfcntrflag;
|
|
+ pic_descriptor->sps_info.vc1.finterpflag = v->finterpflag;
|
|
+ pic_descriptor->sps_info.vc1.reserved = 1;
|
|
+ // eventually check if this makes sense together with interlace
|
|
+ pic_descriptor->sps_info.vc1.psf = v->psf;
|
|
+ // what about if it is a frame (page 31)
|
|
+ // looked at xvba-driver
|
|
+ pic_descriptor->sps_info.vc1.second_field = !s->first_field;
|
|
+ pic_descriptor->sps_info.vc1.xvba_vc1_sps_reserved = 0;
|
|
+
|
|
+ // VC-1 explicit parameters see page 30 of sdk
|
|
+ // pps_info
|
|
+ pic_descriptor->pps_info.vc1.panscan_flag = v->panscanflag;
|
|
+ pic_descriptor->pps_info.vc1.refdist_flag = v->refdist_flag;
|
|
+ pic_descriptor->pps_info.vc1.loopfilter = s->loop_filter;
|
|
+ pic_descriptor->pps_info.vc1.fastuvmc = v->fastuvmc;
|
|
+ pic_descriptor->pps_info.vc1.extended_mv = v->extended_mv;
|
|
+ pic_descriptor->pps_info.vc1.dquant = v->dquant;
|
|
+ pic_descriptor->pps_info.vc1.vstransform = v->vstransform;
|
|
+ pic_descriptor->pps_info.vc1.overlap = v->overlap;
|
|
+ pic_descriptor->pps_info.vc1.quantizer = v->quantizer_mode;
|
|
+ pic_descriptor->pps_info.vc1.extended_dmv = v->extended_dmv;
|
|
+ pic_descriptor->pps_info.vc1.maxbframes = s->avctx->max_b_frames;
|
|
+ pic_descriptor->pps_info.vc1.rangered = (pic_descriptor->profile == PROFILE_SIMPLE) ? 0 : v->rangered;
|
|
+ pic_descriptor->pps_info.vc1.syncmarker = (pic_descriptor->profile == PROFILE_SIMPLE) ? 0 : s->resync_marker;
|
|
+ pic_descriptor->pps_info.vc1.multires = v->multires;
|
|
+ pic_descriptor->pps_info.vc1.reserved = 1;
|
|
+ pic_descriptor->pps_info.vc1.range_mapy_flag = v->range_mapy_flag;
|
|
+ pic_descriptor->pps_info.vc1.range_mapy = v->range_mapy;
|
|
+ pic_descriptor->pps_info.vc1.range_mapuv_flag = v->range_mapuv_flag;
|
|
+ pic_descriptor->pps_info.vc1.range_mapuv = v->range_mapuv;
|
|
+ pic_descriptor->pps_info.vc1.xvba_vc1_pps_reserved = 0;
|
|
+
|
|
+ pic_descriptor->past_surface = 0;
|
|
+ pic_descriptor->future_surface = 0;
|
|
+ switch (s->pict_type) {
|
|
+ case AV_PICTURE_TYPE_B:
|
|
+ next = (struct xvba_render_state *)s->next_picture.f.data[0];
|
|
+ assert(next);
|
|
+ if (next)
|
|
+ pic_descriptor->past_surface = next->surface;
|
|
+ // fall-through
|
|
+ case AV_PICTURE_TYPE_P:
|
|
+ last = (struct xvba_render_state *)s->last_picture.f.data[0];
|
|
+ assert(last);
|
|
+ if (last)
|
|
+ pic_descriptor->future_surface = last->surface;
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ ff_draw_horiz_band(s, 0, s->avctx->height);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int decode_slice(AVCodecContext *avctx, const uint8_t *buffer, uint32_t size)
|
|
+{
|
|
+ VC1Context* const v = avctx->priv_data;
|
|
+ MpegEncContext* const s = &v->s;
|
|
+ struct xvba_render_state *render;
|
|
+
|
|
+ render = (struct xvba_render_state *)s->current_picture_ptr->f.data[0];
|
|
+ assert(render);
|
|
+
|
|
+ if (avctx->codec_id == CODEC_ID_VC1 &&
|
|
+ size >= 4 && IS_MARKER(AV_RB32(buffer))) {
|
|
+ buffer += 4;
|
|
+ size -= 4;
|
|
+ }
|
|
+
|
|
+ ff_xvba_add_slice_data(render, buffer, size);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+#if CONFIG_WMV3_XVBA_HWACCEL
|
|
+AVHWAccel ff_wmv3_xvba_hwaccel = {
|
|
+ .name = "wmv3_xvba",
|
|
+ .type = AVMEDIA_TYPE_VIDEO,
|
|
+ .id = CODEC_ID_WMV3,
|
|
+ .pix_fmt = PIX_FMT_XVBA_VLD,
|
|
+ .start_frame = start_frame,
|
|
+ .end_frame = end_frame,
|
|
+ .decode_slice = decode_slice,
|
|
+};
|
|
+#endif
|
|
+
|
|
+AVHWAccel ff_vc1_xvba_hwaccel = {
|
|
+ .name = "vc1_xvba",
|
|
+ .type = AVMEDIA_TYPE_VIDEO,
|
|
+ .id = CODEC_ID_VC1,
|
|
+ .pix_fmt = PIX_FMT_XVBA_VLD,
|
|
+ .start_frame = start_frame,
|
|
+ .end_frame = end_frame,
|
|
+ .decode_slice = decode_slice,
|
|
+};
|
|
diff --git a/lib/ffmpeg/libavcodec/xvmc_internal.h b/lib/ffmpeg/libavcodec/xvmc_internal.h
|
|
index 04197ce..d925eb1 100644
|
|
--- a/lib/ffmpeg/libavcodec/xvmc_internal.h
|
|
+++ b/lib/ffmpeg/libavcodec/xvmc_internal.h
|
|
@@ -1,5 +1,7 @@
|
|
/*
|
|
- * XVideo Motion Compensation internal functions
|
|
+ * HW decode acceleration for MPEG-2, H.264 and VC-1
|
|
+ *
|
|
+ * Copyright (C) 2005-2011 Team XBMC
|
|
*
|
|
* This file is part of FFmpeg.
|
|
*
|
|
diff --git a/lib/ffmpeg/libavutil/pixdesc.c b/lib/ffmpeg/libavutil/pixdesc.c
|
|
index e73fbfe..5abbd14 100644
|
|
--- a/lib/ffmpeg/libavutil/pixdesc.c
|
|
+++ b/lib/ffmpeg/libavutil/pixdesc.c
|
|
@@ -874,6 +874,12 @@ void av_write_image_line(const uint16_t *src, uint8_t *data[4], const int linesi
|
|
.log2_chroma_h = 1,
|
|
.flags = PIX_FMT_HWACCEL,
|
|
},
|
|
+ [PIX_FMT_XVBA_VLD] = {
|
|
+ .name = "xvba_vld",
|
|
+ .log2_chroma_w = 1,
|
|
+ .log2_chroma_h = 1,
|
|
+ .flags = PIX_FMT_HWACCEL,
|
|
+ },
|
|
[PIX_FMT_YUV420P9LE] = {
|
|
.name = "yuv420p9le",
|
|
.nb_components = 3,
|
|
diff --git a/lib/ffmpeg/libavutil/pixfmt.h b/lib/ffmpeg/libavutil/pixfmt.h
|
|
index f0d9c01..0f8cf7b 100644
|
|
--- a/lib/ffmpeg/libavutil/pixfmt.h
|
|
+++ b/lib/ffmpeg/libavutil/pixfmt.h
|
|
@@ -129,6 +129,7 @@ enum PixelFormat {
|
|
PIX_FMT_YUV444P16BE, ///< planar YUV 4:4:4, 48bpp, (1 Cr & Cb sample per 1x1 Y samples), big-endian
|
|
PIX_FMT_VDPAU_MPEG4, ///< MPEG4 HW decoding with VDPAU, data[0] contains a vdpau_render_state struct which contains the bitstream of the slices as well as various fields extracted from headers
|
|
PIX_FMT_DXVA2_VLD, ///< HW decoding through DXVA2, Picture.data[3] contains a LPDIRECT3DSURFACE9 pointer
|
|
+ PIX_FMT_XVBA_VLD, ///< HW decoding through DXVA2, Picture.data[3] contains a vaapi_render_state struct which contains the bitstream of the slices as well as various fields extracted from headers
|
|
|
|
PIX_FMT_RGB444LE, ///< packed RGB 4:4:4, 16bpp, (msb)4A 4R 4G 4B(lsb), little-endian, most significant bits to 0
|
|
PIX_FMT_RGB444BE, ///< packed RGB 4:4:4, 16bpp, (msb)4A 4R 4G 4B(lsb), big-endian, most significant bits to 0
|
|
--
|
|
1.7.10
|
|
|
|
|
|
From 922cada27e255bc3f685b700c2ffa4a146f87624 Mon Sep 17 00:00:00 2001
|
|
From: xbmc <fernetmenta@online.de>
|
|
Date: Thu, 12 Apr 2012 12:09:31 +0200
|
|
Subject: [PATCH 42/72] xvba: add decoder
|
|
|
|
---
|
|
configure.in | 48 +
|
|
language/English/strings.po | 12 +-
|
|
xbmc/cores/VideoRenderers/LinuxRendererGL.cpp | 218 +-
|
|
xbmc/cores/VideoRenderers/LinuxRendererGL.h | 15 +-
|
|
xbmc/cores/VideoRenderers/RenderFormats.h | 1 +
|
|
xbmc/cores/VideoRenderers/RenderManager.cpp | 9 +-
|
|
.../dvdplayer/DVDCodecs/Video/DVDVideoCodec.h | 4 +
|
|
.../DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp | 16 +
|
|
xbmc/cores/dvdplayer/DVDCodecs/Video/Makefile.in | 4 +
|
|
xbmc/cores/dvdplayer/DVDCodecs/Video/XVBA.cpp | 2354 ++++++++++++++++++++
|
|
xbmc/cores/dvdplayer/DVDCodecs/Video/XVBA.h | 382 ++++
|
|
xbmc/cores/dvdplayer/DVDPlayerVideo.cpp | 3 +
|
|
xbmc/settings/GUISettings.cpp | 3 +
|
|
xbmc/settings/VideoSettings.h | 2 +
|
|
xbmc/video/dialogs/GUIDialogVideoSettings.cpp | 1 +
|
|
15 files changed, 3064 insertions(+), 8 deletions(-)
|
|
create mode 100644 xbmc/cores/dvdplayer/DVDCodecs/Video/XVBA.cpp
|
|
create mode 100644 xbmc/cores/dvdplayer/DVDCodecs/Video/XVBA.h
|
|
|
|
diff --git a/configure.in b/configure.in
|
|
index 350d960..3660fa4 100644
|
|
--- a/configure.in
|
|
+++ b/configure.in
|
|
@@ -124,6 +124,8 @@ vaapi_not_found="== Could not find libva. VAAPI support disabled. =="
|
|
vaapi_disabled="== VAAPI support manually disabled. =="
|
|
crystalhd_not_found="== Could not find libcrystalhd. CrystalHD support disabled. =="
|
|
crystalhd_disabled="== CrystalHD support manually disabled. =="
|
|
+xvba_not_found="== Could not find amdxvba.h. XVBA support disabled. =="
|
|
+xvba_disabled="== XVBA support manually disabled. =="
|
|
vdadecoder_enabled="== VDADecoder support enabled. =="
|
|
vdadecoder_disabled="== VDADecoder support manually disabled. =="
|
|
vtbdecoder_enabled="== VTBDecoder support enabled. =="
|
|
@@ -247,6 +249,12 @@ AC_ARG_ENABLE([crystalhd],
|
|
[enable CrystalHD decoding (default is auto)])],
|
|
[use_crystalhd=$enableval],
|
|
[use_crystalhd=auto])
|
|
+
|
|
+AC_ARG_ENABLE([xvba],
|
|
+ [AS_HELP_STRING([--enable-xvba],
|
|
+ [enable XVBA decoding (default is auto)])],
|
|
+ [use_xvba=$enableval],
|
|
+ [use_xvba=auto])
|
|
|
|
AC_ARG_ENABLE([vdadecoder],
|
|
[AS_HELP_STRING([--enable-vdadecoder],
|
|
@@ -1759,6 +1767,38 @@ else
|
|
USE_CRYSTALHD=0
|
|
fi
|
|
|
|
+# XVBA
|
|
+if test "x$use_xvba" != "xno"; then
|
|
+ if test "$host_vendor" = "apple" ; then
|
|
+ if test "x$use_xvba" = "xyes"; then
|
|
+ AC_MSG_ERROR([XVBA not supported on this platform])
|
|
+ else
|
|
+ use_xvba="no"
|
|
+ AC_MSG_NOTICE($xvba_disabled)
|
|
+ fi
|
|
+ USE_XVBA=0
|
|
+ else
|
|
+ initial_val=$use_xvba
|
|
+ AC_CHECK_HEADER([amd/amdxvba.h],, use_xvba=no, [#include <X11/Xlib.h>])
|
|
+
|
|
+ if test "x$use_xvba" = "xno"; then
|
|
+ if test "x$initial_val" = "xyes"; then
|
|
+ AC_MSG_ERROR($xvba_not_found)
|
|
+ else
|
|
+ AC_MSG_RESULT($xvba_not_found)
|
|
+ fi
|
|
+ USE_XVBA=0
|
|
+ else
|
|
+ AC_DEFINE([HAVE_LIBXVBA], [1], [Define to 1 if you have the 'xvba' header (amdxvba.h)])
|
|
+ USE_XVBA=1
|
|
+ fi
|
|
+ fi
|
|
+else
|
|
+ AC_MSG_NOTICE($xvba_disabled)
|
|
+ USE_XVBA=0
|
|
+fi
|
|
+
|
|
+
|
|
# VDADecoder
|
|
if test "x$use_vdadecoder" != "xno"; then
|
|
if test "$host_vendor" = "apple" ; then
|
|
@@ -1970,6 +2010,12 @@ else
|
|
final_message="$final_message\n CrystalHD:\tNo"
|
|
fi
|
|
|
|
+if test "x$use_xvba" != "xno"; then
|
|
+ final_message="$final_message\n XVBA:\t\tYes"
|
|
+else
|
|
+ final_message="$final_message\n XVBA:\t\tNo"
|
|
+fi
|
|
+
|
|
if test "x$use_vdadecoder" != "xno"; then
|
|
final_message="$final_message\n VDADecoder:\tYes"
|
|
else
|
|
@@ -2443,6 +2489,7 @@ AC_SUBST(USE_OPENGLES)
|
|
AC_SUBST(USE_VDPAU)
|
|
AC_SUBST(USE_VAAPI)
|
|
AC_SUBST(USE_CRYSTALHD)
|
|
+AC_SUBST(USE_XVBA)
|
|
AC_SUBST(USE_LIBSMBCLIENT)
|
|
AC_SUBST(USE_LIBNFS)
|
|
AC_SUBST(USE_LIBAFPCLIENT)
|
|
@@ -2626,6 +2673,7 @@ XB_CONFIG_MODULE([lib/ffmpeg], [
|
|
`if test "x$use_vdpau" != "xno"; then echo --enable-vdpau; else echo --disable-vdpau; fi` \
|
|
`if test "x$use_vaapi" != "xno"; then echo --enable-vaapi; else echo --disable-vaapi; fi` \
|
|
`if test "$use_optimizations" != "no"; then echo --enable-optimizations; else echo --disable-optimizations; fi` \
|
|
+ `if test "x$use_xvba" != "xno"; then echo --enable-xvba; else echo --disable-xvba; fi` \
|
|
--enable-protocol=http \
|
|
--enable-pthreads \
|
|
--enable-runtime-cpudetect \
|
|
diff --git a/language/English/strings.po b/language/English/strings.po
|
|
index bba7284..ede18b3 100644
|
|
--- a/language/English/strings.po
|
|
+++ b/language/English/strings.po
|
|
@@ -5124,7 +5124,11 @@ msgctxt "#13436"
|
|
msgid "Allow Vdpau OpenGL interop YUV"
|
|
msgstr ""
|
|
|
|
-#empty strings from id 13437 to 13499
|
|
+msgctxt "#13437"
|
|
+msgid "Allow hardware acceleration (XVBA)"
|
|
+msgstr ""
|
|
+
|
|
+#empty strings from id 13438 to 13499
|
|
|
|
msgctxt "#13500"
|
|
msgid "A/V sync method"
|
|
@@ -6346,7 +6350,11 @@ msgctxt "#16325"
|
|
msgid "VDPAU - Bob"
|
|
msgstr ""
|
|
|
|
-#empty strings from id 16326 to 16399
|
|
+msgctxt "#16326"
|
|
+msgid "XVBA"
|
|
+msgstr ""
|
|
+
|
|
+#empty strings from id 16327 to 16399
|
|
|
|
msgctxt "#16400"
|
|
msgid "Post-processing"
|
|
diff --git a/xbmc/cores/VideoRenderers/LinuxRendererGL.cpp b/xbmc/cores/VideoRenderers/LinuxRendererGL.cpp
|
|
index b281ca7..ec3606a 100644
|
|
--- a/xbmc/cores/VideoRenderers/LinuxRendererGL.cpp
|
|
+++ b/xbmc/cores/VideoRenderers/LinuxRendererGL.cpp
|
|
@@ -63,6 +63,9 @@
|
|
VA_MICRO_VERSION == 0 && VA_SDS_VERSION < 5)))
|
|
|
|
#endif
|
|
+#ifdef HAVE_LIBXVBA
|
|
+#include "cores/dvdplayer/DVDCodecs/Video/XVBA.h"
|
|
+#endif
|
|
|
|
#ifdef TARGET_DARWIN
|
|
#include "osx/CocoaInterface.h"
|
|
@@ -129,6 +132,9 @@
|
|
#ifdef HAVE_LIBVDPAU
|
|
vdpau = NULL;
|
|
#endif
|
|
+#ifdef HAVE_LIBXVBA
|
|
+ xvba = NULL;
|
|
+#endif
|
|
}
|
|
|
|
CLinuxRendererGL::YUVBUFFER::~YUVBUFFER()
|
|
@@ -604,6 +610,9 @@ void CLinuxRendererGL::ReleaseBuffer(int idx)
|
|
#ifdef HAVE_LIBVDPAU
|
|
SAFE_RELEASE(buf.vdpau);
|
|
#endif
|
|
+#ifdef HAVE_LIBXVBA
|
|
+ SAFE_RELEASE(buf.xvba);
|
|
+#endif
|
|
#ifdef HAVE_LIBVA
|
|
buf.vaapi.surface.reset();
|
|
#endif
|
|
@@ -879,7 +888,7 @@ void CLinuxRendererGL::UpdateVideoFilter()
|
|
case VS_SCALINGMETHOD_LINEAR:
|
|
SetTextureFilter(m_scalingMethod == VS_SCALINGMETHOD_NEAREST ? GL_NEAREST : GL_LINEAR);
|
|
m_renderQuality = RQ_SINGLEPASS;
|
|
- if (((m_renderMethod & RENDER_VDPAU) || (m_renderMethod & RENDER_VAAPI)) && m_nonLinStretch)
|
|
+ if (((m_renderMethod & RENDER_VDPAU) || (m_renderMethod & RENDER_VAAPI) || (m_renderMethod & RENDER_XVBA)) && m_nonLinStretch)
|
|
{
|
|
m_pVideoFilterShader = new StretchFilterShader();
|
|
if (!m_pVideoFilterShader->CompileAndLink())
|
|
@@ -965,6 +974,11 @@ void CLinuxRendererGL::LoadShaders(int field)
|
|
CLog::Log(LOGNOTICE, "GL: Using CVBREF render method");
|
|
m_renderMethod = RENDER_CVREF;
|
|
}
|
|
+ else if (m_format == RENDER_FMT_XVBA)
|
|
+ {
|
|
+ CLog::Log(LOGNOTICE, "GL: Using XVBA render method");
|
|
+ m_renderMethod = RENDER_XVBA;
|
|
+ }
|
|
else
|
|
{
|
|
int requestedMethod = g_guiSettings.GetInt("videoplayer.rendermethod");
|
|
@@ -1113,6 +1127,12 @@ void CLinuxRendererGL::LoadShaders(int field)
|
|
m_textureCreate = &CLinuxRendererGL::CreateCVRefTexture;
|
|
m_textureDelete = &CLinuxRendererGL::DeleteCVRefTexture;
|
|
}
|
|
+ else if (m_format == RENDER_FMT_XVBA)
|
|
+ {
|
|
+ m_textureUpload = &CLinuxRendererGL::UploadXVBATexture;
|
|
+ m_textureCreate = &CLinuxRendererGL::CreateXVBATexture;
|
|
+ m_textureDelete = &CLinuxRendererGL::DeleteXVBATexture;
|
|
+ }
|
|
else
|
|
{
|
|
// setup default YV12 texture handlers
|
|
@@ -1225,6 +1245,13 @@ void CLinuxRendererGL::Render(DWORD flags, int renderBuffer)
|
|
RenderVAAPI(renderBuffer, m_currentField);
|
|
}
|
|
#endif
|
|
+#ifdef HAVE_LIBXVBA
|
|
+ else if (m_renderMethod & RENDER_XVBA)
|
|
+ {
|
|
+ UpdateVideoFilter();
|
|
+ RenderXVBA(renderBuffer, m_currentField);
|
|
+ }
|
|
+#endif
|
|
else
|
|
{
|
|
// RENDER_CVREF uses the same render as the default case
|
|
@@ -1732,6 +1759,77 @@ void CLinuxRendererGL::RenderVAAPI(int index, int field)
|
|
#endif
|
|
}
|
|
|
|
+void CLinuxRendererGL::RenderXVBA(int index, int field)
|
|
+{
|
|
+#ifdef HAVE_LIBXVBA
|
|
+ YUVPLANE &plane = m_buffers[index].fields[0][1];
|
|
+
|
|
+ glEnable(m_textureTarget);
|
|
+ glActiveTextureARB(GL_TEXTURE0);
|
|
+
|
|
+ glBindTexture(m_textureTarget, plane.id);
|
|
+
|
|
+ // Try some clamping or wrapping
|
|
+ glTexParameteri(m_textureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
|
+ glTexParameteri(m_textureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
|
+
|
|
+ if (m_pVideoFilterShader)
|
|
+ {
|
|
+ GLint filter;
|
|
+ if (!m_pVideoFilterShader->GetTextureFilter(filter))
|
|
+ filter = m_scalingMethod == VS_SCALINGMETHOD_NEAREST ? GL_NEAREST : GL_LINEAR;
|
|
+
|
|
+ glTexParameteri(m_textureTarget, GL_TEXTURE_MAG_FILTER, filter);
|
|
+ glTexParameteri(m_textureTarget, GL_TEXTURE_MIN_FILTER, filter);
|
|
+ m_pVideoFilterShader->SetSourceTexture(0);
|
|
+ m_pVideoFilterShader->SetWidth(m_sourceWidth);
|
|
+ m_pVideoFilterShader->SetHeight(m_sourceHeight);
|
|
+
|
|
+ //disable non-linear stretch when a dvd menu is shown, parts of the menu are rendered through the overlay renderer
|
|
+ //having non-linear stretch on breaks the alignment
|
|
+ if (g_application.m_pPlayer && g_application.m_pPlayer->IsInMenu())
|
|
+ m_pVideoFilterShader->SetNonLinStretch(1.0);
|
|
+ else
|
|
+ m_pVideoFilterShader->SetNonLinStretch(pow(g_settings.m_fPixelRatio, g_advancedSettings.m_videoNonLinStretchRatio));
|
|
+
|
|
+ m_pVideoFilterShader->Enable();
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ GLint filter = m_scalingMethod == VS_SCALINGMETHOD_NEAREST ? GL_NEAREST : GL_LINEAR;
|
|
+ glTexParameteri(m_textureTarget, GL_TEXTURE_MAG_FILTER, filter);
|
|
+ glTexParameteri(m_textureTarget, GL_TEXTURE_MIN_FILTER, filter);
|
|
+ }
|
|
+
|
|
+ glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
|
|
+ VerifyGLState();
|
|
+
|
|
+ glBegin(GL_QUADS);
|
|
+ if (m_textureTarget==GL_TEXTURE_2D)
|
|
+ {
|
|
+ glTexCoord2f(plane.rect.x1, plane.rect.y1); glVertex2f(m_destRect.x1, m_destRect.y1);
|
|
+ glTexCoord2f(plane.rect.x2, plane.rect.y1); glVertex2f(m_destRect.x2, m_destRect.y1);
|
|
+ glTexCoord2f(plane.rect.x2, plane.rect.y2); glVertex2f(m_destRect.x2, m_destRect.y2);
|
|
+ glTexCoord2f(plane.rect.x1, plane.rect.y2); glVertex2f(m_destRect.x1, m_destRect.y2);
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ glTexCoord2f(m_destRect.x1, m_destRect.y1); glVertex4f(m_destRect.x1, m_destRect.y1, 0.0f, 0.0f);
|
|
+ glTexCoord2f(m_destRect.x2, m_destRect.y1); glVertex4f(m_destRect.x2, m_destRect.y1, 1.0f, 0.0f);
|
|
+ glTexCoord2f(m_destRect.x2, m_destRect.y2); glVertex4f(m_destRect.x2, m_destRect.y2, 1.0f, 1.0f);
|
|
+ glTexCoord2f(m_destRect.x1, m_destRect.y2); glVertex4f(m_destRect.x1, m_destRect.y2, 0.0f, 1.0f);
|
|
+ }
|
|
+ glEnd();
|
|
+ VerifyGLState();
|
|
+
|
|
+ if (m_pVideoFilterShader)
|
|
+ m_pVideoFilterShader->Disable();
|
|
+
|
|
+ glBindTexture (m_textureTarget, 0);
|
|
+ glDisable(m_textureTarget);
|
|
+#endif
|
|
+}
|
|
+
|
|
void CLinuxRendererGL::RenderSoftware(int index, int field)
|
|
{
|
|
// used for textues uploaded from rgba or CVPixelBuffers.
|
|
@@ -2783,6 +2881,93 @@ bool CLinuxRendererGL::CreateCVRefTexture(int index)
|
|
return true;
|
|
}
|
|
|
|
+void CLinuxRendererGL::DeleteXVBATexture(int index)
|
|
+{
|
|
+#ifdef HAVE_LIBXVBA
|
|
+ YUVPLANE &plane = m_buffers[index].fields[0][0];
|
|
+ YUVFIELDS &fields = m_buffers[index].fields;
|
|
+
|
|
+ SAFE_RELEASE(m_buffers[index].xvba);
|
|
+
|
|
+ if(plane.id && glIsTexture(plane.id))
|
|
+ glDeleteTextures(1, &plane.id);
|
|
+ plane.id = 0;
|
|
+ fields[0][1].id = 0;
|
|
+#endif
|
|
+}
|
|
+
|
|
+bool CLinuxRendererGL::CreateXVBATexture(int index)
|
|
+{
|
|
+#ifdef HAVE_LIBXVBA
|
|
+ YV12Image &im = m_buffers[index].image;
|
|
+ YUVFIELDS &fields = m_buffers[index].fields;
|
|
+ YUVPLANE &plane = fields[0][0];
|
|
+
|
|
+ DeleteXVBATexture(index);
|
|
+
|
|
+ memset(&im , 0, sizeof(im));
|
|
+ memset(&fields, 0, sizeof(fields));
|
|
+
|
|
+ glGenTextures(1, &plane.id);
|
|
+
|
|
+ m_eventTexturesDone[index]->Set();
|
|
+#endif
|
|
+ return true;
|
|
+}
|
|
+
|
|
+void CLinuxRendererGL::UploadXVBATexture(int index)
|
|
+{
|
|
+#ifdef HAVE_LIBXVBA
|
|
+ XVBA::CXvbaRenderPicture *xvba = m_buffers[index].xvba;
|
|
+ YV12Image &im = m_buffers[index].image;
|
|
+
|
|
+ YUVFIELDS &fields = m_buffers[index].fields;
|
|
+ YUVPLANE &plane = fields[0][1];
|
|
+
|
|
+ if (!xvba)
|
|
+ {
|
|
+ fields[0][1].id = fields[0][0].id;
|
|
+ m_eventTexturesDone[index]->Set();
|
|
+ CLog::Log(LOGWARNING,"CLinuxRendererGL::UploadXVBATexture no xvba texture, index: %d", index);
|
|
+ return;
|
|
+ }
|
|
+// xvba->Transfer();
|
|
+
|
|
+ fields[0][1].id = xvba->texture;
|
|
+
|
|
+ im.height = xvba->texHeight;
|
|
+ im.width = xvba->texWidth;
|
|
+
|
|
+ plane.texwidth = xvba->texWidth;
|
|
+ plane.texheight = xvba->texHeight;
|
|
+ plane.pixpertex_x = 1;
|
|
+ plane.pixpertex_y = 1;
|
|
+
|
|
+ plane.rect = m_sourceRect;
|
|
+ plane.width = im.width;
|
|
+ plane.height = im.height;
|
|
+
|
|
+ plane.height /= plane.pixpertex_y;
|
|
+ plane.rect.y1 /= plane.pixpertex_y;
|
|
+ plane.rect.y2 /= plane.pixpertex_y;
|
|
+ plane.width /= plane.pixpertex_x;
|
|
+ plane.rect.x1 /= plane.pixpertex_x;
|
|
+ plane.rect.x2 /= plane.pixpertex_x;
|
|
+
|
|
+ if (m_textureTarget == GL_TEXTURE_2D)
|
|
+ {
|
|
+ plane.height /= plane.texheight;
|
|
+ plane.rect.y1 /= plane.texheight;
|
|
+ plane.rect.y2 /= plane.texheight;
|
|
+ plane.width /= plane.texwidth;
|
|
+ plane.rect.x1 /= plane.texwidth;
|
|
+ plane.rect.x2 /= plane.texwidth;
|
|
+ }
|
|
+
|
|
+ m_eventTexturesDone[index]->Set();
|
|
+#endif
|
|
+}
|
|
+
|
|
void CLinuxRendererGL::UploadYUV422PackedTexture(int source)
|
|
{
|
|
YUVBUFFER& buf = m_buffers[source];
|
|
@@ -3368,6 +3553,9 @@ bool CLinuxRendererGL::Supports(ERENDERFEATURE feature)
|
|
if (m_renderMethod & RENDER_VAAPI)
|
|
return false;
|
|
|
|
+ if (m_renderMethod & RENDER_XVBA)
|
|
+ return false;
|
|
+
|
|
return (m_renderMethod & RENDER_GLSL)
|
|
|| (m_renderMethod & RENDER_ARB)
|
|
|| ((m_renderMethod & RENDER_SW) && glewIsSupported("GL_ARB_imaging") == GL_TRUE);
|
|
@@ -3381,6 +3569,9 @@ bool CLinuxRendererGL::Supports(ERENDERFEATURE feature)
|
|
if (m_renderMethod & RENDER_VAAPI)
|
|
return false;
|
|
|
|
+ if (m_renderMethod & RENDER_XVBA)
|
|
+ return false;
|
|
+
|
|
return (m_renderMethod & RENDER_GLSL)
|
|
|| (m_renderMethod & RENDER_ARB)
|
|
|| ((m_renderMethod & RENDER_SW) && glewIsSupported("GL_ARB_imaging") == GL_TRUE);
|
|
@@ -3404,7 +3595,8 @@ bool CLinuxRendererGL::Supports(ERENDERFEATURE feature)
|
|
if (feature == RENDERFEATURE_NONLINSTRETCH)
|
|
{
|
|
if (((m_renderMethod & RENDER_GLSL) && !(m_renderMethod & RENDER_POT)) ||
|
|
- (m_renderMethod & RENDER_VDPAU) || (m_renderMethod & RENDER_VAAPI))
|
|
+ (m_renderMethod & RENDER_VDPAU) || (m_renderMethod & RENDER_VAAPI) ||
|
|
+ (m_renderMethod & RENDER_XVBA))
|
|
return true;
|
|
}
|
|
|
|
@@ -3476,6 +3668,16 @@ bool CLinuxRendererGL::Supports(EINTERLACEMETHOD method)
|
|
return false;
|
|
}
|
|
|
|
+ if(m_renderMethod & RENDER_XVBA)
|
|
+ {
|
|
+#ifdef HAVE_LIBXVBA
|
|
+ XVBA::CXvbaRenderPicture *xvba = m_buffers[m_iYV12RenderBuffer].xvba;
|
|
+ if(xvba)
|
|
+ return xvba->xvba->Supports(method);
|
|
+#endif
|
|
+ return false;
|
|
+ }
|
|
+
|
|
#ifdef TARGET_DARWIN
|
|
// YADIF too slow for HD but we have no methods to fall back
|
|
// to something that works so just turn it off.
|
|
@@ -3518,7 +3720,7 @@ bool CLinuxRendererGL::Supports(ESCALINGMETHOD method)
|
|
|| method == VS_SCALINGMETHOD_LANCZOS3)
|
|
{
|
|
if ((glewIsSupported("GL_EXT_framebuffer_object") && (m_renderMethod & RENDER_GLSL)) ||
|
|
- (m_renderMethod & RENDER_VDPAU) || (m_renderMethod & RENDER_VAAPI))
|
|
+ (m_renderMethod & RENDER_VDPAU) || (m_renderMethod & RENDER_VAAPI) || (m_renderMethod & RENDER_XVBA))
|
|
{
|
|
// spline36 and lanczos3 are only allowed through advancedsettings.xml
|
|
if(method != VS_SCALINGMETHOD_SPLINE36
|
|
@@ -3610,4 +3812,14 @@ void CLinuxRendererGL::AddProcessor(struct __CVBuffer *cvBufferRef, int index)
|
|
}
|
|
#endif
|
|
|
|
+#ifdef HAVE_LIBXVBA
|
|
+void CLinuxRendererGL::AddProcessor(XVBA::CXvbaRenderPicture* xvba, int index)
|
|
+{
|
|
+ YUVBUFFER &buf = m_buffers[index];
|
|
+ XVBA::CXvbaRenderPicture *pic = xvba->Acquire();
|
|
+ SAFE_RELEASE(buf.xvba);
|
|
+ buf.xvba = pic;
|
|
+}
|
|
+#endif
|
|
+
|
|
#endif
|
|
diff --git a/xbmc/cores/VideoRenderers/LinuxRendererGL.h b/xbmc/cores/VideoRenderers/LinuxRendererGL.h
|
|
index 2fc34ae..e76624b 100644
|
|
--- a/xbmc/cores/VideoRenderers/LinuxRendererGL.h
|
|
+++ b/xbmc/cores/VideoRenderers/LinuxRendererGL.h
|
|
@@ -43,6 +43,8 @@
|
|
namespace Shaders { class BaseVideoFilterShader; }
|
|
namespace VAAPI { struct CHolder; }
|
|
namespace VDPAU { class CVdpauRenderPicture; }
|
|
+namespace XVBA { class CXvbaRenderPicture; }
|
|
+
|
|
|
|
#define NUM_BUFFERS 10
|
|
|
|
@@ -90,6 +92,7 @@ enum RenderMethod
|
|
RENDER_POT=0x10,
|
|
RENDER_VAAPI=0x20,
|
|
RENDER_CVREF = 0x40,
|
|
+ RENDER_XVBA=0x80,
|
|
};
|
|
|
|
enum RenderQuality
|
|
@@ -151,7 +154,9 @@ class CLinuxRendererGL : public CBaseRenderer
|
|
#ifdef TARGET_DARWIN
|
|
virtual void AddProcessor(struct __CVBuffer *cvBufferRef, int index);
|
|
#endif
|
|
-
|
|
+#ifdef HAVE_LIBXVBA
|
|
+ virtual void AddProcessor(XVBA::CXvbaRenderPicture* xvba, int index);
|
|
+#endif
|
|
virtual void RenderUpdate(bool clear, DWORD flags = 0, DWORD alpha = 255);
|
|
|
|
// Feature support
|
|
@@ -210,6 +215,10 @@ class CLinuxRendererGL : public CBaseRenderer
|
|
void DeleteYUV422PackedTexture(int index);
|
|
bool CreateYUV422PackedTexture(int index);
|
|
|
|
+ void UploadXVBATexture(int index);
|
|
+ void DeleteXVBATexture(int index);
|
|
+ bool CreateXVBATexture(int index);
|
|
+
|
|
void UploadRGBTexture(int index);
|
|
void ToRGBFrame(YV12Image* im, unsigned flipIndexPlane, unsigned flipIndexBuf);
|
|
void ToRGBFields(YV12Image* im, unsigned flipIndexPlaneTop, unsigned flipIndexPlaneBot, unsigned flipIndexBuf);
|
|
@@ -225,6 +234,7 @@ class CLinuxRendererGL : public CBaseRenderer
|
|
void RenderVDPAU(int renderBuffer, int field); // render using vdpau hardware
|
|
void RenderProgressiveWeave(int renderBuffer, int field); // render using vdpau hardware
|
|
void RenderVAAPI(int renderBuffer, int field); // render using vdpau hardware
|
|
+ void RenderXVBA(int renderBuffer, int field); // render using xvba hardware
|
|
|
|
struct
|
|
{
|
|
@@ -292,6 +302,9 @@ class CLinuxRendererGL : public CBaseRenderer
|
|
#ifdef TARGET_DARWIN_OSX
|
|
struct __CVBuffer *cvBufferRef;
|
|
#endif
|
|
+#ifdef HAVE_LIBXVBA
|
|
+ XVBA::CXvbaRenderPicture *xvba;
|
|
+#endif
|
|
};
|
|
|
|
typedef YUVBUFFER YUVBUFFERS[NUM_BUFFERS];
|
|
diff --git a/xbmc/cores/VideoRenderers/RenderFormats.h b/xbmc/cores/VideoRenderers/RenderFormats.h
|
|
index 0262c60..a727d94 100644
|
|
--- a/xbmc/cores/VideoRenderers/RenderFormats.h
|
|
+++ b/xbmc/cores/VideoRenderers/RenderFormats.h
|
|
@@ -35,6 +35,7 @@ enum ERenderFormat {
|
|
RENDER_FMT_OMXEGL,
|
|
RENDER_FMT_CVBREF,
|
|
RENDER_FMT_BYPASS,
|
|
+ RENDER_FMT_XVBA,
|
|
};
|
|
|
|
#endif
|
|
diff --git a/xbmc/cores/VideoRenderers/RenderManager.cpp b/xbmc/cores/VideoRenderers/RenderManager.cpp
|
|
index a521680..0506823 100644
|
|
--- a/xbmc/cores/VideoRenderers/RenderManager.cpp
|
|
+++ b/xbmc/cores/VideoRenderers/RenderManager.cpp
|
|
@@ -250,8 +250,9 @@ bool CXBMCRenderManager::Configure(unsigned int width, unsigned int height, unsi
|
|
|
|
// check if decoder supports buffering
|
|
m_bCodecSupportsBuffering = false;
|
|
- if (format == RENDER_FMT_VDPAU ||
|
|
- format == RENDER_FMT_VDPAU_420)
|
|
+ if (format == RENDER_FMT_VDPAU
|
|
+ || format == RENDER_FMT_VDPAU_420
|
|
+ || format == RENDER_FMT_XVBA)
|
|
m_bCodecSupportsBuffering = true;
|
|
|
|
bool result = m_pRenderer->Configure(width, height, d_width, d_height, fps, flags, format, extended_format, orientation);
|
|
@@ -873,6 +874,10 @@ int CXBMCRenderManager::AddVideoPicture(DVDVideoPicture& pic)
|
|
else if(pic.format == RENDER_FMT_VAAPI)
|
|
m_pRenderer->AddProcessor(*pic.vaapi, index);
|
|
#endif
|
|
+#ifdef HAVE_LIBXVBA
|
|
+ else if(pic.format == RENDER_FMT_XVBA)
|
|
+ m_pRenderer->AddProcessor(pic.xvba, index);
|
|
+#endif
|
|
m_pRenderer->ReleaseImage(index, false);
|
|
|
|
return index;
|
|
diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h
|
|
index 98d8f89..76d3575 100644
|
|
--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h
|
|
+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h
|
|
@@ -35,6 +35,7 @@
|
|
namespace DXVA { class CSurfaceContext; }
|
|
namespace VAAPI { struct CHolder; }
|
|
namespace VDPAU { class CVdpauRenderPicture; }
|
|
+namespace XVBA { class CXvbaRenderPicture; }
|
|
class COpenMax;
|
|
class COpenMaxVideo;
|
|
struct OpenMaxVideoBuffer;
|
|
@@ -60,6 +61,9 @@ struct DVDVideoPicture
|
|
struct {
|
|
VAAPI::CHolder* vaapi;
|
|
};
|
|
+ struct {
|
|
+ XVBA::CXvbaRenderPicture* xvba;
|
|
+ };
|
|
|
|
struct {
|
|
COpenMax *openMax;
|
|
diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp
|
|
index a6e42e5..b3252ec 100644
|
|
--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp
|
|
+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp
|
|
@@ -56,6 +56,9 @@
|
|
#ifdef HAVE_LIBVA
|
|
#include "VAAPI.h"
|
|
#endif
|
|
+#ifdef HAVE_LIBXVBA
|
|
+#include "XVBA.h"
|
|
+#endif
|
|
|
|
using namespace boost;
|
|
|
|
@@ -100,6 +103,19 @@ enum PixelFormat CDVDVideoCodecFFmpeg::GetFormat( struct AVCodecContext * avctx
|
|
dec->Release();
|
|
}
|
|
#endif
|
|
+#ifdef HAVE_LIBXVBA
|
|
+ if(*cur == PIX_FMT_XVBA_VLD && g_guiSettings.GetBool("videoplayer.usexvba"))
|
|
+ {
|
|
+ XVBA::CDecoder* dec = new XVBA::CDecoder();
|
|
+ if(dec->Open(avctx, *cur, ctx->m_uSurfacesCount))
|
|
+ {
|
|
+ ctx->SetHardware(dec);
|
|
+ return *cur;
|
|
+ }
|
|
+ else
|
|
+ dec->Release();
|
|
+ }
|
|
+#endif
|
|
#ifdef HAVE_LIBVA
|
|
// mpeg4 vaapi decoding is disabled
|
|
if(*cur == PIX_FMT_VAAPI_VLD && g_guiSettings.GetBool("videoplayer.usevaapi")
|
|
diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/Makefile.in b/xbmc/cores/dvdplayer/DVDCodecs/Video/Makefile.in
|
|
index 176ceff..c58422b 100644
|
|
--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/Makefile.in
|
|
+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/Makefile.in
|
|
@@ -14,6 +14,10 @@ ifeq (@USE_CRYSTALHD@,1)
|
|
SRCS += CrystalHD.cpp
|
|
SRCS += DVDVideoCodecCrystalHD.cpp
|
|
endif
|
|
+ifeq (@USE_XVBA@,1)
|
|
+SRCS+= XVBA.cpp \
|
|
+
|
|
+endif
|
|
ifeq (@USE_VDA@,1)
|
|
SRCS += DVDVideoCodecVDA.cpp
|
|
endif
|
|
diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/XVBA.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/XVBA.cpp
|
|
new file mode 100644
|
|
index 0000000..e8e376a
|
|
--- /dev/null
|
|
+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/XVBA.cpp
|
|
@@ -0,0 +1,2354 @@
|
|
+/*
|
|
+ * Copyright (C) 2005-2011 Team XBMC
|
|
+ * http://www.xbmc.org
|
|
+ *
|
|
+ * This Program is free software; you can redistribute it and/or modify
|
|
+ * it under the terms of the GNU General Public License as published by
|
|
+ * the Free Software Foundation; either version 2, or (at your option)
|
|
+ * any later version.
|
|
+ *
|
|
+ * This Program is distributed in the hope that it will be useful,
|
|
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
+ * GNU General Public License for more details.
|
|
+ *
|
|
+ * You should have received a copy of the GNU General Public License
|
|
+ * along with XBMC; see the file COPYING. If not, write to
|
|
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
+ * http://www.gnu.org/copyleft/gpl.html
|
|
+ *
|
|
+ */
|
|
+
|
|
+#include "system.h"
|
|
+#ifdef HAVE_LIBXVBA
|
|
+
|
|
+#include "system_gl.h"
|
|
+#include <dlfcn.h>
|
|
+#include <string>
|
|
+#include "XVBA.h"
|
|
+#include "windowing/WindowingFactory.h"
|
|
+#include "guilib/GraphicContext.h"
|
|
+#include "settings/GUISettings.h"
|
|
+#include "settings/Settings.h"
|
|
+#include "utils/TimeUtils.h"
|
|
+#include "cores/dvdplayer/DVDClock.h"
|
|
+
|
|
+using namespace XVBA;
|
|
+
|
|
+// XVBA interface
|
|
+
|
|
+#define XVBA_LIBRARY "libXvBAW.so.1"
|
|
+
|
|
+typedef Bool (*XVBAQueryExtensionProc) (Display *dpy, int *vers);
|
|
+typedef Status (*XVBACreateContextProc) (void *input, void *output);
|
|
+typedef Status (*XVBADestroyContextProc) (void *context);
|
|
+typedef Bool (*XVBAGetSessionInfoProc) (void *input, void *output);
|
|
+typedef Status (*XVBACreateSurfaceProc) (void *input, void *output);
|
|
+typedef Status (*XVBACreateGLSharedSurfaceProc)(void *input, void *output);
|
|
+typedef Status (*XVBADestroySurfaceProc) (void *surface);
|
|
+typedef Status (*XVBACreateDecodeBuffersProc) (void *input, void *output);
|
|
+typedef Status (*XVBADestroyDecodeBuffersProc) (void *input);
|
|
+typedef Status (*XVBAGetCapDecodeProc) (void *input, void *output);
|
|
+typedef Status (*XVBACreateDecodeProc) (void *input, void *output);
|
|
+typedef Status (*XVBADestroyDecodeProc) (void *session);
|
|
+typedef Status (*XVBAStartDecodePictureProc) (void *input);
|
|
+typedef Status (*XVBADecodePictureProc) (void *input);
|
|
+typedef Status (*XVBAEndDecodePictureProc) (void *input);
|
|
+typedef Status (*XVBASyncSurfaceProc) (void *input, void *output);
|
|
+typedef Status (*XVBAGetSurfaceProc) (void *input);
|
|
+typedef Status (*XVBATransferSurfaceProc) (void *input);
|
|
+
|
|
+static struct
|
|
+{
|
|
+ XVBAQueryExtensionProc QueryExtension;
|
|
+ XVBACreateContextProc CreateContext;
|
|
+ XVBADestroyContextProc DestroyContext;
|
|
+ XVBAGetSessionInfoProc GetSessionInfo;
|
|
+ XVBACreateSurfaceProc CreateSurface;
|
|
+ XVBACreateGLSharedSurfaceProc CreateGLSharedSurface;
|
|
+ XVBADestroySurfaceProc DestroySurface;
|
|
+ XVBACreateDecodeBuffersProc CreateDecodeBuffers;
|
|
+ XVBADestroyDecodeBuffersProc DestroyDecodeBuffers;
|
|
+ XVBAGetCapDecodeProc GetCapDecode;
|
|
+ XVBACreateDecodeProc CreateDecode;
|
|
+ XVBADestroyDecodeProc DestroyDecode;
|
|
+ XVBAStartDecodePictureProc StartDecodePicture;
|
|
+ XVBADecodePictureProc DecodePicture;
|
|
+ XVBAEndDecodePictureProc EndDecodePicture;
|
|
+ XVBASyncSurfaceProc SyncSurface;
|
|
+ XVBAGetSurfaceProc GetSurface;
|
|
+ XVBATransferSurfaceProc TransferSurface;
|
|
+}g_XVBA_vtable;
|
|
+
|
|
+//-----------------------------------------------------------------------------
|
|
+//-----------------------------------------------------------------------------
|
|
+
|
|
+CXVBAContext *CXVBAContext::m_context = 0;
|
|
+CCriticalSection CXVBAContext::m_section;
|
|
+Display *CXVBAContext::m_display = 0;
|
|
+void *CXVBAContext::m_dlHandle = 0;
|
|
+
|
|
+CXVBAContext::CXVBAContext()
|
|
+{
|
|
+ m_context = 0;
|
|
+// m_dlHandle = 0;
|
|
+ m_xvbaContext = 0;
|
|
+ m_refCount = 0;
|
|
+}
|
|
+
|
|
+void CXVBAContext::Release()
|
|
+{
|
|
+ CSingleLock lock(m_section);
|
|
+
|
|
+ m_refCount--;
|
|
+ if (m_refCount <= 0)
|
|
+ {
|
|
+ Close();
|
|
+ delete this;
|
|
+ m_context = 0;
|
|
+ }
|
|
+}
|
|
+
|
|
+void CXVBAContext::Close()
|
|
+{
|
|
+ CLog::Log(LOGNOTICE, "XVBA::Close - closing decoder context");
|
|
+
|
|
+ DestroyContext();
|
|
+// if (m_dlHandle)
|
|
+// {
|
|
+// dlclose(m_dlHandle);
|
|
+// m_dlHandle = 0;
|
|
+// }
|
|
+}
|
|
+
|
|
+bool CXVBAContext::EnsureContext(CXVBAContext **ctx)
|
|
+{
|
|
+ CSingleLock lock(m_section);
|
|
+
|
|
+ if (m_context)
|
|
+ {
|
|
+ m_context->m_refCount++;
|
|
+ *ctx = m_context;
|
|
+ return true;
|
|
+ }
|
|
+
|
|
+ m_context = new CXVBAContext();
|
|
+ *ctx = m_context;
|
|
+ {
|
|
+ CSingleLock gLock(g_graphicsContext);
|
|
+ if (!m_context->LoadSymbols() || !m_context->CreateContext())
|
|
+ {
|
|
+ delete m_context;
|
|
+ m_context = 0;
|
|
+ return false;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ m_context->m_refCount++;
|
|
+
|
|
+ *ctx = m_context;
|
|
+ return true;
|
|
+}
|
|
+
|
|
+bool CXVBAContext::LoadSymbols()
|
|
+{
|
|
+ if (!m_dlHandle)
|
|
+ {
|
|
+ m_dlHandle = dlopen(XVBA_LIBRARY, RTLD_LAZY);
|
|
+ if (!m_dlHandle)
|
|
+ {
|
|
+ const char* error = dlerror();
|
|
+ if (!error)
|
|
+ error = "dlerror() returned NULL";
|
|
+
|
|
+ CLog::Log(LOGERROR,"XVBA::LoadSymbols: Unable to get handle to lib: %s", error);
|
|
+ return false;
|
|
+ }
|
|
+ }
|
|
+ else
|
|
+ return true;
|
|
+
|
|
+#define INIT_PROC(PREFIX, PROC) do { \
|
|
+ g_##PREFIX##_vtable.PROC = (PREFIX##PROC##Proc) \
|
|
+ dlsym(m_dlHandle, #PREFIX #PROC); \
|
|
+ } while (0)
|
|
+
|
|
+#define INIT_PROC_CHECK(PREFIX, PROC) do { \
|
|
+ dlerror(); \
|
|
+ INIT_PROC(PREFIX, PROC); \
|
|
+ if (dlerror()) { \
|
|
+ dlclose(m_dlHandle); \
|
|
+ m_dlHandle = NULL; \
|
|
+ return false; \
|
|
+ } \
|
|
+ } while (0)
|
|
+
|
|
+#define XVBA_INIT_PROC(PROC) INIT_PROC_CHECK(XVBA, PROC)
|
|
+
|
|
+ XVBA_INIT_PROC(QueryExtension);
|
|
+ XVBA_INIT_PROC(CreateContext);
|
|
+ XVBA_INIT_PROC(DestroyContext);
|
|
+ XVBA_INIT_PROC(GetSessionInfo);
|
|
+ XVBA_INIT_PROC(CreateSurface);
|
|
+ XVBA_INIT_PROC(CreateGLSharedSurface);
|
|
+ XVBA_INIT_PROC(DestroySurface);
|
|
+ XVBA_INIT_PROC(CreateDecodeBuffers);
|
|
+ XVBA_INIT_PROC(DestroyDecodeBuffers);
|
|
+ XVBA_INIT_PROC(GetCapDecode);
|
|
+ XVBA_INIT_PROC(CreateDecode);
|
|
+ XVBA_INIT_PROC(DestroyDecode);
|
|
+ XVBA_INIT_PROC(StartDecodePicture);
|
|
+ XVBA_INIT_PROC(DecodePicture);
|
|
+ XVBA_INIT_PROC(EndDecodePicture);
|
|
+ XVBA_INIT_PROC(SyncSurface);
|
|
+ XVBA_INIT_PROC(GetSurface);
|
|
+ XVBA_INIT_PROC(TransferSurface);
|
|
+
|
|
+#undef XVBA_INIT_PROC
|
|
+#undef INIT_PROC
|
|
+
|
|
+ return true;
|
|
+}
|
|
+
|
|
+bool CXVBAContext::CreateContext()
|
|
+{
|
|
+ if (m_xvbaContext)
|
|
+ return true;
|
|
+
|
|
+ CLog::Log(LOGNOTICE,"XVBA::CreateContext - creating decoder context");
|
|
+
|
|
+ Drawable window;
|
|
+ { CSingleLock lock(g_graphicsContext);
|
|
+ if (!m_display)
|
|
+ m_display = XOpenDisplay(NULL);
|
|
+ window = 0;
|
|
+ }
|
|
+
|
|
+ int version;
|
|
+ if (!g_XVBA_vtable.QueryExtension(m_display, &version))
|
|
+ return false;
|
|
+ CLog::Log(LOGNOTICE,"XVBA::CreateContext - opening xvba version: %i", version);
|
|
+
|
|
+ // create XVBA Context
|
|
+ XVBA_Create_Context_Input contextInput;
|
|
+ XVBA_Create_Context_Output contextOutput;
|
|
+ contextInput.size = sizeof(contextInput);
|
|
+ contextInput.display = m_display;
|
|
+ contextInput.draw = window;
|
|
+ contextOutput.size = sizeof(contextOutput);
|
|
+ if(Success != g_XVBA_vtable.CreateContext(&contextInput, &contextOutput))
|
|
+ {
|
|
+ CLog::Log(LOGERROR,"XVBA::CreateContext - failed to create context");
|
|
+ return false;
|
|
+ }
|
|
+ m_xvbaContext = contextOutput.context;
|
|
+
|
|
+ return true;
|
|
+}
|
|
+
|
|
+void CXVBAContext::DestroyContext()
|
|
+{
|
|
+ if (!m_xvbaContext)
|
|
+ return;
|
|
+
|
|
+ g_XVBA_vtable.DestroyContext(m_xvbaContext);
|
|
+ m_xvbaContext = 0;
|
|
+// XCloseDisplay(m_display);
|
|
+}
|
|
+
|
|
+void *CXVBAContext::GetContext()
|
|
+{
|
|
+ return m_xvbaContext;
|
|
+}
|
|
+
|
|
+//-----------------------------------------------------------------------------
|
|
+//-----------------------------------------------------------------------------
|
|
+
|
|
+static unsigned int decoderId = 0;
|
|
+
|
|
+CDecoder::CDecoder() : m_xvbaOutput(&m_inMsgEvent)
|
|
+{
|
|
+ m_xvbaConfig.context = 0;
|
|
+ m_xvbaConfig.xvbaSession = 0;
|
|
+ m_xvbaConfig.videoSurfaces = &m_videoSurfaces;
|
|
+ m_xvbaConfig.videoSurfaceSec = &m_videoSurfaceSec;
|
|
+ m_xvbaConfig.apiSec = &m_apiSec;
|
|
+
|
|
+ m_displayState = XVBA_OPEN;
|
|
+}
|
|
+
|
|
+CDecoder::~CDecoder()
|
|
+{
|
|
+ Close();
|
|
+}
|
|
+
|
|
+typedef struct {
|
|
+ unsigned int size;
|
|
+ unsigned int num_of_decodecaps;
|
|
+ XVBADecodeCap decode_caps_list[];
|
|
+} XVBA_GetCapDecode_Output_Base;
|
|
+
|
|
+void CDecoder::OnLostDevice()
|
|
+{
|
|
+ CLog::Log(LOGNOTICE,"XVBA::OnLostDevice event");
|
|
+
|
|
+ CSingleLock lock(m_decoderSection);
|
|
+ DestroySession();
|
|
+ if (m_xvbaConfig.context)
|
|
+ m_xvbaConfig.context->Release();
|
|
+ m_xvbaConfig.context = 0;
|
|
+
|
|
+ m_displayState = XVBA_LOST;
|
|
+ m_displayEvent.Reset();
|
|
+}
|
|
+
|
|
+void CDecoder::OnResetDevice()
|
|
+{
|
|
+ CLog::Log(LOGNOTICE,"XVBA::OnResetDevice event");
|
|
+
|
|
+ CSingleLock lock(m_decoderSection);
|
|
+ if (m_displayState == XVBA_LOST)
|
|
+ {
|
|
+ m_displayState = XVBA_RESET;
|
|
+ lock.Leave();
|
|
+ m_displayEvent.Set();
|
|
+ }
|
|
+}
|
|
+
|
|
+bool CDecoder::Open(AVCodecContext* avctx, const enum PixelFormat fmt, unsigned int surfaces)
|
|
+{
|
|
+ std::string Vendor = g_Windowing.GetRenderVendor();
|
|
+ std::transform(Vendor.begin(), Vendor.end(), Vendor.begin(), ::tolower);
|
|
+ if (Vendor.compare(0, 3, "ati") != 0)
|
|
+ {
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ m_decoderId = decoderId++;
|
|
+
|
|
+ CLog::Log(LOGNOTICE,"(XVBA::Open) opening xvba decoder, id: %d", m_decoderId);
|
|
+
|
|
+ if(avctx->coded_width == 0
|
|
+ || avctx->coded_height == 0)
|
|
+ {
|
|
+ CLog::Log(LOGWARNING,"(XVBA) no width/height available, can't init");
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ if (!m_dllAvUtil.Load())
|
|
+ return false;
|
|
+
|
|
+ if (!CXVBAContext::EnsureContext(&m_xvbaConfig.context))
|
|
+ return false;
|
|
+
|
|
+ // xvba get session info
|
|
+ XVBA_GetSessionInfo_Input sessionInput;
|
|
+ XVBA_GetSessionInfo_Output sessionOutput;
|
|
+ sessionInput.size = sizeof(sessionInput);
|
|
+ sessionInput.context = m_xvbaConfig.context->GetContext();
|
|
+ sessionOutput.size = sizeof(sessionOutput);
|
|
+ if (Success != g_XVBA_vtable.GetSessionInfo(&sessionInput, &sessionOutput))
|
|
+ {
|
|
+ CLog::Log(LOGERROR,"(XVBA) can't get session info");
|
|
+ return false;
|
|
+ }
|
|
+ if (sessionOutput.getcapdecode_output_size == 0)
|
|
+ {
|
|
+ CLog::Log(LOGERROR,"(XVBA) session decode not supported");
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ // get decoder capabilities
|
|
+ XVBA_GetCapDecode_Input capInput;
|
|
+ XVBA_GetCapDecode_Output *capOutput;
|
|
+ capInput.size = sizeof(capInput);
|
|
+ capInput.context = m_xvbaConfig.context->GetContext();
|
|
+ capOutput = (XVBA_GetCapDecode_Output *)calloc(sessionOutput.getcapdecode_output_size, 1);
|
|
+ capOutput->size = sessionOutput.getcapdecode_output_size;
|
|
+ if (Success != g_XVBA_vtable.GetCapDecode(&capInput, capOutput))
|
|
+ {
|
|
+ CLog::Log(LOGERROR,"(XVBA) can't get decode capabilities");
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ int match = -1;
|
|
+ if (avctx->codec_id == CODEC_ID_H264)
|
|
+ {
|
|
+ // search for profile high
|
|
+ for (unsigned int i = 0; i < capOutput->num_of_decodecaps; ++i)
|
|
+ {
|
|
+ if (capOutput->decode_caps_list[i].capability_id == XVBA_H264 &&
|
|
+ capOutput->decode_caps_list[i].flags == XVBA_H264_HIGH)
|
|
+ {
|
|
+ match = (int) i;
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ if (match < 0)
|
|
+ {
|
|
+ CLog::Log(LOGNOTICE, "(XVBA::Open) - profile XVBA_H264_HIGH not found");
|
|
+ }
|
|
+ }
|
|
+ else if (avctx->codec_id == CODEC_ID_VC1)
|
|
+ {
|
|
+ // search for profile advanced
|
|
+ for (unsigned int i = 0; i < capOutput->num_of_decodecaps; ++i)
|
|
+ {
|
|
+ if (capOutput->decode_caps_list[i].capability_id == XVBA_VC1 &&
|
|
+ capOutput->decode_caps_list[i].flags == XVBA_VC1_ADVANCED)
|
|
+ {
|
|
+ match = (int) i;
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ if (match < 0)
|
|
+ {
|
|
+ CLog::Log(LOGNOTICE, "(XVBA::Open) - profile XVBA_VC1_ADVANCED not found");
|
|
+ }
|
|
+ }
|
|
+ else if (avctx->codec_id == CODEC_ID_MPEG2VIDEO)
|
|
+ {
|
|
+ // search for profile high
|
|
+ for (unsigned int i = 0; i < capOutput->num_of_decodecaps; ++i)
|
|
+ {
|
|
+ if (capOutput->decode_caps_list[i].capability_id == XVBA_MPEG2_VLD)
|
|
+ {
|
|
+ // XXX: uncomment when implemented
|
|
+ // match = (int) i;
|
|
+ // break;
|
|
+ }
|
|
+ }
|
|
+ if (match < 0)
|
|
+ {
|
|
+ CLog::Log(LOGNOTICE, "(XVBA::Open) - profile XVBA_MPEG2_VLD not found");
|
|
+ }
|
|
+ }
|
|
+ else if (avctx->codec_id == CODEC_ID_WMV3)
|
|
+ {
|
|
+ // search for profile high
|
|
+ for (unsigned int i = 0; i < capOutput->num_of_decodecaps; ++i)
|
|
+ {
|
|
+ if (capOutput->decode_caps_list[i].capability_id == XVBA_VC1 &&
|
|
+ capOutput->decode_caps_list[i].flags == XVBA_VC1_MAIN)
|
|
+ {
|
|
+ match = (int) i;
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ if (match < 0)
|
|
+ {
|
|
+ CLog::Log(LOGNOTICE, "(XVBA::Open) - profile XVBA_VC1_MAIN not found");
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (match < 0)
|
|
+ {
|
|
+ free(capOutput);
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ CLog::Log(LOGNOTICE,"(XVBA) using decoder capability id: %i flags: %i",
|
|
+ capOutput->decode_caps_list[match].capability_id,
|
|
+ capOutput->decode_caps_list[match].flags);
|
|
+ CLog::Log(LOGNOTICE,"(XVBA) using surface type: %x",
|
|
+ capOutput->decode_caps_list[match].surface_type);
|
|
+
|
|
+ m_xvbaConfig.decoderCap = capOutput->decode_caps_list[match];
|
|
+
|
|
+ free(capOutput);
|
|
+
|
|
+ // set some varables
|
|
+ m_xvbaConfig.xvbaSession = 0;
|
|
+ m_xvbaBufferPool.data_buffer = 0;
|
|
+ m_xvbaBufferPool.iq_matrix_buffer = 0;
|
|
+ m_xvbaBufferPool.picture_descriptor_buffer = 0;
|
|
+ m_presentPicture = 0;
|
|
+ m_xvbaConfig.numRenderBuffers = surfaces;
|
|
+ m_decoderThread = CThread::GetCurrentThreadId();
|
|
+ m_speed = DVD_PLAYSPEED_NORMAL;
|
|
+
|
|
+ if (1) //g_guiSettings.GetBool("videoplayer.usexvbasharedsurface"))
|
|
+ m_xvbaConfig.useSharedSurfaces = true;
|
|
+ else
|
|
+ m_xvbaConfig.useSharedSurfaces = false;
|
|
+
|
|
+ m_displayState = XVBA_OPEN;
|
|
+
|
|
+ // setup ffmpeg
|
|
+ avctx->thread_count = 1;
|
|
+ avctx->get_buffer = CDecoder::FFGetBuffer;
|
|
+ avctx->release_buffer = CDecoder::FFReleaseBuffer;
|
|
+ avctx->draw_horiz_band = CDecoder::FFDrawSlice;
|
|
+ avctx->slice_flags = SLICE_FLAG_CODED_ORDER|SLICE_FLAG_ALLOW_FIELD;
|
|
+
|
|
+ g_Windowing.Register(this);
|
|
+ return true;
|
|
+}
|
|
+
|
|
+void CDecoder::Close()
|
|
+{
|
|
+ CLog::Log(LOGNOTICE, "XVBA::Close - closing decoder, id: %d", m_decoderId);
|
|
+
|
|
+ if (!m_xvbaConfig.context)
|
|
+ return;
|
|
+
|
|
+ DestroySession();
|
|
+ if (m_xvbaConfig.context)
|
|
+ m_xvbaConfig.context->Release();
|
|
+ m_xvbaConfig.context = 0;
|
|
+
|
|
+ while (!m_videoSurfaces.empty())
|
|
+ {
|
|
+ xvba_render_state *render = m_videoSurfaces.back();
|
|
+ if(render->buffers_alllocated > 0)
|
|
+ m_dllAvUtil.av_free(render->buffers);
|
|
+ m_videoSurfaces.pop_back();
|
|
+ free(render);
|
|
+ }
|
|
+
|
|
+ g_Windowing.Unregister(this);
|
|
+ m_dllAvUtil.Unload();
|
|
+}
|
|
+
|
|
+long CDecoder::Release()
|
|
+{
|
|
+ // check if we should do some pre-cleanup here
|
|
+ // a second decoder might need resources
|
|
+ if (m_xvbaConfig.xvbaSession)
|
|
+ {
|
|
+ CSingleLock lock(m_decoderSection);
|
|
+ CLog::Log(LOGNOTICE,"XVBA::Release pre-cleanup");
|
|
+ DestroySession(true);
|
|
+ }
|
|
+ return IHardwareDecoder::Release();
|
|
+}
|
|
+
|
|
+long CDecoder::ReleasePicReference()
|
|
+{
|
|
+ return IHardwareDecoder::Release();
|
|
+}
|
|
+
|
|
+bool CDecoder::Supports(EINTERLACEMETHOD method)
|
|
+{
|
|
+ if(method == VS_INTERLACEMETHOD_AUTO)
|
|
+ return true;
|
|
+
|
|
+ if (1) //g_guiSettings.GetBool("videoplayer.usexvbasharedsurface"))
|
|
+ {
|
|
+ if (method == VS_INTERLACEMETHOD_XVBA)
|
|
+ return true;
|
|
+ }
|
|
+
|
|
+ return false;
|
|
+}
|
|
+
|
|
+void CDecoder::ResetState()
|
|
+{
|
|
+ m_displayState = XVBA_OPEN;
|
|
+}
|
|
+
|
|
+int CDecoder::Check(AVCodecContext* avctx)
|
|
+{
|
|
+ EDisplayState state;
|
|
+
|
|
+ { CSingleLock lock(m_decoderSection);
|
|
+ state = m_displayState;
|
|
+ }
|
|
+
|
|
+ if (state == XVBA_LOST)
|
|
+ {
|
|
+ CLog::Log(LOGNOTICE,"XVBA::Check waiting for display reset event");
|
|
+ if (!m_displayEvent.WaitMSec(2000))
|
|
+ {
|
|
+ CLog::Log(LOGERROR, "XVBA::Check - device didn't reset in reasonable time");
|
|
+ state = XVBA_RESET;;
|
|
+ }
|
|
+ else
|
|
+ { CSingleLock lock(m_decoderSection);
|
|
+ state = m_displayState;
|
|
+ }
|
|
+ }
|
|
+ if (state == XVBA_RESET || state == XVBA_ERROR)
|
|
+ {
|
|
+ CLog::Log(LOGNOTICE,"XVBA::Check - Attempting recovery");
|
|
+
|
|
+ CSingleLock gLock(g_graphicsContext);
|
|
+ CSingleLock lock(m_decoderSection);
|
|
+
|
|
+ DestroySession();
|
|
+ ResetState();
|
|
+ CXVBAContext::EnsureContext(&m_xvbaConfig.context);
|
|
+
|
|
+ if (state == XVBA_RESET)
|
|
+ return VC_FLUSHED;
|
|
+ else
|
|
+ return VC_ERROR;
|
|
+ }
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+void CDecoder::SetError(const char* function, const char* msg, int line)
|
|
+{
|
|
+ CLog::Log(LOGERROR, "XVBA::%s - %s, line %d", function, msg, line);
|
|
+ CSingleLock lock(m_decoderSection);
|
|
+ m_displayState = XVBA_ERROR;
|
|
+}
|
|
+
|
|
+bool CDecoder::CreateSession(AVCodecContext* avctx)
|
|
+{
|
|
+ m_xvbaConfig.surfaceWidth = (avctx->coded_width+15) & ~15;
|
|
+ m_xvbaConfig.surfaceHeight = (avctx->coded_height+15) & ~15;
|
|
+
|
|
+ m_xvbaConfig.vidWidth = avctx->width;
|
|
+ m_xvbaConfig.vidHeight = avctx->height;
|
|
+
|
|
+ XVBA_Create_Decode_Session_Input sessionInput;
|
|
+ XVBA_Create_Decode_Session_Output sessionOutput;
|
|
+
|
|
+ sessionInput.size = sizeof(sessionInput);
|
|
+ sessionInput.width = m_xvbaConfig.surfaceWidth;
|
|
+ sessionInput.height = m_xvbaConfig.surfaceHeight;
|
|
+ sessionInput.context = m_xvbaConfig.context->GetContext();
|
|
+ sessionInput.decode_cap = &m_xvbaConfig.decoderCap;
|
|
+ sessionOutput.size = sizeof(sessionOutput);
|
|
+
|
|
+ if (Success != g_XVBA_vtable.CreateDecode(&sessionInput, &sessionOutput))
|
|
+ {
|
|
+ SetError(__FUNCTION__, "failed to create decoder session", __LINE__);
|
|
+ CLog::Log(LOGERROR, "Decoder failed with following stats: m_surfaceWidth %u, m_surfaceHeight %u,"
|
|
+ " m_vidWidth %u, m_vidHeight %u, coded_width %d, coded_height %d",
|
|
+ m_xvbaConfig.surfaceWidth,
|
|
+ m_xvbaConfig.surfaceHeight,
|
|
+ m_xvbaConfig.vidWidth,
|
|
+ m_xvbaConfig.vidHeight,
|
|
+ avctx->coded_width,
|
|
+ avctx->coded_height);
|
|
+ return false;
|
|
+ }
|
|
+ m_xvbaConfig.xvbaSession = sessionOutput.session;
|
|
+
|
|
+ // create decode buffers
|
|
+ XVBA_Create_DecodeBuff_Input bufferInput;
|
|
+ XVBA_Create_DecodeBuff_Output bufferOutput;
|
|
+
|
|
+ bufferInput.size = sizeof(bufferInput);
|
|
+ bufferInput.session = m_xvbaConfig.xvbaSession;
|
|
+ bufferInput.buffer_type = XVBA_PICTURE_DESCRIPTION_BUFFER;
|
|
+ bufferInput.num_of_buffers = 1;
|
|
+ bufferOutput.size = sizeof(bufferOutput);
|
|
+ if (Success != g_XVBA_vtable.CreateDecodeBuffers(&bufferInput, &bufferOutput)
|
|
+ || bufferOutput.num_of_buffers_in_list != 1)
|
|
+ {
|
|
+ SetError(__FUNCTION__, "failed to create picture buffer", __LINE__);
|
|
+ return false;
|
|
+ }
|
|
+ m_xvbaBufferPool.picture_descriptor_buffer = bufferOutput.buffer_list;
|
|
+
|
|
+ // data buffer
|
|
+ bufferInput.buffer_type = XVBA_DATA_BUFFER;
|
|
+ if (Success != g_XVBA_vtable.CreateDecodeBuffers(&bufferInput, &bufferOutput)
|
|
+ || bufferOutput.num_of_buffers_in_list != 1)
|
|
+ {
|
|
+ SetError(__FUNCTION__, "failed to create data buffer", __LINE__);
|
|
+ return false;
|
|
+ }
|
|
+ m_xvbaBufferPool.data_buffer = bufferOutput.buffer_list;
|
|
+
|
|
+ // QO Buffer
|
|
+ bufferInput.buffer_type = XVBA_QM_BUFFER;
|
|
+ if (Success != g_XVBA_vtable.CreateDecodeBuffers(&bufferInput, &bufferOutput)
|
|
+ || bufferOutput.num_of_buffers_in_list != 1)
|
|
+ {
|
|
+ SetError(__FUNCTION__, "failed to create qm buffer", __LINE__);
|
|
+ return false;
|
|
+ }
|
|
+ m_xvbaBufferPool.iq_matrix_buffer = bufferOutput.buffer_list;
|
|
+
|
|
+
|
|
+ // initialize output
|
|
+ CSingleLock lock(g_graphicsContext);
|
|
+ m_xvbaConfig.stats = &m_bufferStats;
|
|
+ m_bufferStats.Reset();
|
|
+ m_xvbaOutput.Start();
|
|
+ Message *reply;
|
|
+ if (m_xvbaOutput.m_controlPort.SendOutMessageSync(COutputControlProtocol::INIT,
|
|
+ &reply,
|
|
+ 2000,
|
|
+ &m_xvbaConfig,
|
|
+ sizeof(m_xvbaConfig)))
|
|
+ {
|
|
+ bool success = reply->signal == COutputControlProtocol::ACC ? true : false;
|
|
+ reply->Release();
|
|
+ if (!success)
|
|
+ {
|
|
+ CLog::Log(LOGERROR, "XVBA::%s - vdpau output returned error", __FUNCTION__);
|
|
+ m_xvbaOutput.Dispose();
|
|
+ return false;
|
|
+ }
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ CLog::Log(LOGERROR, "XVBA::%s - failed to init output", __FUNCTION__);
|
|
+ m_xvbaOutput.Dispose();
|
|
+ return false;
|
|
+ }
|
|
+ m_inMsgEvent.Reset();
|
|
+
|
|
+ return true;
|
|
+}
|
|
+
|
|
+void CDecoder::DestroySession(bool precleanup /*= false*/)
|
|
+{
|
|
+ // wait for unfinished decoding jobs
|
|
+ XbmcThreads::EndTime timer;
|
|
+ if (m_xvbaConfig.xvbaSession)
|
|
+ {
|
|
+ for (unsigned int i = 0; i < m_videoSurfaces.size(); ++i)
|
|
+ {
|
|
+ xvba_render_state *render = m_videoSurfaces[i];
|
|
+ if (render->surface)
|
|
+ {
|
|
+ XVBA_Surface_Sync_Input syncInput;
|
|
+ XVBA_Surface_Sync_Output syncOutput;
|
|
+ syncInput.size = sizeof(syncInput);
|
|
+ syncInput.session = m_xvbaConfig.xvbaSession;
|
|
+ syncInput.surface = render->surface;
|
|
+ syncInput.query_status = XVBA_GET_SURFACE_STATUS;
|
|
+ syncOutput.size = sizeof(syncOutput);
|
|
+ timer.Set(1000);
|
|
+ while(!timer.IsTimePast())
|
|
+ {
|
|
+ if (Success != g_XVBA_vtable.SyncSurface(&syncInput, &syncOutput))
|
|
+ {
|
|
+ CLog::Log(LOGERROR,"XVBA::DestroySession - failed sync surface");
|
|
+ break;
|
|
+ }
|
|
+ if (!(syncOutput.status_flags & XVBA_STILL_PENDING))
|
|
+ break;
|
|
+ Sleep(10);
|
|
+ }
|
|
+ if (timer.IsTimePast())
|
|
+ CLog::Log(LOGERROR,"XVBA::DestroySession - unfinished decoding job");
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (precleanup)
|
|
+ {
|
|
+ Message *reply;
|
|
+ if (m_xvbaOutput.m_controlPort.SendOutMessageSync(COutputControlProtocol::PRECLEANUP,
|
|
+ &reply,
|
|
+ 2000))
|
|
+ {
|
|
+ bool success = reply->signal == COutputControlProtocol::ACC ? true : false;
|
|
+ reply->Release();
|
|
+ if (!success)
|
|
+ {
|
|
+ CLog::Log(LOGERROR, "XVBA::%s - pre-cleanup returned error", __FUNCTION__);
|
|
+ m_displayState = XVBA_ERROR;
|
|
+ }
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ CLog::Log(LOGERROR, "XVBA::%s - pre-cleanup timed out", __FUNCTION__);
|
|
+ m_displayState = XVBA_ERROR;
|
|
+ }
|
|
+ }
|
|
+ else
|
|
+ m_xvbaOutput.Dispose();
|
|
+
|
|
+ XVBA_Destroy_Decode_Buffers_Input bufInput;
|
|
+ bufInput.size = sizeof(bufInput);
|
|
+ bufInput.num_of_buffers_in_list = 1;
|
|
+ bufInput.session = m_xvbaConfig.xvbaSession;
|
|
+
|
|
+ for (unsigned int i=0; i<m_xvbaBufferPool.data_control_buffers.size() ; ++i)
|
|
+ {
|
|
+ bufInput.buffer_list = m_xvbaBufferPool.data_control_buffers[i];
|
|
+ g_XVBA_vtable.DestroyDecodeBuffers(&bufInput);
|
|
+ }
|
|
+ m_xvbaBufferPool.data_control_buffers.clear();
|
|
+
|
|
+ if (m_xvbaConfig.xvbaSession && m_xvbaBufferPool.data_buffer)
|
|
+ {
|
|
+ bufInput.buffer_list = m_xvbaBufferPool.data_buffer;
|
|
+ g_XVBA_vtable.DestroyDecodeBuffers(&bufInput);
|
|
+ }
|
|
+ m_xvbaBufferPool.data_buffer = 0;
|
|
+
|
|
+ if (m_xvbaConfig.xvbaSession && m_xvbaBufferPool.picture_descriptor_buffer)
|
|
+ {
|
|
+ bufInput.buffer_list = m_xvbaBufferPool.picture_descriptor_buffer;
|
|
+ g_XVBA_vtable.DestroyDecodeBuffers(&bufInput);
|
|
+ }
|
|
+ m_xvbaBufferPool.picture_descriptor_buffer = 0;
|
|
+
|
|
+ if (m_xvbaConfig.xvbaSession && m_xvbaBufferPool.iq_matrix_buffer)
|
|
+ {
|
|
+ bufInput.buffer_list = m_xvbaBufferPool.iq_matrix_buffer;
|
|
+ g_XVBA_vtable.DestroyDecodeBuffers(&bufInput);
|
|
+ }
|
|
+ m_xvbaBufferPool.iq_matrix_buffer = 0;
|
|
+
|
|
+ for (unsigned int i = 0; i < m_videoSurfaces.size(); ++i)
|
|
+ {
|
|
+ xvba_render_state *render = m_videoSurfaces[i];
|
|
+ if (m_xvbaConfig.xvbaSession && render->surface)
|
|
+ {
|
|
+ g_XVBA_vtable.DestroySurface(render->surface);
|
|
+ render->surface = 0;
|
|
+ render->state = 0;
|
|
+ render->picture_descriptor = 0;
|
|
+ render->iq_matrix = 0;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (m_xvbaConfig.xvbaSession)
|
|
+ g_XVBA_vtable.DestroyDecode(m_xvbaConfig.xvbaSession);
|
|
+ m_xvbaConfig.xvbaSession = 0;
|
|
+}
|
|
+
|
|
+bool CDecoder::IsSurfaceValid(xvba_render_state *render)
|
|
+{
|
|
+ // find render state in queue
|
|
+ bool found(false);
|
|
+ unsigned int i;
|
|
+ for(i = 0; i < m_videoSurfaces.size(); ++i)
|
|
+ {
|
|
+ if(m_videoSurfaces[i] == render)
|
|
+ {
|
|
+ found = true;
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ if (!found)
|
|
+ {
|
|
+ CLog::Log(LOGERROR,"%s - video surface not found", __FUNCTION__);
|
|
+ return false;
|
|
+ }
|
|
+ if (m_videoSurfaces[i]->surface == 0)
|
|
+ {
|
|
+ m_videoSurfaces[i]->state = 0;
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ return true;
|
|
+}
|
|
+
|
|
+bool CDecoder::EnsureDataControlBuffers(unsigned int num)
|
|
+{
|
|
+ if (m_xvbaBufferPool.data_control_buffers.size() >= num)
|
|
+ return true;
|
|
+
|
|
+ unsigned int missing = num - m_xvbaBufferPool.data_control_buffers.size();
|
|
+
|
|
+ XVBA_Create_DecodeBuff_Input bufferInput;
|
|
+ XVBA_Create_DecodeBuff_Output bufferOutput;
|
|
+ bufferInput.size = sizeof(bufferInput);
|
|
+ bufferInput.session = m_xvbaConfig.xvbaSession;
|
|
+ bufferInput.buffer_type = XVBA_DATA_CTRL_BUFFER;
|
|
+ bufferInput.num_of_buffers = 1;
|
|
+ bufferOutput.size = sizeof(bufferOutput);
|
|
+
|
|
+ for (unsigned int i=0; i<missing; ++i)
|
|
+ {
|
|
+ { CSingleLock lock(m_apiSec);
|
|
+ if (Success != g_XVBA_vtable.CreateDecodeBuffers(&bufferInput, &bufferOutput)
|
|
+ || bufferOutput.num_of_buffers_in_list != 1)
|
|
+ {
|
|
+ SetError(__FUNCTION__, "failed to create data control buffer", __LINE__);
|
|
+ return false;
|
|
+ }
|
|
+ }
|
|
+ m_xvbaBufferPool.data_control_buffers.push_back(bufferOutput.buffer_list);
|
|
+ }
|
|
+
|
|
+ return true;
|
|
+}
|
|
+
|
|
+void CDecoder::FFReleaseBuffer(AVCodecContext *avctx, AVFrame *pic)
|
|
+{
|
|
+ CDVDVideoCodecFFmpeg* ctx = (CDVDVideoCodecFFmpeg*)avctx->opaque;
|
|
+ CDecoder* xvba = (CDecoder*)ctx->GetHardware();
|
|
+ unsigned int i;
|
|
+
|
|
+ CSingleLock lock(xvba->m_decoderSection);
|
|
+
|
|
+ xvba_render_state * render = NULL;
|
|
+ render = (xvba_render_state*)pic->data[0];
|
|
+ if(!render)
|
|
+ {
|
|
+ CLog::Log(LOGERROR, "XVBA::FFReleaseBuffer - invalid context handle provided");
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ for(i=0; i<4; i++)
|
|
+ pic->data[i]= NULL;
|
|
+
|
|
+ // find render state in queue
|
|
+ if (!xvba->IsSurfaceValid(render))
|
|
+ {
|
|
+ CLog::Log(LOGDEBUG, "XVBA::FFReleaseBuffer - ignoring invalid buffer");
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ render->state &= ~FF_XVBA_STATE_USED_FOR_REFERENCE;
|
|
+}
|
|
+
|
|
+void CDecoder::FFDrawSlice(struct AVCodecContext *avctx,
|
|
+ const AVFrame *src, int offset[4],
|
|
+ int y, int type, int height)
|
|
+{
|
|
+ CDVDVideoCodecFFmpeg* ctx = (CDVDVideoCodecFFmpeg*)avctx->opaque;
|
|
+ CDecoder* xvba = (CDecoder*)ctx->GetHardware();
|
|
+
|
|
+ CSingleLock lock(xvba->m_decoderSection);
|
|
+
|
|
+ if(xvba->m_displayState != XVBA_OPEN)
|
|
+ return;
|
|
+
|
|
+ if(src->linesize[0] || src->linesize[1] || src->linesize[2]
|
|
+ || offset[0] || offset[1] || offset[2])
|
|
+ {
|
|
+ CLog::Log(LOGERROR, "XVBA::FFDrawSlice - invalid linesizes or offsets provided");
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ xvba_render_state * render;
|
|
+
|
|
+ render = (xvba_render_state*)src->data[0];
|
|
+ if(!render)
|
|
+ {
|
|
+ CLog::Log(LOGERROR, "XVBA::FFDrawSlice - invalid context handle provided");
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ // ffmpeg vc-1 decoder does not flush, make sure the data buffer is still valid
|
|
+ if (!xvba->IsSurfaceValid(render))
|
|
+ {
|
|
+ CLog::Log(LOGWARNING, "XVBA::FFDrawSlice - ignoring invalid buffer");
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ // decoding
|
|
+ XVBA_Decode_Picture_Start_Input startInput;
|
|
+ startInput.size = sizeof(startInput);
|
|
+ startInput.session = xvba->m_xvbaConfig.xvbaSession;
|
|
+ startInput.target_surface = render->surface;
|
|
+ { CSingleLock lock(xvba->m_apiSec);
|
|
+ if (Success != g_XVBA_vtable.StartDecodePicture(&startInput))
|
|
+ {
|
|
+ xvba->SetError(__FUNCTION__, "failed to start decoding", __LINE__);
|
|
+ return;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ XVBA_Decode_Picture_Input picInput;
|
|
+ picInput.size = sizeof(picInput);
|
|
+ picInput.session = xvba->m_xvbaConfig.xvbaSession;
|
|
+ XVBABufferDescriptor *list[2];
|
|
+ picInput.buffer_list = list;
|
|
+ list[0] = xvba->m_xvbaBufferPool.picture_descriptor_buffer;
|
|
+ picInput.num_of_buffers_in_list = 1;
|
|
+ if (avctx->codec_id == CODEC_ID_H264)
|
|
+ {
|
|
+ list[1] = xvba->m_xvbaBufferPool.iq_matrix_buffer;
|
|
+ picInput.num_of_buffers_in_list = 2;
|
|
+ }
|
|
+
|
|
+ { CSingleLock lock(xvba->m_apiSec);
|
|
+ if (Success != g_XVBA_vtable.DecodePicture(&picInput))
|
|
+ {
|
|
+ xvba->SetError(__FUNCTION__, "failed to decode picture 1", __LINE__);
|
|
+ return;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (!xvba->EnsureDataControlBuffers(render->num_slices))
|
|
+ return;
|
|
+
|
|
+ XVBADataCtrl *dataControl;
|
|
+ int location = 0;
|
|
+ xvba->m_xvbaBufferPool.data_buffer->data_size_in_buffer = 0;
|
|
+ for (unsigned int j = 0; j < render->num_slices; ++j)
|
|
+ {
|
|
+ int startCodeSize = 0;
|
|
+ uint8_t startCode[] = {0x00,0x00,0x01};
|
|
+ if (avctx->codec_id == CODEC_ID_H264)
|
|
+ {
|
|
+ startCodeSize = 3;
|
|
+ memcpy((uint8_t*)xvba->m_xvbaBufferPool.data_buffer->bufferXVBA+location,
|
|
+ startCode, 3);
|
|
+ }
|
|
+ else if (avctx->codec_id == CODEC_ID_VC1 &&
|
|
+ (memcmp(render->buffers[j].buffer, startCode, 3) != 0))
|
|
+ {
|
|
+ startCodeSize = 4;
|
|
+ uint8_t sdf = 0x0d;
|
|
+ memcpy((uint8_t*)xvba->m_xvbaBufferPool.data_buffer->bufferXVBA+location,
|
|
+ startCode, 3);
|
|
+ memcpy((uint8_t*)xvba->m_xvbaBufferPool.data_buffer->bufferXVBA+location+3,
|
|
+ &sdf, 1);
|
|
+ }
|
|
+ // check for potential buffer overwrite
|
|
+ unsigned int bytesToCopy = render->buffers[j].size;
|
|
+ unsigned int freeBufferSize = xvba->m_xvbaBufferPool.data_buffer->buffer_size -
|
|
+ xvba->m_xvbaBufferPool.data_buffer->data_size_in_buffer;
|
|
+ if (bytesToCopy >= freeBufferSize)
|
|
+ {
|
|
+ xvba->SetError(__FUNCTION__, "bitstream buffer too large, maybe corrupted packet", __LINE__);
|
|
+ return;
|
|
+ }
|
|
+ memcpy((uint8_t*)xvba->m_xvbaBufferPool.data_buffer->bufferXVBA+location+startCodeSize,
|
|
+ render->buffers[j].buffer,
|
|
+ render->buffers[j].size);
|
|
+ dataControl = (XVBADataCtrl*)xvba->m_xvbaBufferPool.data_control_buffers[j]->bufferXVBA;
|
|
+ dataControl->SliceDataLocation = location;
|
|
+ dataControl->SliceBytesInBuffer = render->buffers[j].size+startCodeSize;
|
|
+ dataControl->SliceBitsInBuffer = dataControl->SliceBytesInBuffer * 8;
|
|
+ xvba->m_xvbaBufferPool.data_buffer->data_size_in_buffer += dataControl->SliceBytesInBuffer;
|
|
+ location += dataControl->SliceBytesInBuffer;
|
|
+ }
|
|
+
|
|
+ int bufSize = xvba->m_xvbaBufferPool.data_buffer->data_size_in_buffer;
|
|
+ int padding = bufSize % 128;
|
|
+ if (padding)
|
|
+ {
|
|
+ padding = 128 - padding;
|
|
+ xvba->m_xvbaBufferPool.data_buffer->data_size_in_buffer += padding;
|
|
+ memset((uint8_t*)xvba->m_xvbaBufferPool.data_buffer->bufferXVBA+bufSize,0,padding);
|
|
+ }
|
|
+
|
|
+ picInput.num_of_buffers_in_list = 2;
|
|
+ for (unsigned int i = 0; i < render->num_slices; ++i)
|
|
+ {
|
|
+ list[0] = xvba->m_xvbaBufferPool.data_buffer;
|
|
+ list[0]->data_offset = 0;
|
|
+ list[1] = xvba->m_xvbaBufferPool.data_control_buffers[i];
|
|
+ list[1]->data_size_in_buffer = sizeof(*dataControl);
|
|
+ { CSingleLock lock(xvba->m_apiSec);
|
|
+ if (Success != g_XVBA_vtable.DecodePicture(&picInput))
|
|
+ {
|
|
+ xvba->SetError(__FUNCTION__, "failed to decode picture 2", __LINE__);
|
|
+ return;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ XVBA_Decode_Picture_End_Input endInput;
|
|
+ endInput.size = sizeof(endInput);
|
|
+ endInput.session = xvba->m_xvbaConfig.xvbaSession;
|
|
+ { CSingleLock lock(xvba->m_apiSec);
|
|
+ if (Success != g_XVBA_vtable.EndDecodePicture(&endInput))
|
|
+ {
|
|
+ xvba->SetError(__FUNCTION__, "failed to decode picture 3", __LINE__);
|
|
+ return;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ // decode sync and error
|
|
+ XVBA_Surface_Sync_Input syncInput;
|
|
+ XVBA_Surface_Sync_Output syncOutput;
|
|
+ syncInput.size = sizeof(syncInput);
|
|
+ syncInput.session = xvba->m_xvbaConfig.xvbaSession;
|
|
+ syncInput.surface = render->surface;
|
|
+ syncInput.query_status = XVBA_GET_SURFACE_STATUS;
|
|
+ syncOutput.size = sizeof(syncOutput);
|
|
+ int64_t start = CurrentHostCounter();
|
|
+ while (1)
|
|
+ {
|
|
+ { CSingleLock lock(xvba->m_apiSec);
|
|
+ if (Success != g_XVBA_vtable.SyncSurface(&syncInput, &syncOutput))
|
|
+ {
|
|
+ xvba->SetError(__FUNCTION__, "failed sync surface 1", __LINE__);
|
|
+ return;
|
|
+ }
|
|
+ }
|
|
+ if (!(syncOutput.status_flags & XVBA_STILL_PENDING))
|
|
+ break;
|
|
+ if (CurrentHostCounter() - start > CurrentHostFrequency())
|
|
+ {
|
|
+ xvba->SetError(__FUNCTION__, "timed out waiting for surface", __LINE__);
|
|
+ break;
|
|
+ }
|
|
+ usleep(100);
|
|
+ }
|
|
+ render->state |= FF_XVBA_STATE_DECODED;
|
|
+}
|
|
+
|
|
+int CDecoder::FFGetBuffer(AVCodecContext *avctx, AVFrame *pic)
|
|
+{
|
|
+ CDVDVideoCodecFFmpeg* ctx = (CDVDVideoCodecFFmpeg*)avctx->opaque;
|
|
+ CDecoder* xvba = (CDecoder*)ctx->GetHardware();
|
|
+
|
|
+ pic->data[0] =
|
|
+ pic->data[1] =
|
|
+ pic->data[2] =
|
|
+ pic->data[3] = 0;
|
|
+
|
|
+ pic->linesize[0] =
|
|
+ pic->linesize[1] =
|
|
+ pic->linesize[2] =
|
|
+ pic->linesize[3] = 0;
|
|
+
|
|
+ CSingleLock lock(xvba->m_decoderSection);
|
|
+
|
|
+ if(xvba->m_displayState != XVBA_OPEN)
|
|
+ return -1;
|
|
+
|
|
+ if (xvba->m_xvbaConfig.xvbaSession == 0)
|
|
+ {
|
|
+ if (!xvba->CreateSession(avctx))
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ xvba_render_state * render = NULL;
|
|
+ // find unused surface
|
|
+ { CSingleLock lock(xvba->m_videoSurfaceSec);
|
|
+ for(unsigned int i = 0; i < xvba->m_videoSurfaces.size(); ++i)
|
|
+ {
|
|
+ if(!(xvba->m_videoSurfaces[i]->state & (FF_XVBA_STATE_USED_FOR_REFERENCE | FF_XVBA_STATE_USED_FOR_RENDER)))
|
|
+ {
|
|
+ render = xvba->m_videoSurfaces[i];
|
|
+ render->state = 0;
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ // create a new render state
|
|
+ if (render == NULL)
|
|
+ {
|
|
+ render = (xvba_render_state*)calloc(sizeof(xvba_render_state), 1);
|
|
+ if (render == NULL)
|
|
+ {
|
|
+ CLog::Log(LOGERROR, "XVBA::FFGetBuffer - calloc failed");
|
|
+ return -1;
|
|
+ }
|
|
+ render->surface = 0;
|
|
+ render->buffers_alllocated = 0;
|
|
+ CSingleLock lock(xvba->m_videoSurfaceSec);
|
|
+ xvba->m_videoSurfaces.push_back(render);
|
|
+ }
|
|
+
|
|
+ // create a new surface
|
|
+ if (render->surface == 0)
|
|
+ {
|
|
+ XVBA_Create_Surface_Input surfaceInput;
|
|
+ XVBA_Create_Surface_Output surfaceOutput;
|
|
+ surfaceInput.size = sizeof(surfaceInput);
|
|
+ surfaceInput.surface_type = xvba->m_xvbaConfig.decoderCap.surface_type;
|
|
+ surfaceInput.width = xvba->m_xvbaConfig.surfaceWidth;
|
|
+ surfaceInput.height = xvba->m_xvbaConfig.surfaceHeight;
|
|
+ surfaceInput.session = xvba->m_xvbaConfig.xvbaSession;
|
|
+ surfaceOutput.size = sizeof(surfaceOutput);
|
|
+ { CSingleLock lock(xvba->m_apiSec);
|
|
+ if (Success != g_XVBA_vtable.CreateSurface(&surfaceInput, &surfaceOutput))
|
|
+ {
|
|
+ xvba->SetError(__FUNCTION__, "failed to create video surface", __LINE__);
|
|
+ return -1;
|
|
+ }
|
|
+ }
|
|
+ render->surface = surfaceOutput.surface;
|
|
+ render->picture_descriptor = (XVBAPictureDescriptor *)xvba->m_xvbaBufferPool.picture_descriptor_buffer->bufferXVBA;
|
|
+ render->iq_matrix = (XVBAQuantMatrixAvc *)xvba->m_xvbaBufferPool.iq_matrix_buffer->bufferXVBA;
|
|
+ CLog::Log(LOGDEBUG, "XVBA::FFGetBuffer - created video surface");
|
|
+ }
|
|
+
|
|
+ if (render == NULL)
|
|
+ return -1;
|
|
+
|
|
+ pic->data[0] = (uint8_t*)render;
|
|
+
|
|
+ pic->type= FF_BUFFER_TYPE_USER;
|
|
+
|
|
+ render->state |= FF_XVBA_STATE_USED_FOR_REFERENCE;
|
|
+ render->state &= ~FF_XVBA_STATE_DECODED;
|
|
+ pic->reordered_opaque= avctx->reordered_opaque;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+int CDecoder::Decode(AVCodecContext* avctx, AVFrame* frame)
|
|
+{
|
|
+ int result = Check(avctx);
|
|
+ if (result)
|
|
+ return result;
|
|
+
|
|
+ CSingleLock lock(m_decoderSection);
|
|
+
|
|
+ if(frame)
|
|
+ { // we have a new frame from decoder
|
|
+
|
|
+ xvba_render_state * render = (xvba_render_state*)frame->data[0];
|
|
+ if(!render)
|
|
+ {
|
|
+ CLog::Log(LOGERROR, "XVBA::Decode - no render buffer");
|
|
+ return VC_ERROR;
|
|
+ }
|
|
+
|
|
+ // ffmpeg vc-1 decoder does not flush, make sure the data buffer is still valid
|
|
+ if (!IsSurfaceValid(render))
|
|
+ {
|
|
+ CLog::Log(LOGWARNING, "XVBA::Decode - ignoring invalid buffer");
|
|
+ return VC_BUFFER;
|
|
+ }
|
|
+ if (!(render->state & FF_XVBA_STATE_DECODED))
|
|
+ {
|
|
+ CLog::Log(LOGDEBUG, "XVBA::Decode - ffmpeg failed");
|
|
+ return VC_BUFFER;
|
|
+ }
|
|
+
|
|
+ CSingleLock lock(m_videoSurfaceSec);
|
|
+ render->state |= FF_XVBA_STATE_USED_FOR_RENDER;
|
|
+ lock.Leave();
|
|
+
|
|
+ // send frame to output for processing
|
|
+ CXvbaDecodedPicture pic;
|
|
+ memset(&pic.DVDPic, 0, sizeof(pic.DVDPic));
|
|
+ ((CDVDVideoCodecFFmpeg*)avctx->opaque)->GetPictureCommon(&pic.DVDPic);
|
|
+ pic.render = render;
|
|
+ m_bufferStats.IncDecoded();
|
|
+ m_xvbaOutput.m_dataPort.SendOutMessage(COutputDataProtocol::NEWFRAME, &pic, sizeof(pic));
|
|
+
|
|
+ m_codecControl = pic.DVDPic.iFlags & (DVP_FLAG_DRAIN | DVP_FLAG_NO_POSTPROC);
|
|
+ }
|
|
+
|
|
+ int retval = 0;
|
|
+ uint16_t decoded, processed, render;
|
|
+ Message *msg;
|
|
+ while (m_xvbaOutput.m_controlPort.ReceiveInMessage(&msg))
|
|
+ {
|
|
+ if (msg->signal == COutputControlProtocol::ERROR)
|
|
+ {
|
|
+ m_displayState = XVBA_ERROR;
|
|
+ retval |= VC_ERROR;
|
|
+ }
|
|
+ msg->Release();
|
|
+ }
|
|
+
|
|
+ m_bufferStats.Get(decoded, processed, render);
|
|
+
|
|
+ uint64_t startTime = CurrentHostCounter();
|
|
+ while (!retval)
|
|
+ {
|
|
+ if (m_xvbaOutput.m_dataPort.ReceiveInMessage(&msg))
|
|
+ {
|
|
+ if (msg->signal == COutputDataProtocol::PICTURE)
|
|
+ {
|
|
+ if (m_presentPicture)
|
|
+ {
|
|
+ m_presentPicture->ReturnUnused();
|
|
+ m_presentPicture = 0;
|
|
+ }
|
|
+
|
|
+ m_presentPicture = *(CXvbaRenderPicture**)msg->data;
|
|
+ m_presentPicture->xvba = this;
|
|
+ m_bufferStats.DecRender();
|
|
+ m_bufferStats.Get(decoded, processed, render);
|
|
+ retval |= VC_PICTURE;
|
|
+ }
|
|
+ msg->Release();
|
|
+ }
|
|
+ else if (m_xvbaOutput.m_controlPort.ReceiveInMessage(&msg))
|
|
+ {
|
|
+ if (msg->signal == COutputControlProtocol::STATS)
|
|
+ {
|
|
+ m_bufferStats.Get(decoded, processed, render);
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ m_displayState = XVBA_ERROR;
|
|
+ retval |= VC_ERROR;
|
|
+ }
|
|
+ msg->Release();
|
|
+ }
|
|
+
|
|
+ if ((m_codecControl & DVP_FLAG_DRAIN))
|
|
+ {
|
|
+ if (decoded + processed + render < 2)
|
|
+ {
|
|
+ retval |= VC_BUFFER;
|
|
+ }
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ if (decoded + processed + render < 4)
|
|
+ {
|
|
+ retval |= VC_BUFFER;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (!retval && !m_inMsgEvent.WaitMSec(2000))
|
|
+ break;
|
|
+ }
|
|
+ uint64_t diff = CurrentHostCounter() - startTime;
|
|
+ if (retval & VC_PICTURE)
|
|
+ {
|
|
+ m_bufferStats.SetParams(diff, m_speed);
|
|
+ if (diff*1000/CurrentHostFrequency() > 50)
|
|
+ CLog::Log(LOGDEBUG,"XVBA::Decode long wait: %d", (int)((diff*1000)/CurrentHostFrequency()));
|
|
+ }
|
|
+
|
|
+ if (!retval)
|
|
+ {
|
|
+ CLog::Log(LOGERROR, "XVBA::%s - timed out waiting for output message", __FUNCTION__);
|
|
+ m_displayState = XVBA_ERROR;
|
|
+ retval |= VC_ERROR;
|
|
+ }
|
|
+
|
|
+ return retval;
|
|
+
|
|
+}
|
|
+
|
|
+bool CDecoder::GetPicture(AVCodecContext* avctx, AVFrame* frame, DVDVideoPicture* picture)
|
|
+{
|
|
+ CSingleLock lock(m_decoderSection);
|
|
+
|
|
+ if (m_displayState != XVBA_OPEN)
|
|
+ return false;
|
|
+
|
|
+ *picture = m_presentPicture->DVDPic;
|
|
+ picture->xvba = m_presentPicture;
|
|
+
|
|
+ return true;
|
|
+}
|
|
+
|
|
+void CDecoder::ReturnRenderPicture(CXvbaRenderPicture *renderPic)
|
|
+{
|
|
+ m_xvbaOutput.m_dataPort.SendOutMessage(COutputDataProtocol::RETURNPIC, &renderPic, sizeof(renderPic));
|
|
+}
|
|
+
|
|
+
|
|
+//void CDecoder::CopyYV12(int index, uint8_t *dest)
|
|
+//{
|
|
+// CSharedLock lock(m_decoderSection);
|
|
+//
|
|
+// { CSharedLock dLock(m_displaySection);
|
|
+// if(m_displayState != XVBA_OPEN)
|
|
+// return;
|
|
+// }
|
|
+//
|
|
+// if (!m_flipBuffer[index].outPic)
|
|
+// {
|
|
+// CLog::Log(LOGWARNING, "XVBA::Present: present picture is NULL");
|
|
+// return;
|
|
+// }
|
|
+//
|
|
+// XVBA_GetSurface_Target target;
|
|
+// target.size = sizeof(target);
|
|
+// target.surfaceType = XVBA_YV12;
|
|
+// target.flag = XVBA_FRAME;
|
|
+//
|
|
+// XVBA_Get_Surface_Input input;
|
|
+// input.size = sizeof(input);
|
|
+// input.session = m_xvbaSession;
|
|
+// input.src_surface = m_flipBuffer[index].outPic->render->surface;
|
|
+// input.target_buffer = dest;
|
|
+// input.target_pitch = m_surfaceWidth;
|
|
+// input.target_width = m_surfaceWidth;
|
|
+// input.target_height = m_surfaceHeight;
|
|
+// input.target_parameter = target;
|
|
+// { CSingleLock lock(m_apiSec);
|
|
+// if (Success != g_XVBA_vtable.GetSurface(&input))
|
|
+// {
|
|
+// CLog::Log(LOGERROR,"(XVBA::CopyYV12) failed to get surface");
|
|
+// }
|
|
+// }
|
|
+//}
|
|
+
|
|
+void CDecoder::Reset()
|
|
+{
|
|
+ CSingleLock lock(m_decoderSection);
|
|
+
|
|
+ if (!m_xvbaConfig.xvbaSession)
|
|
+ return;
|
|
+
|
|
+ Message *reply;
|
|
+ if (m_xvbaOutput.m_controlPort.SendOutMessageSync(COutputControlProtocol::FLUSH,
|
|
+ &reply,
|
|
+ 2000))
|
|
+ {
|
|
+ bool success = reply->signal == COutputControlProtocol::ACC ? true : false;
|
|
+ reply->Release();
|
|
+ if (!success)
|
|
+ {
|
|
+ CLog::Log(LOGERROR, "XVBA::%s - flush returned error", __FUNCTION__);
|
|
+ m_displayState = XVBA_ERROR;
|
|
+ }
|
|
+ else
|
|
+ m_bufferStats.Reset();
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ CLog::Log(LOGERROR, "XVBA::%s - flush timed out", __FUNCTION__);
|
|
+ m_displayState = XVBA_ERROR;
|
|
+ }
|
|
+}
|
|
+
|
|
+bool CDecoder::CanSkipDeint()
|
|
+{
|
|
+ return m_bufferStats.CanSkipDeint();
|
|
+}
|
|
+
|
|
+void CDecoder::SetSpeed(int speed)
|
|
+{
|
|
+ m_speed = speed;
|
|
+}
|
|
+
|
|
+//-----------------------------------------------------------------------------
|
|
+// RenderPicture
|
|
+//-----------------------------------------------------------------------------
|
|
+
|
|
+CXvbaRenderPicture* CXvbaRenderPicture::Acquire()
|
|
+{
|
|
+ CSingleLock lock(*renderPicSection);
|
|
+
|
|
+ if (refCount == 0)
|
|
+ xvba->Acquire();
|
|
+
|
|
+ refCount++;
|
|
+ return this;
|
|
+}
|
|
+
|
|
+long CXvbaRenderPicture::Release()
|
|
+{
|
|
+ CSingleLock lock(*renderPicSection);
|
|
+
|
|
+ refCount--;
|
|
+ if (refCount > 0)
|
|
+ return refCount;
|
|
+
|
|
+ lock.Leave();
|
|
+ xvba->ReturnRenderPicture(this);
|
|
+ xvba->ReleasePicReference();
|
|
+
|
|
+ return refCount;
|
|
+}
|
|
+
|
|
+void CXvbaRenderPicture::ReturnUnused()
|
|
+{
|
|
+ { CSingleLock lock(*renderPicSection);
|
|
+ if (refCount > 0)
|
|
+ return;
|
|
+ }
|
|
+ if (xvba)
|
|
+ xvba->ReturnRenderPicture(this);
|
|
+}
|
|
+
|
|
+//-----------------------------------------------------------------------------
|
|
+// Output
|
|
+//-----------------------------------------------------------------------------
|
|
+COutput::COutput(CEvent *inMsgEvent) :
|
|
+ CThread("XVBA Output Thread"),
|
|
+ m_controlPort("OutputControlPort", inMsgEvent, &m_outMsgEvent),
|
|
+ m_dataPort("OutputDataPort", inMsgEvent, &m_outMsgEvent)
|
|
+{
|
|
+ m_inMsgEvent = inMsgEvent;
|
|
+
|
|
+ CXvbaRenderPicture pic;
|
|
+ pic.renderPicSection = &m_bufferPool.renderPicSec;
|
|
+ pic.refCount = 0;
|
|
+ for (unsigned int i = 0; i < NUM_RENDER_PICS; i++)
|
|
+ {
|
|
+ m_bufferPool.allRenderPics.push_back(pic);
|
|
+ }
|
|
+ for (unsigned int i = 0; i < m_bufferPool.allRenderPics.size(); ++i)
|
|
+ {
|
|
+ m_bufferPool.freeRenderPics.push_back(&m_bufferPool.allRenderPics[i]);
|
|
+ }
|
|
+}
|
|
+
|
|
+void COutput::Start()
|
|
+{
|
|
+ Create();
|
|
+}
|
|
+
|
|
+COutput::~COutput()
|
|
+{
|
|
+ Dispose();
|
|
+
|
|
+ m_bufferPool.freeRenderPics.clear();
|
|
+ m_bufferPool.usedRenderPics.clear();
|
|
+ m_bufferPool.allRenderPics.clear();
|
|
+}
|
|
+
|
|
+void COutput::Dispose()
|
|
+{
|
|
+ CSingleLock lock(g_graphicsContext);
|
|
+ m_bStop = true;
|
|
+ m_outMsgEvent.Set();
|
|
+ StopThread();
|
|
+ m_controlPort.Purge();
|
|
+ m_dataPort.Purge();
|
|
+}
|
|
+
|
|
+void COutput::OnStartup()
|
|
+{
|
|
+ CLog::Log(LOGNOTICE, "COutput::OnStartup: Output Thread created");
|
|
+}
|
|
+
|
|
+void COutput::OnExit()
|
|
+{
|
|
+ CLog::Log(LOGNOTICE, "COutput::OnExit: Output Thread terminated");
|
|
+}
|
|
+
|
|
+enum OUTPUT_STATES
|
|
+{
|
|
+ O_TOP = 0, // 0
|
|
+ O_TOP_ERROR, // 1
|
|
+ O_TOP_UNCONFIGURED, // 2
|
|
+ O_TOP_CONFIGURED, // 3
|
|
+ O_TOP_CONFIGURED_WAIT_RES1, // 4
|
|
+ O_TOP_CONFIGURED_WAIT_DEC, // 5
|
|
+ O_TOP_CONFIGURED_STEP1, // 6
|
|
+ O_TOP_CONFIGURED_WAIT_RES2, // 7
|
|
+ O_TOP_CONFIGURED_STEP2, // 8
|
|
+};
|
|
+
|
|
+int OUTPUT_parentStates[] = {
|
|
+ -1,
|
|
+ 0, //TOP_ERROR
|
|
+ 0, //TOP_UNCONFIGURED
|
|
+ 0, //TOP_CONFIGURED
|
|
+ 3, //TOP_CONFIGURED_WAIT_RES1
|
|
+ 3, //TOP_CONFIGURED_WAIT_DEC
|
|
+ 3, //TOP_CONFIGURED_STEP1
|
|
+ 3, //TOP_CONFIGURED_WAIT_RES2
|
|
+ 3, //TOP_CONFIGURED_STEP2
|
|
+};
|
|
+
|
|
+void COutput::StateMachine(int signal, Protocol *port, Message *msg)
|
|
+{
|
|
+ for (int state = m_state; ; state = OUTPUT_parentStates[state])
|
|
+ {
|
|
+ switch (state)
|
|
+ {
|
|
+ case O_TOP: // TOP
|
|
+ if (port == &m_controlPort)
|
|
+ {
|
|
+ switch (signal)
|
|
+ {
|
|
+ case COutputControlProtocol::FLUSH:
|
|
+ msg->Reply(COutputControlProtocol::ACC);
|
|
+ return;
|
|
+ case COutputControlProtocol::PRECLEANUP:
|
|
+ msg->Reply(COutputControlProtocol::ACC);
|
|
+ return;
|
|
+ default:
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ else if (port == &m_dataPort)
|
|
+ {
|
|
+ switch (signal)
|
|
+ {
|
|
+ case COutputDataProtocol::RETURNPIC:
|
|
+ CXvbaRenderPicture *pic;
|
|
+ pic = *((CXvbaRenderPicture**)msg->data);
|
|
+ ProcessReturnPicture(pic);
|
|
+ return;
|
|
+ default:
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ {
|
|
+ std::string portName = port == NULL ? "timer" : port->portName;
|
|
+ CLog::Log(LOGWARNING, "COutput::%s - signal: %d form port: %s not handled for state: %d", __FUNCTION__, signal, portName.c_str(), m_state);
|
|
+ }
|
|
+ return;
|
|
+
|
|
+ case O_TOP_ERROR:
|
|
+ m_extTimeout = 1000;
|
|
+ break;
|
|
+
|
|
+ case O_TOP_UNCONFIGURED:
|
|
+ if (port == &m_controlPort)
|
|
+ {
|
|
+ switch (signal)
|
|
+ {
|
|
+ case COutputControlProtocol::INIT:
|
|
+ CXvbaConfig *data;
|
|
+ data = (CXvbaConfig*)msg->data;
|
|
+ if (data)
|
|
+ {
|
|
+ m_config = *data;
|
|
+ }
|
|
+ Init();
|
|
+ EnsureBufferPool();
|
|
+ if (!m_xvbaError)
|
|
+ {
|
|
+ m_state = O_TOP_CONFIGURED_WAIT_RES1;
|
|
+ msg->Reply(COutputControlProtocol::ACC);
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ m_state = O_TOP_ERROR;
|
|
+ msg->Reply(COutputControlProtocol::ERROR);
|
|
+ }
|
|
+ return;
|
|
+ default:
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ case O_TOP_CONFIGURED:
|
|
+ if (port == &m_controlPort)
|
|
+ {
|
|
+ switch (signal)
|
|
+ {
|
|
+ case COutputControlProtocol::FLUSH:
|
|
+ m_state = O_TOP_CONFIGURED_WAIT_RES1;
|
|
+ Flush();
|
|
+ msg->Reply(COutputControlProtocol::ACC);
|
|
+ return;
|
|
+ case COutputControlProtocol::PRECLEANUP:
|
|
+ m_state = O_TOP_UNCONFIGURED;
|
|
+ m_extTimeout = 10000;
|
|
+ Flush();
|
|
+ ReleaseBufferPool(true);
|
|
+ msg->Reply(COutputControlProtocol::ACC);
|
|
+ return;
|
|
+ default:
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ else if (port == &m_dataPort)
|
|
+ {
|
|
+ switch (signal)
|
|
+ {
|
|
+ case COutputDataProtocol::NEWFRAME:
|
|
+ CXvbaDecodedPicture *frame;
|
|
+ frame = (CXvbaDecodedPicture*)msg->data;
|
|
+ if (frame)
|
|
+ {
|
|
+ m_decodedPics.push(*frame);
|
|
+ m_extTimeout = 0;
|
|
+ }
|
|
+ return;
|
|
+ case COutputDataProtocol::RETURNPIC:
|
|
+ CXvbaRenderPicture *pic;
|
|
+ pic = *((CXvbaRenderPicture**)msg->data);
|
|
+ ProcessReturnPicture(pic);
|
|
+ m_controlPort.SendInMessage(COutputControlProtocol::STATS);
|
|
+ m_extTimeout = 0;
|
|
+ return;
|
|
+ default:
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ case O_TOP_CONFIGURED_WAIT_RES1:
|
|
+ if (port == NULL) // timeout
|
|
+ {
|
|
+ switch (signal)
|
|
+ {
|
|
+ case COutputControlProtocol::TIMEOUT:
|
|
+ if (!m_decodedPics.empty() && FindFreeSurface() >= 0 && !m_bufferPool.freeRenderPics.empty())
|
|
+ {
|
|
+ m_state = O_TOP_CONFIGURED_WAIT_DEC;
|
|
+ m_bStateMachineSelfTrigger = true;
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ if (m_extTimeout != 0)
|
|
+ {
|
|
+ uint16_t decoded, processed, render;
|
|
+ m_config.stats->Get(decoded, processed, render);
|
|
+// CLog::Log(LOGDEBUG, "CVDPAU::COutput - timeout idle: decoded: %d, proc: %d, render: %d", decoded, processed, render);
|
|
+ }
|
|
+ m_extTimeout = 100;
|
|
+ }
|
|
+ return;
|
|
+ default:
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ case O_TOP_CONFIGURED_WAIT_DEC:
|
|
+ if (port == NULL) // timeout
|
|
+ {
|
|
+ switch (signal)
|
|
+ {
|
|
+ case COutputControlProtocol::TIMEOUT:
|
|
+ if (IsDecodingFinished())
|
|
+ {
|
|
+ m_state = O_TOP_CONFIGURED_STEP1;
|
|
+ m_bStateMachineSelfTrigger = true;
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ m_extTimeout = 1;
|
|
+ }
|
|
+ return;
|
|
+ default:
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ case O_TOP_CONFIGURED_STEP1:
|
|
+ if (port == NULL) // timeout
|
|
+ {
|
|
+ switch (signal)
|
|
+ {
|
|
+ case COutputControlProtocol::TIMEOUT:
|
|
+ m_processPicture = m_decodedPics.front();
|
|
+ m_decodedPics.pop();
|
|
+ InitCycle();
|
|
+ CXvbaRenderPicture *pic;
|
|
+ pic = ProcessPicture();
|
|
+ if (pic)
|
|
+ {
|
|
+ m_config.stats->IncRender();
|
|
+ m_dataPort.SendInMessage(COutputDataProtocol::PICTURE, &pic, sizeof(pic));
|
|
+ }
|
|
+ if (m_xvbaError)
|
|
+ {
|
|
+ m_state = O_TOP_ERROR;
|
|
+ return;
|
|
+ }
|
|
+ if (m_deinterlacing && !m_deintSkip)
|
|
+ {
|
|
+ m_state = O_TOP_CONFIGURED_WAIT_RES2;
|
|
+ m_extTimeout = 0;
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ FiniCycle();
|
|
+ m_state = O_TOP_CONFIGURED_WAIT_RES1;
|
|
+ m_extTimeout = 0;
|
|
+ }
|
|
+ return;
|
|
+ default:
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ case O_TOP_CONFIGURED_WAIT_RES2:
|
|
+ if (port == NULL) // timeout
|
|
+ {
|
|
+ switch (signal)
|
|
+ {
|
|
+ case COutputControlProtocol::TIMEOUT:
|
|
+ if (FindFreeSurface() >= 0 && !m_bufferPool.freeRenderPics.empty())
|
|
+ {
|
|
+ m_state = O_TOP_CONFIGURED_STEP2;
|
|
+ m_bStateMachineSelfTrigger = true;
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ if (m_extTimeout != 0)
|
|
+ {
|
|
+ uint16_t decoded, processed, render;
|
|
+ m_config.stats->Get(decoded, processed, render);
|
|
+ CLog::Log(LOGDEBUG, "CVDPAU::COutput - timeout idle: decoded: %d, proc: %d, render: %d", decoded, processed, render);
|
|
+ }
|
|
+ m_extTimeout = 100;
|
|
+ }
|
|
+ return;
|
|
+ default:
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ case O_TOP_CONFIGURED_STEP2:
|
|
+ if (port == NULL) // timeout
|
|
+ {
|
|
+ switch (signal)
|
|
+ {
|
|
+ case COutputControlProtocol::TIMEOUT:
|
|
+ CXvbaRenderPicture *pic;
|
|
+ m_deintStep = 1;
|
|
+ pic = ProcessPicture();
|
|
+ if (pic)
|
|
+ {
|
|
+ m_config.stats->IncRender();
|
|
+ m_dataPort.SendInMessage(COutputDataProtocol::PICTURE, &pic, sizeof(pic));
|
|
+ }
|
|
+ if (m_xvbaError)
|
|
+ {
|
|
+ m_state = O_TOP_ERROR;
|
|
+ return;
|
|
+ }
|
|
+ FiniCycle();
|
|
+ m_state = O_TOP_CONFIGURED_WAIT_RES1;
|
|
+ m_extTimeout = 0;
|
|
+ return;
|
|
+ default:
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ default: // we are in no state, should not happen
|
|
+ CLog::Log(LOGERROR, "COutput::%s - no valid state: %d", __FUNCTION__, m_state);
|
|
+ return;
|
|
+ }
|
|
+ } // for
|
|
+}
|
|
+
|
|
+void COutput::Process()
|
|
+{
|
|
+ Message *msg;
|
|
+ Protocol *port;
|
|
+ bool gotMsg;
|
|
+
|
|
+ m_state = O_TOP_UNCONFIGURED;
|
|
+ m_extTimeout = 1000;
|
|
+ m_bStateMachineSelfTrigger = false;
|
|
+
|
|
+ while (!m_bStop)
|
|
+ {
|
|
+ gotMsg = false;
|
|
+
|
|
+ if (m_bStateMachineSelfTrigger)
|
|
+ {
|
|
+ m_bStateMachineSelfTrigger = false;
|
|
+ // self trigger state machine
|
|
+ StateMachine(msg->signal, port, msg);
|
|
+ if (!m_bStateMachineSelfTrigger)
|
|
+ {
|
|
+ msg->Release();
|
|
+ msg = NULL;
|
|
+ }
|
|
+ continue;
|
|
+ }
|
|
+ // check control port
|
|
+ else if (m_controlPort.ReceiveOutMessage(&msg))
|
|
+ {
|
|
+ gotMsg = true;
|
|
+ port = &m_controlPort;
|
|
+ }
|
|
+ // check data port
|
|
+ else if (m_dataPort.ReceiveOutMessage(&msg))
|
|
+ {
|
|
+ gotMsg = true;
|
|
+ port = &m_dataPort;
|
|
+ }
|
|
+ if (gotMsg)
|
|
+ {
|
|
+ StateMachine(msg->signal, port, msg);
|
|
+ if (!m_bStateMachineSelfTrigger)
|
|
+ {
|
|
+ msg->Release();
|
|
+ msg = NULL;
|
|
+ }
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ // wait for message
|
|
+ else if (m_outMsgEvent.WaitMSec(m_extTimeout))
|
|
+ {
|
|
+ continue;
|
|
+ }
|
|
+ // time out
|
|
+ else
|
|
+ {
|
|
+ msg = m_controlPort.GetMessage();
|
|
+ msg->signal = COutputControlProtocol::TIMEOUT;
|
|
+ port = 0;
|
|
+ // signal timeout to state machine
|
|
+ StateMachine(msg->signal, port, msg);
|
|
+ if (!m_bStateMachineSelfTrigger)
|
|
+ {
|
|
+ msg->Release();
|
|
+ msg = NULL;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ Flush();
|
|
+ Uninit();
|
|
+}
|
|
+
|
|
+bool COutput::Init()
|
|
+{
|
|
+ if (!CreateGlxContext())
|
|
+ return false;
|
|
+
|
|
+ m_xvbaError = false;
|
|
+ m_processPicture.render = 0;
|
|
+ m_fence = None;
|
|
+
|
|
+ return true;
|
|
+}
|
|
+
|
|
+bool COutput::Uninit()
|
|
+{
|
|
+ ReleaseBufferPool();
|
|
+ DestroyGlxContext();
|
|
+ return true;
|
|
+}
|
|
+
|
|
+void COutput::Flush()
|
|
+{
|
|
+ while (!m_decodedPics.empty())
|
|
+ {
|
|
+ CXvbaDecodedPicture pic = m_decodedPics.front();
|
|
+ m_decodedPics.pop();
|
|
+ CSingleLock lock(*m_config.videoSurfaceSec);
|
|
+ if (pic.render)
|
|
+ pic.render->state &= ~(FF_XVBA_STATE_USED_FOR_RENDER | FF_XVBA_STATE_DECODED);
|
|
+ }
|
|
+
|
|
+ if (m_processPicture.render)
|
|
+ {
|
|
+ CSingleLock lock(*m_config.videoSurfaceSec);
|
|
+ m_processPicture.render->state &= ~(FF_XVBA_STATE_USED_FOR_RENDER | FF_XVBA_STATE_DECODED);
|
|
+ m_processPicture.render = 0;
|
|
+ }
|
|
+
|
|
+ Message *msg;
|
|
+ while (m_dataPort.ReceiveOutMessage(&msg))
|
|
+ {
|
|
+ if (msg->signal == COutputDataProtocol::NEWFRAME)
|
|
+ {
|
|
+ CXvbaDecodedPicture pic = *(CXvbaDecodedPicture*)msg->data;
|
|
+ CSingleLock lock(*m_config.videoSurfaceSec);
|
|
+ if (pic.render)
|
|
+ pic.render->state &= ~(FF_XVBA_STATE_USED_FOR_RENDER | FF_XVBA_STATE_DECODED);
|
|
+ }
|
|
+ else if (msg->signal == COutputDataProtocol::RETURNPIC)
|
|
+ {
|
|
+ CXvbaRenderPicture *pic;
|
|
+ pic = *((CXvbaRenderPicture**)msg->data);
|
|
+ ProcessReturnPicture(pic);
|
|
+ }
|
|
+ msg->Release();
|
|
+ }
|
|
+
|
|
+ while (m_dataPort.ReceiveInMessage(&msg))
|
|
+ {
|
|
+ if (msg->signal == COutputDataProtocol::PICTURE)
|
|
+ {
|
|
+ CXvbaRenderPicture *pic;
|
|
+ pic = *((CXvbaRenderPicture**)msg->data);
|
|
+ ProcessReturnPicture(pic);
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
+bool COutput::IsDecodingFinished()
|
|
+{
|
|
+ return true;
|
|
+
|
|
+ // check for decoding to be finished
|
|
+ CXvbaDecodedPicture decodedPic = m_decodedPics.front();
|
|
+
|
|
+ XVBA_Surface_Sync_Input syncInput;
|
|
+ XVBA_Surface_Sync_Output syncOutput;
|
|
+ syncInput.size = sizeof(syncInput);
|
|
+ syncInput.session = m_config.xvbaSession;
|
|
+ syncInput.surface = decodedPic.render->surface;
|
|
+ syncInput.query_status = XVBA_GET_SURFACE_STATUS;
|
|
+ syncOutput.size = sizeof(syncOutput);
|
|
+ { CSingleLock lock(*(m_config.apiSec));
|
|
+ if (Success != g_XVBA_vtable.SyncSurface(&syncInput, &syncOutput))
|
|
+ {
|
|
+ CLog::Log(LOGERROR,"XVBA - failed sync surface");
|
|
+ m_xvbaError = true;
|
|
+ return false;
|
|
+ }
|
|
+ }
|
|
+ if (!(syncOutput.status_flags & XVBA_STILL_PENDING))
|
|
+ return true;
|
|
+
|
|
+ return false;
|
|
+}
|
|
+
|
|
+CXvbaRenderPicture* COutput::ProcessPicture()
|
|
+{
|
|
+ CXvbaRenderPicture *retPic = 0;
|
|
+
|
|
+ if (m_deintStep == 1)
|
|
+ {
|
|
+ if(m_field == XVBA_TOP_FIELD)
|
|
+ m_field = XVBA_BOTTOM_FIELD;
|
|
+ else
|
|
+ m_field = XVBA_TOP_FIELD;
|
|
+ }
|
|
+
|
|
+ // find unused shared surface
|
|
+ unsigned int idx = FindFreeSurface();
|
|
+ XvbaBufferPool::GLVideoSurface *glSurface = &m_bufferPool.glSurfaces[idx];
|
|
+ glSurface->used = true;
|
|
+ glSurface->field = m_field;
|
|
+ glSurface->render = m_processPicture.render;
|
|
+ glSurface->transferred = false;
|
|
+
|
|
+ int cmd = 0;
|
|
+ m_config.stats->GetCmd(cmd);
|
|
+
|
|
+// if (m_fence)
|
|
+// glDeleteSync(m_fence);
|
|
+// m_fence = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
|
|
+
|
|
+ // transfer surface
|
|
+ XVBA_Transfer_Surface_Input transInput;
|
|
+ transInput.size = sizeof(transInput);
|
|
+ transInput.session = m_config.xvbaSession;
|
|
+ transInput.src_surface = m_processPicture.render->surface;
|
|
+ transInput.target_surface = glSurface->glSurface;
|
|
+ transInput.flag = m_field;
|
|
+ { CSingleLock lock(*(m_config.apiSec));
|
|
+ if (Success != g_XVBA_vtable.TransferSurface(&transInput))
|
|
+ {
|
|
+ CLog::Log(LOGERROR,"(XVBA) failed to transfer surface");
|
|
+ m_xvbaError = true;
|
|
+ return retPic;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ // prepare render pic
|
|
+ retPic = m_bufferPool.freeRenderPics.front();
|
|
+ m_bufferPool.freeRenderPics.pop_front();
|
|
+ m_bufferPool.usedRenderPics.push_back(retPic);
|
|
+ retPic->sourceIdx = glSurface->id;
|
|
+ retPic->DVDPic = m_processPicture.DVDPic;
|
|
+ retPic->valid = true;
|
|
+ retPic->texture = glSurface->texture;
|
|
+ retPic->crop = CRect(0,0,0,0);
|
|
+ retPic->texWidth = m_config.surfaceWidth;
|
|
+ retPic->texHeight = m_config.surfaceHeight;
|
|
+ retPic->xvbaOutput = this;
|
|
+
|
|
+ // set repeat pic for de-interlacing
|
|
+ if (m_deinterlacing)
|
|
+ {
|
|
+ if (m_deintStep == 1)
|
|
+ {
|
|
+ retPic->DVDPic.pts = DVD_NOPTS_VALUE;
|
|
+ retPic->DVDPic.dts = DVD_NOPTS_VALUE;
|
|
+ }
|
|
+ retPic->DVDPic.iRepeatPicture = 0.0;
|
|
+ }
|
|
+
|
|
+ return retPic;
|
|
+}
|
|
+
|
|
+void COutput::ProcessReturnPicture(CXvbaRenderPicture *pic)
|
|
+{
|
|
+ std::deque<CXvbaRenderPicture*>::iterator it;
|
|
+ it = std::find(m_bufferPool.usedRenderPics.begin(), m_bufferPool.usedRenderPics.end(), pic);
|
|
+ if (it == m_bufferPool.usedRenderPics.end())
|
|
+ {
|
|
+ CLog::Log(LOGWARNING, "COutput::ProcessReturnPicture - pic not found");
|
|
+ return;
|
|
+ }
|
|
+ m_bufferPool.usedRenderPics.erase(it);
|
|
+ m_bufferPool.freeRenderPics.push_back(pic);
|
|
+ if (!pic->valid)
|
|
+ {
|
|
+ CLog::Log(LOGDEBUG, "COutput::%s - return of invalid render pic", __FUNCTION__);
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ xvba_render_state *render = m_bufferPool.glSurfaces[pic->sourceIdx].render;
|
|
+ if (render)
|
|
+ {
|
|
+ // check if video surface is referenced by other glSurfaces
|
|
+ bool referenced(false);
|
|
+ for (unsigned int i=0; i<m_bufferPool.glSurfaces.size();++i)
|
|
+ {
|
|
+ if (i == pic->sourceIdx)
|
|
+ continue;
|
|
+ if (m_bufferPool.glSurfaces[i].render == render)
|
|
+ {
|
|
+ referenced = true;
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ if (m_processPicture.render == render)
|
|
+ referenced = true;
|
|
+
|
|
+ // release video surface
|
|
+ if (!referenced)
|
|
+ {
|
|
+ CSingleLock lock(*m_config.videoSurfaceSec);
|
|
+ render->state &= ~(FF_XVBA_STATE_USED_FOR_RENDER | FF_XVBA_STATE_DECODED);
|
|
+ }
|
|
+
|
|
+ // unreference video surface
|
|
+ m_bufferPool.glSurfaces[pic->sourceIdx].render = 0;
|
|
+
|
|
+ m_bufferPool.glSurfaces[pic->sourceIdx].used = false;
|
|
+ return;
|
|
+ }
|
|
+}
|
|
+
|
|
+int COutput::FindFreeSurface()
|
|
+{
|
|
+ // find free shared surface
|
|
+ unsigned int i;
|
|
+ for (i = 0; i < m_bufferPool.glSurfaces.size(); ++i)
|
|
+ {
|
|
+ if (!m_bufferPool.glSurfaces[i].used)
|
|
+ break;
|
|
+ }
|
|
+ if (i == m_bufferPool.glSurfaces.size())
|
|
+ return -1;
|
|
+ else
|
|
+ return i;
|
|
+}
|
|
+
|
|
+void COutput::InitCycle()
|
|
+{
|
|
+ uint64_t latency;
|
|
+ int speed;
|
|
+ m_config.stats->GetParams(latency, speed);
|
|
+ latency = (latency*1000)/CurrentHostFrequency();
|
|
+
|
|
+ m_config.stats->SetCanSkipDeint(false);
|
|
+
|
|
+ EDEINTERLACEMODE mode = g_settings.m_currentVideoSettings.m_DeinterlaceMode;
|
|
+ EINTERLACEMETHOD method = g_settings.m_currentVideoSettings.m_InterlaceMethod;
|
|
+ bool interlaced = m_processPicture.DVDPic.iFlags & DVP_FLAG_INTERLACED;
|
|
+
|
|
+ if (mode == VS_DEINTERLACEMODE_FORCE ||
|
|
+ (mode == VS_DEINTERLACEMODE_AUTO && interlaced))
|
|
+ {
|
|
+ if((method == VS_INTERLACEMETHOD_AUTO && interlaced)
|
|
+ || method == VS_INTERLACEMETHOD_XVBA)
|
|
+ {
|
|
+ m_deinterlacing = true;
|
|
+ m_deintSkip = false;
|
|
+ m_config.stats->SetCanSkipDeint(true);
|
|
+
|
|
+ if (m_processPicture.DVDPic.iFlags & DVP_FLAG_DROPDEINT)
|
|
+ {
|
|
+ m_deintSkip = true;
|
|
+ }
|
|
+
|
|
+ // do only half deinterlacing
|
|
+ if (speed != DVD_PLAYSPEED_NORMAL || !g_graphicsContext.IsFullScreenVideo())
|
|
+ {
|
|
+ m_config.stats->SetCanSkipDeint(false);
|
|
+ m_deintSkip = true;
|
|
+ }
|
|
+
|
|
+ if(m_processPicture.DVDPic.iFlags & DVP_FLAG_TOP_FIELD_FIRST)
|
|
+ m_field = XVBA_TOP_FIELD;
|
|
+ else
|
|
+ m_field = XVBA_BOTTOM_FIELD;
|
|
+ }
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ m_deinterlacing = false;
|
|
+ m_field = XVBA_FRAME;
|
|
+ }
|
|
+
|
|
+ m_processPicture.DVDPic.format = RENDER_FMT_XVBA;
|
|
+ m_processPicture.DVDPic.iFlags &= ~(DVP_FLAG_TOP_FIELD_FIRST |
|
|
+ DVP_FLAG_REPEAT_TOP_FIELD |
|
|
+ DVP_FLAG_INTERLACED);
|
|
+ m_processPicture.DVDPic.iWidth = m_config.vidWidth;
|
|
+ m_processPicture.DVDPic.iHeight = m_config.vidHeight;
|
|
+
|
|
+ m_deintStep = 0;
|
|
+}
|
|
+
|
|
+void COutput::FiniCycle()
|
|
+{
|
|
+// { CSingleLock lock(*m_config.videoSurfaceSec);
|
|
+// m_processPicture.render->state &= ~FF_XVBA_STATE_USED_FOR_RENDER;
|
|
+// }
|
|
+ m_processPicture.render = 0;
|
|
+ m_config.stats->DecDecoded();
|
|
+}
|
|
+
|
|
+bool COutput::EnsureBufferPool()
|
|
+{
|
|
+ if (m_config.useSharedSurfaces && m_bufferPool.glSurfaces.empty())
|
|
+ {
|
|
+ GLenum textureTarget;
|
|
+ if (!glewIsSupported("GL_ARB_texture_non_power_of_two") && glewIsSupported("GL_ARB_texture_rectangle"))
|
|
+ {
|
|
+ textureTarget = GL_TEXTURE_RECTANGLE_ARB;
|
|
+ }
|
|
+ else
|
|
+ textureTarget = GL_TEXTURE_2D;
|
|
+
|
|
+ // create shared surfaces
|
|
+ XvbaBufferPool::GLVideoSurface surface;
|
|
+ for (unsigned int i = 0; i < NUM_RENDER_PICS; ++i)
|
|
+ {
|
|
+ glEnable(textureTarget);
|
|
+ glGenTextures(1, &surface.texture);
|
|
+ glBindTexture(textureTarget, surface.texture);
|
|
+ glTexParameteri(textureTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
|
+ glTexParameteri(textureTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
+ glTexParameteri(textureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
|
+ glTexParameteri(textureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
|
+ glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
|
|
+ glTexImage2D(textureTarget, 0, GL_RGBA, m_config.surfaceWidth, m_config.surfaceHeight, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL);
|
|
+
|
|
+ XVBA_Create_GLShared_Surface_Input surfInput;
|
|
+ XVBA_Create_GLShared_Surface_Output surfOutput;
|
|
+ surfInput.size = sizeof(surfInput);
|
|
+ surfInput.session = m_config.xvbaSession;
|
|
+ surfInput.gltexture = surface.texture;
|
|
+ surfInput.glcontext = m_glContext;
|
|
+ surfOutput.size = sizeof(surfOutput);
|
|
+ surfOutput.surface = 0;
|
|
+ if (Success != g_XVBA_vtable.CreateGLSharedSurface(&surfInput, &surfOutput))
|
|
+ {
|
|
+ CLog::Log(LOGERROR,"(XVBA) failed to create shared surface");
|
|
+ m_xvbaError = true;
|
|
+ break;
|
|
+ }
|
|
+ CLog::Log(LOGDEBUG, "XVBA::GetTexture - created shared surface");
|
|
+
|
|
+ surface.glSurface = surfOutput.surface;
|
|
+ surface.id = i;
|
|
+ surface.used = false;
|
|
+ surface.render = 0;
|
|
+ m_bufferPool.glSurfaces.push_back(surface);
|
|
+ }
|
|
+ glDisable(textureTarget);
|
|
+ }
|
|
+
|
|
+ return true;
|
|
+}
|
|
+
|
|
+void COutput::ReleaseBufferPool(bool precleanup /*= false*/)
|
|
+{
|
|
+// if (m_fence)
|
|
+// {
|
|
+// uint64_t maxTimeout = 1000000000LL;
|
|
+// glClientWaitSync(m_fence, GL_SYNC_FLUSH_COMMANDS_BIT, maxTimeout);
|
|
+// glDeleteSync(m_fence);
|
|
+// m_fence = None;
|
|
+// }
|
|
+
|
|
+ CSingleLock lock(m_bufferPool.renderPicSec);
|
|
+
|
|
+ for (unsigned int i = 0; i < m_bufferPool.glSurfaces.size(); ++i)
|
|
+ {
|
|
+ if (m_bufferPool.glSurfaces[i].glSurface)
|
|
+ {
|
|
+ g_XVBA_vtable.DestroySurface(m_bufferPool.glSurfaces[i].glSurface);
|
|
+ m_bufferPool.glSurfaces[i].glSurface = 0;
|
|
+ }
|
|
+ if (m_bufferPool.glSurfaces[i].texture && !precleanup)
|
|
+ {
|
|
+ glDeleteTextures(1, &m_bufferPool.glSurfaces[i].texture);
|
|
+ m_bufferPool.glSurfaces[i].texture = 0;
|
|
+ }
|
|
+ m_bufferPool.glSurfaces[i].render = 0;
|
|
+ m_bufferPool.glSurfaces[i].used = true;
|
|
+ }
|
|
+
|
|
+ if (!precleanup)
|
|
+ {
|
|
+ m_bufferPool.glSurfaces.clear();
|
|
+
|
|
+ // invalidate all used render pictures
|
|
+ for (unsigned int i = 0; i < m_bufferPool.usedRenderPics.size(); ++i)
|
|
+ {
|
|
+ m_bufferPool.usedRenderPics[i]->valid = false;
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
+void COutput::PreReleaseBufferPool()
|
|
+{
|
|
+ CSingleLock lock(m_bufferPool.renderPicSec);
|
|
+
|
|
+ if (m_config.useSharedSurfaces)
|
|
+ {
|
|
+ for (unsigned int i = 0; i < m_bufferPool.glSurfaces.size(); ++i)
|
|
+ {
|
|
+ if (!m_bufferPool.glSurfaces[i].used)
|
|
+ {
|
|
+ g_XVBA_vtable.DestroySurface(m_bufferPool.glSurfaces[i].glSurface);
|
|
+ glDeleteTextures(1, &m_bufferPool.glSurfaces[i].texture);
|
|
+ m_bufferPool.glSurfaces[i].glSurface = 0;
|
|
+ m_bufferPool.glSurfaces[i].used = true;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
+bool COutput::CreateGlxContext()
|
|
+{
|
|
+ GLXContext glContext;
|
|
+
|
|
+ m_Display = g_Windowing.GetDisplay();
|
|
+ glContext = g_Windowing.GetGlxContext();
|
|
+ m_Window = g_Windowing.GetWindow();
|
|
+
|
|
+ // Get our window attribs.
|
|
+ XWindowAttributes wndattribs;
|
|
+ XGetWindowAttributes(m_Display, m_Window, &wndattribs);
|
|
+
|
|
+ // Get visual Info
|
|
+ XVisualInfo visInfo;
|
|
+ visInfo.visualid = wndattribs.visual->visualid;
|
|
+ int nvisuals = 0;
|
|
+ XVisualInfo* visuals = XGetVisualInfo(m_Display, VisualIDMask, &visInfo, &nvisuals);
|
|
+ if (nvisuals != 1)
|
|
+ {
|
|
+ CLog::Log(LOGERROR, "XVBA::COutput::CreateGlxContext - could not find visual");
|
|
+ return false;
|
|
+ }
|
|
+ visInfo = visuals[0];
|
|
+ XFree(visuals);
|
|
+
|
|
+ m_pixmap = XCreatePixmap(m_Display,
|
|
+ m_Window,
|
|
+ 192,
|
|
+ 108,
|
|
+ visInfo.depth);
|
|
+ if (!m_pixmap)
|
|
+ {
|
|
+ CLog::Log(LOGERROR, "XVBA::COutput::CreateGlxContext - Unable to create XPixmap");
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ // create gl pixmap
|
|
+ m_glPixmap = glXCreateGLXPixmap(m_Display, &visInfo, m_pixmap);
|
|
+
|
|
+ if (!m_glPixmap)
|
|
+ {
|
|
+ CLog::Log(LOGINFO, "XVBA::COutput::CreateGlxContext - Could not create glPixmap");
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ m_glContext = glXCreateContext(m_Display, &visInfo, glContext, True);
|
|
+
|
|
+ if (!glXMakeCurrent(m_Display, m_glPixmap, m_glContext))
|
|
+ {
|
|
+ CLog::Log(LOGINFO, "XVBA::COutput::CreateGlxContext - Could not make Pixmap current");
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ CLog::Log(LOGNOTICE, "XVBA::COutput::CreateGlxContext - created context");
|
|
+ return true;
|
|
+}
|
|
+
|
|
+bool COutput::DestroyGlxContext()
|
|
+{
|
|
+ if (m_glContext)
|
|
+ {
|
|
+ glXMakeCurrent(m_Display, None, NULL);
|
|
+ glXDestroyContext(m_Display, m_glContext);
|
|
+ }
|
|
+ m_glContext = 0;
|
|
+
|
|
+ if (m_glPixmap)
|
|
+ glXDestroyPixmap(m_Display, m_glPixmap);
|
|
+ m_glPixmap = 0;
|
|
+
|
|
+ if (m_pixmap)
|
|
+ XFreePixmap(m_Display, m_pixmap);
|
|
+ m_pixmap = 0;
|
|
+
|
|
+ return true;
|
|
+}
|
|
+
|
|
+#endif
|
|
diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/XVBA.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/XVBA.h
|
|
new file mode 100644
|
|
index 0000000..f38444c
|
|
--- /dev/null
|
|
+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/XVBA.h
|
|
@@ -0,0 +1,382 @@
|
|
+/*
|
|
+ * Copyright (C) 2005-2011 Team XBMC
|
|
+ * http://www.xbmc.org
|
|
+ *
|
|
+ * This Program is free software; you can redistribute it and/or modify
|
|
+ * it under the terms of the GNU General Public License as published by
|
|
+ * the Free Software Foundation; either version 2, or (at your option)
|
|
+ * any later version.
|
|
+ *
|
|
+ * This Program is distributed in the hope that it will be useful,
|
|
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
+ * GNU General Public License for more details.
|
|
+ *
|
|
+ * You should have received a copy of the GNU General Public License
|
|
+ * along with XBMC; see the file COPYING. If not, write to
|
|
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
+ * http://www.gnu.org/copyleft/gpl.html
|
|
+ *
|
|
+ */
|
|
+#pragma once
|
|
+
|
|
+#include "X11/Xlib.h"
|
|
+#include "amd/amdxvba.h"
|
|
+#include "DllAvCodec.h"
|
|
+#include "DVDCodecs/Video/DVDVideoCodecFFmpeg.h"
|
|
+#include "threads/Thread.h"
|
|
+#include "threads/CriticalSection.h"
|
|
+#include "threads/SharedSection.h"
|
|
+#include "threads/Event.h"
|
|
+#include "guilib/DispResource.h"
|
|
+#include "guilib/Geometry.h"
|
|
+#include "libavcodec/xvba.h"
|
|
+#include "utils/ActorProtocol.h"
|
|
+#include "settings/VideoSettings.h"
|
|
+#include <GL/glx.h>
|
|
+#include <vector>
|
|
+#include <deque>
|
|
+
|
|
+using namespace Actor;
|
|
+
|
|
+
|
|
+namespace XVBA
|
|
+{
|
|
+
|
|
+//-----------------------------------------------------------------------------
|
|
+// XVBA data structs
|
|
+//-----------------------------------------------------------------------------
|
|
+
|
|
+class CDecoder;
|
|
+class CXVBAContext;
|
|
+class COutput;
|
|
+
|
|
+#define NUM_RENDER_PICS 9
|
|
+
|
|
+/**
|
|
+ * Buffer statistics used to control number of frames in queue
|
|
+ */
|
|
+
|
|
+class CXvbaBufferStats
|
|
+{
|
|
+public:
|
|
+ uint16_t decodedPics;
|
|
+ uint16_t processedPics;
|
|
+ uint16_t renderPics;
|
|
+ uint64_t latency; // time decoder has waited for a frame, ideally there is no latency
|
|
+ int playSpeed;
|
|
+ bool canSkipDeint;
|
|
+ int processCmd;
|
|
+
|
|
+ void IncDecoded() { CSingleLock l(m_sec); decodedPics++;}
|
|
+ void DecDecoded() { CSingleLock l(m_sec); decodedPics--;}
|
|
+ void IncProcessed() { CSingleLock l(m_sec); processedPics++;}
|
|
+ void DecProcessed() { CSingleLock l(m_sec); processedPics--;}
|
|
+ void IncRender() { CSingleLock l(m_sec); renderPics++;}
|
|
+ void DecRender() { CSingleLock l(m_sec); renderPics--;}
|
|
+ void Reset() { CSingleLock l(m_sec); decodedPics=0; processedPics=0;renderPics=0;latency=0;}
|
|
+ void Get(uint16_t &decoded, uint16_t &processed, uint16_t &render) {CSingleLock l(m_sec); decoded = decodedPics, processed=processedPics, render=renderPics;}
|
|
+ void SetParams(uint64_t time, int speed) { CSingleLock l(m_sec); latency = time; playSpeed = speed; }
|
|
+ void GetParams(uint64_t &lat, int &speed) { CSingleLock l(m_sec); lat = latency; speed = playSpeed; }
|
|
+ void SetCmd(int cmd) { CSingleLock l(m_sec); processCmd = cmd; }
|
|
+ void GetCmd(int &cmd) { CSingleLock l(m_sec); cmd = processCmd; processCmd = 0; }
|
|
+ void SetCanSkipDeint(bool canSkip) { CSingleLock l(m_sec); canSkipDeint = canSkip; }
|
|
+ bool CanSkipDeint() { CSingleLock l(m_sec); if (canSkipDeint) return true; else return false;}
|
|
+private:
|
|
+ CCriticalSection m_sec;
|
|
+};
|
|
+
|
|
+/**
|
|
+ * CXvbaConfig holds all configuration parameters needed by vdpau
|
|
+ * The structure is sent to the internal classes CMixer and COutput
|
|
+ * for init.
|
|
+ */
|
|
+
|
|
+struct CXvbaConfig
|
|
+{
|
|
+ int surfaceWidth;
|
|
+ int surfaceHeight;
|
|
+ int vidWidth;
|
|
+ int vidHeight;
|
|
+ int outWidth;
|
|
+ int outHeight;
|
|
+ bool useSharedSurfaces;
|
|
+
|
|
+ CXVBAContext *context;
|
|
+ XVBADecodeCap decoderCap;
|
|
+ void *xvbaSession;
|
|
+ std::vector<xvba_render_state*> *videoSurfaces;
|
|
+ CCriticalSection *videoSurfaceSec;
|
|
+ CCriticalSection *apiSec;
|
|
+
|
|
+ CXvbaBufferStats *stats;
|
|
+ int numRenderBuffers;
|
|
+ uint32_t maxReferences;
|
|
+};
|
|
+
|
|
+/**
|
|
+ * Holds a decoded frame
|
|
+ * Input to COutput for further processing
|
|
+ */
|
|
+struct CXvbaDecodedPicture
|
|
+{
|
|
+ DVDVideoPicture DVDPic;
|
|
+ xvba_render_state *render;
|
|
+};
|
|
+
|
|
+/**
|
|
+ * Ready to render textures
|
|
+ * Sent from COutput back to CDecoder
|
|
+ * Objects are referenced by DVDVideoPicture and are sent
|
|
+ * to renderer
|
|
+ */
|
|
+class CXvbaRenderPicture
|
|
+{
|
|
+ friend class CDecoder;
|
|
+ friend class COutput;
|
|
+public:
|
|
+ DVDVideoPicture DVDPic;
|
|
+ int texWidth, texHeight;
|
|
+ CRect crop;
|
|
+ GLuint texture;
|
|
+ uint32_t sourceIdx;
|
|
+ bool valid;
|
|
+ CDecoder *xvba;
|
|
+ CXvbaRenderPicture* Acquire();
|
|
+ long Release();
|
|
+private:
|
|
+ void ReturnUnused();
|
|
+ int refCount;
|
|
+ CCriticalSection *renderPicSection;
|
|
+ COutput *xvbaOutput;
|
|
+};
|
|
+
|
|
+//-----------------------------------------------------------------------------
|
|
+// Output
|
|
+//-----------------------------------------------------------------------------
|
|
+
|
|
+/**
|
|
+ * Buffer pool holds allocated xvba and gl resources
|
|
+ * Embedded in COutput
|
|
+ */
|
|
+struct XvbaBufferPool
|
|
+{
|
|
+ struct GLVideoSurface
|
|
+ {
|
|
+ unsigned int id;
|
|
+ bool used;
|
|
+ bool transferred;
|
|
+ GLuint texture;
|
|
+ void *glSurface;
|
|
+ xvba_render_state *render;
|
|
+ XVBA_SURFACE_FLAG field;
|
|
+ };
|
|
+ std::vector<GLVideoSurface> glSurfaces;
|
|
+ std::vector<CXvbaRenderPicture> allRenderPics;
|
|
+ std::deque<CXvbaRenderPicture*> usedRenderPics;
|
|
+ std::deque<CXvbaRenderPicture*> freeRenderPics;
|
|
+ CCriticalSection renderPicSec;
|
|
+};
|
|
+
|
|
+class COutputControlProtocol : public Protocol
|
|
+{
|
|
+public:
|
|
+ COutputControlProtocol(std::string name, CEvent* inEvent, CEvent *outEvent) : Protocol(name, inEvent, outEvent) {};
|
|
+ enum OutSignal
|
|
+ {
|
|
+ INIT,
|
|
+ FLUSH,
|
|
+ PRECLEANUP,
|
|
+ TIMEOUT,
|
|
+ };
|
|
+ enum InSignal
|
|
+ {
|
|
+ ACC,
|
|
+ ERROR,
|
|
+ STATS,
|
|
+ };
|
|
+};
|
|
+
|
|
+class COutputDataProtocol : public Protocol
|
|
+{
|
|
+public:
|
|
+ COutputDataProtocol(std::string name, CEvent* inEvent, CEvent *outEvent) : Protocol(name, inEvent, outEvent) {};
|
|
+ enum OutSignal
|
|
+ {
|
|
+ NEWFRAME = 0,
|
|
+ RETURNPIC,
|
|
+ };
|
|
+ enum InSignal
|
|
+ {
|
|
+ PICTURE,
|
|
+ };
|
|
+};
|
|
+
|
|
+/**
|
|
+ * COutput is embedded in CDecoder and embeds CMixer
|
|
+ * The class has its own OpenGl context which is shared with render thread
|
|
+ * COuput generated ready to render textures and passes them back to
|
|
+ * CDecoder
|
|
+ */
|
|
+class COutput : private CThread
|
|
+{
|
|
+public:
|
|
+ COutput(CEvent *inMsgEvent);
|
|
+ virtual ~COutput();
|
|
+ void Start();
|
|
+ void Dispose();
|
|
+ COutputControlProtocol m_controlPort;
|
|
+ COutputDataProtocol m_dataPort;
|
|
+protected:
|
|
+ void OnStartup();
|
|
+ void OnExit();
|
|
+ void Process();
|
|
+ void StateMachine(int signal, Protocol *port, Message *msg);
|
|
+ bool HasWork();
|
|
+ bool IsDecodingFinished();
|
|
+ CXvbaRenderPicture* ProcessPicture();
|
|
+ void ProcessReturnPicture(CXvbaRenderPicture *pic);
|
|
+ int FindFreeSurface();
|
|
+ void InitCycle();
|
|
+ void FiniCycle();
|
|
+ bool Init();
|
|
+ bool Uninit();
|
|
+ void Flush();
|
|
+ bool CreateGlxContext();
|
|
+ bool DestroyGlxContext();
|
|
+ bool EnsureBufferPool();
|
|
+ void ReleaseBufferPool(bool precleanup = false);
|
|
+ void PreReleaseBufferPool();
|
|
+ CEvent m_outMsgEvent;
|
|
+ CEvent *m_inMsgEvent;
|
|
+ int m_state;
|
|
+ bool m_bStateMachineSelfTrigger;
|
|
+
|
|
+ // extended state variables for state machine
|
|
+ int m_extTimeout;
|
|
+ bool m_xvbaError;
|
|
+ CXvbaConfig m_config;
|
|
+ XvbaBufferPool m_bufferPool;
|
|
+ Display *m_Display;
|
|
+ Window m_Window;
|
|
+ GLXContext m_glContext;
|
|
+ GLXWindow m_glWindow;
|
|
+ Pixmap m_pixmap;
|
|
+ GLXPixmap m_glPixmap;
|
|
+ GLsync m_fence;
|
|
+ std::queue<CXvbaDecodedPicture> m_decodedPics;
|
|
+ CXvbaDecodedPicture m_processPicture;
|
|
+ XVBA_SURFACE_FLAG m_field;
|
|
+ bool m_deinterlacing;
|
|
+ int m_deintStep;
|
|
+ bool m_deintSkip;
|
|
+};
|
|
+
|
|
+//-----------------------------------------------------------------------------
|
|
+// XVBA decoder
|
|
+//-----------------------------------------------------------------------------
|
|
+
|
|
+class CXVBAContext
|
|
+{
|
|
+public:
|
|
+ static bool EnsureContext(CXVBAContext **ctx);
|
|
+ void *GetContext();
|
|
+ void Release();
|
|
+private:
|
|
+ CXVBAContext();
|
|
+ void Close();
|
|
+ bool LoadSymbols();
|
|
+ bool CreateContext();
|
|
+ void DestroyContext();
|
|
+ static CXVBAContext *m_context;
|
|
+ static CCriticalSection m_section;
|
|
+ static Display *m_display;
|
|
+ int m_refCount;
|
|
+ static void *m_dlHandle;
|
|
+ void *m_xvbaContext;
|
|
+};
|
|
+
|
|
+class CDecoder : public CDVDVideoCodecFFmpeg::IHardwareDecoder,
|
|
+ public IDispResource
|
|
+{
|
|
+ friend class CXvbaRenderPicture;
|
|
+
|
|
+public:
|
|
+
|
|
+ struct pictureAge
|
|
+ {
|
|
+ int b_age;
|
|
+ int ip_age[2];
|
|
+ };
|
|
+
|
|
+ enum EDisplayState
|
|
+ { XVBA_OPEN
|
|
+ , XVBA_RESET
|
|
+ , XVBA_LOST
|
|
+ , XVBA_ERROR
|
|
+ };
|
|
+
|
|
+ CDecoder();
|
|
+ virtual ~CDecoder();
|
|
+ virtual void OnLostDevice();
|
|
+ virtual void OnResetDevice();
|
|
+
|
|
+ virtual bool Open(AVCodecContext* avctx, const enum PixelFormat fmt, unsigned int surfaces = 0);
|
|
+ virtual int Decode (AVCodecContext* avctx, AVFrame* frame);
|
|
+ virtual bool GetPicture(AVCodecContext* avctx, AVFrame* frame, DVDVideoPicture* picture);
|
|
+ virtual void Reset();
|
|
+ virtual void Close();
|
|
+ virtual int Check(AVCodecContext* avctx);
|
|
+ virtual long Release();
|
|
+ virtual const std::string Name() { return "xvba"; }
|
|
+ virtual bool CanSkipDeint();
|
|
+ virtual void SetSpeed(int speed);
|
|
+
|
|
+ bool Supports(EINTERLACEMETHOD method);
|
|
+ long ReleasePicReference();
|
|
+
|
|
+protected:
|
|
+ bool CreateSession(AVCodecContext* avctx);
|
|
+ void DestroySession(bool precleanup = false);
|
|
+ bool EnsureDataControlBuffers(unsigned int num);
|
|
+ void ResetState();
|
|
+ void SetError(const char* function, const char* msg, int line);
|
|
+ bool IsSurfaceValid(xvba_render_state *render);
|
|
+ void ReturnRenderPicture(CXvbaRenderPicture *renderPic);
|
|
+
|
|
+ // callbacks for ffmpeg
|
|
+ static void FFReleaseBuffer(AVCodecContext *avctx, AVFrame *pic);
|
|
+ static void FFDrawSlice(struct AVCodecContext *avctx,
|
|
+ const AVFrame *src, int offset[4],
|
|
+ int y, int type, int height);
|
|
+ static int FFGetBuffer(AVCodecContext *avctx, AVFrame *pic);
|
|
+
|
|
+ DllAvUtil m_dllAvUtil;
|
|
+ CCriticalSection m_decoderSection;
|
|
+ CEvent m_displayEvent;
|
|
+ EDisplayState m_displayState;
|
|
+ CXvbaConfig m_xvbaConfig;
|
|
+ std::vector<xvba_render_state*> m_videoSurfaces;
|
|
+ CCriticalSection m_apiSec, m_videoSurfaceSec;
|
|
+ ThreadIdentifier m_decoderThread;
|
|
+
|
|
+ unsigned int m_decoderId;
|
|
+ struct XVBABufferPool
|
|
+ {
|
|
+ XVBABufferDescriptor *picture_descriptor_buffer;
|
|
+ XVBABufferDescriptor *iq_matrix_buffer;
|
|
+ XVBABufferDescriptor *data_buffer;
|
|
+ std::vector<XVBABufferDescriptor*> data_control_buffers;
|
|
+ };
|
|
+ XVBABufferPool m_xvbaBufferPool;
|
|
+
|
|
+ COutput m_xvbaOutput;
|
|
+ CXvbaBufferStats m_bufferStats;
|
|
+ CEvent m_inMsgEvent;
|
|
+ CXvbaRenderPicture *m_presentPicture;
|
|
+
|
|
+ int m_speed;
|
|
+ int m_codecControl;
|
|
+};
|
|
+
|
|
+}
|
|
diff --git a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp
|
|
index 15a39fa..e5e71f3 100644
|
|
--- a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp
|
|
+++ b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp
|
|
@@ -1162,6 +1162,9 @@ int CDVDPlayerVideo::OutputPicture(const DVDVideoPicture* src, double pts)
|
|
case RENDER_FMT_NONE:
|
|
formatstr = "NONE";
|
|
break;
|
|
+ case RENDER_FMT_XVBA:
|
|
+ formatstr = "XVBA";
|
|
+ break;
|
|
}
|
|
|
|
if(m_bAllowFullscreen)
|
|
diff --git a/xbmc/settings/GUISettings.cpp b/xbmc/settings/GUISettings.cpp
|
|
index 0e320e1..10ef779 100644
|
|
--- a/xbmc/settings/GUISettings.cpp
|
|
+++ b/xbmc/settings/GUISettings.cpp
|
|
@@ -696,6 +696,9 @@ void CGUISettings::Initialize()
|
|
#ifdef HAVE_LIBVA
|
|
AddBool(vp, "videoplayer.usevaapi", 13426, true);
|
|
#endif
|
|
+#ifdef HAVE_LIBXVBA
|
|
+ AddBool(vp, "videoplayer.usexvba", 13437, true);
|
|
+#endif
|
|
#ifdef HAS_DX
|
|
AddBool(g_sysinfo.IsVistaOrHigher() ? vp: NULL, "videoplayer.usedxva2", 13427, g_sysinfo.IsVistaOrHigher() ? true : false);
|
|
#endif
|
|
diff --git a/xbmc/settings/VideoSettings.h b/xbmc/settings/VideoSettings.h
|
|
index f8093b2..f54a837 100644
|
|
--- a/xbmc/settings/VideoSettings.h
|
|
+++ b/xbmc/settings/VideoSettings.h
|
|
@@ -65,6 +65,8 @@ enum EINTERLACEMETHOD
|
|
VS_INTERLACEMETHOD_SW_BLEND = 20,
|
|
VS_INTERLACEMETHOD_AUTO_ION = 21,
|
|
|
|
+ VS_INTERLACEMETHOD_XVBA = 22,
|
|
+
|
|
VS_INTERLACEMETHOD_MAX // do not use and keep as last enum value.
|
|
};
|
|
|
|
diff --git a/xbmc/video/dialogs/GUIDialogVideoSettings.cpp b/xbmc/video/dialogs/GUIDialogVideoSettings.cpp
|
|
index f25d10d..f6b1ea4 100644
|
|
--- a/xbmc/video/dialogs/GUIDialogVideoSettings.cpp
|
|
+++ b/xbmc/video/dialogs/GUIDialogVideoSettings.cpp
|
|
@@ -110,6 +110,7 @@ void CGUIDialogVideoSettings::CreateSettings()
|
|
entries.push_back(make_pair(VS_INTERLACEMETHOD_DXVA_BOB , 16320));
|
|
entries.push_back(make_pair(VS_INTERLACEMETHOD_DXVA_BEST , 16321));
|
|
entries.push_back(make_pair(VS_INTERLACEMETHOD_AUTO_ION , 16325));
|
|
+ entries.push_back(make_pair(VS_INTERLACEMETHOD_XVBA , 16326));
|
|
|
|
/* remove unsupported methods */
|
|
for(vector<pair<int, int> >::iterator it = entries.begin(); it != entries.end();)
|
|
--
|
|
1.7.10
|
|
|
|
|
|
From 517eda0bf58a6376a82839ab92e51b97c143edf1 Mon Sep 17 00:00:00 2001
|
|
From: xbmc <fernetmenta@online.de>
|
|
Date: Thu, 23 Aug 2012 19:39:49 +0200
|
|
Subject: [PATCH 43/72] ffmpeg: add av_find_default_stream_index to interface
|
|
|
|
---
|
|
lib/DllAvFormat.h | 4 ++++
|
|
1 file changed, 4 insertions(+)
|
|
|
|
diff --git a/lib/DllAvFormat.h b/lib/DllAvFormat.h
|
|
index 9bda3f3..bf31fcb 100644
|
|
--- a/lib/DllAvFormat.h
|
|
+++ b/lib/DllAvFormat.h
|
|
@@ -98,6 +98,7 @@ class DllAvFormatInterface
|
|
virtual int avformat_write_header (AVFormatContext *s, AVDictionary **options)=0;
|
|
virtual int av_write_trailer(AVFormatContext *s)=0;
|
|
virtual int av_write_frame (AVFormatContext *s, AVPacket *pkt)=0;
|
|
+ virtual int av_find_default_stream_index(AVFormatContext *s)=0;
|
|
};
|
|
|
|
#if (defined USE_EXTERNAL_FFMPEG) || (defined TARGET_DARWIN)
|
|
@@ -153,6 +154,7 @@ class DllAvFormat : public DllDynamic, DllAvFormatInterface
|
|
virtual int avformat_write_header (AVFormatContext *s, AVDictionary **options) { return ::avformat_write_header (s, options); }
|
|
virtual int av_write_trailer(AVFormatContext *s) { return ::av_write_trailer(s); }
|
|
virtual int av_write_frame (AVFormatContext *s, AVPacket *pkt) { return ::av_write_frame(s, pkt); }
|
|
+ virtual int av_find_default_stream_index(AVFormatContext *s) { return ::av_find_default_stream_index(s); }
|
|
|
|
// DLL faking.
|
|
virtual bool ResolveExports() { return true; }
|
|
@@ -209,6 +211,7 @@ class DllAvFormat : public DllDynamic, DllAvFormatInterface
|
|
DEFINE_METHOD2(int, avformat_write_header , (AVFormatContext *p1, AVDictionary **p2))
|
|
DEFINE_METHOD1(int, av_write_trailer, (AVFormatContext *p1))
|
|
DEFINE_METHOD2(int, av_write_frame , (AVFormatContext *p1, AVPacket *p2))
|
|
+ DEFINE_METHOD1(int, av_find_default_stream_index, (AVFormatContext *p1))
|
|
BEGIN_METHOD_RESOLVE()
|
|
RESOLVE_METHOD_RENAME(av_register_all, av_register_all_dont_call)
|
|
RESOLVE_METHOD(av_find_input_format)
|
|
@@ -243,6 +246,7 @@ class DllAvFormat : public DllDynamic, DllAvFormatInterface
|
|
RESOLVE_METHOD(avformat_write_header)
|
|
RESOLVE_METHOD(av_write_trailer)
|
|
RESOLVE_METHOD(av_write_frame)
|
|
+ RESOLVE_METHOD(av_find_default_stream_index)
|
|
END_METHOD_RESOLVE()
|
|
|
|
/* dependencies of libavformat */
|
|
--
|
|
1.7.10
|
|
|
|
|
|
From 23be471842ae9ea7bd62c18261a5e96a11045d04 Mon Sep 17 00:00:00 2001
|
|
From: xbmc <fernetmenta@online.de>
|
|
Date: Mon, 20 Aug 2012 16:06:39 +0200
|
|
Subject: [PATCH 44/72] dvdplayer: observe pts counter overflow
|
|
|
|
---
|
|
.../cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp | 198 +++++++++++++++++++-
|
|
xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.h | 4 +
|
|
2 files changed, 201 insertions(+), 1 deletion(-)
|
|
|
|
diff --git a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp
|
|
index 7c0ab03..f91be3c 100644
|
|
--- a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp
|
|
+++ b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp
|
|
@@ -18,13 +18,13 @@
|
|
*
|
|
*/
|
|
|
|
-#include "system.h"
|
|
#ifndef __STDC_CONSTANT_MACROS
|
|
#define __STDC_CONSTANT_MACROS
|
|
#endif
|
|
#ifndef __STDC_LIMIT_MACROS
|
|
#define __STDC_LIMIT_MACROS
|
|
#endif
|
|
+#include "system.h"
|
|
#ifdef _LINUX
|
|
#include "stdint.h"
|
|
#endif
|
|
@@ -495,6 +495,9 @@ bool CDVDDemuxFFmpeg::Open(CDVDInputStream* pInput)
|
|
AddStream(i);
|
|
}
|
|
|
|
+ m_bPtsWrapChecked = false;
|
|
+ m_bPtsWrap = false;
|
|
+
|
|
return true;
|
|
}
|
|
|
|
@@ -605,6 +608,12 @@ double CDVDDemuxFFmpeg::ConvertTimestamp(int64_t pts, int den, int num)
|
|
if (pts == (int64_t)AV_NOPTS_VALUE)
|
|
return DVD_NOPTS_VALUE;
|
|
|
|
+ if (m_bPtsWrap)
|
|
+ {
|
|
+ if (pts < m_iStartTime && pts < m_iEndTime)
|
|
+ pts += m_iMaxTime;
|
|
+ }
|
|
+
|
|
// do calculations in floats as they can easily overflow otherwise
|
|
// we don't care for having a completly exact timestamp anyway
|
|
double timestamp = (double)pts * num / den;
|
|
@@ -729,6 +738,24 @@ DemuxPacket* CDVDDemuxFFmpeg::Read()
|
|
pkt.pts = AV_NOPTS_VALUE;
|
|
}
|
|
|
|
+ if (!m_bPtsWrapChecked && m_pFormatContext->iformat->flags & AVFMT_TS_DISCONT)
|
|
+ {
|
|
+ int defaultStream = m_dllAvFormat.av_find_default_stream_index(m_pFormatContext);
|
|
+ int64_t duration = m_pFormatContext->streams[defaultStream]->duration * 1.5;
|
|
+ m_iMaxTime = 1LL<<m_pFormatContext->streams[defaultStream]->pts_wrap_bits;
|
|
+ m_iStartTime = m_pFormatContext->streams[defaultStream]->start_time;
|
|
+ if (m_iStartTime != DVD_NOPTS_VALUE)
|
|
+ {
|
|
+ m_iEndTime = (m_iStartTime + duration) & ~m_iMaxTime;
|
|
+ if (m_iEndTime < m_iStartTime)
|
|
+ {
|
|
+ CLog::Log(LOGNOTICE,"CDVDDemuxFFmpeg::Read - file contains pts overflow");
|
|
+ m_bPtsWrap = true;
|
|
+ }
|
|
+ }
|
|
+ m_bPtsWrapChecked = true;
|
|
+ }
|
|
+
|
|
// copy contents into our own packet
|
|
pPacket->iSize = pkt.size;
|
|
|
|
@@ -845,10 +872,20 @@ bool CDVDDemuxFFmpeg::SeekTime(int time, bool backwords, double *startpts)
|
|
int ret;
|
|
{
|
|
CSingleLock lock(m_critSection);
|
|
+
|
|
ret = m_dllAvFormat.av_seek_frame(m_pFormatContext, -1, seek_pts, backwords ? AVSEEK_FLAG_BACKWARD : 0);
|
|
|
|
if(ret >= 0)
|
|
+ {
|
|
UpdateCurrentPTS();
|
|
+
|
|
+ // seek may fail silently on streams which allow discontinuity
|
|
+ // if current timestamp is way off asume a pts overflow and try bisect seek
|
|
+ if (m_bPtsWrap && fabs(time - m_iCurrentPts/1000) > 10000)
|
|
+ {
|
|
+ ret = SeekTimeDiscont(seek_pts, backwords) ? 1 : -1;
|
|
+ }
|
|
+ }
|
|
}
|
|
|
|
if(m_iCurrentPts == DVD_NOPTS_VALUE)
|
|
@@ -867,6 +904,165 @@ bool CDVDDemuxFFmpeg::SeekTime(int time, bool backwords, double *startpts)
|
|
return (ret >= 0);
|
|
}
|
|
|
|
+bool CDVDDemuxFFmpeg::SeekTimeDiscont(int64_t pts, bool backwards)
|
|
+{
|
|
+ // this code is taken from ffmpeg function ff_gen_search
|
|
+ // it is modified to assume a pts overflow if timestamp < start_time
|
|
+ if (!m_pFormatContext->iformat->read_timestamp)
|
|
+ return false;
|
|
+
|
|
+ int defaultStream = m_dllAvFormat.av_find_default_stream_index(m_pFormatContext);
|
|
+
|
|
+ if (defaultStream < 0)
|
|
+ {
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ // timestamp for default must be expressed in AV_TIME_BASE units
|
|
+ pts = m_dllAvUtil.av_rescale_rnd(pts, m_pFormatContext->streams[defaultStream]->time_base.den,
|
|
+ AV_TIME_BASE * (int64_t)m_pFormatContext->streams[defaultStream]->time_base.num,
|
|
+ AV_ROUND_NEAR_INF);
|
|
+
|
|
+ int64_t pos, pos_min, pos_max, pos_limit, ts, ts_min, ts_max;
|
|
+ int64_t start_pos, filesize;
|
|
+ int no_change;
|
|
+
|
|
+ pos_min = m_pFormatContext->data_offset;
|
|
+ ts_min = m_pFormatContext->iformat->read_timestamp(m_pFormatContext, defaultStream,
|
|
+ &pos_min, INT64_MAX);
|
|
+ if (ts_min == AV_NOPTS_VALUE)
|
|
+ return false;
|
|
+
|
|
+ if(ts_min >= pts)
|
|
+ {
|
|
+ pos = pos_min;
|
|
+ return true;
|
|
+ }
|
|
+
|
|
+ int step= 1024;
|
|
+ filesize = m_pInput->GetLength();
|
|
+ pos_max = filesize - 1;
|
|
+ do
|
|
+ {
|
|
+ pos_max -= step;
|
|
+ ts_max = m_pFormatContext->iformat->read_timestamp(m_pFormatContext, defaultStream,
|
|
+ &pos_max, pos_max + step);
|
|
+ step += step;
|
|
+ }while (ts_max == AV_NOPTS_VALUE && pos_max >= step);
|
|
+
|
|
+ if (ts_max == AV_NOPTS_VALUE)
|
|
+ return false;
|
|
+
|
|
+ if (ts_max < m_iStartTime && ts_max < m_iEndTime)
|
|
+ ts_max += m_iMaxTime;
|
|
+
|
|
+ for(;;)
|
|
+ {
|
|
+ int64_t tmp_pos = pos_max + 1;
|
|
+ int64_t tmp_ts = m_pFormatContext->iformat->read_timestamp(m_pFormatContext, defaultStream,
|
|
+ &tmp_pos, INT64_MAX);
|
|
+ if(tmp_ts == AV_NOPTS_VALUE)
|
|
+ break;
|
|
+
|
|
+ if (tmp_ts < m_iStartTime && tmp_ts < m_iEndTime)
|
|
+ tmp_ts += m_iMaxTime;
|
|
+
|
|
+ ts_max = tmp_ts;
|
|
+ pos_max = tmp_pos;
|
|
+ if (tmp_pos >= filesize)
|
|
+ break;
|
|
+ }
|
|
+ pos_limit = pos_max;
|
|
+
|
|
+ if(ts_max <= pts)
|
|
+ {
|
|
+ bool ret = SeekByte(pos_max);
|
|
+ if (ret)
|
|
+ {
|
|
+ m_iCurrentPts = ConvertTimestamp(ts_max, m_pFormatContext->streams[defaultStream]->time_base.den,
|
|
+ m_pFormatContext->streams[defaultStream]->time_base.num);
|
|
+ }
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ if(ts_min > ts_max)
|
|
+ {
|
|
+ return false;
|
|
+ }
|
|
+ else if (ts_min == ts_max)
|
|
+ {
|
|
+ pos_limit = pos_min;
|
|
+ }
|
|
+
|
|
+ no_change=0;
|
|
+ while (pos_min < pos_limit)
|
|
+ {
|
|
+ if (no_change == 0)
|
|
+ {
|
|
+ int64_t approximate_keyframe_distance= pos_max - pos_limit;
|
|
+ // interpolate position (better than dichotomy)
|
|
+ pos = m_dllAvUtil.av_rescale_rnd(pts - ts_min, pos_max - pos_min,
|
|
+ ts_max - ts_min, AV_ROUND_NEAR_INF)
|
|
+ + pos_min - approximate_keyframe_distance;
|
|
+ }
|
|
+ else if (no_change == 1)
|
|
+ {
|
|
+ // bisection, if interpolation failed to change min or max pos last time
|
|
+ pos = (pos_min + pos_limit) >> 1;
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ /* linear search if bisection failed, can only happen if there
|
|
+ are very few or no keyframes between min/max */
|
|
+ pos = pos_min;
|
|
+ }
|
|
+ if (pos <= pos_min)
|
|
+ pos= pos_min + 1;
|
|
+ else if (pos > pos_limit)
|
|
+ pos= pos_limit;
|
|
+ start_pos = pos;
|
|
+
|
|
+ ts = m_pFormatContext->iformat->read_timestamp(m_pFormatContext, defaultStream,
|
|
+ &pos, INT64_MAX);
|
|
+ if (pos == pos_max)
|
|
+ no_change++;
|
|
+ else
|
|
+ no_change=0;
|
|
+
|
|
+ if (ts == AV_NOPTS_VALUE)
|
|
+ {
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ if (ts < m_iStartTime && ts < m_iEndTime)
|
|
+ ts += m_iMaxTime;
|
|
+
|
|
+ if (pts <= ts)
|
|
+ {
|
|
+ pos_limit = start_pos - 1;
|
|
+ pos_max = pos;
|
|
+ ts_max = ts;
|
|
+ }
|
|
+ if (pts >= ts)
|
|
+ {
|
|
+ pos_min = pos;
|
|
+ ts_min = ts;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ pos = (backwards) ? pos_min : pos_max;
|
|
+ ts = (backwards) ? ts_min : ts_max;
|
|
+
|
|
+ bool ret = SeekByte(pos);
|
|
+ if (ret)
|
|
+ {
|
|
+ m_iCurrentPts = ConvertTimestamp(ts, m_pFormatContext->streams[defaultStream]->time_base.den,
|
|
+ m_pFormatContext->streams[defaultStream]->time_base.num);
|
|
+ }
|
|
+
|
|
+ return ret;
|
|
+}
|
|
+
|
|
bool CDVDDemuxFFmpeg::SeekByte(int64_t pos)
|
|
{
|
|
g_demuxer.set(this);
|
|
diff --git a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.h b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.h
|
|
index 2b5f2e8..e0acf29 100644
|
|
--- a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.h
|
|
+++ b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.h
|
|
@@ -97,6 +97,7 @@ class CDVDDemuxFFmpeg : public CDVDDemux
|
|
DemuxPacket* Read();
|
|
|
|
bool SeekTime(int time, bool backwords = false, double* startpts = NULL);
|
|
+ bool SeekTimeDiscont(int64_t pts, bool backwards);
|
|
bool SeekByte(int64_t pos);
|
|
int GetStreamLength();
|
|
CDemuxStream* GetStream(int iStreamId);
|
|
@@ -141,5 +142,8 @@ class CDVDDemuxFFmpeg : public CDVDDemux
|
|
XbmcThreads::EndTime m_timeout;
|
|
|
|
CDVDInputStream* m_pInput;
|
|
+
|
|
+ bool m_bPtsWrap, m_bPtsWrapChecked;
|
|
+ int64_t m_iStartTime, m_iMaxTime, m_iEndTime;
|
|
};
|
|
|
|
--
|
|
1.7.10
|
|
|
|
|
|
From 66382788a903f99ba317e972ba0445fc68320750 Mon Sep 17 00:00:00 2001
|
|
From: xbmc <fernetmenta@online.de>
|
|
Date: Tue, 2 Oct 2012 13:02:10 +0200
|
|
Subject: [PATCH 45/72] dvdplayer: avoid short screen flicker caused by
|
|
unnecessary reconfigure of renderer
|
|
|
|
---
|
|
xbmc/cores/dvdplayer/DVDPlayerVideo.cpp | 4 ++--
|
|
1 file changed, 2 insertions(+), 2 deletions(-)
|
|
|
|
diff --git a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp
|
|
index e5e71f3..8b02d81 100644
|
|
--- a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp
|
|
+++ b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp
|
|
@@ -1033,7 +1033,7 @@ int CDVDPlayerVideo::OutputPicture(const DVDVideoPicture* src, double pts)
|
|
|| m_output.height != pPicture->iHeight
|
|
|| m_output.dwidth != pPicture->iDisplayWidth
|
|
|| m_output.dheight != pPicture->iDisplayHeight
|
|
- || m_output.framerate != config_framerate
|
|
+ || (!m_bFpsInvalid && fmod(m_output.framerate, config_framerate) != 0.0 )
|
|
|| m_output.color_format != (unsigned int)pPicture->format
|
|
|| m_output.extended_format != pPicture->extended_format
|
|
|| ( m_output.color_matrix != pPicture->color_matrix && pPicture->color_matrix != 0 ) // don't reconfigure on unspecified
|
|
@@ -1184,7 +1184,7 @@ int CDVDPlayerVideo::OutputPicture(const DVDVideoPicture* src, double pts)
|
|
m_output.height = pPicture->iHeight;
|
|
m_output.dwidth = pPicture->iDisplayWidth;
|
|
m_output.dheight = pPicture->iDisplayHeight;
|
|
- m_output.framerate = config_framerate;
|
|
+ m_output.framerate = config_framerate == 0.0 ? g_graphicsContext.GetFPS() : config_framerate;
|
|
m_output.color_format = pPicture->format;
|
|
m_output.extended_format = pPicture->extended_format;
|
|
m_output.color_matrix = pPicture->color_matrix;
|
|
--
|
|
1.7.10
|
|
|
|
|
|
From 04f4521c1938a7ac17acd59f3bd6be59c7ba8184 Mon Sep 17 00:00:00 2001
|
|
From: xbmc <fernetmenta@online.de>
|
|
Date: Sat, 16 Jun 2012 12:46:30 +0200
|
|
Subject: [PATCH 46/72] xvba: do not use vaapi if xvba is present
|
|
|
|
---
|
|
xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.cpp | 9 +++++++++
|
|
1 file changed, 9 insertions(+)
|
|
|
|
diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.cpp
|
|
index a2b9195..43a05b3 100644
|
|
--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.cpp
|
|
+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.cpp
|
|
@@ -261,6 +261,15 @@ void CDecoder::Close()
|
|
|
|
bool CDecoder::Open(AVCodecContext *avctx, enum PixelFormat fmt, unsigned int surfaces)
|
|
{
|
|
+#ifdef HAVE_LIBXVBA
|
|
+ std::string Vendor = g_Windowing.GetRenderVendor();
|
|
+ std::transform(Vendor.begin(), Vendor.end(), Vendor.begin(), ::tolower);
|
|
+ if (Vendor.compare(0, 3, "ati") == 0)
|
|
+ {
|
|
+ return false;
|
|
+ }
|
|
+#endif
|
|
+
|
|
VAEntrypoint entrypoint = VAEntrypointVLD;
|
|
VAProfile profile;
|
|
|
|
--
|
|
1.7.10
|
|
|
|
|
|
From a133b7fa119e859ec50b9f05a33de984105234f3 Mon Sep 17 00:00:00 2001
|
|
From: xbmc <fernetmenta@online.de>
|
|
Date: Thu, 11 Oct 2012 12:05:50 +0200
|
|
Subject: [PATCH 47/72] vdpau: advanced settings for auto deinterlacing
|
|
|
|
---
|
|
xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp | 8 ++++----
|
|
xbmc/settings/AdvancedSettings.cpp | 4 ++++
|
|
xbmc/settings/AdvancedSettings.h | 2 ++
|
|
3 files changed, 10 insertions(+), 4 deletions(-)
|
|
|
|
diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp
|
|
index 235f565..d95797b 100644
|
|
--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp
|
|
+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp
|
|
@@ -1770,10 +1770,10 @@ EINTERLACEMETHOD CMixer::GetDeinterlacingMethod(bool log /* = false */)
|
|
if (method == VS_INTERLACEMETHOD_AUTO)
|
|
{
|
|
int deint = -1;
|
|
-// if (m_config.outHeight >= 720)
|
|
-// deint = g_advancedSettings.m_videoVDPAUdeintHD;
|
|
-// else
|
|
-// deint = g_advancedSettings.m_videoVDPAUdeintSD;
|
|
+ if (m_config.outHeight >= 720)
|
|
+ deint = g_advancedSettings.m_videoVDPAUdeintHD;
|
|
+ else
|
|
+ deint = g_advancedSettings.m_videoVDPAUdeintSD;
|
|
|
|
if (deint != -1)
|
|
{
|
|
diff --git a/xbmc/settings/AdvancedSettings.cpp b/xbmc/settings/AdvancedSettings.cpp
|
|
index 844f8e8..d913924 100644
|
|
--- a/xbmc/settings/AdvancedSettings.cpp
|
|
+++ b/xbmc/settings/AdvancedSettings.cpp
|
|
@@ -106,6 +106,8 @@ void CAdvancedSettings::Initialize()
|
|
m_videoAllowMpeg4VAAPI = false;
|
|
m_videoDisableBackgroundDeinterlace = false;
|
|
m_videoCaptureUseOcclusionQuery = -1; //-1 is auto detect
|
|
+ m_videoVDPAUdeintHD = -1;
|
|
+ m_videoVDPAUdeintSD = -1;
|
|
m_videoVDPAUtelecine = false;
|
|
m_videoVDPAUdeintSkipChromaHD = false;
|
|
m_DXVACheckCompatibility = false;
|
|
@@ -503,6 +505,8 @@ void CAdvancedSettings::ParseSettingsFile(const CStdString &file)
|
|
XMLUtils::GetBoolean(pElement,"allowmpeg4vaapi",m_videoAllowMpeg4VAAPI);
|
|
XMLUtils::GetBoolean(pElement, "disablebackgrounddeinterlace", m_videoDisableBackgroundDeinterlace);
|
|
XMLUtils::GetInt(pElement, "useocclusionquery", m_videoCaptureUseOcclusionQuery, -1, 1);
|
|
+ XMLUtils::GetInt(pElement,"vdpauHDdeint",m_videoVDPAUdeintHD);
|
|
+ XMLUtils::GetInt(pElement,"vdpauSDdeint",m_videoVDPAUdeintSD);
|
|
XMLUtils::GetBoolean(pElement,"vdpauInvTelecine",m_videoVDPAUtelecine);
|
|
XMLUtils::GetBoolean(pElement,"vdpauHDdeintSkipChroma",m_videoVDPAUdeintSkipChromaHD);
|
|
|
|
diff --git a/xbmc/settings/AdvancedSettings.h b/xbmc/settings/AdvancedSettings.h
|
|
index 72718e5..aaa4702 100644
|
|
--- a/xbmc/settings/AdvancedSettings.h
|
|
+++ b/xbmc/settings/AdvancedSettings.h
|
|
@@ -133,6 +133,8 @@ class CAdvancedSettings
|
|
int m_videoPercentSeekBackwardBig;
|
|
CStdString m_videoPPFFmpegDeint;
|
|
CStdString m_videoPPFFmpegPostProc;
|
|
+ int m_videoVDPAUdeintHD;
|
|
+ int m_videoVDPAUdeintSD;
|
|
bool m_videoVDPAUtelecine;
|
|
bool m_videoVDPAUdeintSkipChromaHD;
|
|
bool m_musicUseTimeSeeking;
|
|
--
|
|
1.7.10
|
|
|
|
|
|
From 62540aeaa356823bd34e9367ac39eef23a6e4ce4 Mon Sep 17 00:00:00 2001
|
|
From: xbmc <fernetmenta@online.de>
|
|
Date: Thu, 11 Oct 2012 13:01:08 +0200
|
|
Subject: [PATCH 48/72] dvdplayer: correct determination if video is playing
|
|
|
|
---
|
|
xbmc/cores/dvdplayer/DVDPlayer.cpp | 11 +++++++++--
|
|
1 file changed, 9 insertions(+), 2 deletions(-)
|
|
|
|
diff --git a/xbmc/cores/dvdplayer/DVDPlayer.cpp b/xbmc/cores/dvdplayer/DVDPlayer.cpp
|
|
index 6fcb6b3..f76691d 100644
|
|
--- a/xbmc/cores/dvdplayer/DVDPlayer.cpp
|
|
+++ b/xbmc/cores/dvdplayer/DVDPlayer.cpp
|
|
@@ -2382,9 +2382,16 @@ bool CDVDPlayer::IsPaused() const
|
|
|
|
bool CDVDPlayer::HasVideo() const
|
|
{
|
|
- if (m_pInputStream && m_pInputStream->IsStreamType(DVDSTREAM_TYPE_DVD)) return true;
|
|
+ bool hasVideo(false);
|
|
|
|
- return m_SelectionStreams.Count(STREAM_VIDEO) > 0 ? true : false;
|
|
+ if (m_pInputStream && m_pInputStream->IsStreamType(DVDSTREAM_TYPE_DVD))
|
|
+ hasVideo = true;
|
|
+ else if (m_SelectionStreams.Count(STREAM_VIDEO) > 0)
|
|
+ hasVideo = true;
|
|
+ else if (g_renderManager.IsConfigured())
|
|
+ hasVideo = true;
|
|
+
|
|
+ return hasVideo;
|
|
}
|
|
|
|
bool CDVDPlayer::HasAudio() const
|
|
--
|
|
1.7.10
|
|
|
|
|
|
From 5a093bbd60d1ca47ed7c5e4639f28dafc1b565c1 Mon Sep 17 00:00:00 2001
|
|
From: xbmc <fernetmenta@online.de>
|
|
Date: Sun, 14 Oct 2012 13:46:54 +0200
|
|
Subject: [PATCH 49/72] rendermanager: fix stuttering in non full-screen mode,
|
|
squash to add buffering
|
|
|
|
---
|
|
xbmc/cores/VideoRenderers/RenderManager.cpp | 3 ++-
|
|
1 file changed, 2 insertions(+), 1 deletion(-)
|
|
|
|
diff --git a/xbmc/cores/VideoRenderers/RenderManager.cpp b/xbmc/cores/VideoRenderers/RenderManager.cpp
|
|
index 0506823..b141c80 100644
|
|
--- a/xbmc/cores/VideoRenderers/RenderManager.cpp
|
|
+++ b/xbmc/cores/VideoRenderers/RenderManager.cpp
|
|
@@ -1057,8 +1057,9 @@ void CXBMCRenderManager::PrepareNextRender()
|
|
presenttime = clocktime + MAXPRESENTDELAY;
|
|
|
|
m_sleeptime = presenttime - clocktime;
|
|
+ double frametime = 1 / g_graphicsContext.GetFPS();
|
|
|
|
- if (g_graphicsContext.IsFullScreenVideo() || presenttime <= clocktime+0.01)
|
|
+ if (g_graphicsContext.IsFullScreenVideo() || presenttime <= clocktime + frametime)
|
|
{
|
|
m_presentPts = m_renderBuffers[idx].pts;
|
|
m_presenttime = presenttime;
|
|
--
|
|
1.7.10
|
|
|
|
|
|
From d0597caa2c922575efdf081d719d5665c626ffec Mon Sep 17 00:00:00 2001
|
|
From: xbmc <fernetmenta@online.de>
|
|
Date: Sun, 14 Oct 2012 17:54:02 +0200
|
|
Subject: [PATCH 50/72] rendermanager: forgot to set flip event if buffering
|
|
is not used
|
|
|
|
---
|
|
xbmc/cores/VideoRenderers/RenderManager.cpp | 20 ++++++++++----------
|
|
1 file changed, 10 insertions(+), 10 deletions(-)
|
|
|
|
diff --git a/xbmc/cores/VideoRenderers/RenderManager.cpp b/xbmc/cores/VideoRenderers/RenderManager.cpp
|
|
index b141c80..9290f80 100644
|
|
--- a/xbmc/cores/VideoRenderers/RenderManager.cpp
|
|
+++ b/xbmc/cores/VideoRenderers/RenderManager.cpp
|
|
@@ -1096,17 +1096,17 @@ void CXBMCRenderManager::NotifyDisplayFlip()
|
|
if (!m_pRenderer)
|
|
return;
|
|
|
|
- if (m_iNumRenderBuffers < 3)
|
|
- return;
|
|
-
|
|
- int last = m_iDisplayedRenderBuffer;
|
|
- m_iDisplayedRenderBuffer = (m_iCurrentRenderBuffer + m_iNumRenderBuffers - 1) % m_iNumRenderBuffers;
|
|
-
|
|
- if (last != m_iDisplayedRenderBuffer
|
|
- && m_iDisplayedRenderBuffer != m_iCurrentRenderBuffer)
|
|
+ if (m_iNumRenderBuffers >= 3)
|
|
{
|
|
- m_pRenderer->ReleaseBuffer(m_iDisplayedRenderBuffer);
|
|
- m_overlays.ReleaseBuffer(m_iDisplayedRenderBuffer);
|
|
+ int last = m_iDisplayedRenderBuffer;
|
|
+ m_iDisplayedRenderBuffer = (m_iCurrentRenderBuffer + m_iNumRenderBuffers - 1) % m_iNumRenderBuffers;
|
|
+
|
|
+ if (last != m_iDisplayedRenderBuffer
|
|
+ && m_iDisplayedRenderBuffer != m_iCurrentRenderBuffer)
|
|
+ {
|
|
+ m_pRenderer->ReleaseBuffer(m_iDisplayedRenderBuffer);
|
|
+ m_overlays.ReleaseBuffer(m_iDisplayedRenderBuffer);
|
|
+ }
|
|
}
|
|
|
|
lock.Leave();
|
|
--
|
|
1.7.10
|
|
|
|
|
|
From c485392afa608bfbcf903fa53a9dd824258c96dd Mon Sep 17 00:00:00 2001
|
|
From: xbmc <fernetmenta@online.de>
|
|
Date: Fri, 26 Oct 2012 15:30:22 +0200
|
|
Subject: [PATCH 51/72] vdpau: fix small mem leak
|
|
|
|
---
|
|
xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp | 2 ++
|
|
1 file changed, 2 insertions(+)
|
|
|
|
diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp
|
|
index d95797b..fec4b88 100644
|
|
--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp
|
|
+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp
|
|
@@ -2052,6 +2052,8 @@ void CMixer::Uninit()
|
|
m_outputSurfaces.pop();
|
|
}
|
|
m_config.vdpProcs.vdp_video_mixer_destroy(m_videoMixer);
|
|
+
|
|
+ delete [] m_BlackBar;
|
|
}
|
|
|
|
void CMixer::Flush()
|
|
--
|
|
1.7.10
|
|
|
|
|
|
From 9d7228a84013e409149d7b05d34545d1bdf06e27 Mon Sep 17 00:00:00 2001
|
|
From: xbmc <fernetmenta@online.de>
|
|
Date: Mon, 29 Oct 2012 18:25:56 +0100
|
|
Subject: [PATCH 52/72] xvba: do not render if there is no valid texture
|
|
|
|
---
|
|
xbmc/cores/VideoRenderers/LinuxRendererGL.cpp | 8 +++-----
|
|
1 file changed, 3 insertions(+), 5 deletions(-)
|
|
|
|
diff --git a/xbmc/cores/VideoRenderers/LinuxRendererGL.cpp b/xbmc/cores/VideoRenderers/LinuxRendererGL.cpp
|
|
index ec3606a..7c3adcb 100644
|
|
--- a/xbmc/cores/VideoRenderers/LinuxRendererGL.cpp
|
|
+++ b/xbmc/cores/VideoRenderers/LinuxRendererGL.cpp
|
|
@@ -2924,16 +2924,14 @@ void CLinuxRendererGL::UploadXVBATexture(int index)
|
|
YUVFIELDS &fields = m_buffers[index].fields;
|
|
YUVPLANE &plane = fields[0][1];
|
|
|
|
- if (!xvba)
|
|
+ if (!xvba || !xvba->valid)
|
|
{
|
|
- fields[0][1].id = fields[0][0].id;
|
|
m_eventTexturesDone[index]->Set();
|
|
- CLog::Log(LOGWARNING,"CLinuxRendererGL::UploadXVBATexture no xvba texture, index: %d", index);
|
|
+ m_skipRender = true;
|
|
return;
|
|
}
|
|
-// xvba->Transfer();
|
|
|
|
- fields[0][1].id = xvba->texture;
|
|
+ plane.id = xvba->texture;
|
|
|
|
im.height = xvba->texHeight;
|
|
im.width = xvba->texWidth;
|
|
--
|
|
1.7.10
|
|
|
|
|
|
From 85be082db41b27cdd3824b8360dc021e17a84c22 Mon Sep 17 00:00:00 2001
|
|
From: xbmc <fernetmenta@online.de>
|
|
Date: Fri, 2 Nov 2012 13:20:03 +0100
|
|
Subject: [PATCH 53/72] player: fix rewind
|
|
|
|
---
|
|
xbmc/cores/dvdplayer/DVDMessage.h | 5 ++++-
|
|
xbmc/cores/dvdplayer/DVDPlayer.cpp | 33 ++++++++++++++++++++-----------
|
|
xbmc/cores/dvdplayer/DVDPlayer.h | 7 ++++---
|
|
xbmc/cores/dvdplayer/DVDPlayerVideo.cpp | 10 ++++++----
|
|
xbmc/cores/dvdplayer/DVDPlayerVideo.h | 1 +
|
|
5 files changed, 36 insertions(+), 20 deletions(-)
|
|
|
|
diff --git a/xbmc/cores/dvdplayer/DVDMessage.h b/xbmc/cores/dvdplayer/DVDMessage.h
|
|
index 30b2f5c..b9831d4 100644
|
|
--- a/xbmc/cores/dvdplayer/DVDMessage.h
|
|
+++ b/xbmc/cores/dvdplayer/DVDMessage.h
|
|
@@ -218,7 +218,7 @@ class CDVDMsgPlayerSetState : public CDVDMsg
|
|
class CDVDMsgPlayerSeek : public CDVDMsg
|
|
{
|
|
public:
|
|
- CDVDMsgPlayerSeek(int time, bool backward, bool flush = true, bool accurate = true, bool restore = true, bool trickplay = false)
|
|
+ CDVDMsgPlayerSeek(int time, bool backward, bool flush = true, bool accurate = true, bool restore = true, bool trickplay = false, bool sync = true)
|
|
: CDVDMsg(PLAYER_SEEK)
|
|
, m_time(time)
|
|
, m_backward(backward)
|
|
@@ -226,6 +226,7 @@ class CDVDMsgPlayerSeek : public CDVDMsg
|
|
, m_accurate(accurate)
|
|
, m_restore(restore)
|
|
, m_trickplay(trickplay)
|
|
+ , m_sync(sync)
|
|
{}
|
|
int GetTime() { return m_time; }
|
|
bool GetBackward() { return m_backward; }
|
|
@@ -233,6 +234,7 @@ class CDVDMsgPlayerSeek : public CDVDMsg
|
|
bool GetAccurate() { return m_accurate; }
|
|
bool GetRestore() { return m_restore; }
|
|
bool GetTrickPlay() { return m_trickplay; }
|
|
+ bool GetSync() { return m_sync; }
|
|
private:
|
|
int m_time;
|
|
bool m_backward;
|
|
@@ -240,6 +242,7 @@ class CDVDMsgPlayerSeek : public CDVDMsg
|
|
bool m_accurate;
|
|
bool m_restore; // whether to restore any EDL cut time
|
|
bool m_trickplay;
|
|
+ bool m_sync;
|
|
};
|
|
|
|
class CDVDMsgPlayerSeekChapter : public CDVDMsg
|
|
diff --git a/xbmc/cores/dvdplayer/DVDPlayer.cpp b/xbmc/cores/dvdplayer/DVDPlayer.cpp
|
|
index f76691d..07df0d8 100644
|
|
--- a/xbmc/cores/dvdplayer/DVDPlayer.cpp
|
|
+++ b/xbmc/cores/dvdplayer/DVDPlayer.cpp
|
|
@@ -1543,11 +1543,13 @@ void CDVDPlayer::HandlePlaySpeed()
|
|
}
|
|
else if (m_CurrentVideo.id >= 0
|
|
&& (m_CurrentVideo.inited == true || GetPlaySpeed() < 0) // allow rewind at end of file
|
|
- && m_SpeedState.lastpts != m_dvdPlayerVideo.GetCurrentPts()
|
|
+ && (m_SpeedState.lastpts != m_dvdPlayerVideo.GetCurrentPts() || fabs(m_SpeedState.lastabstime - CDVDClock::GetAbsoluteClock()) > DVD_MSEC_TO_TIME(200))
|
|
+ && (m_dvdPlayerVideo.GetCurrentPts() != DVD_NOPTS_VALUE)
|
|
&& m_SpeedState.lasttime != GetTime())
|
|
{
|
|
m_SpeedState.lastpts = m_dvdPlayerVideo.GetCurrentPts();
|
|
m_SpeedState.lasttime = GetTime();
|
|
+ m_SpeedState.lastabstime = CDVDClock::GetAbsoluteClock();
|
|
// check how much off clock video is when ff/rw:ing
|
|
// a problem here is that seeking isn't very accurate
|
|
// and since the clock will be resynced after seek
|
|
@@ -1566,7 +1568,7 @@ void CDVDPlayer::HandlePlaySpeed()
|
|
{
|
|
CLog::Log(LOGDEBUG, "CDVDPlayer::Process - Seeking to catch up");
|
|
int64_t iTime = (int64_t)DVD_TIME_TO_MSEC(m_clock.GetClock() + m_State.time_offset + 500000.0 * m_playSpeed / DVD_PLAYSPEED_NORMAL);
|
|
- m_messenger.Put(new CDVDMsgPlayerSeek(iTime, (GetPlaySpeed() < 0), true, false, false, true));
|
|
+ m_messenger.Put(new CDVDMsgPlayerSeek(iTime, (GetPlaySpeed() < 0), true, false, false, true, false));
|
|
}
|
|
}
|
|
}
|
|
@@ -2030,7 +2032,7 @@ void CDVDPlayer::HandleMessages()
|
|
if(!m_pSubtitleDemuxer->SeekTime(time, msg.GetBackward()))
|
|
CLog::Log(LOGDEBUG, "failed to seek subtitle demuxer: %d, success", time);
|
|
}
|
|
- FlushBuffers(!msg.GetFlush(), start, msg.GetAccurate());
|
|
+ FlushBuffers(!msg.GetFlush(), start, msg.GetAccurate(), msg.GetSync());
|
|
}
|
|
else
|
|
CLog::Log(LOGWARNING, "error while seeking");
|
|
@@ -2168,9 +2170,10 @@ void CDVDPlayer::HandleMessages()
|
|
double offset;
|
|
offset = CDVDClock::GetAbsoluteClock() - m_State.timestamp;
|
|
offset *= m_playSpeed / DVD_PLAYSPEED_NORMAL;
|
|
+ offset = DVD_TIME_TO_MSEC(offset);
|
|
if(offset > 1000) offset = 1000;
|
|
if(offset < -1000) offset = -1000;
|
|
- m_State.time += DVD_TIME_TO_MSEC(offset);
|
|
+ m_State.time += offset;
|
|
m_State.timestamp = CDVDClock::GetAbsoluteClock();
|
|
}
|
|
|
|
@@ -2186,7 +2189,8 @@ void CDVDPlayer::HandleMessages()
|
|
// do a seek after rewind, clock is not in sync with current pts
|
|
if (m_playSpeed < 0 && speed >= 0)
|
|
{
|
|
- m_messenger.Put(new CDVDMsgPlayerSeek(GetTime(), true, true, true));
|
|
+ int64_t iTime = (int64_t)DVD_TIME_TO_MSEC(m_clock.GetClock() + m_State.time_offset);
|
|
+ m_messenger.Put(new CDVDMsgPlayerSeek(iTime, true, true, false, false, true));
|
|
}
|
|
|
|
// if playspeed is different then DVD_PLAYSPEED_NORMAL or DVD_PLAYSPEED_PAUSE
|
|
@@ -2767,10 +2771,11 @@ int64_t CDVDPlayer::GetTime()
|
|
{
|
|
offset = CDVDClock::GetAbsoluteClock() - m_State.timestamp;
|
|
offset *= m_playSpeed / DVD_PLAYSPEED_NORMAL;
|
|
+ offset = DVD_TIME_TO_MSEC(offset);
|
|
if(offset > 1000) offset = 1000;
|
|
if(offset < -1000) offset = -1000;
|
|
}
|
|
- return llrint(m_State.time + DVD_TIME_TO_MSEC(offset));
|
|
+ return llrint(m_State.time + offset);
|
|
}
|
|
|
|
// return length in msec
|
|
@@ -3140,7 +3145,7 @@ bool CDVDPlayer::CloseTeletextStream(bool bWaitForBuffers)
|
|
return true;
|
|
}
|
|
|
|
-void CDVDPlayer::FlushBuffers(bool queued, double pts, bool accurate)
|
|
+void CDVDPlayer::FlushBuffers(bool queued, double pts, bool accurate, bool sync)
|
|
{
|
|
double startpts;
|
|
if(accurate)
|
|
@@ -3152,19 +3157,23 @@ void CDVDPlayer::FlushBuffers(bool queued, double pts, bool accurate)
|
|
if(startpts != DVD_NOPTS_VALUE)
|
|
startpts -= m_offset_pts;
|
|
|
|
- m_CurrentAudio.inited = false;
|
|
+ if (sync)
|
|
+ {
|
|
+ m_CurrentAudio.inited = false;
|
|
+ m_CurrentVideo.inited = false;
|
|
+ m_CurrentSubtitle.inited = false;
|
|
+ m_CurrentTeletext.inited = false;
|
|
+ }
|
|
+
|
|
m_CurrentAudio.dts = DVD_NOPTS_VALUE;
|
|
m_CurrentAudio.startpts = startpts;
|
|
|
|
- m_CurrentVideo.inited = false;
|
|
m_CurrentVideo.dts = DVD_NOPTS_VALUE;
|
|
m_CurrentVideo.startpts = startpts;
|
|
|
|
- m_CurrentSubtitle.inited = false;
|
|
m_CurrentSubtitle.dts = DVD_NOPTS_VALUE;
|
|
m_CurrentSubtitle.startpts = startpts;
|
|
|
|
- m_CurrentTeletext.inited = false;
|
|
m_CurrentTeletext.dts = DVD_NOPTS_VALUE;
|
|
m_CurrentTeletext.startpts = startpts;
|
|
|
|
@@ -3208,7 +3217,7 @@ void CDVDPlayer::FlushBuffers(bool queued, double pts, bool accurate)
|
|
m_CurrentTeletext.started = false;
|
|
}
|
|
|
|
- if(pts != DVD_NOPTS_VALUE)
|
|
+ if(pts != DVD_NOPTS_VALUE && sync)
|
|
m_clock.Discontinuity(pts);
|
|
UpdatePlayState(0);
|
|
}
|
|
diff --git a/xbmc/cores/dvdplayer/DVDPlayer.h b/xbmc/cores/dvdplayer/DVDPlayer.h
|
|
index d3c201e..70ecea9 100644
|
|
--- a/xbmc/cores/dvdplayer/DVDPlayer.h
|
|
+++ b/xbmc/cores/dvdplayer/DVDPlayer.h
|
|
@@ -310,7 +310,7 @@ class CDVDPlayer : public IPlayer, public CThread, public IDVDPlayer
|
|
bool GetCachingTimes(double& play_left, double& cache_left, double& file_offset);
|
|
|
|
|
|
- void FlushBuffers(bool queued, double pts = DVD_NOPTS_VALUE, bool accurate = true);
|
|
+ void FlushBuffers(bool queued, double pts = DVD_NOPTS_VALUE, bool accurate = true, bool sync = true);
|
|
|
|
void HandleMessages();
|
|
void HandlePlaySpeed();
|
|
@@ -359,8 +359,9 @@ class CDVDPlayer : public IPlayer, public CThread, public IDVDPlayer
|
|
int m_playSpeed;
|
|
struct SSpeedState
|
|
{
|
|
- double lastpts; // holds last display pts during ff/rw operations
|
|
- double lasttime;
|
|
+ double lastpts; // holds last display pts during ff/rw operations
|
|
+ int64_t lasttime;
|
|
+ double lastabstime;
|
|
} m_SpeedState;
|
|
|
|
int m_errorCount;
|
|
diff --git a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp
|
|
index 8b02d81..d26ab9c 100644
|
|
--- a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp
|
|
+++ b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp
|
|
@@ -1268,13 +1268,13 @@ int CDVDPlayerVideo::OutputPicture(const DVDVideoPicture* src, double pts)
|
|
|
|
if( m_speed < 0 )
|
|
{
|
|
- double decoderPts = m_droppingStats.m_lastDecoderPts;
|
|
+ double inputPts = m_droppingStats.m_lastPts;
|
|
double renderPts = m_droppingStats.m_lastRenderPts;
|
|
if (pts > renderPts)
|
|
{
|
|
- if (decoderPts >= renderPts)
|
|
+ if (inputPts >= renderPts)
|
|
{
|
|
- Sleep(200);
|
|
+ Sleep(50);
|
|
}
|
|
return result | EOS_DROPPED;
|
|
}
|
|
@@ -1571,7 +1571,7 @@ double CDVDPlayerVideo::GetCurrentPts()
|
|
|
|
if( m_stalled )
|
|
iRenderPts = DVD_NOPTS_VALUE;
|
|
- else
|
|
+ else if ( m_speed == DVD_PLAYSPEED_NORMAL)
|
|
iRenderPts = iRenderPts - max(0.0, iSleepTime);
|
|
|
|
return iRenderPts;
|
|
@@ -1671,6 +1671,8 @@ int CDVDPlayerVideo::CalcDropRequirement(double pts)
|
|
int iSkippedDeint = 0;
|
|
int iBufferLevel;
|
|
|
|
+ m_droppingStats.m_lastPts = pts;
|
|
+
|
|
// get decoder stats
|
|
if (!m_pVideoCodec->GetPts(iDecoderPts, iSkippedDeint, interlaced))
|
|
iDecoderPts = pts;
|
|
diff --git a/xbmc/cores/dvdplayer/DVDPlayerVideo.h b/xbmc/cores/dvdplayer/DVDPlayerVideo.h
|
|
index 509d5f7..7cddda7 100644
|
|
--- a/xbmc/cores/dvdplayer/DVDPlayerVideo.h
|
|
+++ b/xbmc/cores/dvdplayer/DVDPlayerVideo.h
|
|
@@ -51,6 +51,7 @@ class CDroppingStats
|
|
double m_totalGain;
|
|
double m_lastDecoderPts;
|
|
double m_lastRenderPts;
|
|
+ double m_lastPts;
|
|
unsigned int m_lateFrames;
|
|
unsigned int m_dropRequests;
|
|
bool m_requestOutputDrop;
|
|
--
|
|
1.7.10
|
|
|
|
|
|
From 024ecda241754f02ad985fab9116e33b06b8d174 Mon Sep 17 00:00:00 2001
|
|
From: fritsch <peter.fruehberger@gmail.com>
|
|
Date: Fri, 2 Nov 2012 17:56:12 +0100
|
|
Subject: [PATCH 54/72] xvba: do not create decoder for surfaces larger than
|
|
width 2048 or height 1536
|
|
|
|
---
|
|
xbmc/cores/dvdplayer/DVDCodecs/Video/XVBA.cpp | 15 +++++++++++++++
|
|
1 file changed, 15 insertions(+)
|
|
|
|
diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/XVBA.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/XVBA.cpp
|
|
index e8e376a..b73c48a 100644
|
|
--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/XVBA.cpp
|
|
+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/XVBA.cpp
|
|
@@ -335,6 +335,21 @@ bool CDecoder::Open(AVCodecContext* avctx, const enum PixelFormat fmt, unsigned
|
|
return false;
|
|
}
|
|
|
|
+ // Fixme: Revisit with new SDK
|
|
+ // Workaround for 0.74.01-AES-2 that does not signal if surfaces are too large
|
|
+ // it seems that xvba does not support anything > 2k
|
|
+ // return false, for files that are larger
|
|
+ // if you are unlucky, this would kill your decoder
|
|
+ // we limit to 2048x1536(+8) now - as this was tested working
|
|
+ int surfaceWidth = (avctx->coded_width+15) & ~15;
|
|
+ int surfaceHeight = (avctx->coded_height+15) & ~15;
|
|
+ if(surfaceHeight > 1544 || surfaceWidth > 2048)
|
|
+ {
|
|
+ CLog::Log(LOGERROR, "Surface too large, decoder skipped: surfaceWidth %u, surfaceHeight %u",
|
|
+ surfaceWidth, surfaceHeight);
|
|
+ return false;
|
|
+ }
|
|
+
|
|
if (!m_dllAvUtil.Load())
|
|
return false;
|
|
|
|
--
|
|
1.7.10
|
|
|
|
|
|
From 98ebb0d0232cf4a7ea2082f9f16e210a39e983e8 Mon Sep 17 00:00:00 2001
|
|
From: fritsch <peter.fruehberger@gmail.com>
|
|
Date: Sun, 4 Nov 2012 16:24:10 +0100
|
|
Subject: [PATCH 55/72] xvba: add string for available decoders - we are
|
|
important so make sure we are there
|
|
|
|
---
|
|
xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.cpp | 5 +++++
|
|
1 file changed, 5 insertions(+)
|
|
|
|
diff --git a/xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.cpp b/xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.cpp
|
|
index 0cea7a9..6fb74b7 100644
|
|
--- a/xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.cpp
|
|
+++ b/xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.cpp
|
|
@@ -169,6 +169,11 @@ CDVDVideoCodec* CDVDFactoryCodec::CreateVideoCodec(CDVDStreamInfo &hint, unsigne
|
|
#elif defined(_LINUX) && !defined(TARGET_DARWIN)
|
|
hwSupport += "VAAPI:no ";
|
|
#endif
|
|
+#if defined(HAVE_LIBXVBA) && defined(TARGET_LINUX)
|
|
+ hwSupport += "XVBA:yes ";
|
|
+#elif defined(TARGET_LINUX)
|
|
+ hwSupport += "XVBA:no ";
|
|
+#endif
|
|
|
|
CLog::Log(LOGDEBUG, "CDVDFactoryCodec: compiled in hardware support: %s", hwSupport.c_str());
|
|
|
|
--
|
|
1.7.10
|
|
|
|
|
|
From 84e701f7db6603a2942611d5c74ba645c625ec0d Mon Sep 17 00:00:00 2001
|
|
From: fritsch <Peter.Fruehberger@gmail.com>
|
|
Date: Thu, 22 Nov 2012 21:32:21 +0100
|
|
Subject: [PATCH 56/72] xvba: revisit Artefacts. There are more broken video
|
|
files out there
|
|
|
|
---
|
|
lib/ffmpeg/libavcodec/xvba_h264.c | 10 ++++++++--
|
|
1 file changed, 8 insertions(+), 2 deletions(-)
|
|
|
|
diff --git a/lib/ffmpeg/libavcodec/xvba_h264.c b/lib/ffmpeg/libavcodec/xvba_h264.c
|
|
index a077442..87af687 100644
|
|
--- a/lib/ffmpeg/libavcodec/xvba_h264.c
|
|
+++ b/lib/ffmpeg/libavcodec/xvba_h264.c
|
|
@@ -102,10 +102,16 @@ static int end_frame(AVCodecContext *avctx)
|
|
pic_descriptor->avc_num_ref_frames = h->sps.ref_frame_count;
|
|
pic_descriptor->avc_reserved_8bit = 0;
|
|
|
|
- /* Set correct level */
|
|
- if (pic_descriptor->level == 41) {
|
|
+ /* Set a level that can decode stuff in every case without a lookup table
|
|
+ xvba seems to have problems only when the number of Reframes goes beyond
|
|
+ the max support number of Level4.1@High. So in praxis decoding a Level 3.0
|
|
+ file that in deed has level4.1@High specs does not matter. We use this fact
|
|
+ and check if the ref_frames stay in the range Level4.1@high can decode if
|
|
+ not, we set Level5.1 */
|
|
+ if (pic_descriptor->avc_num_ref_frames > 4) {
|
|
const unsigned int mbw = pic_descriptor->width_in_mb;
|
|
const unsigned int mbh = pic_descriptor->height_in_mb;
|
|
+ // this matches Level4.1@High stats to differ between <= 4.1 and 5.1
|
|
const unsigned int max_ref_frames = 12288 * 1024 / (mbw * mbh * 384);
|
|
const unsigned int num_ref_frames = pic_descriptor->avc_num_ref_frames;
|
|
if (max_ref_frames < num_ref_frames)
|
|
--
|
|
1.7.10
|
|
|
|
|
|
From afd776e3e90a1787ce4c3392266d70368de4e164 Mon Sep 17 00:00:00 2001
|
|
From: xbmc <fernetmenta@online.de>
|
|
Date: Fri, 23 Nov 2012 09:42:02 +0100
|
|
Subject: [PATCH 57/72] xvba: reactivate accidently disabled
|
|
IsDecodingFinished
|
|
|
|
---
|
|
xbmc/cores/dvdplayer/DVDCodecs/Video/XVBA.cpp | 2 --
|
|
1 file changed, 2 deletions(-)
|
|
|
|
diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/XVBA.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/XVBA.cpp
|
|
index b73c48a..47ff25f 100644
|
|
--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/XVBA.cpp
|
|
+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/XVBA.cpp
|
|
@@ -1949,8 +1949,6 @@ void COutput::Flush()
|
|
|
|
bool COutput::IsDecodingFinished()
|
|
{
|
|
- return true;
|
|
-
|
|
// check for decoding to be finished
|
|
CXvbaDecodedPicture decodedPic = m_decodedPics.front();
|
|
|
|
--
|
|
1.7.10
|
|
|
|
|
|
From 37576c15f9e3a0c2dce593e9d9cb5a7863845de7 Mon Sep 17 00:00:00 2001
|
|
From: xbmc <fernetmenta@online.de>
|
|
Date: Fri, 23 Nov 2012 17:41:12 +0100
|
|
Subject: [PATCH 58/72] xrandr: fix query for multiple screens
|
|
|
|
---
|
|
xbmc/windowing/X11/XRandR.cpp | 10 ++++++----
|
|
1 file changed, 6 insertions(+), 4 deletions(-)
|
|
|
|
diff --git a/xbmc/windowing/X11/XRandR.cpp b/xbmc/windowing/X11/XRandR.cpp
|
|
index cc933b9..533e03d 100644
|
|
--- a/xbmc/windowing/X11/XRandR.cpp
|
|
+++ b/xbmc/windowing/X11/XRandR.cpp
|
|
@@ -57,12 +57,14 @@ bool CXRandR::Query(bool force)
|
|
|
|
m_outputs.clear();
|
|
// query all screens
|
|
+ // we are happy if at least one screen returns results
|
|
+ bool success = false;
|
|
for(unsigned int screennum=0; screennum<m_numScreens; ++screennum)
|
|
{
|
|
- if(!Query(force, screennum))
|
|
- return false;
|
|
+ if(Query(force, screennum))
|
|
+ success = true;
|
|
}
|
|
- return true;
|
|
+ return success;
|
|
}
|
|
|
|
bool CXRandR::Query(bool force, int screennum)
|
|
@@ -70,7 +72,7 @@ bool CXRandR::Query(bool force, int screennum)
|
|
CStdString cmd;
|
|
cmd = getenv("XBMC_BIN_HOME");
|
|
cmd += "/xbmc-xrandr";
|
|
- cmd.append("-q --screen %d", screennum);
|
|
+ cmd.AppendFormat(" -q --screen %d", screennum);
|
|
|
|
FILE* file = popen(cmd.c_str(),"r");
|
|
if (!file)
|
|
--
|
|
1.7.10
|
|
|
|
|
|
From bd5d572c69ee254beedb5e9339831652943ea8b4 Mon Sep 17 00:00:00 2001
|
|
From: xbmc <fernetmenta@online.de>
|
|
Date: Sun, 2 Dec 2012 15:46:55 +0100
|
|
Subject: [PATCH 59/72] X11: add debug log to print out refresh after xrr
|
|
event
|
|
|
|
---
|
|
xbmc/windowing/X11/WinSystemX11.cpp | 6 ++++++
|
|
1 file changed, 6 insertions(+)
|
|
|
|
diff --git a/xbmc/windowing/X11/WinSystemX11.cpp b/xbmc/windowing/X11/WinSystemX11.cpp
|
|
index ef83133..76c6362 100644
|
|
--- a/xbmc/windowing/X11/WinSystemX11.cpp
|
|
+++ b/xbmc/windowing/X11/WinSystemX11.cpp
|
|
@@ -685,6 +685,12 @@ void CWinSystemX11::NotifyXRREvent()
|
|
XOutput *out = g_xrandr.GetOutput(currentOutput);
|
|
XMode mode = g_xrandr.GetCurrentMode(currentOutput);
|
|
|
|
+ if (out)
|
|
+ CLog::Log(LOGDEBUG, "%s - current output: %s, mode: %s, refresh: %.3f", __FUNCTION__
|
|
+ , out->name.c_str(), mode.id.c_str(), mode.hz);
|
|
+ else
|
|
+ CLog::Log(LOGWARNING, "%s - output name not set", __FUNCTION__);
|
|
+
|
|
RESOLUTION_INFO res;
|
|
unsigned int i;
|
|
bool found(false);
|
|
--
|
|
1.7.10
|
|
|
|
|
|
From d418ae1053a3842eb3e6a3bbd84666a5ee3defe2 Mon Sep 17 00:00:00 2001
|
|
From: xbmc <fernetmenta@online.de>
|
|
Date: Tue, 11 Dec 2012 11:08:13 +0100
|
|
Subject: [PATCH 60/72] X11: dont call XCloseDisplay on shutdown, it crashes
|
|
when powered doen by cec on ATI
|
|
|
|
---
|
|
xbmc/windowing/X11/WinSystemX11.cpp | 3 ++-
|
|
1 file changed, 2 insertions(+), 1 deletion(-)
|
|
|
|
diff --git a/xbmc/windowing/X11/WinSystemX11.cpp b/xbmc/windowing/X11/WinSystemX11.cpp
|
|
index 76c6362..e4e25b2 100644
|
|
--- a/xbmc/windowing/X11/WinSystemX11.cpp
|
|
+++ b/xbmc/windowing/X11/WinSystemX11.cpp
|
|
@@ -108,7 +108,8 @@ bool CWinSystemX11::DestroyWindowSystem()
|
|
//we don't call XCloseDisplay() here, since ati keeps a pointer to our m_dpy
|
|
//so instead we just let m_dpy die on exit
|
|
// i have seen core dumps on ATI if the display is not closed here
|
|
- XCloseDisplay(m_dpy);
|
|
+ // crashes when shutting down via cec
|
|
+// XCloseDisplay(m_dpy);
|
|
}
|
|
|
|
// m_SDLSurface is free()'d by SDL_Quit().
|
|
--
|
|
1.7.10
|
|
|
|
|
|
From 3b700401e9aace50b5ce6c5d7ba2a2e33bb5217f Mon Sep 17 00:00:00 2001
|
|
From: xbmc <fernetmenta@online.de>
|
|
Date: Wed, 12 Dec 2012 09:52:17 +0100
|
|
Subject: [PATCH 61/72] vdpau: make interop gl default and remove setting,
|
|
rename and intvert interop yuv
|
|
|
|
---
|
|
language/English/strings.po | 2 +-
|
|
xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp | 17 ++++++++++-------
|
|
xbmc/settings/GUISettings.cpp | 3 +--
|
|
xbmc/settings/GUIWindowSettingsCategory.cpp | 23 +++--------------------
|
|
4 files changed, 15 insertions(+), 30 deletions(-)
|
|
|
|
diff --git a/language/English/strings.po b/language/English/strings.po
|
|
index ede18b3..281a8a1 100644
|
|
--- a/language/English/strings.po
|
|
+++ b/language/English/strings.po
|
|
@@ -5121,7 +5121,7 @@ msgid "Allow Vdpau OpenGL interop"
|
|
msgstr ""
|
|
|
|
msgctxt "#13436"
|
|
-msgid "Allow Vdpau OpenGL interop YUV"
|
|
+msgid "Prefer VDPAU Video Mixer"
|
|
msgstr ""
|
|
|
|
msgctxt "#13437"
|
|
diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp
|
|
index fec4b88..ad140fb 100644
|
|
--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp
|
|
+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp
|
|
@@ -365,12 +365,15 @@ bool CDecoder::Supports(EINTERLACEMETHOD method)
|
|
|| method == VS_INTERLACEMETHOD_AUTO)
|
|
return true;
|
|
|
|
- if (g_guiSettings.GetBool("videoplayer.usevdpauinteropyuv"))
|
|
+ if (!m_vdpauConfig.usePixmaps)
|
|
{
|
|
if (method == VS_INTERLACEMETHOD_RENDER_BOB)
|
|
return true;
|
|
}
|
|
|
|
+ if (method == VS_INTERLACEMETHOD_VDPAU_INVERSE_TELECINE)
|
|
+ return false;
|
|
+
|
|
for(SInterlaceMapping* p = g_interlace_mapping; p->method != VS_INTERLACEMETHOD_NONE; p++)
|
|
{
|
|
if(p->method == method)
|
|
@@ -1847,7 +1850,7 @@ void CMixer::SetDeinterlacing()
|
|
|
|
SetDeintSkipChroma();
|
|
|
|
- m_config.useInteropYuv = g_guiSettings.GetBool("videoplayer.usevdpauinteropyuv");
|
|
+ m_config.useInteropYuv = !g_guiSettings.GetBool("videoplayer.usevdpaumixer");
|
|
}
|
|
|
|
void CMixer::SetDeintSkipChroma()
|
|
@@ -2039,7 +2042,7 @@ void CMixer::Init()
|
|
m_vdpError = false;
|
|
|
|
m_config.upscale = g_advancedSettings.m_videoVDPAUScaling;
|
|
- m_config.useInteropYuv = g_guiSettings.GetBool("videoplayer.usevdpauinteropyuv");
|
|
+ m_config.useInteropYuv = !g_guiSettings.GetBool("videoplayer.usevdpaumixer");
|
|
|
|
CreateVdpauMixer();
|
|
}
|
|
@@ -2149,11 +2152,12 @@ void CMixer::InitCycle()
|
|
DVP_FLAG_INTERLACED);
|
|
m_config.useInteropYuv = false;
|
|
}
|
|
- else if (method == VS_INTERLACEMETHOD_RENDER_BOB && m_config.useInteropYuv)
|
|
+ else if (method == VS_INTERLACEMETHOD_RENDER_BOB)
|
|
{
|
|
m_mixersteps = 1;
|
|
m_mixerfield = VDP_VIDEO_MIXER_PICTURE_STRUCTURE_FRAME;
|
|
m_mixerInput[1].DVDPic.format = RENDER_FMT_VDPAU_420;
|
|
+ m_config.useInteropYuv = true;
|
|
}
|
|
else
|
|
{
|
|
@@ -3185,7 +3189,7 @@ bool COutput::GLInit()
|
|
glVDPAUGetSurfaceivNV = NULL;
|
|
#endif
|
|
|
|
- m_config.usePixmaps = !g_guiSettings.GetBool("videoplayer.usevdpauinterop");
|
|
+ m_config.usePixmaps = false;
|
|
|
|
#ifdef GL_NV_vdpau_interop
|
|
if (glewIsSupported("GL_NV_vdpau_interop"))
|
|
@@ -3217,8 +3221,7 @@ bool COutput::GLInit()
|
|
#endif
|
|
{
|
|
m_config.usePixmaps = true;
|
|
- g_guiSettings.SetBool("videoplayer.usevdpauinterop",false);
|
|
- g_guiSettings.SetBool("videoplayer.usevdpauinteropyuv",false);
|
|
+ g_guiSettings.SetBool("videoplayer.usevdpaumixer",true);
|
|
}
|
|
if (!glXBindTexImageEXT)
|
|
glXBindTexImageEXT = (PFNGLXBINDTEXIMAGEEXTPROC)glXGetProcAddress((GLubyte *) "glXBindTexImageEXT");
|
|
diff --git a/xbmc/settings/GUISettings.cpp b/xbmc/settings/GUISettings.cpp
|
|
index 10ef779..a4bd524 100644
|
|
--- a/xbmc/settings/GUISettings.cpp
|
|
+++ b/xbmc/settings/GUISettings.cpp
|
|
@@ -690,8 +690,7 @@ void CGUISettings::Initialize()
|
|
|
|
#ifdef HAVE_LIBVDPAU
|
|
AddBool(vp, "videoplayer.usevdpau", 13425, true);
|
|
- AddBool(vp, "videoplayer.usevdpauinterop", 13435, true);
|
|
- AddBool(vp, "videoplayer.usevdpauinteropyuv", 13436, false);
|
|
+ AddBool(vp, "videoplayer.usevdpaumixer", 13436, true);
|
|
#endif
|
|
#ifdef HAVE_LIBVA
|
|
AddBool(vp, "videoplayer.usevaapi", 13426, true);
|
|
diff --git a/xbmc/settings/GUIWindowSettingsCategory.cpp b/xbmc/settings/GUIWindowSettingsCategory.cpp
|
|
index 3c19a06..b9f18e4 100644
|
|
--- a/xbmc/settings/GUIWindowSettingsCategory.cpp
|
|
+++ b/xbmc/settings/GUIWindowSettingsCategory.cpp
|
|
@@ -602,9 +602,9 @@ void CGUIWindowSettingsCategory::UpdateSettings()
|
|
pControl->SetEnabled(true);
|
|
}
|
|
}
|
|
- else if (strSetting.Equals("videoplayer.usevdpauinteropyuv"))
|
|
+ else if (strSetting.Equals("videoplayer.usevdpaumixer"))
|
|
{
|
|
- bool hasInterop = g_guiSettings.GetBool("videoplayer.usevdpauinterop");
|
|
+ bool hasInterop = true;
|
|
#ifndef GL_NV_vdpau_interop
|
|
hasInterop = false;
|
|
#endif
|
|
@@ -616,24 +616,7 @@ void CGUIWindowSettingsCategory::UpdateSettings()
|
|
else
|
|
{
|
|
pControl->SetEnabled(false);
|
|
- g_guiSettings.SetBool("videoplayer.usevdpauinteropyuv",false);
|
|
- }
|
|
- }
|
|
- else if (strSetting.Equals("videoplayer.usevdpauinterop"))
|
|
- {
|
|
- bool hasInterop = g_guiSettings.GetBool("videoplayer.usevdpau");
|
|
-#ifndef GL_NV_vdpau_interop
|
|
- hasInterop = false;
|
|
-#endif
|
|
- CGUIControl *pControl = (CGUIControl *)GetControl(pSettingControl->GetID());
|
|
- if (pControl && hasInterop && glewIsSupported("GL_NV_vdpau_interop"))
|
|
- {
|
|
- pControl->SetEnabled(true);
|
|
- }
|
|
- else
|
|
- {
|
|
- pControl->SetEnabled(false);
|
|
- g_guiSettings.SetBool("videoplayer.usevdpauinterop",false);
|
|
+ g_guiSettings.SetBool("videoplayer.usevdpaumixer",true);
|
|
}
|
|
}
|
|
else
|
|
--
|
|
1.7.10
|
|
|
|
|
|
From a060312a4e236858bf3c9a97d663c5643796b649 Mon Sep 17 00:00:00 2001
|
|
From: xbmc <fernetmenta@online.de>
|
|
Date: Wed, 12 Dec 2012 18:34:47 +0100
|
|
Subject: [PATCH 62/72] vdpau: drop studio level conversion
|
|
|
|
---
|
|
language/English/strings.po | 6 +-
|
|
xbmc/cores/VideoRenderers/LinuxRendererGL.cpp | 4 +-
|
|
xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp | 94 +-----------------------
|
|
xbmc/settings/GUISettings.cpp | 1 -
|
|
4 files changed, 7 insertions(+), 98 deletions(-)
|
|
|
|
diff --git a/language/English/strings.po b/language/English/strings.po
|
|
index 281a8a1..fc896b3 100644
|
|
--- a/language/English/strings.po
|
|
+++ b/language/English/strings.po
|
|
@@ -4371,11 +4371,7 @@ msgctxt "#13121"
|
|
msgid "VDPAU HQ Upscaling level"
|
|
msgstr ""
|
|
|
|
-msgctxt "#13122"
|
|
-msgid "VDPAU Studio level color conversion"
|
|
-msgstr ""
|
|
-
|
|
-#empty strings from id 13123 to 13129
|
|
+#empty strings from id 13122 to 13129
|
|
|
|
msgctxt "#13130"
|
|
msgid "Blank other displays"
|
|
diff --git a/xbmc/cores/VideoRenderers/LinuxRendererGL.cpp b/xbmc/cores/VideoRenderers/LinuxRendererGL.cpp
|
|
index 7c3adcb..0bb924b 100644
|
|
--- a/xbmc/cores/VideoRenderers/LinuxRendererGL.cpp
|
|
+++ b/xbmc/cores/VideoRenderers/LinuxRendererGL.cpp
|
|
@@ -3545,7 +3545,7 @@ bool CLinuxRendererGL::Supports(ERENDERFEATURE feature)
|
|
{
|
|
if(feature == RENDERFEATURE_BRIGHTNESS)
|
|
{
|
|
- if ((m_renderMethod & RENDER_VDPAU) && !g_guiSettings.GetBool("videoplayer.vdpaustudiolevel"))
|
|
+ if (m_renderMethod & RENDER_VDPAU)
|
|
return true;
|
|
|
|
if (m_renderMethod & RENDER_VAAPI)
|
|
@@ -3561,7 +3561,7 @@ bool CLinuxRendererGL::Supports(ERENDERFEATURE feature)
|
|
|
|
if(feature == RENDERFEATURE_CONTRAST)
|
|
{
|
|
- if ((m_renderMethod & RENDER_VDPAU) && !g_guiSettings.GetBool("videoplayer.vdpaustudiolevel"))
|
|
+ if (m_renderMethod & RENDER_VDPAU)
|
|
return true;
|
|
|
|
if (m_renderMethod & RENDER_VAAPI)
|
|
diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp
|
|
index ad140fb..5851e1a 100644
|
|
--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp
|
|
+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp
|
|
@@ -57,15 +57,6 @@
|
|
};
|
|
const size_t decoder_profile_count = sizeof(decoder_profiles)/sizeof(CDecoder::Desc);
|
|
|
|
-//static float studioCSC[3][4] =
|
|
-//{
|
|
-// { 1.0f, 0.0f, 1.57480000f,-0.78740000f},
|
|
-// { 1.0f,-0.18737736f,-0.46813736f, 0.32775736f},
|
|
-// { 1.0f, 1.85556000f, 0.0f,-0.92780000f}
|
|
-//};
|
|
-static float studioCSCKCoeffs601[3] = {0.299, 0.587, 0.114}; //BT601 {Kr, Kg, Kb}
|
|
-static float studioCSCKCoeffs709[3] = {0.2126, 0.7152, 0.0722}; //BT709 {Kr, Kg, Kb}
|
|
-
|
|
static struct SInterlaceMapping
|
|
{
|
|
const EINTERLACEMETHOD method;
|
|
@@ -1614,74 +1605,6 @@ void CMixer::PostProcOff()
|
|
DisableHQScaling();
|
|
}
|
|
|
|
-
|
|
-bool CMixer::GenerateStudioCSCMatrix(VdpColorStandard colorStandard, VdpCSCMatrix &studioCSCMatrix)
|
|
-{
|
|
- // instead use studioCSCKCoeffs601[3], studioCSCKCoeffs709[3] to generate float[3][4] matrix (float studioCSC[3][4])
|
|
- // m00 = mRY = red: luma factor (contrast factor) (1.0)
|
|
- // m10 = mGY = green: luma factor (contrast factor) (1.0)
|
|
- // m20 = mBY = blue: luma factor (contrast factor) (1.0)
|
|
- //
|
|
- // m01 = mRB = red: blue color diff coeff (0.0)
|
|
- // m11 = mGB = green: blue color diff coeff (-2Kb(1-Kb)/(Kg))
|
|
- // m21 = mBB = blue: blue color diff coeff ((1-Kb)/0.5)
|
|
- //
|
|
- // m02 = mRR = red: red color diff coeff ((1-Kr)/0.5)
|
|
- // m12 = mGR = green: red color diff coeff (-2Kr(1-Kr)/(Kg))
|
|
- // m22 = mBR = blue: red color diff coeff (0.0)
|
|
- //
|
|
- // m03 = mRC = red: colour zero offset (brightness factor) (-(1-Kr)/0.5 * (128/255))
|
|
- // m13 = mGC = green: colour zero offset (brightness factor) ((256/255) * (Kb(1-Kb) + Kr(1-Kr)) / Kg)
|
|
- // m23 = mBC = blue: colour zero offset (brightness factor) (-(1-Kb)/0.5 * (128/255))
|
|
-
|
|
- // columns
|
|
- int Y = 0;
|
|
- int Cb = 1;
|
|
- int Cr = 2;
|
|
- int C = 3;
|
|
- // rows
|
|
- int R = 0;
|
|
- int G = 1;
|
|
- int B = 2;
|
|
- // colour standard coefficients for red, geen, blue
|
|
- double Kr, Kg, Kb;
|
|
- // colour diff zero position (use standard 8-bit coding precision)
|
|
- double CDZ = 128; //256*0.5
|
|
- // range excursion (use standard 8-bit coding precision)
|
|
- double EXC = 255; //256-1
|
|
-
|
|
- if (colorStandard == VDP_COLOR_STANDARD_ITUR_BT_601)
|
|
- {
|
|
- Kr = studioCSCKCoeffs601[0];
|
|
- Kg = studioCSCKCoeffs601[1];
|
|
- Kb = studioCSCKCoeffs601[2];
|
|
- }
|
|
- else // assume VDP_COLOR_STANDARD_ITUR_BT_709
|
|
- {
|
|
- Kr = studioCSCKCoeffs709[0];
|
|
- Kg = studioCSCKCoeffs709[1];
|
|
- Kb = studioCSCKCoeffs709[2];
|
|
- }
|
|
- // we keep luma unscaled to retain the levels present in source so that 16-235 luma is converted to RGB 16-235
|
|
- studioCSCMatrix[R][Y] = 1.0;
|
|
- studioCSCMatrix[G][Y] = 1.0;
|
|
- studioCSCMatrix[B][Y] = 1.0;
|
|
-
|
|
- studioCSCMatrix[R][Cb] = 0.0;
|
|
- studioCSCMatrix[G][Cb] = (double)-2 * Kb * (1 - Kb) / Kg;
|
|
- studioCSCMatrix[B][Cb] = (double)(1 - Kb) / 0.5;
|
|
-
|
|
- studioCSCMatrix[R][Cr] = (double)(1 - Kr) / 0.5;
|
|
- studioCSCMatrix[G][Cr] = (double)-2 * Kr * (1 - Kr) / Kg;
|
|
- studioCSCMatrix[B][Cr] = 0.0;
|
|
-
|
|
- studioCSCMatrix[R][C] = (double)-1 * studioCSCMatrix[R][Cr] * CDZ/EXC;
|
|
- studioCSCMatrix[G][C] = (double)-1 * (studioCSCMatrix[G][Cb] + studioCSCMatrix[G][Cr]) * CDZ/EXC;
|
|
- studioCSCMatrix[B][C] = (double)-1 * studioCSCMatrix[B][Cb] * CDZ/EXC;
|
|
-
|
|
- return true;
|
|
-}
|
|
-
|
|
void CMixer::SetColor()
|
|
{
|
|
VdpStatus vdp_st;
|
|
@@ -1701,19 +1624,10 @@ void CMixer::SetColor()
|
|
//vdp_st = vdp_generate_csc_matrix(&m_Procamp, VDP_COLOR_STANDARD_ITUR_BT_601, &m_CSCMatrix);
|
|
|
|
VdpVideoMixerAttribute attributes[] = { VDP_VIDEO_MIXER_ATTRIBUTE_CSC_MATRIX };
|
|
- if (g_guiSettings.GetBool("videoplayer.vdpaustudiolevel"))
|
|
- {
|
|
- float studioCSC[3][4];
|
|
- GenerateStudioCSCMatrix(colorStandard, studioCSC);
|
|
- void const * pm_CSCMatix[] = { &studioCSC };
|
|
- vdp_st = m_config.vdpProcs.vdp_video_mixer_set_attribute_values(m_videoMixer, ARSIZE(attributes), attributes, pm_CSCMatix);
|
|
- }
|
|
- else
|
|
- {
|
|
- vdp_st = m_config.vdpProcs.vdp_generate_csc_matrix(&m_Procamp, colorStandard, &m_CSCMatrix);
|
|
- void const * pm_CSCMatix[] = { &m_CSCMatrix };
|
|
- vdp_st = m_config.vdpProcs.vdp_video_mixer_set_attribute_values(m_videoMixer, ARSIZE(attributes), attributes, pm_CSCMatix);
|
|
- }
|
|
+ vdp_st = m_config.vdpProcs.vdp_generate_csc_matrix(&m_Procamp, colorStandard, &m_CSCMatrix);
|
|
+ void const * pm_CSCMatix[] = { &m_CSCMatrix };
|
|
+ vdp_st = m_config.vdpProcs.vdp_video_mixer_set_attribute_values(m_videoMixer, ARSIZE(attributes), attributes, pm_CSCMatix);
|
|
+
|
|
CheckStatus(vdp_st, __LINE__);
|
|
}
|
|
|
|
diff --git a/xbmc/settings/GUISettings.cpp b/xbmc/settings/GUISettings.cpp
|
|
index a4bd524..67aeec9 100644
|
|
--- a/xbmc/settings/GUISettings.cpp
|
|
+++ b/xbmc/settings/GUISettings.cpp
|
|
@@ -772,7 +772,6 @@ void CGUISettings::Initialize()
|
|
AddSeparator(vp, "videoplayer.sep1.5");
|
|
#ifdef HAVE_LIBVDPAU
|
|
AddBool(NULL, "videoplayer.vdpauUpscalingLevel", 13121, false);
|
|
- AddBool(vp, "videoplayer.vdpaustudiolevel", 13122, false);
|
|
#endif
|
|
#endif
|
|
AddSeparator(vp, "videoplayer.sep5");
|
|
--
|
|
1.7.10
|
|
|
|
|
|
From 6d03704ce1cbc7d09d684da1ced478b2b59c0b35 Mon Sep 17 00:00:00 2001
|
|
From: =?UTF-8?q?Gr=C3=A9gory=20Coutant?= <gregory.coutant@gmail.com>
|
|
Date: Wed, 12 Dec 2012 19:49:47 +0100
|
|
Subject: [PATCH 63/72] x11: support for multiple x screens
|
|
|
|
---
|
|
xbmc/windowing/X11/XRandR.cpp | 2 +-
|
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
|
|
|
diff --git a/xbmc/windowing/X11/XRandR.cpp b/xbmc/windowing/X11/XRandR.cpp
|
|
index 533e03d..7a16488 100644
|
|
--- a/xbmc/windowing/X11/XRandR.cpp
|
|
+++ b/xbmc/windowing/X11/XRandR.cpp
|
|
@@ -92,7 +92,7 @@ bool CXRandR::Query(bool force, int screennum)
|
|
pclose(file);
|
|
|
|
TiXmlElement *pRootElement = xmlDoc.RootElement();
|
|
- if (strcasecmp(pRootElement->Value(), "screen") != screennum)
|
|
+ if (atoi(pRootElement->Attribute("id")) != screennum)
|
|
{
|
|
// TODO ERROR
|
|
return false;
|
|
--
|
|
1.7.10
|
|
|
|
|
|
From 597c8449084e1e5ebfebfb31db570f7826d06517 Mon Sep 17 00:00:00 2001
|
|
From: xbmc <fernetmenta@online.de>
|
|
Date: Wed, 12 Dec 2012 20:28:49 +0100
|
|
Subject: [PATCH 64/72] vdpau: observe ffmpeg tags for color space
|
|
|
|
---
|
|
xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp | 38 ++++++++++++++++--------
|
|
xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.h | 1 +
|
|
2 files changed, 27 insertions(+), 12 deletions(-)
|
|
|
|
diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp
|
|
index 5851e1a..8858614 100644
|
|
--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp
|
|
+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp
|
|
@@ -907,6 +907,7 @@ int CDecoder::Decode(AVCodecContext *avctx, AVFrame *pFrame)
|
|
memset(&pic.DVDPic, 0, sizeof(pic.DVDPic));
|
|
((CDVDVideoCodecFFmpeg*)avctx->opaque)->GetPictureCommon(&pic.DVDPic);
|
|
pic.render = render;
|
|
+ pic.DVDPic.color_matrix = avctx->colorspace;
|
|
m_bufferStats.IncDecoded();
|
|
m_vdpauOutput.m_dataPort.SendOutMessage(COutputDataProtocol::NEWFRAME, &pic, sizeof(pic));
|
|
|
|
@@ -1513,10 +1514,6 @@ void CMixer::InitCSCMatrix(int Width)
|
|
m_Procamp.contrast = 1.0;
|
|
m_Procamp.saturation = 1.0;
|
|
m_Procamp.hue = 0;
|
|
- vdp_st = m_config.vdpProcs.vdp_generate_csc_matrix(&m_Procamp,
|
|
- (Width < 1000)? VDP_COLOR_STANDARD_ITUR_BT_601 : VDP_COLOR_STANDARD_ITUR_BT_709,
|
|
- &m_CSCMatrix);
|
|
- CheckStatus(vdp_st, __LINE__);
|
|
}
|
|
|
|
void CMixer::CheckFeatures()
|
|
@@ -1527,11 +1524,13 @@ void CMixer::CheckFeatures()
|
|
m_Upscale = m_config.upscale;
|
|
}
|
|
if (m_Brightness != g_settings.m_currentVideoSettings.m_Brightness ||
|
|
- m_Contrast != g_settings.m_currentVideoSettings.m_Contrast)
|
|
+ m_Contrast != g_settings.m_currentVideoSettings.m_Contrast ||
|
|
+ m_ColorMatrix != m_mixerInput[1].DVDPic.color_matrix)
|
|
{
|
|
SetColor();
|
|
m_Brightness = g_settings.m_currentVideoSettings.m_Brightness;
|
|
m_Contrast = g_settings.m_currentVideoSettings.m_Contrast;
|
|
+ m_ColorMatrix = m_mixerInput[1].DVDPic.color_matrix;
|
|
}
|
|
if (m_NoiseReduction != g_settings.m_currentVideoSettings.m_NoiseReduction)
|
|
{
|
|
@@ -1615,13 +1614,27 @@ void CMixer::SetColor()
|
|
m_Procamp.contrast = (float)((g_settings.m_currentVideoSettings.m_Contrast)+50) / 100;
|
|
|
|
VdpColorStandard colorStandard;
|
|
-// if(vid_height >= 600 || vid_width > 1024)
|
|
- if(m_config.surfaceWidth > 1000)
|
|
- colorStandard = VDP_COLOR_STANDARD_ITUR_BT_709;
|
|
- //vdp_st = vdp_generate_csc_matrix(&m_Procamp, VDP_COLOR_STANDARD_ITUR_BT_709, &m_CSCMatrix);
|
|
- else
|
|
- colorStandard = VDP_COLOR_STANDARD_ITUR_BT_601;
|
|
- //vdp_st = vdp_generate_csc_matrix(&m_Procamp, VDP_COLOR_STANDARD_ITUR_BT_601, &m_CSCMatrix);
|
|
+ switch(m_mixerInput[1].DVDPic.color_matrix)
|
|
+ {
|
|
+ case AVCOL_SPC_BT709:
|
|
+ colorStandard = VDP_COLOR_STANDARD_ITUR_BT_709;
|
|
+ break;
|
|
+ case AVCOL_SPC_BT470BG:
|
|
+ case AVCOL_SPC_SMPTE170M:
|
|
+ colorStandard = VDP_COLOR_STANDARD_ITUR_BT_601;
|
|
+ break;
|
|
+ case AVCOL_SPC_SMPTE240M:
|
|
+ colorStandard = VDP_COLOR_STANDARD_SMPTE_240M;
|
|
+ break;
|
|
+ case AVCOL_SPC_FCC:
|
|
+ case AVCOL_SPC_UNSPECIFIED:
|
|
+ case AVCOL_SPC_RGB:
|
|
+ default:
|
|
+ if(m_config.surfaceWidth > 1000)
|
|
+ colorStandard = VDP_COLOR_STANDARD_ITUR_BT_709;
|
|
+ else
|
|
+ colorStandard = VDP_COLOR_STANDARD_ITUR_BT_601;
|
|
+ }
|
|
|
|
VdpVideoMixerAttribute attributes[] = { VDP_VIDEO_MIXER_ATTRIBUTE_CSC_MATRIX };
|
|
vdp_st = m_config.vdpProcs.vdp_generate_csc_matrix(&m_Procamp, colorStandard, &m_CSCMatrix);
|
|
@@ -1952,6 +1965,7 @@ void CMixer::Init()
|
|
m_Sharpness = 0.0;
|
|
m_DeintMode = 0;
|
|
m_Deint = 0;
|
|
+ m_ColorMatrix = 0;
|
|
m_PostProc = false;
|
|
m_vdpError = false;
|
|
|
|
diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.h
|
|
index 4d1559c..471ad68 100644
|
|
--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.h
|
|
+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.h
|
|
@@ -334,6 +334,7 @@ class CMixer : private CThread
|
|
int m_DeintMode;
|
|
int m_Deint;
|
|
int m_Upscale;
|
|
+ unsigned int m_ColorMatrix : 4;
|
|
uint32_t *m_BlackBar;
|
|
VdpVideoMixerPictureStructure m_mixerfield;
|
|
int m_mixerstep;
|
|
--
|
|
1.7.10
|
|
|
|
|
|
From 3f9308d76025ef1e31923fa9a06587f75c00f870 Mon Sep 17 00:00:00 2001
|
|
From: xbmc <fernetmenta@online.de>
|
|
Date: Thu, 20 Dec 2012 19:35:38 +0100
|
|
Subject: [PATCH 65/72] fix compile error after recent change
|
|
|
|
---
|
|
xbmc/settings/GUIWindowSettingsCategory.cpp | 2 +-
|
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
|
|
|
diff --git a/xbmc/settings/GUIWindowSettingsCategory.cpp b/xbmc/settings/GUIWindowSettingsCategory.cpp
|
|
index b9f18e4..cacb32a 100644
|
|
--- a/xbmc/settings/GUIWindowSettingsCategory.cpp
|
|
+++ b/xbmc/settings/GUIWindowSettingsCategory.cpp
|
|
@@ -2453,7 +2453,7 @@ void CGUIWindowSettingsCategory::FillInMonitors(CStdString strSetting)
|
|
{
|
|
// we expect "videoscreen.monitor" but it might be hidden on some platforms,
|
|
// so check that we actually have a visable control.
|
|
- CBaseSettingControl *control = GetSetting(strSetting);
|
|
+ BaseSettingControlPtr control = GetSetting(strSetting);
|
|
if (control)
|
|
{
|
|
control->SetDelayed();
|
|
--
|
|
1.7.10
|
|
|
|
|
|
From 213792b2678760d42740d581a1ee71e186a31c4d Mon Sep 17 00:00:00 2001
|
|
From: xbmc <fernetmenta@online.de>
|
|
Date: Mon, 24 Dec 2012 16:02:42 +0100
|
|
Subject: [PATCH 66/72] pvr: increase changes counter of stream on stream
|
|
change, cosmetics after
|
|
dd307930d39d92f145a01a16600cd00e01ec39be
|
|
|
|
---
|
|
xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxPVRClient.cpp | 5 ++---
|
|
1 file changed, 2 insertions(+), 3 deletions(-)
|
|
|
|
diff --git a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxPVRClient.cpp b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxPVRClient.cpp
|
|
index 8c984f6..034e545 100644
|
|
--- a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxPVRClient.cpp
|
|
+++ b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxPVRClient.cpp
|
|
@@ -348,9 +348,7 @@ void CDVDDemuxPVRClient::RequestStreams()
|
|
if (stm)
|
|
{
|
|
st = dynamic_cast<CDemuxStreamAudioPVRClient*>(stm);
|
|
- if (!st
|
|
- || (st->codec != (CodecID)props.stream[i].iCodecId)
|
|
- || (st->iChannels != props.stream[i].iChannels))
|
|
+ if (!st || (st->codec != (CodecID)props.stream[i].iCodecId))
|
|
DisposeStream(i);
|
|
}
|
|
if (!m_streams[i])
|
|
@@ -367,6 +365,7 @@ void CDVDDemuxPVRClient::RequestStreams()
|
|
st->iBitsPerSample = props.stream[i].iBitsPerSample;
|
|
m_streams[i] = st;
|
|
st->m_parser_split = true;
|
|
+ st->changes++;
|
|
}
|
|
else if (props.stream[i].iCodecType == AVMEDIA_TYPE_VIDEO)
|
|
{
|
|
--
|
|
1.7.10
|
|
|
|
|
|
From e810d3bd68e89e800fba217e88184c2df0fe4040 Mon Sep 17 00:00:00 2001
|
|
From: xbmc <fernetmenta@online.de>
|
|
Date: Thu, 17 Jan 2013 16:03:22 +0100
|
|
Subject: [PATCH 67/72] X11: add keymapping for XF86XK_Sleep
|
|
|
|
---
|
|
xbmc/windowing/WinEventsX11.cpp | 1 +
|
|
1 file changed, 1 insertion(+)
|
|
|
|
diff --git a/xbmc/windowing/WinEventsX11.cpp b/xbmc/windowing/WinEventsX11.cpp
|
|
index c31877e..ed31c04 100644
|
|
--- a/xbmc/windowing/WinEventsX11.cpp
|
|
+++ b/xbmc/windowing/WinEventsX11.cpp
|
|
@@ -143,6 +143,7 @@
|
|
, {XK_Break, XBMCK_BREAK}
|
|
, {XK_Menu, XBMCK_MENU}
|
|
, {XF86XK_PowerOff, XBMCK_POWER}
|
|
+, {XF86XK_Sleep, XBMCK_SLEEP}
|
|
, {XK_EcuSign, XBMCK_EURO}
|
|
, {XK_Undo, XBMCK_UNDO}
|
|
/* Media keys */
|
|
--
|
|
1.7.10
|
|
|
|
|
|
From 2cb807b2f801f06723cde1bdd636550c08fc08ab Mon Sep 17 00:00:00 2001
|
|
From: fritsch <peter.fruehberger@gmail.com>
|
|
Date: Sat, 12 Jan 2013 13:03:50 +0100
|
|
Subject: [PATCH 68/72] dvdplayer: Allow multithread decoding for hi10p
|
|
content by default
|
|
|
|
This allows decoding of some hi10p material on e.g. AMD Fusion with
|
|
both cores at the max. This introduces a new advancedsetting named
|
|
disablehi10pmultithreading to disable hi10p decoded multithreaded.
|
|
---
|
|
.../DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp | 18 ++++++++++++++++--
|
|
.../dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.h | 1 +
|
|
xbmc/settings/AdvancedSettings.cpp | 2 ++
|
|
xbmc/settings/AdvancedSettings.h | 1 +
|
|
4 files changed, 20 insertions(+), 2 deletions(-)
|
|
|
|
diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp
|
|
index b3252ec..3f8a6e8 100644
|
|
--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp
|
|
+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp
|
|
@@ -154,6 +154,7 @@ enum PixelFormat CDVDVideoCodecFFmpeg::GetFormat( struct AVCodecContext * avctx
|
|
m_iScreenHeight = 0;
|
|
m_iOrientation = 0;
|
|
m_bSoftware = false;
|
|
+ m_isHi10p = false;
|
|
m_pHardware = NULL;
|
|
m_iLastKeyframe = 0;
|
|
m_dts = DVD_NOPTS_VALUE;
|
|
@@ -204,7 +205,10 @@ bool CDVDVideoCodecFFmpeg::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options
|
|
case FF_PROFILE_H264_HIGH_444_PREDICTIVE:
|
|
case FF_PROFILE_H264_HIGH_444_INTRA:
|
|
case FF_PROFILE_H264_CAVLC_444:
|
|
+ // this is needed to not open the decoders
|
|
m_bSoftware = true;
|
|
+ // this we need to enable multithreading for hi10p via advancedsettings
|
|
+ m_isHi10p = true;
|
|
break;
|
|
}
|
|
}
|
|
@@ -277,8 +281,18 @@ bool CDVDVideoCodecFFmpeg::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options
|
|
m_pCodecContext->codec_tag = hints.codec_tag;
|
|
/* Only allow slice threading, since frame threading is more
|
|
* sensitive to changes in frame sizes, and it causes crashes
|
|
- * during HW accell */
|
|
- m_pCodecContext->thread_type = FF_THREAD_SLICE;
|
|
+ * during HW accell - so we unset it in this case.
|
|
+ *
|
|
+ * When we detect Hi10p and user did not disable hi10pmultithreading
|
|
+ * via advancedsettings.xml we keep the ffmpeg default thread type.
|
|
+ * */
|
|
+ if(m_isHi10p && !g_advancedSettings.m_videoDisableHi10pMultithreading)
|
|
+ {
|
|
+ CLog::Log(LOGDEBUG,"CDVDVideoCodecFFmpeg::Open() Keep default threading for Hi10p: %d",
|
|
+ m_pCodecContext->thread_type);
|
|
+ }
|
|
+ else
|
|
+ m_pCodecContext->thread_type = FF_THREAD_SLICE;
|
|
|
|
#if defined(TARGET_DARWIN_IOS)
|
|
// ffmpeg with enabled neon will crash and burn if this is enabled
|
|
diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.h
|
|
index bf4367c..db1d2b2 100644
|
|
--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.h
|
|
+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.h
|
|
@@ -116,6 +116,7 @@ class CDVDVideoCodecFFmpeg : public CDVDVideoCodec
|
|
|
|
std::string m_name;
|
|
bool m_bSoftware;
|
|
+ bool m_isHi10p;
|
|
IHardwareDecoder *m_pHardware;
|
|
int m_iLastKeyframe;
|
|
double m_dts;
|
|
diff --git a/xbmc/settings/AdvancedSettings.cpp b/xbmc/settings/AdvancedSettings.cpp
|
|
index d913924..6a48309 100644
|
|
--- a/xbmc/settings/AdvancedSettings.cpp
|
|
+++ b/xbmc/settings/AdvancedSettings.cpp
|
|
@@ -116,6 +116,7 @@ void CAdvancedSettings::Initialize()
|
|
m_DXVANoDeintProcForProgressive = false;
|
|
m_videoFpsDetect = 1;
|
|
m_videoDefaultLatency = 0.0;
|
|
+ m_videoDisableHi10pMultithreading = false;
|
|
|
|
m_musicUseTimeSeeking = true;
|
|
m_musicTimeSeekForward = 10;
|
|
@@ -502,6 +503,7 @@ void CAdvancedSettings::ParseSettingsFile(const CStdString &file)
|
|
XMLUtils::GetBoolean(pElement,"enablehighqualityhwscalers", m_videoEnableHighQualityHwScalers);
|
|
XMLUtils::GetFloat(pElement,"autoscalemaxfps",m_videoAutoScaleMaxFps, 0.0f, 1000.0f);
|
|
XMLUtils::GetBoolean(pElement,"allowmpeg4vdpau",m_videoAllowMpeg4VDPAU);
|
|
+ XMLUtils::GetBoolean(pElement,"disablehi10pmultithreading",m_videoDisableHi10pMultithreading);
|
|
XMLUtils::GetBoolean(pElement,"allowmpeg4vaapi",m_videoAllowMpeg4VAAPI);
|
|
XMLUtils::GetBoolean(pElement, "disablebackgrounddeinterlace", m_videoDisableBackgroundDeinterlace);
|
|
XMLUtils::GetInt(pElement, "useocclusionquery", m_videoCaptureUseOcclusionQuery, -1, 1);
|
|
diff --git a/xbmc/settings/AdvancedSettings.h b/xbmc/settings/AdvancedSettings.h
|
|
index aaa4702..863e4f3 100644
|
|
--- a/xbmc/settings/AdvancedSettings.h
|
|
+++ b/xbmc/settings/AdvancedSettings.h
|
|
@@ -168,6 +168,7 @@ class CAdvancedSettings
|
|
bool m_DXVAForceProcessorRenderer;
|
|
bool m_DXVANoDeintProcForProgressive;
|
|
int m_videoFpsDetect;
|
|
+ bool m_videoDisableHi10pMultithreading;
|
|
|
|
CStdString m_videoDefaultPlayer;
|
|
CStdString m_videoDefaultDVDPlayer;
|
|
--
|
|
1.7.10
|
|
|
|
|
|
From 5e52fa15742e1300ac394738ead4ca2792c4812c Mon Sep 17 00:00:00 2001
|
|
From: xbmc <fernetmenta@online.de>
|
|
Date: Mon, 21 Jan 2013 09:00:19 +0100
|
|
Subject: [PATCH 69/72] X11: remove toggle full screen after resume
|
|
|
|
---
|
|
xbmc/powermanagement/PowerManager.cpp | 5 -----
|
|
1 file changed, 5 deletions(-)
|
|
|
|
diff --git a/xbmc/powermanagement/PowerManager.cpp b/xbmc/powermanagement/PowerManager.cpp
|
|
index a5534c9..7e2ddc6 100644
|
|
--- a/xbmc/powermanagement/PowerManager.cpp
|
|
+++ b/xbmc/powermanagement/PowerManager.cpp
|
|
@@ -223,11 +223,6 @@ void CPowerManager::OnWake()
|
|
#if defined(_WIN32)
|
|
ShowWindow(g_hWnd,SW_RESTORE);
|
|
SetForegroundWindow(g_hWnd);
|
|
-#elif !defined(TARGET_DARWIN_OSX)
|
|
- // Hack to reclaim focus, thus rehiding system mouse pointer.
|
|
- // Surely there's a better way?
|
|
- g_graphicsContext.ToggleFullScreenRoot();
|
|
- g_graphicsContext.ToggleFullScreenRoot();
|
|
#endif
|
|
}
|
|
g_application.ResetScreenSaver();
|
|
--
|
|
1.7.10
|
|
|
|
|
|
From e8f3e20dfb3bde4434e2aea69b34e22ba1859a31 Mon Sep 17 00:00:00 2001
|
|
From: xbmc <fernetmenta@online.de>
|
|
Date: Wed, 23 Jan 2013 17:03:02 +0100
|
|
Subject: [PATCH 70/72] xrandr: set screen on mode change command
|
|
|
|
---
|
|
xbmc/windowing/X11/XRandR.cpp | 2 +-
|
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
|
|
|
diff --git a/xbmc/windowing/X11/XRandR.cpp b/xbmc/windowing/X11/XRandR.cpp
|
|
index 7a16488..6531ba3 100644
|
|
--- a/xbmc/windowing/X11/XRandR.cpp
|
|
+++ b/xbmc/windowing/X11/XRandR.cpp
|
|
@@ -246,7 +246,7 @@ bool CXRandR::SetMode(XOutput output, XMode mode)
|
|
m_currentMode = modeFound.id;
|
|
char cmd[255];
|
|
if (getenv("XBMC_BIN_HOME"))
|
|
- snprintf(cmd, sizeof(cmd), "%s/xbmc-xrandr --output %s --mode %s", getenv("XBMC_BIN_HOME"), outputFound.name.c_str(), modeFound.id.c_str());
|
|
+ snprintf(cmd, sizeof(cmd), "%s/xbmc-xrandr --screen %d --output %s --mode %s", getenv("XBMC_BIN_HOME"), outputFound.screen, outputFound.name.c_str(), modeFound.id.c_str());
|
|
else
|
|
return false;
|
|
CLog::Log(LOGINFO, "XRANDR: %s", cmd);
|
|
--
|
|
1.7.10
|
|
|
|
|
|
From f229dba603070e1f0528d395c9d5d63f9044ae6e Mon Sep 17 00:00:00 2001
|
|
From: xbmc <fernetmenta@online.de>
|
|
Date: Wed, 23 Jan 2013 17:03:39 +0100
|
|
Subject: [PATCH 71/72] X11: recreate glx context when output changes
|
|
|
|
---
|
|
xbmc/windowing/X11/WinSystemX11.cpp | 6 +++---
|
|
xbmc/windowing/X11/WinSystemX11.h | 2 +-
|
|
2 files changed, 4 insertions(+), 4 deletions(-)
|
|
|
|
diff --git a/xbmc/windowing/X11/WinSystemX11.cpp b/xbmc/windowing/X11/WinSystemX11.cpp
|
|
index e4e25b2..b87e264 100644
|
|
--- a/xbmc/windowing/X11/WinSystemX11.cpp
|
|
+++ b/xbmc/windowing/X11/WinSystemX11.cpp
|
|
@@ -409,11 +409,11 @@ bool CWinSystemX11::IsSuitableVisual(XVisualInfo *vInfo)
|
|
return true;
|
|
}
|
|
|
|
-bool CWinSystemX11::RefreshGlxContext()
|
|
+bool CWinSystemX11::RefreshGlxContext(bool force)
|
|
{
|
|
bool retVal = false;
|
|
|
|
- if (m_glContext)
|
|
+ if (m_glContext && !force)
|
|
{
|
|
CLog::Log(LOGDEBUG, "CWinSystemX11::RefreshGlxContext: refreshing context");
|
|
glXMakeCurrent(m_dpy, None, NULL);
|
|
@@ -930,7 +930,7 @@ bool CWinSystemX11::SetWindow(int width, int height, bool fullscreen, const CStd
|
|
}
|
|
|
|
CDirtyRegionList dr;
|
|
- RefreshGlxContext();
|
|
+ RefreshGlxContext(!m_currentOutput.Equals(output));
|
|
XSync(m_dpy, FALSE);
|
|
g_graphicsContext.Clear(0);
|
|
g_graphicsContext.Flip(dr);
|
|
diff --git a/xbmc/windowing/X11/WinSystemX11.h b/xbmc/windowing/X11/WinSystemX11.h
|
|
index 0b7c10a..33b1739 100644
|
|
--- a/xbmc/windowing/X11/WinSystemX11.h
|
|
+++ b/xbmc/windowing/X11/WinSystemX11.h
|
|
@@ -74,7 +74,7 @@ class CWinSystemX11 : public CWinSystemBase
|
|
void NotifyMouseCoverage(bool covered);
|
|
|
|
protected:
|
|
- bool RefreshGlxContext();
|
|
+ bool RefreshGlxContext(bool force);
|
|
void CheckDisplayEvents();
|
|
void OnLostDevice();
|
|
bool SetWindow(int width, int height, bool fullscreen, const CStdString &output);
|
|
--
|
|
1.7.10
|
|
|
|
|
|
From ae08a23a2f4fd78139e2ebca8a4a87ab619feb0b Mon Sep 17 00:00:00 2001
|
|
From: xbmc <fernetmenta@online.de>
|
|
Date: Sun, 27 Jan 2013 12:10:19 +0100
|
|
Subject: [PATCH 72/72] vdpau: switch off de-interlacing on ff
|
|
|
|
---
|
|
xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp | 5 +++--
|
|
1 file changed, 3 insertions(+), 2 deletions(-)
|
|
|
|
diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp
|
|
index 8858614..3e21d9d 100644
|
|
--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp
|
|
+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp
|
|
@@ -2043,8 +2043,9 @@ void CMixer::InitCycle()
|
|
EINTERLACEMETHOD method = GetDeinterlacingMethod();
|
|
bool interlaced = m_mixerInput[1].DVDPic.iFlags & DVP_FLAG_INTERLACED;
|
|
|
|
- if (mode == VS_DEINTERLACEMODE_FORCE ||
|
|
- (mode == VS_DEINTERLACEMODE_AUTO && interlaced))
|
|
+ if (!(flags & DVP_FLAG_NO_POSTPROC) &&
|
|
+ (mode == VS_DEINTERLACEMODE_FORCE ||
|
|
+ (mode == VS_DEINTERLACEMODE_AUTO && interlaced)))
|
|
{
|
|
if((method == VS_INTERLACEMETHOD_AUTO && interlaced)
|
|
|| method == VS_INTERLACEMETHOD_VDPAU_BOB
|
|
--
|
|
1.7.10
|
|
|