Files
LibreELEC.tv/packages/mediacenter/xbmc/patches/xbmc-995.01-fernetmenta-fixes-b3b79dd.patch
2014-03-09 00:52:24 +02:00

11104 lines
366 KiB
Diff

From 320046ba60eca428368d9fe229670a61ea31ff80 Mon Sep 17 00:00:00 2001
From: xbmc <fernetmenta@online.de>
Date: Mon, 28 May 2012 10:34:39 +0200
Subject: [PATCH 01/93] videoplayer: adapt lateness detection and dropping to
buffering
---
xbmc/cores/VideoRenderers/RenderManager.cpp | 16 +-
xbmc/cores/VideoRenderers/RenderManager.h | 12 +-
.../dvdplayer/DVDCodecs/Video/DVDVideoCodec.h | 15 +-
.../DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp | 31 ++++
.../DVDCodecs/Video/DVDVideoCodecFFmpeg.h | 7 +
xbmc/cores/dvdplayer/DVDPlayerVideo.cpp | 194 +++++++++++++++++----
xbmc/cores/dvdplayer/DVDPlayerVideo.h | 23 +++
7 files changed, 260 insertions(+), 38 deletions(-)
diff --git a/xbmc/cores/VideoRenderers/RenderManager.cpp b/xbmc/cores/VideoRenderers/RenderManager.cpp
index a33591d..9e2c055 100644
--- a/xbmc/cores/VideoRenderers/RenderManager.cpp
+++ b/xbmc/cores/VideoRenderers/RenderManager.cpp
@@ -284,6 +284,8 @@ bool CXBMCRenderManager::Configure(unsigned int width, unsigned int height, unsi
m_bIsStarted = true;
m_bReconfigured = true;
m_presentstep = PRESENT_IDLE;
+ m_presentpts = DVD_NOPTS_VALUE;
+ m_sleeptime = 1.0;
m_presentevent.notifyAll();
m_firstFlipPage = false; // tempfix
@@ -627,7 +629,7 @@ void CXBMCRenderManager::SetViewMode(int iViewMode)
m_pRenderer->SetViewMode(iViewMode);
}
-void CXBMCRenderManager::FlipPage(volatile bool& bStop, double timestamp /* = 0LL*/, int source /*= -1*/, EFIELDSYNC sync /*= FS_NONE*/)
+void CXBMCRenderManager::FlipPage(volatile bool& bStop, double timestamp /* = 0LL*/, double pts /* = 0 */, int source /*= -1*/, EFIELDSYNC sync /*= FS_NONE*/)
{
{ CSharedLock lock(m_sharedSection);
@@ -695,6 +697,7 @@ void CXBMCRenderManager::FlipPage(volatile bool& bStop, double timestamp /* = 0L
m.timestamp = timestamp;
m.presentfield = sync;
m.presentmethod = presentmethod;
+ m.pts = pts;
requeue(m_queued, m_free);
/* signal to any waiters to check state */
@@ -1063,6 +1066,8 @@ void CXBMCRenderManager::PrepareNextRender()
m_discard.push_back(m_presentsource);
m_presentsource = idx;
m_queued.pop_front();
+ m_sleeptime = m_Queue[idx].timestamp - clocktime;
+ m_presentpts = m_Queue[idx].pts;
m_presentevent.notifyAll();
}
}
@@ -1079,3 +1084,12 @@ void CXBMCRenderManager::DiscardBuffer()
m_presentstep = PRESENT_IDLE;
m_presentevent.notifyAll();
}
+
+bool CXBMCRenderManager::GetStats(double &sleeptime, double &pts, int &bufferLevel)
+{
+ CSingleLock lock(m_presentlock);
+ sleeptime = m_sleeptime;
+ pts = m_presentpts;
+ bufferLevel = m_queued.size() + m_discard.size();
+ return true;
+}
diff --git a/xbmc/cores/VideoRenderers/RenderManager.h b/xbmc/cores/VideoRenderers/RenderManager.h
index c469795..949c652 100644
--- a/xbmc/cores/VideoRenderers/RenderManager.h
+++ b/xbmc/cores/VideoRenderers/RenderManager.h
@@ -98,10 +98,11 @@ public:
*
* @param bStop reference to stop flag of calling thread
* @param timestamp of frame delivered with AddVideoPicture
+ * @param pts used for lateness detection
* @param source depreciated
* @param sync signals frame, top, or bottom field
*/
- void FlipPage(volatile bool& bStop, double timestamp = 0.0, int source = -1, EFIELDSYNC sync = FS_NONE);
+ void FlipPage(volatile bool& bStop, double timestamp = 0.0, double pts = 0.0, int source = -1, EFIELDSYNC sync = FS_NONE);
unsigned int PreInit();
void UnInit();
bool Flush();
@@ -176,6 +177,12 @@ public:
int WaitForBuffer(volatile bool& bStop, int timeout = 100);
/**
+ * Can be called by player for lateness detection. This is done best by
+ * looking at the end of the queue.
+ */
+ bool GetStats(double &sleeptime, double &pts, int &bufferLevel);
+
+ /**
* Video player call this on flush in oder to discard any queued frames
*/
void DiscardBuffer();
@@ -222,6 +229,7 @@ protected:
struct SPresent
{
+ double pts;
double timestamp;
EFIELDSYNC presentfield;
EPRESENTMETHOD presentmethod;
@@ -233,6 +241,8 @@ protected:
ERenderFormat m_format;
+ double m_sleeptime;
+ double m_presentpts;
double m_presentcorr;
double m_presenterr;
double m_errorbuff[ERRORBUFFSIZE];
diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h
index f6751f4..fb34463 100644
--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h
+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h
@@ -132,6 +132,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
@@ -149,6 +153,9 @@ class CDVDCodecOptions;
#define VC_PICTURE 0x00000004 // the decoder got a picture, call Decode(NULL, 0) again to parse the rest of the data
#define VC_USERDATA 0x00000008 // the decoder found some userdata, call Decode(NULL, 0) again to parse the rest of the data
#define VC_FLUSHED 0x00000010 // the decoder lost it's state, we need to restart decoding again
+#define VC_DROPPED 0x00000020 // needed to identify if a picture was dropped
+#define VC_HURRY 0x00000040
+
class CDVDVideoCodec
{
public:
@@ -266,7 +273,6 @@ public:
return 0;
}
-
/**
* Number of references to old pictures that are allowed to
* be retained when calling decode on the next demux packet
@@ -283,4 +289,11 @@ public:
* Interact with user settings so that user disabled codecs are disabled
*/
static bool IsCodecDisabled(DVDCodecAvailableType* map, unsigned int size, AVCodecID id);
+
+ 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 9b6a34d..413151d 100644
--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp
+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp
@@ -164,6 +164,7 @@ CDVDVideoCodecFFmpeg::CDVDVideoCodecFFmpeg() : CDVDVideoCodec()
m_iLastKeyframe = 0;
m_dts = DVD_NOPTS_VALUE;
m_started = false;
+ m_decoderPts = DVD_NOPTS_VALUE;
}
CDVDVideoCodecFFmpeg::~CDVDVideoCodecFFmpeg()
@@ -355,6 +356,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
@@ -556,6 +565,7 @@ int CDVDVideoCodecFFmpeg::Decode(uint8_t* pData, int iSize, double dts, double p
void CDVDVideoCodecFFmpeg::Reset()
{
m_started = false;
+ m_decoderPts = DVD_NOPTS_VALUE;
m_iLastKeyframe = m_pCodecContext->has_b_frames;
m_dllAvCodec.avcodec_flush_buffers(m_pCodecContext);
@@ -665,6 +675,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;
@@ -924,3 +950,8 @@ unsigned CDVDVideoCodecFFmpeg::GetAllowedReferences()
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 2287031..8376f72 100644
--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.h
+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.h
@@ -45,6 +45,7 @@ public:
virtual int Check (AVCodecContext* avctx) = 0;
virtual void Reset () {}
virtual unsigned GetAllowedReferences() { return 0; }
+ virtual bool CanSkipDeint() {return false; }
virtual const std::string Name() = 0;
virtual CCriticalSection* Section() { return NULL; }
};
@@ -62,6 +63,8 @@ public:
virtual const char* GetName() { return m_name.c_str(); }; // m_name is never changed after open
virtual unsigned GetConvergeCount();
virtual unsigned GetAllowedReferences();
+ 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; };
@@ -127,4 +130,8 @@ protected:
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 99b3155..4fad1a3 100644
--- a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp
+++ b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp
@@ -38,6 +38,7 @@
#include "DVDCodecs/DVDCodecs.h"
#include "DVDCodecs/Overlay/DVDOverlayCodecCC.h"
#include "DVDCodecs/Overlay/DVDOverlaySSA.h"
+#include "guilib/GraphicContext.h"
#include <sstream>
#include <iomanip>
#include <numeric>
@@ -320,8 +321,10 @@ void CDVDPlayerVideo::Process()
int iDropped = 0; //frames dropped in a row
bool bRequestDrop = false;
+ int iDropDirective;
m_videoStats.Start();
+ m_droppingStats.Reset();
while (!m_bStop)
{
@@ -431,6 +434,7 @@ void CDVDPlayerVideo::Process()
picture.iFlags &= ~DVP_FLAG_ALLOCATED;
m_packets.clear();
m_started = false;
+ m_droppingStats.Reset();
}
else if (pMsg->IsType(CDVDMsg::GENERAL_FLUSH)) // private message sent by (CDVDPlayerVideo::Flush())
{
@@ -443,6 +447,7 @@ void CDVDPlayerVideo::Process()
//we need to recalculate the framerate
//TODO: this needs to be set on a streamchange instead
ResetFrameRateCalc();
+ m_droppingStats.Reset();
m_stalled = true;
m_started = false;
@@ -460,8 +465,10 @@ void CDVDPlayerVideo::Process()
m_speed = static_cast<CDVDMsgInt*>(pMsg)->m_value;
if(m_speed == DVD_PLAYSPEED_PAUSE)
m_iNrOfPicturesNotToSkip = 0;
+
if (m_pVideoCodec)
m_pVideoCodec->SetSpeed(m_speed);
+ m_droppingStats.Reset();
}
else if (pMsg->IsType(CDVDMsg::PLAYER_STARTED))
{
@@ -507,6 +514,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++;
+ }
+
if (m_messageQueue.GetDataSize() == 0
|| m_speed < 0)
{
@@ -559,15 +588,7 @@ void CDVDPlayerVideo::Process()
}
m_videoStats.AddSampleBytes(pPacket->iSize);
- // assume decoder dropped a picture if it didn't give us any
- // picture from a demux packet, this should be reasonable
- // for libavformat as a demuxer as it normally packetizes
- // pictures when they come from demuxer
- if(bRequestDrop && !bPacketDrop && (iDecoderState & VC_BUFFER) && !(iDecoderState & VC_PICTURE))
- {
- m_iDroppedFrames++;
- iDropped++;
- }
+
// reset the request, the following while loop may break before
// setting the flag to a new value
bRequestDrop = false;
@@ -1176,33 +1197,12 @@ 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_DROPPED))
{
- if (!(pPicture->iFlags & DVP_FLAG_NOSKIP))
- {
- //if we're calculating the framerate,
- //don't drop frames until we've calculated a stable framerate
- if (m_bAllowDrop || m_speed != DVD_PLAYSPEED_NORMAL)
- {
- result |= EOS_VERYLATE;
- m_pullupCorrection.Flush(); //dropped frames mess up the pattern, so just flush it
- }
- m_iDroppedRequest++;
- }
- }
- else
- {
- m_iDroppedRequest = 0;
- }
-
- if( (pPicture->iFlags & DVP_FLAG_DROPPED) )
+ m_droppingStats.AddOutputDropGain(pts, 1/m_fFrameRate);
+ CLog::Log(LOGDEBUG,"%s - dropped in output", __FUNCTION__);
return result | EOS_DROPPED;
+ }
// set fieldsync if picture is interlaced
EFIELDSYNC mDisplayField = FS_NONE;
@@ -1235,7 +1235,7 @@ int CDVDPlayerVideo::OutputPicture(const DVDVideoPicture* src, double pts)
if (index < 0)
return EOS_DROPPED;
- g_renderManager.FlipPage(CThread::m_bStop, (iCurrentClock + iSleepTime) / DVD_TIME_BASE, -1, mDisplayField);
+ g_renderManager.FlipPage(CThread::m_bStop, (iCurrentClock + iSleepTime) / DVD_TIME_BASE, pts, -1, mDisplayField);
return result;
#else
@@ -1535,3 +1535,127 @@ 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;
+ if (bNewFrame)
+ m_droppingStats.m_dropRequests++;
+ }
+ }
+ }
+ else
+ {
+ m_droppingStats.m_dropRequests = 0;
+ m_droppingStats.m_lateFrames = 0;
+ }
+ m_droppingStats.m_lastRenderPts = iRenderPts;
+ return result;
+}
+
+void CDroppingStats::Reset()
+{
+ m_gain.clear();
+ m_totalGain = 0;
+ m_lastDecoderPts = 0;
+ m_lastRenderPts = 0;
+ m_lateFrames = 0;
+ m_dropRequests = 0;
+}
+
+void CDroppingStats::AddOutputDropGain(double pts, double frametime)
+{
+ CDroppingStats::CGain gain;
+ gain.gain = frametime;
+ gain.pts = pts;
+ m_gain.push_back(gain);
+ m_totalGain += frametime;
+}
diff --git a/xbmc/cores/dvdplayer/DVDPlayerVideo.h b/xbmc/cores/dvdplayer/DVDPlayerVideo.h
index f8ad541..186e271 100644
--- a/xbmc/cores/dvdplayer/DVDPlayerVideo.h
+++ b/xbmc/cores/dvdplayer/DVDPlayerVideo.h
@@ -36,6 +36,25 @@ class CDVDOverlayCodecCC;
#define VIDEO_PICTURE_QUEUE_SIZE 1
+class CDroppingStats
+{
+public:
+ void Reset();
+ void AddOutputDropGain(double pts, double frametime);
+ struct CGain
+ {
+ double gain;
+ double pts;
+ };
+ std::deque<CGain> m_gain;
+ double m_totalGain;
+ double m_lastDecoderPts;
+ double m_lastRenderPts;
+ unsigned int m_lateFrames;
+ unsigned int m_dropRequests;
+};
+
+
class CDVDPlayerVideo : public CThread
{
public:
@@ -104,6 +123,7 @@ protected:
#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);
@@ -129,6 +149,7 @@ protected:
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
@@ -182,5 +203,7 @@ protected:
CPullupCorrection m_pullupCorrection;
std::list<DVDMessageListItem> m_packets;
+
+ CDroppingStats m_droppingStats;
};
--
1.9.0
From cbecaef2fb4c319c179c2283e82cead122f3bab5 Mon Sep 17 00:00:00 2001
From: xbmc <fernetmenta@online.de>
Date: Sun, 2 Sep 2012 16:05:21 +0200
Subject: [PATCH 02/93] video player: present correct pts to user for a/v sync
(after buffering in renderer)
---
xbmc/cores/dvdplayer/DVDPlayerVideo.cpp | 25 +++++++++++++++++++++++++
xbmc/cores/dvdplayer/DVDPlayerVideo.h | 2 +-
2 files changed, 26 insertions(+), 1 deletion(-)
diff --git a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp
index 4fad1a3..1d29b6f 100644
--- a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp
+++ b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp
@@ -1455,6 +1455,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
@@ -1573,6 +1589,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 186e271..59c7f09 100644
--- a/xbmc/cores/dvdplayer/DVDPlayerVideo.h
+++ b/xbmc/cores/dvdplayer/DVDPlayerVideo.h
@@ -100,7 +100,7 @@ public:
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.9.0
From 893b7955a20aeaf74b06b7de1c28e08ef05625dd Mon Sep 17 00:00:00 2001
From: xbmc <fernetmenta@online.de>
Date: Sat, 16 Feb 2013 18:25:53 +0100
Subject: [PATCH 03/93] videoplayer: some rework and documentation
---
.../dvdplayer/DVDCodecs/Video/DVDVideoCodec.h | 28 ++++++++++++++++++++--
.../DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp | 11 +++++++++
.../DVDCodecs/Video/DVDVideoCodecFFmpeg.h | 2 +-
xbmc/cores/dvdplayer/DVDPlayerVideo.cpp | 2 +-
4 files changed, 39 insertions(+), 4 deletions(-)
diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h
index fb34463..ecd325c 100644
--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h
+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h
@@ -154,7 +154,6 @@ class CDVDCodecOptions;
#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
{
@@ -290,10 +289,35 @@ public:
*/
static bool IsCodecDisabled(DVDCodecAvailableType* map, unsigned int size, AVCodecID id);
- virtual bool GetPts(double &pts, int &skippedDeint, int &interlaced)
+ /* For calculation of dropping requirements player asks for some information.
+ *
+ * - pts : right after decoder, used to detect gaps (dropped frames in decoder)
+ * - skippedDeint : indicates if decoder has just skipped a deinterlacing cycle
+ * instead of dropping a full frame
+ * - interlaced : when detecting gaps in pts, player needs to know whether
+ * it's interlaced or not
+ *
+ * If codec does not implement this method, pts of decoded frame at input
+ * video player is used. In case coded does post-proc and de-interlacing there
+ * may be quite some frames queued up between exit decoder and entry player.
+ */
+ virtual bool GetCodecStats(double &pts, int &skippedDeint, int &interlaced)
{
return false;
}
+ /**
+ * Codec can be informed by player with the following flags:
+ *
+ * DVP_FLAG_NO_POSTPROC : if speed is not normal the codec can switch off
+ * postprocessing and de-interlacing
+ *
+ * DVP_FLAG_DRAIN : codecs may do postprocessing and de-interlacing.
+ * If video buffers in RenderManager are about to run dry,
+ * this is signaled to codec. Codec can wait for post-proc
+ * to be finished instead of returning empty and getting another
+ * packet.
+ *
+ */
virtual void SetCodecControl(int flags) {}
};
diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp
index 413151d..b59c1ee 100644
--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp
+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp
@@ -951,6 +951,17 @@ unsigned CDVDVideoCodecFFmpeg::GetAllowedReferences()
return 0;
}
+bool CDVDVideoCodecFFmpeg::GetCodecStats(double &pts, int &skippedDeint, int &interlaced)
+{
+ pts = m_decoderPts;
+ skippedDeint = m_skippedDeint;
+ if (m_pFrame)
+ interlaced = m_pFrame->interlaced_frame;
+ else
+ interlaced = 0;
+ return true;
+}
+
void CDVDVideoCodecFFmpeg::SetCodecControl(int flags)
{
m_codecControlFlags = flags;
diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.h
index 8376f72..c0ce198 100644
--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.h
+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.h
@@ -63,7 +63,7 @@ public:
virtual const char* GetName() { return m_name.c_str(); }; // m_name is never changed after open
virtual unsigned GetConvergeCount();
virtual unsigned GetAllowedReferences();
- 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 bool GetCodecStats(double &pts, int &skippedDeint, int &interlaced);
virtual void SetCodecControl(int flags);
bool IsHardwareAllowed() { return !m_bSoftware; }
diff --git a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp
index 1d29b6f..ee07f30 100644
--- a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp
+++ b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp
@@ -1566,7 +1566,7 @@ int CDVDPlayerVideo::CalcDropRequirement(double pts)
int iBufferLevel;
// get decoder stats
- if (!m_pVideoCodec->GetPts(iDecoderPts, iSkippedDeint, interlaced))
+ if (!m_pVideoCodec->GetCodecStats(iDecoderPts, iSkippedDeint, interlaced))
iDecoderPts = pts;
if (iDecoderPts == DVD_NOPTS_VALUE)
iDecoderPts = pts;
--
1.9.0
From af8d9a25047777c7dd11797b07168a7e7f6fe1ce Mon Sep 17 00:00:00 2001
From: Rainer Hochecker <fernetmenta@online.de>
Date: Sat, 1 Jun 2013 11:21:19 +0200
Subject: [PATCH 04/93] renderer: bump buffers to 5
---
xbmc/cores/VideoRenderers/BaseRenderer.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/xbmc/cores/VideoRenderers/BaseRenderer.h b/xbmc/cores/VideoRenderers/BaseRenderer.h
index dc2712a..9edfbd4 100644
--- a/xbmc/cores/VideoRenderers/BaseRenderer.h
+++ b/xbmc/cores/VideoRenderers/BaseRenderer.h
@@ -29,7 +29,7 @@
#define MAX_PLANES 3
#define MAX_FIELDS 3
-#define NUM_BUFFERS 3
+#define NUM_BUFFERS 5
class CSetting;
--
1.9.0
From 2c520fc1ace027ecbecd06eb60aebe607e04c538 Mon Sep 17 00:00:00 2001
From: xbmc <fernetmenta@online.de>
Date: Mon, 28 May 2012 10:41:31 +0200
Subject: [PATCH 05/93] 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 ee07f30..b3175cd 100644
--- a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp
+++ b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp
@@ -708,6 +708,8 @@ void CDVDPlayerVideo::Process()
int iResult = OutputPicture(&picture, pts);
+ frametime = (double)DVD_TIME_BASE/m_fFrameRate;
+
if(m_started == false)
{
m_codecname = m_pVideoCodec->GetName();
--
1.9.0
From e4e8f007146ed6d84a10f56a8ec1c8f70643b050 Mon Sep 17 00:00:00 2001
From: xbmc <fernetmenta@online.de>
Date: Mon, 28 May 2012 10:43:06 +0200
Subject: [PATCH 06/93] 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 b3175cd..9c36bdb 100644
--- a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp
+++ b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp
@@ -1497,7 +1497,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.9.0
From f565af531ea544c02207993205a2c1f79e003a77 Mon Sep 17 00:00:00 2001
From: xbmc <fernetmenta@online.de>
Date: Mon, 28 May 2012 10:49:05 +0200
Subject: [PATCH 07/93] 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 b056c8b..0d2b4ae 100644
--- a/xbmc/cores/dvdplayer/DVDPlayer.cpp
+++ b/xbmc/cores/dvdplayer/DVDPlayer.cpp
@@ -1633,7 +1633,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())
{
@@ -2294,6 +2294,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.9.0
From c686480a53d7cdcf63a3000bf408ef4153e359a1 Mon Sep 17 00:00:00 2001
From: FernetMenta <fernetmenta@online.de>
Date: Thu, 5 Jul 2012 15:22:05 +0200
Subject: [PATCH 08/93] X11: ditch SDL for video and window events
---
xbmc/Application.cpp | 2 +-
xbmc/system.h | 5 +
xbmc/windowing/Makefile.in | 1 +
xbmc/windowing/WinEvents.cpp | 4 +
xbmc/windowing/WinEventsX11.cpp | 784 ++++++++++++++++++++++++++++++++++++
xbmc/windowing/WinEventsX11.h | 65 +++
xbmc/windowing/X11/WinSystemX11.cpp | 386 ++++++++++++------
xbmc/windowing/X11/WinSystemX11.h | 10 +-
8 files changed, 1129 insertions(+), 128 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 265881f..43c4517 100644
--- a/xbmc/Application.cpp
+++ b/xbmc/Application.cpp
@@ -907,7 +907,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 1f4e15f..075e44a 100644
--- a/xbmc/system.h
+++ b/xbmc/system.h
@@ -171,16 +171,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.in b/xbmc/windowing/Makefile.in
index 6704967..4b41723 100644
--- a/xbmc/windowing/Makefile.in
+++ b/xbmc/windowing/Makefile.in
@@ -1,6 +1,7 @@
SRCS=WinEventsSDL.cpp \
WinEventsLinux.cpp \
WinEventsWayland.cpp \
+ WinEventsX11.cpp \
WinSystem.cpp \
WinEvents.cpp
diff --git a/xbmc/windowing/WinEvents.cpp b/xbmc/windowing/WinEvents.cpp
index 1022ad2..8e64497 100644
--- a/xbmc/windowing/WinEvents.cpp
+++ b/xbmc/windowing/WinEvents.cpp
@@ -42,6 +42,10 @@
#include "WinEventsSDL.h"
#define WinEventsType CWinEventsSDL
+#elif (defined(TARGET_FREEBSD) || defined(TARGET_LINUX)) && defined(HAS_X11_WIN_EVENTS)
+#include "WinEventsX11.h"
+#define WinEventsType CWinEventsX11
+
#elif defined(HAVE_WAYLAND)
#include "WinEventsWayland.h"
#define WinEventsType CWinEventsWayland
diff --git a/xbmc/windowing/WinEventsX11.cpp b/xbmc/windowing/WinEventsX11.cpp
new file mode 100644
index 0000000..ad58aad
--- /dev/null
+++ b/xbmc/windowing/WinEventsX11.cpp
@@ -0,0 +1,784 @@
+/*
+* 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"
+
+CWinEventsX11Imp* CWinEventsX11Imp::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}
+};
+
+bool CWinEventsX11::MessagePump()
+{
+ return CWinEventsX11Imp::MessagePump();
+}
+
+size_t CWinEventsX11::GetQueueSize()
+{
+ return CWinEventsX11Imp::GetQueueSize();
+}
+
+CWinEventsX11Imp::CWinEventsX11Imp()
+{
+ m_display = 0;
+ m_window = 0;
+ m_keybuf = 0;
+ m_utf16buf = 0;
+}
+
+CWinEventsX11Imp::~CWinEventsX11Imp()
+{
+ 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 CWinEventsX11Imp::Init(Display *dpy, Window win)
+{
+ if (WinEvents)
+ return true;
+
+ WinEvents = new CWinEventsX11Imp();
+ 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 CWinEventsX11Imp::Quit()
+{
+ if (!WinEvents)
+ return;
+
+ delete WinEvents;
+ WinEvents = 0;
+}
+
+bool CWinEventsX11Imp::HasStructureChanged()
+{
+ if (!WinEvents)
+ return false;
+
+ bool ret = WinEvents->m_structureChanged;
+ WinEvents->m_structureChanged = false;
+ return ret;
+}
+
+bool CWinEventsX11Imp::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.SetRenderGUI(true);
+ break;
+ }
+
+ case UnmapNotify:
+ {
+ g_application.SetRenderGUI(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;
+}
+
+size_t CWinEventsX11Imp::GetQueueSize()
+{
+ int ret = 0;
+
+ if (WinEvents)
+ ret = XPending(WinEvents->m_display);
+
+ return ret;
+}
+
+bool CWinEventsX11Imp::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 CWinEventsX11Imp::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 CWinEventsX11Imp::ProcessKeyRepeat()
+{
+ if (WinEvents && (WinEvents->m_lastKey.type == XBMC_KEYDOWN))
+ {
+ if (WinEvents->m_repeatKeyTimeout.IsTimePast())
+ {
+ return ProcessKey(WinEvents->m_lastKey, 10);
+ }
+ }
+ return false;
+}
+
+int CWinEventsX11Imp::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 CWinEventsX11Imp::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..ce57c23
--- /dev/null
+++ b/xbmc/windowing/WinEventsX11.h
@@ -0,0 +1,65 @@
+/*
+* 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 IWinEvents
+{
+public:
+ virtual bool MessagePump();
+ virtual size_t GetQueueSize();
+};
+
+class CWinEventsX11Imp
+{
+public:
+ CWinEventsX11Imp();
+ virtual ~CWinEventsX11Imp();
+ static bool Init(Display *dpy, Window win);
+ static void Quit();
+ static bool HasStructureChanged();
+ static bool MessagePump();
+ static size_t GetQueueSize();
+
+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 CWinEventsX11Imp *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 083d1e9..40b8403 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/DisplaySettings.h"
#include "settings/Settings.h"
@@ -34,7 +33,6 @@
#include "XRandR.h"
#include <vector>
#include "threads/SingleLock.h"
-#include <X11/Xlib.h>
#include "cores/VideoRenderers/RenderManager.h"
#include "utils/TimeUtils.h"
#include "utils/StringUtils.h"
@@ -43,19 +41,22 @@
#include <X11/extensions/Xrandr.h>
#endif
+#include "../WinEventsX11.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);
}
@@ -68,18 +69,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
@@ -117,45 +106,37 @@ bool CWinSystemX11::DestroyWindowSystem()
bool CWinSystemX11::CreateNewWindow(const CStdString& name, bool fullScreen, RESOLUTION_INFO& res, PHANDLE_EVENT_FUNC userFunction)
{
- RESOLUTION_INFO& desktop = CDisplaySettings::Get().GetResolutionInfo(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;
+ }
+
+ CWinEventsX11Imp::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;
}
@@ -165,67 +146,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;
+}
- if ((m_SDLSurface = SDL_SetVideoMode(m_nWidth, m_nHeight, 0, options)))
+void CWinSystemX11::RefreshWindow()
+{
+ g_xrandr.Query(true);
+ XOutput out = g_xrandr.GetCurrentOutput();
+ XMode mode = g_xrandr.GetCurrentMode(out.name);
+
+ // only overwrite desktop resolution, if we are not in fullscreen mode
+ if (!g_graphicsContext.IsFullScreenVideo())
{
- SetGrabMode();
- 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;
- SetGrabMode();
- RefreshGlxContext();
+ RefreshGlxContext();
- return true;
- }
+ m_nWidth = res.iWidth;
+ m_nHeight = res.iHeight;
+ m_bFullScreen = fullScreen;
- return false;
+ return true;
}
void CWinSystemX11::UpdateResolutions()
@@ -327,17 +346,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;
@@ -349,8 +361,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
@@ -421,7 +431,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()
@@ -435,8 +448,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
@@ -452,13 +463,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;
}
@@ -468,13 +493,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;
@@ -506,6 +531,7 @@ void CWinSystemX11::CheckDisplayEvents()
if (bGotEvent || bTimeout)
{
CLog::Log(LOGDEBUG, "%s - notify display reset event", __FUNCTION__);
+ RefreshWindow();
CSingleLock lock(m_resourceSection);
@@ -564,37 +590,151 @@ bool CWinSystemX11::EnableFrameLimiter()
return m_minimized;
}
-void CWinSystemX11::SetGrabMode(const CSetting *setting /*= NULL*/)
+bool CWinSystemX11::SetWindow(int width, int height, bool fullscreen)
{
- bool enabled;
- if (setting)
- enabled = ((CSettingBool*)setting)->GetValue();
- else
- enabled = CSettings::Get().GetBool("input.enablesystemkeys");
-
- if (m_SDLSurface && m_SDLSurface->flags & SDL_FULLSCREEN)
+ bool changeWindow = false;
+ bool changeSize = false;
+ bool mouseActive = false;
+ float mouseX, mouseY;
+
+ if (m_glWindow && (m_bFullScreen != fullscreen))
{
- if (enabled)
+ mouseActive = g_Mouse.IsActive();
+ if (mouseActive)
{
- //SDL will always call XGrabPointer and XGrabKeyboard when in fullscreen
- //so temporarily zero the SDL_FULLSCREEN flag, then turn off SDL grab mode
- //this will make SDL call XUnGrabPointer and XUnGrabKeyboard
- m_SDLSurface->flags &= ~SDL_FULLSCREEN;
- SDL_WM_GrabInput(SDL_GRAB_OFF);
- m_SDLSurface->flags |= SDL_FULLSCREEN;
+ 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;
}
- else
+ DestroyWindow();
+ }
+
+ // create main window
+ if (!m_glWindow)
+ {
+ GLint att[] =
{
- //turn off key grabbing, which will actually make SDL turn it on when in fullscreen
- SDL_WM_GrabInput(SDL_GRAB_OFF);
- }
+ 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
+ CWinEventsX11Imp::Init(m_dpy, m_glWindow);
+
+ changeWindow = true;
+ changeSize = true;
}
-}
-void CWinSystemX11::OnSettingChanged(const CSetting *setting)
-{
- if (setting->GetId() == "input.enablesystemkeys")
- SetGrabMode(setting);
+ if (!CWinEventsX11Imp::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 b1464d0..34b912f 100644
--- a/xbmc/windowing/X11/WinSystemX11.h
+++ b/xbmc/windowing/X11/WinSystemX11.h
@@ -54,6 +54,7 @@ public:
virtual bool EnableFrameLimiter();
virtual void NotifyAppActiveChange(bool bActivated);
+ virtual void NotifyAppFocusChange(bool bGaining);
virtual bool Minimize();
virtual bool Restore() ;
@@ -66,20 +67,21 @@ public:
Display* GetDisplay() { return m_dpy; }
GLXWindow GetWindow() { return m_glWindow; }
GLXContext GetGlxContext() { return m_glContext; }
- virtual void OnSettingChanged(const CSetting *setting);
+ 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.9.0
From 78d8cdb9dd83a7dfdbe77fa1bb137944200bed06 Mon Sep 17 00:00:00 2001
From: FernetMenta <fernetmenta@online.de>
Date: Thu, 5 Jul 2012 15:24:22 +0200
Subject: [PATCH 09/93] X11: Add xbmc icon
---
xbmc/windowing/X11/WinSystemX11.cpp | 126 +++++++++++++++++++++++++++++++++++-
xbmc/windowing/X11/WinSystemX11.h | 3 +-
2 files changed, 127 insertions(+), 2 deletions(-)
diff --git a/xbmc/windowing/X11/WinSystemX11.cpp b/xbmc/windowing/X11/WinSystemX11.cpp
index 40b8403..858ea5e 100644
--- a/xbmc/windowing/X11/WinSystemX11.cpp
+++ b/xbmc/windowing/X11/WinSystemX11.cpp
@@ -137,6 +137,9 @@ bool CWinSystemX11::DestroyWindow()
XDestroyWindow(m_dpy, m_glWindow);
m_glWindow = 0;
+ if (m_icon)
+ XFreePixmap(m_dpy, m_icon);
+
return true;
}
@@ -691,8 +694,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;
@@ -703,7 +708,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,
@@ -737,4 +742,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 34b912f..352e90e 100644
--- a/xbmc/windowing/X11/WinSystemX11.h
+++ b/xbmc/windowing/X11/WinSystemX11.h
@@ -79,6 +79,7 @@ protected:
GLXContext m_glContext;
Display* m_dpy;
Cursor m_invisibleCursor;
+ Pixmap m_icon;
bool m_bWasFullScreenBeforeMinimize;
bool m_minimized;
bool m_bIgnoreNextFocusMessage;
@@ -90,7 +91,7 @@ protected:
private:
bool IsSuitableVisual(XVisualInfo *vInfo);
static int XErrorHandler(Display* dpy, XErrorEvent* error);
- void SetGrabMode(const CSetting *setting = NULL);
+ bool CreateIconPixmap();
CStopWatch m_screensaverReset;
};
--
1.9.0
From a5da9aa02e7fa7ee91d0c98ef20c57b3737670e0 Mon Sep 17 00:00:00 2001
From: xbmc <fernetmenta@online.de>
Date: Sun, 20 May 2012 14:11:26 +0200
Subject: [PATCH 10/93] 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 ad58aad..6f57a87 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
+
CWinEventsX11Imp* CWinEventsX11Imp::WinEvents = 0;
static uint32_t SymMappingsX11[][2] =
@@ -556,6 +560,28 @@ bool CWinEventsX11Imp::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.9.0
From 97fa84c30a5c726690f886ac596bfd80870d8d77 Mon Sep 17 00:00:00 2001
From: Joakim Plate <elupus@xbmc.org>
Date: Thu, 5 Jul 2012 12:35:55 +0200
Subject: [PATCH 11/93] 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 858ea5e..304dac8 100644
--- a/xbmc/windowing/X11/WinSystemX11.cpp
+++ b/xbmc/windowing/X11/WinSystemX11.cpp
@@ -533,14 +533,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;
@@ -548,6 +541,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 352e90e..3f91b9b 100644
--- a/xbmc/windowing/X11/WinSystemX11.h
+++ b/xbmc/windowing/X11/WinSystemX11.h
@@ -68,6 +68,7 @@ public:
GLXWindow GetWindow() { return m_glWindow; }
GLXContext GetGlxContext() { return m_glContext; }
void RefreshWindow();
+ void NotifyXRREvent();
protected:
bool RefreshGlxContext();
--
1.9.0
From 1d0601d1ec7d1ffcd14fd233d4f4769e862680bc Mon Sep 17 00:00:00 2001
From: FernetMenta <fernetmenta@online.de>
Date: Thu, 5 Jul 2012 15:02:00 +0200
Subject: [PATCH 12/93] 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 6f57a87..d77cb2a 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
@@ -212,6 +216,7 @@ bool CWinEventsX11Imp::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
@@ -275,6 +280,13 @@ bool CWinEventsX11Imp::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;
}
@@ -297,6 +309,15 @@ bool CWinEventsX11Imp::HasStructureChanged()
return ret;
}
+void CWinEventsX11Imp::SetXRRFailSafeTimer(int millis)
+{
+ if (!WinEvents)
+ return;
+
+ WinEvents->m_xrrFailSafeTimer.Set(millis);
+ WinEvents->m_xrrEventPending = true;
+}
+
bool CWinEventsX11Imp::MessagePump()
{
if (!WinEvents)
@@ -556,10 +577,31 @@ bool CWinEventsX11Imp::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 ce57c23..a412f32 100644
--- a/xbmc/windowing/WinEventsX11.h
+++ b/xbmc/windowing/WinEventsX11.h
@@ -40,6 +40,8 @@ public:
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();
static size_t GetQueueSize();
@@ -62,4 +64,7 @@ protected:
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 304dac8..16b13aa 100644
--- a/xbmc/windowing/X11/WinSystemX11.cpp
+++ b/xbmc/windowing/X11/WinSystemX11.cpp
@@ -510,7 +510,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;
@@ -566,8 +566,12 @@ void CWinSystemX11::OnLostDevice()
(*i)->OnLostDevice();
}
+#if defined(HAS_SDL_VIDEO_X11)
// fail safe timer
m_dpyLostTime = CurrentHostCounter();
+#else
+ CWinEventsX11Imp::SetXRRFailSafeTimer(3000);
+#endif
}
void CWinSystemX11::Register(IDispResource *resource)
--
1.9.0
From 3181b919ca96f6837dde69a178ebb43112dff734 Mon Sep 17 00:00:00 2001
From: FernetMenta <fernetmenta@online.de>
Date: Thu, 12 Apr 2012 15:43:56 +0200
Subject: [PATCH 13/93] 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 16b13aa..f61d425 100644
--- a/xbmc/windowing/X11/WinSystemX11.cpp
+++ b/xbmc/windowing/X11/WinSystemX11.cpp
@@ -80,9 +80,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 0ac17ab..7e06655 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 0aec487..00b49dc 100644
--- a/xbmc/windowing/X11/XRandR.h
+++ b/xbmc/windowing/X11/XRandR.h
@@ -99,7 +99,6 @@ public:
bool SetMode(XOutput output, XMode mode);
void LoadCustomModeLinesToAllOutputs(void);
void SaveState();
- void RestoreState();
//bool Has1080i();
//bool Has1080p();
//bool Has720p();
--
1.9.0
From 65e877e82067a917e683c5930b2dc3840693f3ea Mon Sep 17 00:00:00 2001
From: xbmc <fernetmenta@online.de>
Date: Sun, 20 May 2012 13:17:10 +0200
Subject: [PATCH 14/93] xrandr: observe orientation
---
xbmc/windowing/X11/WinSystemX11.cpp | 89 ++++++++++++++++++++++++++++++-------
xbmc/windowing/X11/WinSystemX11.h | 2 +
xbmc/windowing/X11/XRandR.cpp | 7 +++
xbmc/windowing/X11/XRandR.h | 1 +
4 files changed, 82 insertions(+), 17 deletions(-)
diff --git a/xbmc/windowing/X11/WinSystemX11.cpp b/xbmc/windowing/X11/WinSystemX11.cpp
index f61d425..4257aeb 100644
--- a/xbmc/windowing/X11/WinSystemX11.cpp
+++ b/xbmc/windowing/X11/WinSystemX11.cpp
@@ -85,11 +85,11 @@ bool CWinSystemX11::DestroyWindowSystem()
{
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;
+ out.name = CDisplaySettings::Get().GetResolutionInfo(RES_DESKTOP).strOutput;
+ mode.w = CDisplaySettings::Get().GetResolutionInfo(RES_DESKTOP).iWidth;
+ mode.h = CDisplaySettings::Get().GetResolutionInfo(RES_DESKTOP).iHeight;
+ mode.hz = CDisplaySettings::Get().GetResolutionInfo(RES_DESKTOP).fRefreshRate;
+ mode.id = CDisplaySettings::Get().GetResolutionInfo(RES_DESKTOP).strId;
g_xrandr.SetMode(out, mode);
}
#endif
@@ -173,25 +173,34 @@ 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);
- g_settings.m_ResInfo[RES_DESKTOP].strId = mode.id;
- g_settings.m_ResInfo[RES_DESKTOP].strOutput = out.name;
+ if (!out.isRotated)
+ UpdateDesktopResolution(CDisplaySettings::Get().GetResolutionInfo(RES_DESKTOP), 0, mode.w, mode.h, mode.hz);
+ else
+ UpdateDesktopResolution(CDisplaySettings::Get().GetResolutionInfo(RES_DESKTOP), 0, mode.h, mode.w, mode.hz);
+ CDisplaySettings::Get().GetResolutionInfo(RES_DESKTOP).strId = mode.id;
+ CDisplaySettings::Get().GetResolutionInfo(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)
+ for (i = RES_DESKTOP; i < CDisplaySettings::Get().ResolutionInfoSize(); ++i)
{
- if (g_settings.m_ResInfo[i].strId == mode.id)
+ if (CDisplaySettings::Get().GetResolutionInfo(i).strId == mode.id)
{
found = true;
break;
@@ -227,16 +236,24 @@ bool CWinSystemX11::SetFullScreen(bool fullScreen, RESOLUTION_INFO& res, bool bl
}
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;
+ out.name = CDisplaySettings::Get().GetResolutionInfo(RES_DESKTOP).strOutput;
+ mode.w = CDisplaySettings::Get().GetResolutionInfo(RES_DESKTOP).iWidth;
+ mode.h = CDisplaySettings::Get().GetResolutionInfo(RES_DESKTOP).iHeight;
+ mode.hz = CDisplaySettings::Get().GetResolutionInfo(RES_DESKTOP).fRefreshRate;
+ mode.id = CDisplaySettings::Get().GetResolutionInfo(RES_DESKTOP).strId;
}
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)
@@ -269,7 +286,11 @@ void CWinSystemX11::UpdateResolutions()
{
XOutput out = g_xrandr.GetCurrentOutput();
XMode mode = g_xrandr.GetCurrentMode(out.name);
- UpdateDesktopResolution(CDisplaySettings::Get().GetResolutionInfo(RES_DESKTOP), 0, mode.w, mode.h, mode.hz);
+ m_bIsRotated = out.isRotated;
+ if (!m_bIsRotated)
+ UpdateDesktopResolution(CDisplaySettings::Get().GetResolutionInfo(RES_DESKTOP), 0, mode.w, mode.h, mode.hz);
+ else
+ UpdateDesktopResolution(CDisplaySettings::Get().GetResolutionInfo(RES_DESKTOP), 0, mode.h, mode.w, mode.hz);
CDisplaySettings::Get().GetResolutionInfo(RES_DESKTOP).strId = mode.id;
CDisplaySettings::Get().GetResolutionInfo(RES_DESKTOP).strOutput = out.name;
}
@@ -308,6 +329,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
@@ -335,6 +366,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 < CDisplaySettings::Get().ResolutionInfoSize(); ++i)
+ {
+ int width = CDisplaySettings::Get().GetResolutionInfo(i).iWidth;
+ CDisplaySettings::Get().GetResolutionInfo(i).iWidth = CDisplaySettings::Get().GetResolutionInfo(i).iHeight;
+ CDisplaySettings::Get().GetResolutionInfo(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 3f91b9b..4175aab 100644
--- a/xbmc/windowing/X11/WinSystemX11.h
+++ b/xbmc/windowing/X11/WinSystemX11.h
@@ -75,12 +75,14 @@ protected:
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 7e06655..330e945 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 00b49dc..508604d 100644
--- a/xbmc/windowing/X11/XRandR.h
+++ b/xbmc/windowing/X11/XRandR.h
@@ -86,6 +86,7 @@ public:
int wmm;
int hmm;
std::vector<XMode> modes;
+ bool isRotated;
};
class CXRandR
--
1.9.0
From 6c652b01707baa034c3dacd7e2a6c1a38385f514 Mon Sep 17 00:00:00 2001
From: FernetMenta <fernetmenta@online.de>
Date: Thu, 5 Jul 2012 11:54:15 +0200
Subject: [PATCH 15/93] 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 330e945..4685413 100644
--- a/xbmc/windowing/X11/XRandR.cpp
+++ b/xbmc/windowing/X11/XRandR.cpp
@@ -40,6 +40,7 @@ using namespace std;
CXRandR::CXRandR(bool query)
{
m_bInit = false;
+ m_numScreens = 1;
if (query)
Query();
}
@@ -56,11 +57,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)
@@ -80,7 +91,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 = output->Attribute("name");
StringUtils::Trim(xoutput.name);
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();
@@ -329,6 +329,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 508604d..d37838a 100644
--- a/xbmc/windowing/X11/XRandR.h
+++ b/xbmc/windowing/X11/XRandR.h
@@ -79,6 +79,7 @@ public:
}
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 @@ public:
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.9.0
From fec4134865c2071f80276d020f900307f45d8057 Mon Sep 17 00:00:00 2001
From: FernetMenta <fernetmenta@online.de>
Date: Thu, 5 Jul 2012 11:44:00 +0200
Subject: [PATCH 16/93] X11: fix multi-head setups
---
language/English/strings.po | 4 +-
system/settings/settings.xml | 11 ++
xbmc/rendering/gl/RenderSystemGL.h | 1 +
xbmc/settings/DisplaySettings.cpp | 44 ++++++-
xbmc/settings/DisplaySettings.h | 2 +
xbmc/settings/Settings.cpp | 6 +
xbmc/windowing/WinEventsX11.cpp | 7 +
xbmc/windowing/X11/WinSystemX11.cpp | 255 +++++++++++++++++++++---------------
xbmc/windowing/X11/WinSystemX11.h | 10 +-
9 files changed, 227 insertions(+), 113 deletions(-)
diff --git a/language/English/strings.po b/language/English/strings.po
index 6b1070d..d9b34e1 100755
--- a/language/English/strings.po
+++ b/language/English/strings.po
@@ -1021,7 +1021,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/system/settings/settings.xml b/system/settings/settings.xml
index c6b03b9..4882978 100644
--- a/system/settings/settings.xml
+++ b/system/settings/settings.xml
@@ -2250,6 +2250,15 @@
<section id="system" label="13000" help="36349">
<category id="videoscreen" label="21373" help="36603">
<group id="1">
+ <setting id="videoscreen.monitor" type="string" label="246" help="">
+ <visible>HAS_GLX</visible>
+ <level>0</level>
+ <default>Default</default>
+ <constraints>
+ <options>monitors</options>
+ </constraints>
+ <control type="spinner" format="string" delayed="true" />
+ </setting>
<setting id="videoscreen.screen" type="integer" label="240" help="36351">
<level>0</level>
<default>0</default>
@@ -2271,6 +2280,7 @@
<dependency type="enable" setting="videoscreen.screen" operator="!is">-1</dependency> <!-- DM_WINDOWED -->
<dependency type="update" setting="videoscreen.screen" />
<dependency type="update" setting="videoscreen.screenmode" />
+ <dependency type="update" setting="videoscreen.monitor" />
</dependencies>
<control type="list" format="string" />
</setting>
@@ -2288,6 +2298,7 @@
<dependency type="enable" setting="videoscreen.screen" operator="!is">-1</dependency> <!-- DM_WINDOWED -->
<dependency type="update" setting="videoscreen.screen" />
<dependency type="update" setting="videoscreen.resolution" />
+ <dependency type="update" setting="videoscreen.monitor" />
</dependencies>
<control type="spinner" format="string" delayed="true" />
</setting>
diff --git a/xbmc/rendering/gl/RenderSystemGL.h b/xbmc/rendering/gl/RenderSystemGL.h
index 4bd540b..f1e2c50 100644
--- a/xbmc/rendering/gl/RenderSystemGL.h
+++ b/xbmc/rendering/gl/RenderSystemGL.h
@@ -44,6 +44,7 @@ public:
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/DisplaySettings.cpp b/xbmc/settings/DisplaySettings.cpp
index c8c2bbd..966d08f 100644
--- a/xbmc/settings/DisplaySettings.cpp
+++ b/xbmc/settings/DisplaySettings.cpp
@@ -219,13 +219,19 @@ bool CDisplaySettings::OnSettingChanging(const CSetting *setting)
const std::string &settingId = setting->GetId();
if (settingId == "videoscreen.resolution" ||
- settingId == "videoscreen.screen")
+ settingId == "videoscreen.screen" ||
+ settingId == "videoscreen.monitor")
{
RESOLUTION newRes = RES_DESKTOP;
if (settingId == "videoscreen.resolution")
newRes = (RESOLUTION)((CSettingInt*)setting)->GetValue();
else if (settingId == "videoscreen.screen")
newRes = GetResolutionForScreen();
+ else if (settingId == "videoscreen.monitor")
+ {
+ g_Windowing.UpdateResolutions();
+ newRes = GetResolutionForScreen();
+ }
string screenmode = GetStringFromResolution(newRes);
CSettings::Get().SetString("videoscreen.screenmode", screenmode);
@@ -236,7 +242,11 @@ bool CDisplaySettings::OnSettingChanging(const CSetting *setting)
RESOLUTION newRes = GetResolutionFromString(((CSettingString*)setting)->GetValue());
SetCurrentResolution(newRes, false);
- g_graphicsContext.SetVideoResolution(newRes);
+ bool outputChanged = false;
+#if defined(HAS_GLX)
+ outputChanged = !g_Windowing.IsCurrentOutput(CSettings::Get().GetString("videoscreen.monitor"));
+#endif
+ g_graphicsContext.SetVideoResolution(newRes, outputChanged);
// check if the old or the new resolution was/is windowed
// in which case we don't show any prompt to the user
@@ -622,6 +632,10 @@ void CDisplaySettings::SettingOptionsScreensFiller(const CSetting *setting, std:
if (g_advancedSettings.m_canWindowed)
list.push_back(make_pair(g_localizeStrings.Get(242), DM_WINDOWED));
+#if defined(HAS_GLX)
+ list.push_back(make_pair(g_localizeStrings.Get(244), 0));
+#else
+
for (int idx = 0; idx < g_Windowing.GetNumScreens(); idx++)
{
int screen = CDisplaySettings::Get().GetResolutionInfo(RES_DESKTOP + idx).iScreen;
@@ -636,6 +650,7 @@ void CDisplaySettings::SettingOptionsScreensFiller(const CSetting *setting, std:
RESOLUTION_INFO resInfo = CDisplaySettings::Get().GetResolutionInfo(res);
current = resInfo.iScreen;
}
+#endif
}
void CDisplaySettings::SettingOptionsVerticalSyncsFiller(const CSetting *setting, std::vector< std::pair<std::string, int> > &list, int &current)
@@ -663,3 +678,28 @@ void CDisplaySettings::SettingOptionsPreferredStereoscopicViewModesFiller(const
SettingOptionsStereoscopicModesFiller(setting, list, current);
list.push_back(make_pair(g_localizeStrings.Get(36525), RENDER_STEREO_MODE_AUTO)); // option for autodetect
}
+
+void CDisplaySettings::SettingOptionsMonitorsFiller(const CSetting *setting, std::vector< std::pair<std::string, std::string> > &list, std::string &current)
+{
+#if defined(HAS_GLX)
+ std::vector<CStdString> monitors;
+ g_Windowing.GetConnectedOutputs(&monitors);
+ for (unsigned int i=0; i<monitors.size(); ++i)
+ {
+ if(CDisplaySettings::Get().GetResolutionInfo(RES_DESKTOP).strOutput.Equals(monitors[i]))
+ {
+ current = monitors[i];
+ }
+ list.push_back(make_pair(monitors[i], monitors[i]));
+ }
+#endif
+}
+
+void CDisplaySettings::ClearCustomResolutions()
+{
+ if (m_resolutions.size() > RES_CUSTOM)
+ {
+ std::vector<RESOLUTION_INFO>::iterator firstCustom = m_resolutions.begin()+RES_CUSTOM;
+ m_resolutions.erase(firstCustom, m_resolutions.end());
+ }
+}
diff --git a/xbmc/settings/DisplaySettings.h b/xbmc/settings/DisplaySettings.h
index 8ee1be2..bead24b 100644
--- a/xbmc/settings/DisplaySettings.h
+++ b/xbmc/settings/DisplaySettings.h
@@ -78,6 +78,7 @@ public:
void ApplyCalibrations();
void UpdateCalibrations();
+ void ClearCustomResolutions();
float GetZoomAmount() const { return m_zoomAmount; }
void SetZoomAmount(float zoomAmount) { m_zoomAmount = zoomAmount; }
@@ -95,6 +96,7 @@ public:
static void SettingOptionsVerticalSyncsFiller(const CSetting *setting, std::vector< std::pair<std::string, int> > &list, int &current);
static void SettingOptionsStereoscopicModesFiller(const CSetting *setting, std::vector< std::pair<std::string, int> > &list, int &current);
static void SettingOptionsPreferredStereoscopicViewModesFiller(const CSetting *setting, std::vector< std::pair<std::string, int> > &list, int &current);
+ static void SettingOptionsMonitorsFiller(const CSetting *setting, std::vector< std::pair<std::string, std::string> > &list, std::string &current);
protected:
CDisplaySettings();
diff --git a/xbmc/settings/Settings.cpp b/xbmc/settings/Settings.cpp
index 892a139..1037ddb 100644
--- a/xbmc/settings/Settings.cpp
+++ b/xbmc/settings/Settings.cpp
@@ -406,6 +406,7 @@ void CSettings::Uninitialize()
m_settingsManager->UnregisterSettingOptionsFiller("screens");
m_settingsManager->UnregisterSettingOptionsFiller("stereoscopicmodes");
m_settingsManager->UnregisterSettingOptionsFiller("preferedstereoscopicviewmodes");
+ m_settingsManager->UnregisterSettingOptionsFiller("monitors");
m_settingsManager->UnregisterSettingOptionsFiller("shutdownstates");
m_settingsManager->UnregisterSettingOptionsFiller("startupwindows");
m_settingsManager->UnregisterSettingOptionsFiller("streamlanguages");
@@ -835,6 +836,7 @@ void CSettings::InitializeOptionFillers()
m_settingsManager->RegisterSettingOptionsFiller("screens", CDisplaySettings::SettingOptionsScreensFiller);
m_settingsManager->RegisterSettingOptionsFiller("stereoscopicmodes", CDisplaySettings::SettingOptionsStereoscopicModesFiller);
m_settingsManager->RegisterSettingOptionsFiller("preferedstereoscopicviewmodes", CDisplaySettings::SettingOptionsPreferredStereoscopicViewModesFiller);
+ m_settingsManager->RegisterSettingOptionsFiller("monitors", CDisplaySettings::SettingOptionsMonitorsFiller);
m_settingsManager->RegisterSettingOptionsFiller("shutdownstates", CPowerManager::SettingOptionsShutdownStatesFiller);
m_settingsManager->RegisterSettingOptionsFiller("startupwindows", ADDON::CSkinInfo::SettingOptionsStartupWindowsFiller);
m_settingsManager->RegisterSettingOptionsFiller("streamlanguages", CLangInfo::SettingOptionsStreamLanguagesFiller);
@@ -865,6 +867,9 @@ void CSettings::InitializeConditions()
#ifdef HAS_GL
m_settingsManager->AddCondition("has_gl");
#endif
+#ifdef HAS_GLX
+ m_settingsManager->AddCondition("has_glx");
+#endif
#ifdef HAS_GLES
m_settingsManager->AddCondition("has_gles");
#endif
@@ -1017,6 +1022,7 @@ void CSettings::InitializeISettingCallbacks()
settingSet.insert("videoscreen.screen");
settingSet.insert("videoscreen.resolution");
settingSet.insert("videoscreen.screenmode");
+ settingSet.insert("videoscreen.monitor");
m_settingsManager->RegisterCallback(&CDisplaySettings::Get(), settingSet);
settingSet.clear();
diff --git a/xbmc/windowing/WinEventsX11.cpp b/xbmc/windowing/WinEventsX11.cpp
index d77cb2a..d98f12f 100644
--- a/xbmc/windowing/WinEventsX11.cpp
+++ b/xbmc/windowing/WinEventsX11.cpp
@@ -526,9 +526,16 @@ bool CWinEventsX11Imp::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 4257aeb..5e86772 100644
--- a/xbmc/windowing/X11/WinSystemX11.cpp
+++ b/xbmc/windowing/X11/WinSystemX11.cpp
@@ -36,6 +36,8 @@
#include "cores/VideoRenderers/RenderManager.h"
#include "utils/TimeUtils.h"
#include "utils/StringUtils.h"
+#include "settings/Settings.h"
+#include "windowing/WindowingFactory.h"
#if defined(HAS_XRANDR)
#include <X11/extensions/Xrandr.h>
@@ -57,6 +59,7 @@ CWinSystemX11::CWinSystemX11() : CWinSystemBase()
m_bIgnoreNextFocusMessage = false;
m_dpyLostTime = 0;
m_invisibleCursor = 0;
+ m_bIsInternalXrr = false;
XSetErrorHandler(XErrorHandler);
}
@@ -69,7 +72,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");
@@ -106,6 +110,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().
@@ -128,7 +134,10 @@ bool CWinSystemX11::DestroyWindow()
return true;
if (m_glContext)
+ {
+ glFinish();
glXMakeCurrent(m_dpy, None, NULL);
+ }
if (m_invisibleCursor)
{
@@ -158,7 +167,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, CSettings::Get().GetString("videoscreen.monitor")))
{
return false;
}
@@ -167,58 +176,11 @@ bool CWinSystemX11::ResizeWindow(int newWidth, int newHeight, int newLeft, int n
m_nWidth = newWidth;
m_nHeight = newHeight;
m_bFullScreen = false;
+ m_currentOutput = CSettings::Get().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(CDisplaySettings::Get().GetResolutionInfo(RES_DESKTOP), 0, mode.w, mode.h, mode.hz);
- else
- UpdateDesktopResolution(CDisplaySettings::Get().GetResolutionInfo(RES_DESKTOP), 0, mode.h, mode.w, mode.hz);
- CDisplaySettings::Get().GetResolutionInfo(RES_DESKTOP).strId = mode.id;
- CDisplaySettings::Get().GetResolutionInfo(RES_DESKTOP).strOutput = out.name;
- }
-
- RESOLUTION_INFO res;
- unsigned int i;
- bool found(false);
- for (i = RES_DESKTOP; i < CDisplaySettings::Get().ResolutionInfoSize(); ++i)
- {
- if (CDisplaySettings::Get().GetResolutionInfo(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)
{
@@ -243,8 +205,7 @@ bool CWinSystemX11::SetFullScreen(bool fullScreen, RESOLUTION_INFO& res, bool bl
mode.id = CDisplaySettings::Get().GetResolutionInfo(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)
@@ -255,16 +216,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, CSettings::Get().GetString("videoscreen.monitor")))
return false;
RefreshGlxContext();
@@ -272,6 +234,7 @@ bool CWinSystemX11::SetFullScreen(bool fullScreen, RESOLUTION_INFO& res, bool bl
m_nWidth = res.iWidth;
m_nHeight = res.iHeight;
m_bFullScreen = fullScreen;
+ m_currentOutput = CSettings::Get().GetString("videoscreen.monitor");
return true;
}
@@ -280,19 +243,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 = CSettings::Get().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);
+ CSettings::Get().SetString("videoscreen.monitor", currentMonitor);
+ }
+ XMode mode = g_xrandr.GetCurrentMode(currentMonitor);
+ m_bIsRotated = out->isRotated;
if (!m_bIsRotated)
- UpdateDesktopResolution(CDisplaySettings::Get().GetResolutionInfo(RES_DESKTOP), 0, mode.w, mode.h, mode.hz);
+ UpdateDesktopResolution(CDisplaySettings::Get().GetResolutionInfo(RES_DESKTOP), out->screen, mode.w, mode.h, mode.hz);
else
- UpdateDesktopResolution(CDisplaySettings::Get().GetResolutionInfo(RES_DESKTOP), 0, mode.h, mode.w, mode.hz);
+ UpdateDesktopResolution(CDisplaySettings::Get().GetResolutionInfo(RES_DESKTOP), out->screen, mode.h, mode.w, mode.hz);
CDisplaySettings::Get().GetResolutionInfo(RES_DESKTOP).strId = mode.id;
- CDisplaySettings::Get().GetResolutionInfo(RES_DESKTOP).strOutput = out.name;
+ CDisplaySettings::Get().GetResolutionInfo(RES_DESKTOP).strOutput = currentMonitor;
}
else
#endif
@@ -303,23 +277,22 @@ void CWinSystemX11::UpdateResolutions()
UpdateDesktopResolution(CDisplaySettings::Get().GetResolutionInfo(RES_DESKTOP), 0, w, h, 0.0);
}
-
#if defined(HAS_XRANDR)
+ // erase previous stored modes
+ CDisplaySettings::Get().ClearCustomResolutions();
+
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",
@@ -339,8 +312,8 @@ 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;
@@ -366,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 < CDisplaySettings::Get().ResolutionInfoSize(); ++i)
+ vector<XOutput> outs;
+ outs = g_xrandr.GetModes();
+ for(unsigned int i=0; i<outs.size(); ++i)
{
- int width = CDisplaySettings::Get().GetResolutionInfo(i).iWidth;
- CDisplaySettings::Get().GetResolutionInfo(i).iWidth = CDisplaySettings::Get().GetResolutionInfo(i).iHeight;
- CDisplaySettings::Get().GetResolutionInfo(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)
@@ -417,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;
}
@@ -484,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
@@ -525,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;
@@ -608,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 = CSettings::Get().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 < CDisplaySettings::Get().ResolutionInfoSize(); ++i)
+ {
+ if (CDisplaySettings::Get().GetResolutionInfo(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);
}
@@ -667,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)
@@ -696,6 +727,7 @@ bool CWinSystemX11::SetWindow(int width, int height, bool fullscreen)
else
mouseActive = false;
}
+ OnLostDevice();
DestroyWindow();
}
@@ -717,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));
@@ -733,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);
@@ -804,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 4175aab..94584ab 100644
--- a/xbmc/windowing/X11/WinSystemX11.h
+++ b/xbmc/windowing/X11/WinSystemX11.h
@@ -67,15 +67,16 @@ public:
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;
@@ -90,6 +91,9 @@ protected:
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.9.0
From bf5648cf0df4279b2135f65d39542258de32a307 Mon Sep 17 00:00:00 2001
From: FernetMenta <fernetmenta@online.de>
Date: Thu, 5 Jul 2012 11:36:32 +0200
Subject: [PATCH 17/93] 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 5e86772..c4fa17c 100644
--- a/xbmc/windowing/X11/WinSystemX11.cpp
+++ b/xbmc/windowing/X11/WinSystemX11.cpp
@@ -271,7 +271,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(CDisplaySettings::Get().GetResolutionInfo(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 94584ab..2bcaf52 100644
--- a/xbmc/windowing/X11/WinSystemX11.h
+++ b/xbmc/windowing/X11/WinSystemX11.h
@@ -49,6 +49,7 @@ public:
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 6383754..21e7dc5 100644
--- a/xbmc/windowing/X11/WinSystemX11GL.cpp
+++ b/xbmc/windowing/X11/WinSystemX11GL.cpp
@@ -167,7 +167,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.9.0
From 140a3ba6605aaba862ee004e78ff96aa84e0b8d9 Mon Sep 17 00:00:00 2001
From: FernetMenta <fernetmenta@online.de>
Date: Thu, 5 Jul 2012 11:45:22 +0200
Subject: [PATCH 18/93] 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 0b3950a..ca43b5a 100644
--- a/xbmc/video/VideoReferenceClock.cpp
+++ b/xbmc/video/VideoReferenceClock.cpp
@@ -271,7 +271,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.9.0
From bccf49bf686d33cf16db5f99e013a71e2c3a2373 Mon Sep 17 00:00:00 2001
From: xbmc <fernetmenta@online.de>
Date: Wed, 20 Jun 2012 17:37:11 +0200
Subject: [PATCH 19/93] 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 c4fa17c..f2fd18d 100644
--- a/xbmc/windowing/X11/WinSystemX11.cpp
+++ b/xbmc/windowing/X11/WinSystemX11.cpp
@@ -172,7 +172,6 @@ bool CWinSystemX11::ResizeWindow(int newWidth, int newHeight, int newLeft, int n
return false;
}
- RefreshGlxContext();
m_nWidth = newWidth;
m_nHeight = newHeight;
m_bFullScreen = false;
@@ -223,14 +222,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, CSettings::Get().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 2bcaf52..9666cc3 100644
--- a/xbmc/windowing/X11/WinSystemX11.h
+++ b/xbmc/windowing/X11/WinSystemX11.h
@@ -95,6 +95,7 @@ protected:
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 21e7dc5..8e68d5d 100644
--- a/xbmc/windowing/X11/WinSystemX11GL.cpp
+++ b/xbmc/windowing/X11/WinSystemX11GL.cpp
@@ -24,6 +24,7 @@
#include "WinSystemX11GL.h"
#include "utils/log.h"
#include "utils/StringUtils.h"
+#include "Application.h"
CWinSystemX11GL::CWinSystemX11GL()
{
@@ -197,17 +198,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.9.0
From 639f0284a947daac02be7bf2e727226f3f2c1526 Mon Sep 17 00:00:00 2001
From: FernetMenta <fernetmenta@online.de>
Date: Thu, 5 Jul 2012 12:06:25 +0200
Subject: [PATCH 20/93] 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 ca43b5a..0ddf102 100644
--- a/xbmc/video/VideoReferenceClock.cpp
+++ b/xbmc/video/VideoReferenceClock.cpp
@@ -136,12 +136,23 @@ CVideoReferenceClock::CVideoReferenceClock() : CThread("VideoReferenceClock")
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;
@@ -152,6 +163,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)
{
@@ -212,6 +227,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(TARGET_WINDOWS) && defined(HAS_DX)
CleanupD3D();
#elif defined(TARGET_DARWIN)
@@ -223,6 +248,9 @@ void CVideoReferenceClock::Process()
#if defined(TARGET_WINDOWS) && defined(HAS_DX)
g_Windowing.Unregister(&m_D3dCallback);
#endif
+#if defined(HAS_GLX)
+ g_Windowing.Unregister(this);
+#endif
}
bool CVideoReferenceClock::WaitStarted(int MSecs)
@@ -232,6 +260,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 dd65a1b..afd71fc 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(TARGET_WINDOWS) && 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.9.0
From f6ca378b58cabe46334742050fe263a98ac64f94 Mon Sep 17 00:00:00 2001
From: xbmc <fernetmenta@online.de>
Date: Thu, 21 Jun 2012 17:26:51 +0200
Subject: [PATCH 21/93] X11: fix video calibrations
---
xbmc/windowing/WinSystem.h | 1 +
xbmc/windowing/X11/WinSystemX11.cpp | 36 +++++++++++++++++++++++++++++++++++-
xbmc/windowing/X11/WinSystemX11.h | 1 +
3 files changed, 37 insertions(+), 1 deletion(-)
diff --git a/xbmc/windowing/WinSystem.h b/xbmc/windowing/WinSystem.h
index 00a2d24..c0db210 100644
--- a/xbmc/windowing/WinSystem.h
+++ b/xbmc/windowing/WinSystem.h
@@ -103,6 +103,7 @@ public:
std::vector<RESOLUTION_WHR> ScreenResolutions(int screen, float refreshrate);
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; };
// text input interface
virtual void EnableTextInput(bool bEnable) {}
diff --git a/xbmc/windowing/X11/WinSystemX11.cpp b/xbmc/windowing/X11/WinSystemX11.cpp
index f2fd18d..c4152c8 100644
--- a/xbmc/windowing/X11/WinSystemX11.cpp
+++ b/xbmc/windowing/X11/WinSystemX11.cpp
@@ -320,7 +320,7 @@ void CWinSystemX11::UpdateResolutions()
res.strMode = StringUtils::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()
CDisplaySettings::Get().AddResolutionInfo(res);
}
}
+ CDisplaySettings::Get().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 9666cc3..5b52d6c 100644
--- a/xbmc/windowing/X11/WinSystemX11.h
+++ b/xbmc/windowing/X11/WinSystemX11.h
@@ -63,6 +63,7 @@ public:
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.9.0
From c329e543adfd4989b6e53f936200f552ab90a369 Mon Sep 17 00:00:00 2001
From: FernetMenta <fernetmenta@online.de>
Date: Thu, 5 Jul 2012 12:00:26 +0200
Subject: [PATCH 22/93] 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 c4152c8..b76b229 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 5b52d6c..b2bd5a0 100644
--- a/xbmc/windowing/X11/WinSystemX11.h
+++ b/xbmc/windowing/X11/WinSystemX11.h
@@ -53,6 +53,7 @@ public:
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.9.0
From d157d02acb752b074e9691f5b75bd55363dc5528 Mon Sep 17 00:00:00 2001
From: FernetMenta <fernetmenta@online.de>
Date: Thu, 5 Jul 2012 12:10:09 +0200
Subject: [PATCH 23/93] 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 b76b229..869baa8 100644
--- a/xbmc/windowing/X11/WinSystemX11.cpp
+++ b/xbmc/windowing/X11/WinSystemX11.cpp
@@ -38,6 +38,7 @@
#include "utils/StringUtils.h"
#include "settings/Settings.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.9.0
From 237a8d20a027e2fd3dfeb145aca32bff0525903a Mon Sep 17 00:00:00 2001
From: xbmc <fernetmenta@online.de>
Date: Thu, 28 Jun 2012 19:12:39 +0200
Subject: [PATCH 24/93] 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 d98f12f..743aca9 100644
--- a/xbmc/windowing/WinEventsX11.cpp
+++ b/xbmc/windowing/WinEventsX11.cpp
@@ -368,6 +368,8 @@ bool CWinEventsX11Imp::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);
@@ -379,6 +381,7 @@ bool CWinEventsX11Imp::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.9.0
From d86f85ddac13b7d104add8cac02c362f7a4fab28 Mon Sep 17 00:00:00 2001
From: Joakim Plate <elupus@xbmc.org>
Date: Thu, 5 Jul 2012 14:18:46 +0200
Subject: [PATCH 25/93] 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 743aca9..6b98e67 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"
@@ -170,7 +171,6 @@ CWinEventsX11Imp::CWinEventsX11Imp()
m_display = 0;
m_window = 0;
m_keybuf = 0;
- m_utf16buf = 0;
}
CWinEventsX11Imp::~CWinEventsX11Imp()
@@ -181,12 +181,6 @@ CWinEventsX11Imp::~CWinEventsX11Imp()
m_keybuf = 0;
}
- if (m_utf16buf)
- {
- free(m_utf16buf);
- m_utf16buf = 0;
- }
-
if (m_xic)
{
XUnsetICFocus(m_xic);
@@ -212,7 +206,6 @@ bool CWinEventsX11Imp::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;
@@ -442,8 +435,6 @@ bool CWinEventsX11Imp::MessagePump()
}
Status status;
- int utf16size;
- int utf16length;
int len;
len = Xutf8LookupString(WinEvents->m_xic, &xevent.xkey,
WinEvents->m_keybuf, sizeof(WinEvents->m_keybuf),
@@ -462,36 +453,29 @@ bool CWinEventsX11Imp::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;
@@ -762,87 +746,6 @@ bool CWinEventsX11Imp::ProcessKeyRepeat()
return false;
}
-int CWinEventsX11Imp::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 CWinEventsX11Imp::LookupXbmcKeySym(KeySym keysym)
{
// try direct mapping first
diff --git a/xbmc/windowing/WinEventsX11.h b/xbmc/windowing/WinEventsX11.h
index a412f32..9a8a912 100644
--- a/xbmc/windowing/WinEventsX11.h
+++ b/xbmc/windowing/WinEventsX11.h
@@ -46,7 +46,6 @@ public:
static size_t GetQueueSize();
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();
@@ -56,7 +55,6 @@ protected:
Window m_window;
Atom m_wmDeleteMessage;
char *m_keybuf;
- uint16_t *m_utf16buf;
XIM m_xim;
XIC m_xic;
XBMC_Event m_lastKey;
--
1.9.0
From 196db63b99d44b058a6b1fdd80798afbaab4435f Mon Sep 17 00:00:00 2001
From: Joakim Plate <elupus@xbmc.org>
Date: Thu, 5 Jul 2012 14:23:54 +0200
Subject: [PATCH 26/93] 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 6b98e67..a62521f 100644
--- a/xbmc/windowing/WinEventsX11.cpp
+++ b/xbmc/windowing/WinEventsX11.cpp
@@ -171,6 +171,7 @@ CWinEventsX11Imp::CWinEventsX11Imp()
m_display = 0;
m_window = 0;
m_keybuf = 0;
+ m_keybuf_len = 0;
}
CWinEventsX11Imp::~CWinEventsX11Imp()
@@ -205,7 +206,8 @@ bool CWinEventsX11Imp::Init(Display *dpy, Window win)
WinEvents = new CWinEventsX11Imp();
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;
@@ -437,13 +439,14 @@ bool CWinEventsX11Imp::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 9a8a912..c69169c 100644
--- a/xbmc/windowing/WinEventsX11.h
+++ b/xbmc/windowing/WinEventsX11.h
@@ -55,6 +55,7 @@ protected:
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.9.0
From 3ccc149a56b520df7a8933b889273296ba875090 Mon Sep 17 00:00:00 2001
From: xbmc <fernetmenta@online.de>
Date: Sat, 9 Jun 2012 18:23:53 +0200
Subject: [PATCH 27/93] 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 d57f4d3..b807897 100644
--- a/xbmc/input/XBMC_keytable.cpp
+++ b/xbmc/input/XBMC_keytable.cpp
@@ -180,6 +180,8 @@ static const XBMCKEYTABLE XBMCKeyTable[] =
, { 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.9.0
From 2b820efe0e7850414b31495b9569e6dac6e90a28 Mon Sep 17 00:00:00 2001
From: xbmc <fernetmenta@online.de>
Date: Fri, 16 Mar 2012 15:57:51 +0100
Subject: [PATCH 28/93] 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 0ddf102..3ae7107 100644
--- a/xbmc/video/VideoReferenceClock.cpp
+++ b/xbmc/video/VideoReferenceClock.cpp
@@ -136,7 +136,7 @@ CVideoReferenceClock::CVideoReferenceClock() : CThread("VideoReferenceClock")
m_Context = NULL;
m_pixmap = None;
m_glPixmap = None;
- m_UseNvSettings = true;
+ m_UseNvSettings = false;
m_bIsATI = false;
#endif
}
--
1.9.0
From cd2f165acc58eaa519b48cdb53a6b5a4a8120be0 Mon Sep 17 00:00:00 2001
From: xbmc <fernetmenta@online.de>
Date: Mon, 20 Aug 2012 09:09:09 +0200
Subject: [PATCH 29/93] 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 3ae7107..27bebde 100644
--- a/xbmc/video/VideoReferenceClock.cpp
+++ b/xbmc/video/VideoReferenceClock.cpp
@@ -31,6 +31,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.9.0
From 603317efd971a1f90d15ebb5c8bc381912b710e2 Mon Sep 17 00:00:00 2001
From: xbmc <fernetmenta@online.de>
Date: Mon, 9 Jul 2012 14:00:18 +0200
Subject: [PATCH 30/93] 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 869baa8..bfe3797 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.9.0
From 14680a3fd13af0a41b43899fdf3a2da65abad5f4 Mon Sep 17 00:00:00 2001
From: xbmc <fernetmenta@online.de>
Date: Tue, 10 Jul 2012 11:14:12 +0200
Subject: [PATCH 31/93] 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 bfe3797..af82061 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 b2bd5a0..3e62cd8 100644
--- a/xbmc/windowing/X11/WinSystemX11.h
+++ b/xbmc/windowing/X11/WinSystemX11.h
@@ -103,6 +103,7 @@ private:
bool IsSuitableVisual(XVisualInfo *vInfo);
static int XErrorHandler(Display* dpy, XErrorEvent* error);
bool CreateIconPixmap();
+ bool HasWindowManager();
CStopWatch m_screensaverReset;
};
--
1.9.0
From 0665385b9d92a49c75403273444d898589ec4185 Mon Sep 17 00:00:00 2001
From: xbmc <fernetmenta@online.de>
Date: Thu, 12 Jul 2012 11:11:47 +0200
Subject: [PATCH 32/93] 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 af82061..4f33c68 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 = CSettings::Get().GetString("videoscreen.monitor");
--
1.9.0
From 2d78ed515c437b4dd082d585f2d06778bcb5cb03 Mon Sep 17 00:00:00 2001
From: xbmc <fernetmenta@online.de>
Date: Thu, 26 Jul 2012 09:34:28 +0200
Subject: [PATCH 33/93] 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 4f33c68..bc4e963 100644
--- a/xbmc/windowing/X11/WinSystemX11.cpp
+++ b/xbmc/windowing/X11/WinSystemX11.cpp
@@ -223,7 +223,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.9.0
From 8e45aca353568d3b1119aaae29d63ce10f76ca70 Mon Sep 17 00:00:00 2001
From: xbmc <fernetmenta@online.de>
Date: Sat, 15 Sep 2012 18:27:29 +0200
Subject: [PATCH 34/93] 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 bc4e963..57a8d20 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.9.0
From 7cecb116072ee9dd7893f3eef06a11c2c4811294 Mon Sep 17 00:00:00 2001
From: xbmc <fernetmenta@online.de>
Date: Mon, 20 Aug 2012 16:06:39 +0200
Subject: [PATCH 35/93] dvdplayer: observe pts counter overflow
---
.../cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp | 197 ++++++++++++++++++++-
xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.h | 4 +
2 files changed, 200 insertions(+), 1 deletion(-)
diff --git a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp
index 1146c6f..16efae0 100644
--- a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp
+++ b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp
@@ -18,7 +18,6 @@
*
*/
-#include "system.h"
#ifndef __STDC_CONSTANT_MACROS
#define __STDC_CONSTANT_MACROS
#endif
@@ -26,6 +25,7 @@
#define __STDC_LIMIT_MACROS
#endif
#ifdef TARGET_POSIX
+#include "system.h"
#include "stdint.h"
#endif
#include "DVDDemuxFFmpeg.h"
@@ -489,6 +489,9 @@ bool CDVDDemuxFFmpeg::Open(CDVDInputStream* pInput)
CreateStreams();
+ m_bPtsWrapChecked = false;
+ m_bPtsWrap = false;
+
return true;
}
@@ -634,6 +637,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;
@@ -773,6 +782,24 @@ DemuxPacket* CDVDDemuxFFmpeg::Read()
m_pkt.pkt.pts = AV_NOPTS_VALUE;
}
+ if (!m_bPtsWrapChecked && m_pFormatContext->iformat->flags & AVFMT_TS_DISCONT)
+ {
+ int defaultStream = 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 = m_pkt.pkt.size;
@@ -905,7 +932,16 @@ bool CDVDDemuxFFmpeg::SeekTime(int time, bool backwords, double *startpts)
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)
@@ -924,6 +960,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 = av_find_default_stream_index(m_pFormatContext);
+
+ if (defaultStream < 0)
+ {
+ return false;
+ }
+
+ // timestamp for default must be expressed in AV_TIME_BASE units
+ pts = 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 = 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)
{
CSingleLock lock(m_critSection);
diff --git a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.h b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.h
index aef5ab1..35abbdf 100644
--- a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.h
+++ b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.h
@@ -100,6 +100,7 @@ public:
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);
@@ -158,5 +159,8 @@ protected:
AVPacket pkt; // packet ffmpeg returned
int result; // result from av_read_packet
}m_pkt;
+
+ bool m_bPtsWrap, m_bPtsWrapChecked;
+ int64_t m_iStartTime, m_iMaxTime, m_iEndTime;
};
--
1.9.0
From a2b098917cab5f9db00c69177792c373547f2bb8 Mon Sep 17 00:00:00 2001
From: xbmc <fernetmenta@online.de>
Date: Tue, 2 Oct 2012 13:02:10 +0200
Subject: [PATCH 36/93] dvdplayer: avoid short screen flicker caused by
unnecessary reconfigure of renderer
---
xbmc/cores/dvdplayer/DVDPlayerVideo.cpp | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp
index 9c36bdb..322a581 100644
--- a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp
+++ b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp
@@ -1054,13 +1054,16 @@ int CDVDPlayerVideo::OutputPicture(const DVDVideoPicture* src, double pts)
#ifdef HAS_VIDEO_PLAYBACK
double config_framerate = m_bFpsInvalid ? 0.0 : m_fFrameRate;
+ double render_framerate = g_graphicsContext.GetFPS();
+ if (CSettings::Get().GetInt("videoplayer.adjustrefreshrate") == ADJUST_REFRESHRATE_OFF)
+ render_framerate = config_framerate;
/* check so that our format or aspect has changed. if it has, reconfigure renderer */
if (!g_renderManager.IsConfigured()
|| ( m_output.width != pPicture->iWidth )
|| ( 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 && render_framerate != config_framerate)
|| ( 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
--
1.9.0
From a67d385916ef70447e5167ca352f9f53de7e2778 Mon Sep 17 00:00:00 2001
From: xbmc <fernetmenta@online.de>
Date: Thu, 11 Oct 2012 12:05:50 +0200
Subject: [PATCH 37/93] 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 b4d2d38..cd72cc6 100644
--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp
+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp
@@ -1987,10 +1987,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 eff43dd..7532914 100644
--- a/xbmc/settings/AdvancedSettings.cpp
+++ b/xbmc/settings/AdvancedSettings.cpp
@@ -163,6 +163,8 @@ void CAdvancedSettings::Initialize()
m_videoAutoScaleMaxFps = 30.0f;
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;
@@ -600,6 +602,8 @@ void CAdvancedSettings::ParseSettingsFile(const CStdString &file)
XMLUtils::GetBoolean(pElement,"disablehi10pmultithreading",m_videoDisableHi10pMultithreading);
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 3995f35..c43351d 100644
--- a/xbmc/settings/AdvancedSettings.h
+++ b/xbmc/settings/AdvancedSettings.h
@@ -160,6 +160,8 @@ class CAdvancedSettings : public ISettingCallback, public ISettingsHandler
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.9.0
From 56a0e9d6cb08dcecbfdea964b99996c59ebd0c91 Mon Sep 17 00:00:00 2001
From: xbmc <fernetmenta@online.de>
Date: Fri, 2 Nov 2012 13:20:03 +0100
Subject: [PATCH 38/93] player: fix rewind
---
xbmc/cores/dvdplayer/DVDMessage.h | 5 ++++-
xbmc/cores/dvdplayer/DVDPlayer.cpp | 30 +++++++++++++++++++-----------
xbmc/cores/dvdplayer/DVDPlayer.h | 7 ++++---
xbmc/cores/dvdplayer/DVDPlayerVideo.cpp | 4 +++-
xbmc/cores/dvdplayer/DVDPlayerVideo.h | 1 +
5 files changed, 31 insertions(+), 16 deletions(-)
diff --git a/xbmc/cores/dvdplayer/DVDMessage.h b/xbmc/cores/dvdplayer/DVDMessage.h
index 2ea8b8f..e8274f9 100644
--- a/xbmc/cores/dvdplayer/DVDMessage.h
+++ b/xbmc/cores/dvdplayer/DVDMessage.h
@@ -220,7 +220,7 @@ private:
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)
@@ -228,6 +228,7 @@ public:
, m_accurate(accurate)
, m_restore(restore)
, m_trickplay(trickplay)
+ , m_sync(sync)
{}
int GetTime() { return m_time; }
bool GetBackward() { return m_backward; }
@@ -235,6 +236,7 @@ public:
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;
@@ -242,6 +244,7 @@ private:
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 0d2b4ae..a4c0422 100644
--- a/xbmc/cores/dvdplayer/DVDPlayer.cpp
+++ b/xbmc/cores/dvdplayer/DVDPlayer.cpp
@@ -1634,11 +1634,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
@@ -1657,7 +1659,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));
}
}
}
@@ -2143,7 +2145,7 @@ void CDVDPlayer::HandleMessages()
else
m_StateInput.dts = start;
- FlushBuffers(!msg.GetFlush(), start, msg.GetAccurate());
+ FlushBuffers(!msg.GetFlush(), start, msg.GetAccurate(), msg.GetSync());
}
else
CLog::Log(LOGWARNING, "error while seeking");
@@ -2279,9 +2281,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();
}
@@ -2297,7 +2300,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
@@ -3293,7 +3297,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)
@@ -3305,19 +3309,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;
@@ -3361,7 +3369,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 e2a836b..6ecaf3f 100644
--- a/xbmc/cores/dvdplayer/DVDPlayer.h
+++ b/xbmc/cores/dvdplayer/DVDPlayer.h
@@ -308,7 +308,7 @@ protected:
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();
@@ -357,8 +357,9 @@ protected:
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 322a581..9c5469b 100644
--- a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp
+++ b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp
@@ -1470,7 +1470,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;
@@ -1570,6 +1570,8 @@ int CDVDPlayerVideo::CalcDropRequirement(double pts)
int iSkippedDeint = 0;
int iBufferLevel;
+ m_droppingStats.m_lastPts = pts;
+
// get decoder stats
if (!m_pVideoCodec->GetCodecStats(iDecoderPts, iSkippedDeint, interlaced))
iDecoderPts = pts;
diff --git a/xbmc/cores/dvdplayer/DVDPlayerVideo.h b/xbmc/cores/dvdplayer/DVDPlayerVideo.h
index 59c7f09..65dea76 100644
--- a/xbmc/cores/dvdplayer/DVDPlayerVideo.h
+++ b/xbmc/cores/dvdplayer/DVDPlayerVideo.h
@@ -50,6 +50,7 @@ public:
double m_totalGain;
double m_lastDecoderPts;
double m_lastRenderPts;
+ double m_lastPts;
unsigned int m_lateFrames;
unsigned int m_dropRequests;
};
--
1.9.0
From b209430c56ad955fb164c88cf4696a5ab1f162db Mon Sep 17 00:00:00 2001
From: xbmc <fernetmenta@online.de>
Date: Fri, 23 Nov 2012 17:41:12 +0100
Subject: [PATCH 39/93] 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 4685413..e610150 100644
--- a/xbmc/windowing/X11/XRandR.cpp
+++ b/xbmc/windowing/X11/XRandR.cpp
@@ -58,12 +58,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)
@@ -71,7 +73,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.9.0
From 8d42739f0833403d688d7da9676d098ad3be45c6 Mon Sep 17 00:00:00 2001
From: xbmc <fernetmenta@online.de>
Date: Sun, 2 Dec 2012 15:46:55 +0100
Subject: [PATCH 40/93] 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 57a8d20..a237dc0 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.9.0
From ef3118362dcf019e927700e59f0cc4e7a0d506b1 Mon Sep 17 00:00:00 2001
From: xbmc <fernetmenta@online.de>
Date: Tue, 11 Dec 2012 11:08:13 +0100
Subject: [PATCH 41/93] 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 a237dc0..ab660b1 100644
--- a/xbmc/windowing/X11/WinSystemX11.cpp
+++ b/xbmc/windowing/X11/WinSystemX11.cpp
@@ -112,7 +112,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.9.0
From da4c24ede3be3b5c074c44123e83e9059c25688d 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 42/93] 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 e610150..5c53574 100644
--- a/xbmc/windowing/X11/XRandR.cpp
+++ b/xbmc/windowing/X11/XRandR.cpp
@@ -93,7 +93,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.9.0
From c7215a8c352ad44a928a9d18f89ebf52c8dcf9fc Mon Sep 17 00:00:00 2001
From: xbmc <fernetmenta@online.de>
Date: Mon, 24 Dec 2012 16:02:42 +0100
Subject: [PATCH 43/93] 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 e5f8234..96c9e89 100644
--- a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxPVRClient.cpp
+++ b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxPVRClient.cpp
@@ -339,9 +339,7 @@ void CDVDDemuxPVRClient::RequestStreams()
if (stm)
{
st = dynamic_cast<CDemuxStreamAudioPVRClient*>(stm);
- if (!st
- || (st->codec != (AVCodecID)props.stream[i].iCodecId)
- || (st->iChannels != props.stream[i].iChannels))
+ if (!st || (st->codec != (AVCodecID)props.stream[i].iCodecId))
DisposeStream(i);
}
if (!m_streams[i])
@@ -358,6 +356,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 == XBMC_CODEC_TYPE_VIDEO)
{
--
1.9.0
From 26da0298234aeea96c4df4d3317589abb822cf1b Mon Sep 17 00:00:00 2001
From: xbmc <fernetmenta@online.de>
Date: Thu, 17 Jan 2013 16:03:22 +0100
Subject: [PATCH 44/93] 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 a62521f..263cb5a 100644
--- a/xbmc/windowing/WinEventsX11.cpp
+++ b/xbmc/windowing/WinEventsX11.cpp
@@ -143,6 +143,7 @@ static uint32_t SymMappingsX11[][2] =
, {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.9.0
From b0d730552ceac8e144436e96e9a88fe28e565ef6 Mon Sep 17 00:00:00 2001
From: xbmc <fernetmenta@online.de>
Date: Mon, 21 Jan 2013 09:00:19 +0100
Subject: [PATCH 45/93] 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 590a887..35b5a21 100644
--- a/xbmc/powermanagement/PowerManager.cpp
+++ b/xbmc/powermanagement/PowerManager.cpp
@@ -268,11 +268,6 @@ void CPowerManager::OnWake()
#if defined(TARGET_WINDOWS)
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.9.0
From 876139f6eb64b5e72689d5fe6a9bf65f60070b2e Mon Sep 17 00:00:00 2001
From: xbmc <fernetmenta@online.de>
Date: Wed, 23 Jan 2013 17:03:02 +0100
Subject: [PATCH 46/93] 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 5c53574..4355ef7 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.9.0
From 4262d964615f251d99d6d773d5fa9a96f5230053 Mon Sep 17 00:00:00 2001
From: xbmc <fernetmenta@online.de>
Date: Wed, 23 Jan 2013 17:03:39 +0100
Subject: [PATCH 47/93] 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 ab660b1..4329a22 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 3e62cd8..2a1fb41 100644
--- a/xbmc/windowing/X11/WinSystemX11.h
+++ b/xbmc/windowing/X11/WinSystemX11.h
@@ -76,7 +76,7 @@ public:
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.9.0
From 76bab5ec893f9534f50f38474b22a56300307631 Mon Sep 17 00:00:00 2001
From: xbmc <fernetmenta@online.de>
Date: Fri, 14 Dec 2012 14:19:15 +0100
Subject: [PATCH 48/93] pvr: do not show selection dialog for a single menu
hook
---
xbmc/pvr/addons/PVRClients.cpp | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/xbmc/pvr/addons/PVRClients.cpp b/xbmc/pvr/addons/PVRClients.cpp
index 14c9cde..57b18a5 100644
--- a/xbmc/pvr/addons/PVRClients.cpp
+++ b/xbmc/pvr/addons/PVRClients.cpp
@@ -733,6 +733,7 @@ void CPVRClients::ProcessMenuHooks(int iClientID, PVR_MENUHOOK_CAT cat, const CF
{
hooks = client->GetMenuHooks();
std::vector<int> hookIDs;
+ int selection = 0;
CGUIDialogSelect* pDialog = (CGUIDialogSelect*)g_windowManager.GetWindow(WINDOW_DIALOG_SELECT);
pDialog->Reset();
@@ -743,9 +744,11 @@ void CPVRClients::ProcessMenuHooks(int iClientID, PVR_MENUHOOK_CAT cat, const CF
pDialog->Add(client->GetString(hooks->at(i).iLocalizedStringId));
hookIDs.push_back(i);
}
- pDialog->DoModal();
-
- int selection = pDialog->GetSelectedLabel();
+ if (hookIDs.size() > 1)
+ {
+ pDialog->DoModal();
+ selection = pDialog->GetSelectedLabel();
+ }
if (selection >= 0)
client->CallMenuHook(hooks->at(hookIDs.at(selection)), item);
}
--
1.9.0
From 2069a5213f76e57a558189b52f098af75d9c21cf Mon Sep 17 00:00:00 2001
From: xbmc <fernetmenta@online.de>
Date: Sun, 3 Feb 2013 08:17:16 +0100
Subject: [PATCH 49/93] X11: use default screen parameters if no output
connected
---
xbmc/windowing/X11/WinSystemX11.cpp | 55 ++++++++++++++++++++++---------------
1 file changed, 33 insertions(+), 22 deletions(-)
diff --git a/xbmc/windowing/X11/WinSystemX11.cpp b/xbmc/windowing/X11/WinSystemX11.cpp
index 4329a22..2adf8a0 100644
--- a/xbmc/windowing/X11/WinSystemX11.cpp
+++ b/xbmc/windowing/X11/WinSystemX11.cpp
@@ -207,25 +207,27 @@ bool CWinSystemX11::SetFullScreen(bool fullScreen, RESOLUTION_INFO& res, bool bl
}
XMode currmode = g_xrandr.GetCurrentMode(out.name);
-
- // flip h/w when rotated
- if (m_bIsRotated)
+ if (!currmode.name.empty())
{
- int w = mode.w;
- mode.w = mode.h;
- mode.h = w;
- }
+ // 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 (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);
- if (m_glWindow)
- return true;
+ // only call xrandr if mode changes
+ 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);
+ if (m_glWindow)
+ return true;
+ }
}
#endif
@@ -272,9 +274,10 @@ void CWinSystemX11::UpdateResolutions()
else
#endif
{
- int x11screen = m_nScreen;
- int w = DisplayWidth(m_dpy, x11screen);
- int h = DisplayHeight(m_dpy, x11screen);
+ CSettings::Get().SetString("videoscreen.monitor", "Default");
+ m_nScreen = DefaultScreen(m_dpy);
+ int w = DisplayWidth(m_dpy, m_nScreen);
+ int h = DisplayHeight(m_dpy, m_nScreen);
UpdateDesktopResolution(CDisplaySettings::Get().GetResolutionInfo(RES_DESKTOP), 0, w, h, 0.0);
}
@@ -819,11 +822,19 @@ bool CWinSystemX11::SetWindow(int width, int height, bool fullscreen, const CStd
Colormap cmap;
XSetWindowAttributes swa;
XVisualInfo *vi;
+ int x0 = 0;
+ int y0 = 0;
XOutput *out = g_xrandr.GetOutput(output);
if (!out)
out = g_xrandr.GetOutput(m_currentOutput);
- m_nScreen = out->screen;
+ if (out)
+ {
+ m_nScreen = out->screen;
+ x0 = out->x;
+ y0 = out->y;
+ }
+
vi = glXChooseVisual(m_dpy, m_nScreen, att);
cmap = XCreateColormap(m_dpy, RootWindow(m_dpy, vi->screen), vi->visual, AllocNone);
@@ -842,7 +853,7 @@ bool CWinSystemX11::SetWindow(int width, int height, bool fullscreen, const CStd
unsigned long mask = CWBackPixel | CWBorderPixel | CWColormap | CWOverrideRedirect | CWEventMask;
m_glWindow = XCreateWindow(m_dpy, RootWindow(m_dpy, vi->screen),
- out->x, out->y, width, height, 0, vi->depth,
+ x0, y0, width, height, 0, vi->depth,
InputOutput, vi->visual,
mask, &swa);
--
1.9.0
From aebb14e8a7d079871c69f31df00a0b894e9d5ef9 Mon Sep 17 00:00:00 2001
From: xbmc <fernetmenta@online.de>
Date: Sat, 23 Mar 2013 15:13:32 +0100
Subject: [PATCH 50/93] X11: create parent window
---
xbmc/windowing/X11/WinSystemX11.cpp | 69 +++++++++++++++++++++++--------------
xbmc/windowing/X11/WinSystemX11.h | 2 +-
2 files changed, 44 insertions(+), 27 deletions(-)
diff --git a/xbmc/windowing/X11/WinSystemX11.cpp b/xbmc/windowing/X11/WinSystemX11.cpp
index 2adf8a0..07f3f3d 100644
--- a/xbmc/windowing/X11/WinSystemX11.cpp
+++ b/xbmc/windowing/X11/WinSystemX11.cpp
@@ -55,6 +55,7 @@ CWinSystemX11::CWinSystemX11() : CWinSystemBase()
m_glContext = NULL;
m_dpy = NULL;
m_glWindow = 0;
+ m_mainWindow = 0;
m_bWasFullScreenBeforeMinimize = false;
m_minimized = false;
m_bIgnoreNextFocusMessage = false;
@@ -132,7 +133,7 @@ bool CWinSystemX11::CreateNewWindow(const CStdString& name, bool fullScreen, RES
bool CWinSystemX11::DestroyWindow()
{
- if (!m_glWindow)
+ if (!m_mainWindow)
return true;
if (m_glContext)
@@ -143,19 +144,21 @@ bool CWinSystemX11::DestroyWindow()
if (m_invisibleCursor)
{
- XUndefineCursor(m_dpy, m_glWindow);
+ XUndefineCursor(m_dpy, m_mainWindow);
XFreeCursor(m_dpy, m_invisibleCursor);
m_invisibleCursor = 0;
}
CWinEventsX11Imp::Quit();
- XUnmapWindow(m_dpy, m_glWindow);
+ XUnmapWindow(m_dpy, m_mainWindow);
XSync(m_dpy,TRUE);
XUngrabKeyboard(m_dpy, CurrentTime);
XUngrabPointer(m_dpy, CurrentTime);
XDestroyWindow(m_dpy, m_glWindow);
+ XDestroyWindow(m_dpy, m_mainWindow);
m_glWindow = 0;
+ m_mainWindow = 0;
if (m_icon)
XFreePixmap(m_dpy, m_icon);
@@ -225,7 +228,7 @@ bool CWinSystemX11::SetFullScreen(bool fullScreen, RESOLUTION_INFO& res, bool bl
OnLostDevice();
m_bIsInternalXrr = true;
g_xrandr.SetMode(out, mode);
- if (m_glWindow)
+ if (m_mainWindow)
return true;
}
}
@@ -503,9 +506,9 @@ bool CWinSystemX11::RefreshGlxContext(bool force)
void CWinSystemX11::ShowOSMouse(bool show)
{
if (show)
- XUndefineCursor(m_dpy,m_glWindow);
+ XUndefineCursor(m_dpy,m_mainWindow);
else if (m_invisibleCursor)
- XDefineCursor(m_dpy,m_glWindow, m_invisibleCursor);
+ XDefineCursor(m_dpy,m_mainWindow, m_invisibleCursor);
}
void CWinSystemX11::ResetOSScreensaver()
@@ -588,10 +591,10 @@ void CWinSystemX11::NotifyMouseCoverage(bool covered)
int result = -1;
while (result != GrabSuccess && result != AlreadyGrabbed)
{
- result = XGrabPointer(m_dpy, m_glWindow, True, ButtonPressMask, GrabModeAsync, GrabModeAsync, None, None, CurrentTime);
+ result = XGrabPointer(m_dpy, m_mainWindow, True, ButtonPressMask, GrabModeAsync, GrabModeAsync, None, None, CurrentTime);
XbmcThreads::ThreadSleep(100);
}
- XGrabKeyboard(m_dpy, m_glWindow, True, GrabModeAsync, GrabModeAsync, CurrentTime);
+ XGrabKeyboard(m_dpy, m_mainWindow, True, GrabModeAsync, GrabModeAsync, CurrentTime);
}
else
{
@@ -609,7 +612,7 @@ bool CWinSystemX11::Minimize()
g_graphicsContext.ToggleFullScreenRoot();
}
- XIconifyWindow(m_dpy, m_glWindow, m_nScreen);
+ XIconifyWindow(m_dpy, m_mainWindow, m_nScreen);
m_minimized = true;
return true;
@@ -620,13 +623,13 @@ bool CWinSystemX11::Restore()
}
bool CWinSystemX11::Hide()
{
- XUnmapWindow(m_dpy, m_glWindow);
+ XUnmapWindow(m_dpy, m_mainWindow);
XSync(m_dpy, False);
return true;
}
bool CWinSystemX11::Show(bool raise)
{
- XMapWindow(m_dpy, m_glWindow);
+ XMapWindow(m_dpy, m_mainWindow);
XSync(m_dpy, False);
m_minimized = false;
return true;
@@ -776,7 +779,7 @@ bool CWinSystemX11::SetWindow(int width, int height, bool fullscreen, const CStd
bool mouseActive = false;
float mouseX, mouseY;
- if (m_glWindow && ((m_bFullScreen != fullscreen) || !m_currentOutput.Equals(output) || m_windowDirty))
+ if (m_mainWindow && ((m_bFullScreen != fullscreen) || !m_currentOutput.Equals(output) || m_windowDirty))
{
mouseActive = g_Mouse.IsActive();
if (mouseActive)
@@ -785,7 +788,7 @@ bool CWinSystemX11::SetWindow(int width, int height, bool fullscreen, const CStd
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,
+ bool isInWin = XQueryPointer(m_dpy, m_mainWindow, &root_return, &child_return,
&root_x_return, &root_y_return,
&win_x_return, &win_y_return,
&mask_return);
@@ -804,7 +807,7 @@ bool CWinSystemX11::SetWindow(int width, int height, bool fullscreen, const CStd
}
// create main window
- if (!m_glWindow)
+ if (!m_mainWindow)
{
EnableSystemScreenSaver(false);
@@ -845,22 +848,31 @@ bool CWinSystemX11::SetWindow(int width, int height, bool fullscreen, const CStd
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),
+ m_mainWindow = XCreateWindow(m_dpy, RootWindow(m_dpy, vi->screen),
x0, y0, width, height, 0, vi->depth,
InputOutput, vi->visual,
mask, &swa);
+ swa.override_redirect = False;
+ swa.border_pixel = 0;
+ swa.event_mask = 0;
+ mask = CWBackPixel | CWBorderPixel | CWColormap | CWOverrideRedirect | CWColormap;
+
+ m_glWindow = XCreateWindow(m_dpy, m_mainWindow,
+ 0, 0, width, height, 0, vi->depth,
+ InputOutput, vi->visual,
+ mask, &swa);
+
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);
+ XChangeProperty(m_dpy, m_mainWindow, XInternAtom(m_dpy, "_NET_WM_STATE", True), XA_ATOM, 32, PropModeReplace, (unsigned char *) &fs, 1);
}
// define invisible cursor
@@ -869,14 +881,14 @@ bool CWinSystemX11::SetWindow(int width, int height, bool fullscreen, const CStd
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);
+ bitmapNoData = XCreateBitmapFromData(m_dpy, m_mainWindow, 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);
+ XDefineCursor(m_dpy,m_mainWindow, m_invisibleCursor);
//init X11 events
- CWinEventsX11Imp::Init(m_dpy, m_glWindow);
+ CWinEventsX11Imp::Init(m_dpy, m_mainWindow);
changeWindow = true;
changeSize = true;
@@ -889,13 +901,17 @@ bool CWinSystemX11::SetWindow(int width, int height, bool fullscreen, const CStd
if (changeSize || changeWindow)
{
+ XResizeWindow(m_dpy, m_mainWindow, width, height);
+ }
+
+ if ((width != m_nWidth) || (height != m_nHeight) || changeWindow)
+ {
XResizeWindow(m_dpy, m_glWindow, width, height);
}
if (changeWindow)
{
m_icon = None;
- if (!fullscreen)
{
CreateIconPixmap();
XWMHints *wm_hints;
@@ -912,21 +928,22 @@ bool CWinSystemX11::SetWindow(int width, int height, bool fullscreen, const CStd
wm_hints->flags = StateHint | IconPixmapHint;
XSync(m_dpy,False);
- XSetWMProperties(m_dpy, m_glWindow, &windowName, &iconName,
+ XSetWMProperties(m_dpy, m_mainWindow, &windowName, &iconName,
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);
- XSetWMProtocols(m_dpy, m_glWindow, &wmDeleteMessage, 1);
+ XSetWMProtocols(m_dpy, m_mainWindow, &wmDeleteMessage, 1);
}
XMapRaised(m_dpy, m_glWindow);
+ XMapRaised(m_dpy, m_mainWindow);
XSync(m_dpy,TRUE);
if (changeWindow && mouseActive)
{
- XWarpPointer(m_dpy, None, m_glWindow, 0, 0, 0, 0, mouseX*width, mouseY*height);
+ XWarpPointer(m_dpy, None, m_mainWindow, 0, 0, 0, 0, mouseX*width, mouseY*height);
}
if (fullscreen)
@@ -934,10 +951,10 @@ bool CWinSystemX11::SetWindow(int width, int height, bool fullscreen, const CStd
int result = -1;
while (result != GrabSuccess && result != AlreadyGrabbed)
{
- result = XGrabPointer(m_dpy, m_glWindow, True, ButtonPressMask, GrabModeAsync, GrabModeAsync, None, None, CurrentTime);
+ result = XGrabPointer(m_dpy, m_mainWindow, True, ButtonPressMask, GrabModeAsync, GrabModeAsync, None, None, CurrentTime);
XbmcThreads::ThreadSleep(100);
}
- XGrabKeyboard(m_dpy, m_glWindow, True, GrabModeAsync, GrabModeAsync, CurrentTime);
+ XGrabKeyboard(m_dpy, m_mainWindow, True, GrabModeAsync, GrabModeAsync, CurrentTime);
}
CDirtyRegionList dr;
diff --git a/xbmc/windowing/X11/WinSystemX11.h b/xbmc/windowing/X11/WinSystemX11.h
index 2a1fb41..e8993f1 100644
--- a/xbmc/windowing/X11/WinSystemX11.h
+++ b/xbmc/windowing/X11/WinSystemX11.h
@@ -81,7 +81,7 @@ protected:
void OnLostDevice();
bool SetWindow(int width, int height, bool fullscreen, const CStdString &output);
- Window m_glWindow;
+ Window m_glWindow, m_mainWindow;
GLXContext m_glContext;
Display* m_dpy;
Cursor m_invisibleCursor;
--
1.9.0
From ecc4546cbeef4193a0cf2bcad35357f3fcf6fcc8 Mon Sep 17 00:00:00 2001
From: xbmc <fernetmenta@online.de>
Date: Sun, 24 Mar 2013 12:30:12 +0100
Subject: [PATCH 51/93] X11: use system key repeat rate instead of hardcoded
one, taken from 58fd64b194e38b73b5f3132744bab35e994e7441
---
xbmc/windowing/WinEventsX11.cpp | 58 +++++++++++++----------------------------
xbmc/windowing/WinEventsX11.h | 5 +---
2 files changed, 19 insertions(+), 44 deletions(-)
diff --git a/xbmc/windowing/WinEventsX11.cpp b/xbmc/windowing/WinEventsX11.cpp
index 263cb5a..09f56ff 100644
--- a/xbmc/windowing/WinEventsX11.cpp
+++ b/xbmc/windowing/WinEventsX11.cpp
@@ -213,7 +213,6 @@ bool CWinEventsX11Imp::Init(Display *dpy, Window win)
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
char *old_locale = NULL, *old_modifiers = NULL;
@@ -328,20 +327,6 @@ bool CWinEventsX11Imp::MessagePump()
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;
@@ -364,7 +349,6 @@ bool CWinEventsX11Imp::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;
@@ -377,7 +361,6 @@ bool CWinEventsX11Imp::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;
@@ -433,7 +416,7 @@ bool CWinEventsX11Imp::MessagePump()
{
newEvent.key.keysym.unicode = keybuf[0];
}
- ret |= ProcessKey(newEvent, 500);
+ ret |= ProcessKey(newEvent);
break;
}
@@ -472,7 +455,7 @@ bool CWinEventsX11Imp::MessagePump()
newEvent.key.keysym.unicode = keys[i];
newEvent.key.state = xevent.xkey.state;
newEvent.key.type = xevent.xkey.type;
- ret |= ProcessKey(newEvent, 500);
+ ret |= ProcessKey(newEvent);
}
if (keys.length() > 0)
{
@@ -483,7 +466,7 @@ bool CWinEventsX11Imp::MessagePump()
newEvent.key.state = xevent.xkey.state;
newEvent.key.type = xevent.xkey.type;
- ret |= ProcessKey(newEvent, 500);
+ ret |= ProcessKey(newEvent);
}
break;
}
@@ -494,7 +477,7 @@ bool CWinEventsX11Imp::MessagePump()
newEvent.key.keysym.sym = LookupXbmcKeySym(xkeysym);
newEvent.key.state = xevent.xkey.state;
newEvent.key.type = xevent.xkey.type;
- ret |= ProcessKey(newEvent, 500);
+ ret |= ProcessKey(newEvent);
break;
}
@@ -504,6 +487,18 @@ bool CWinEventsX11Imp::MessagePump()
case KeyRelease:
{
+ // if we have a queued press directly after, this is a repeat
+ if( XEventsQueued( WinEvents->m_display, QueuedAfterReading ) )
+ {
+ XEvent next_event;
+ XPeekEvent( WinEvents->m_display, &next_event );
+ if(next_event.type == KeyPress
+ && next_event.xkey.window == xevent.xkey.window
+ && next_event.xkey.keycode == xevent.xkey.keycode
+ && (next_event.xkey.time - xevent.xkey.time < 2) )
+ continue;
+ }
+
XBMC_Event newEvent;
KeySym xkeysym;
memset(&newEvent, 0, sizeof(newEvent));
@@ -513,7 +508,7 @@ bool CWinEventsX11Imp::MessagePump()
newEvent.key.keysym.sym = LookupXbmcKeySym(xkeysym);
newEvent.key.state = xevent.xkey.state;
newEvent.key.type = xevent.xkey.type;
- ret |= ProcessKey(newEvent, 0);
+ ret |= ProcessKey(newEvent);
break;
}
@@ -589,8 +584,6 @@ bool CWinEventsX11Imp::MessagePump()
}// while
- ret |= ProcessKeyRepeat();
-
#if defined(HAS_XRANDR)
if (WinEvents && WinEvents->m_xrrEventPending && WinEvents->m_xrrFailSafeTimer.IsTimePast())
{
@@ -635,7 +628,7 @@ size_t CWinEventsX11Imp::GetQueueSize()
return ret;
}
-bool CWinEventsX11Imp::ProcessKey(XBMC_Event &event, int repeatDelay)
+bool CWinEventsX11Imp::ProcessKey(XBMC_Event &event)
{
if (event.type == XBMC_KEYDOWN)
{
@@ -673,8 +666,6 @@ bool CWinEventsX11Imp::ProcessKey(XBMC_Event &event, int repeatDelay)
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)
@@ -715,7 +706,6 @@ bool CWinEventsX11Imp::ProcessKey(XBMC_Event &event, int repeatDelay)
break;
}
event.key.keysym.mod = (XBMCMod)WinEvents->m_keymodState;
- memset(&(WinEvents->m_lastKey), 0, sizeof(event));
}
return g_application.OnEvent(event);
@@ -738,18 +728,6 @@ bool CWinEventsX11Imp::ProcessShortcuts(XBMC_Event& event)
return false;
}
-bool CWinEventsX11Imp::ProcessKeyRepeat()
-{
- if (WinEvents && (WinEvents->m_lastKey.type == XBMC_KEYDOWN))
- {
- if (WinEvents->m_repeatKeyTimeout.IsTimePast())
- {
- return ProcessKey(WinEvents->m_lastKey, 10);
- }
- }
- return false;
-}
-
XBMCKey CWinEventsX11Imp::LookupXbmcKeySym(KeySym keysym)
{
// try direct mapping first
diff --git a/xbmc/windowing/WinEventsX11.h b/xbmc/windowing/WinEventsX11.h
index c69169c..6429291 100644
--- a/xbmc/windowing/WinEventsX11.h
+++ b/xbmc/windowing/WinEventsX11.h
@@ -47,8 +47,7 @@ public:
protected:
static XBMCKey LookupXbmcKeySym(KeySym keysym);
- static bool ProcessKey(XBMC_Event &event, int repeatDelay);
- static bool ProcessKeyRepeat();
+ static bool ProcessKey(XBMC_Event &event);
static bool ProcessShortcuts(XBMC_Event& event);
static CWinEventsX11Imp *WinEvents;
Display *m_display;
@@ -58,8 +57,6 @@ protected:
size_t m_keybuf_len;
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;
--
1.9.0
From 4e3bbd52ba8c190b152d0ef21a8da4d3d512f056 Mon Sep 17 00:00:00 2001
From: xbmc <fernetmenta@online.de>
Date: Sun, 24 Mar 2013 16:04:48 +0100
Subject: [PATCH 52/93] linux: use CLOCK_MONOTONIC_RAW as this is not subject
to NTP
---
xbmc/threads/SystemClock.cpp | 2 +-
xbmc/utils/TimeUtils.cpp | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/xbmc/threads/SystemClock.cpp b/xbmc/threads/SystemClock.cpp
index 657a154..35e3abf 100644
--- a/xbmc/threads/SystemClock.cpp
+++ b/xbmc/threads/SystemClock.cpp
@@ -43,7 +43,7 @@ namespace XbmcThreads
now_time = (uint64_t)timeGetTime();
#else
struct timespec ts = {};
- clock_gettime(CLOCK_MONOTONIC, &ts);
+ clock_gettime(CLOCK_MONOTONIC_RAW, &ts);
now_time = (ts.tv_sec * 1000) + (ts.tv_nsec / 1000000);
#endif
if (!start_time_set)
diff --git a/xbmc/utils/TimeUtils.cpp b/xbmc/utils/TimeUtils.cpp
index c06b8c5..4390d2e 100644
--- a/xbmc/utils/TimeUtils.cpp
+++ b/xbmc/utils/TimeUtils.cpp
@@ -43,7 +43,7 @@ int64_t CurrentHostCounter(void)
return( (int64_t)PerformanceCount.QuadPart );
#else
struct timespec now;
- clock_gettime(CLOCK_MONOTONIC, &now);
+ clock_gettime(CLOCK_MONOTONIC_RAW, &now);
return( ((int64_t)now.tv_sec * 1000000000L) + now.tv_nsec );
#endif
}
--
1.9.0
From 6f70066f6cc093386d9cc087c3d089012b810f05 Mon Sep 17 00:00:00 2001
From: xbmc <fernetmenta@online.de>
Date: Thu, 28 Mar 2013 15:18:53 +0100
Subject: [PATCH 53/93] OMXPlayer: some caching fixes for pvr
---
xbmc/cores/omxplayer/OMXPlayer.cpp | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/xbmc/cores/omxplayer/OMXPlayer.cpp b/xbmc/cores/omxplayer/OMXPlayer.cpp
index a3d3928..7b81178 100644
--- a/xbmc/cores/omxplayer/OMXPlayer.cpp
+++ b/xbmc/cores/omxplayer/OMXPlayer.cpp
@@ -2556,7 +2556,8 @@ void COMXPlayer::HandleMessages()
m_messenger.Put(new CDVDMsgPlayerSeek(GetTime(), (speed < 0), true, false, false, true));
m_playSpeed = speed;
- m_caching = CACHESTATE_DONE;
+ if (m_caching != CACHESTATE_PVR && m_playSpeed != DVD_PLAYSPEED_NORMAL)
+ m_caching = CACHESTATE_DONE;
m_clock.SetSpeed(speed);
m_av_clock.OMXSetSpeed(speed);
m_av_clock.OMXPause();
--
1.9.0
From 73977466eae71113f367f88b3a6a39e2d2077089 Mon Sep 17 00:00:00 2001
From: xbmc <fernetmenta@online.de>
Date: Thu, 28 Mar 2013 20:50:59 +0100
Subject: [PATCH 54/93] fix incorrect display of fps when dr kicks in
---
xbmc/Application.cpp | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/xbmc/Application.cpp b/xbmc/Application.cpp
index 43c4517..4131707 100644
--- a/xbmc/Application.cpp
+++ b/xbmc/Application.cpp
@@ -2307,10 +2307,11 @@ void CApplication::Render()
if (frameTime < singleFrameTime)
Sleep(singleFrameTime - frameTime);
}
- m_lastFrameTime = XbmcThreads::SystemClockMillis();
if (flip)
g_graphicsContext.Flip(dirtyRegions);
+
+ m_lastFrameTime = XbmcThreads::SystemClockMillis();
CTimeUtils::UpdateFrameTime(flip);
g_renderManager.UpdateResolution();
--
1.9.0
From c0b389a1a384684536183067a0b514bbc9c24477 Mon Sep 17 00:00:00 2001
From: xbmc <fernetmenta@online.de>
Date: Sat, 13 Apr 2013 08:32:06 +0200
Subject: [PATCH 55/93] X11: fix mouse coverage
---
xbmc/windowing/X11/WinSystemX11.cpp | 11 ++++++++---
xbmc/windowing/X11/WinSystemX11.h | 1 +
2 files changed, 9 insertions(+), 3 deletions(-)
diff --git a/xbmc/windowing/X11/WinSystemX11.cpp b/xbmc/windowing/X11/WinSystemX11.cpp
index 07f3f3d..2acb36d 100644
--- a/xbmc/windowing/X11/WinSystemX11.cpp
+++ b/xbmc/windowing/X11/WinSystemX11.cpp
@@ -583,10 +583,10 @@ void CWinSystemX11::NotifyAppFocusChange(bool bGaining)
void CWinSystemX11::NotifyMouseCoverage(bool covered)
{
- if (!m_bFullScreen)
+ if (!m_bFullScreen || !m_mainWindow)
return;
- if (covered)
+ if (covered && !m_bIsGrabbed)
{
int result = -1;
while (result != GrabSuccess && result != AlreadyGrabbed)
@@ -595,11 +595,13 @@ void CWinSystemX11::NotifyMouseCoverage(bool covered)
XbmcThreads::ThreadSleep(100);
}
XGrabKeyboard(m_dpy, m_mainWindow, True, GrabModeAsync, GrabModeAsync, CurrentTime);
+ m_bIsGrabbed = true;
}
- else
+ else if (!covered && m_bIsGrabbed)
{
XUngrabKeyboard(m_dpy, CurrentTime);
XUngrabPointer(m_dpy, CurrentTime);
+ m_bIsGrabbed = false;
}
}
@@ -955,7 +957,10 @@ bool CWinSystemX11::SetWindow(int width, int height, bool fullscreen, const CStd
XbmcThreads::ThreadSleep(100);
}
XGrabKeyboard(m_dpy, m_mainWindow, True, GrabModeAsync, GrabModeAsync, CurrentTime);
+ m_bIsGrabbed = true;
}
+ else
+ m_bIsGrabbed = false;
CDirtyRegionList dr;
RefreshGlxContext(!m_currentOutput.Equals(output));
diff --git a/xbmc/windowing/X11/WinSystemX11.h b/xbmc/windowing/X11/WinSystemX11.h
index e8993f1..5cccfb7 100644
--- a/xbmc/windowing/X11/WinSystemX11.h
+++ b/xbmc/windowing/X11/WinSystemX11.h
@@ -90,6 +90,7 @@ protected:
bool m_bWasFullScreenBeforeMinimize;
bool m_minimized;
bool m_bIgnoreNextFocusMessage;
+ bool m_bIsGrabbed;
int m_RREventBase;
CCriticalSection m_resourceSection;
std::vector<IDispResource*> m_resources;
--
1.9.0
From 884c573f53a288c206bd13348ce3e60dae0cb564 Mon Sep 17 00:00:00 2001
From: Rainer Hochecker <fernetmenta@online.de>
Date: Wed, 8 May 2013 13:14:58 +0200
Subject: [PATCH 56/93] X11: fix incorrectly used screen num in desktop
resolution
---
xbmc/windowing/X11/WinSystemX11.cpp | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/xbmc/windowing/X11/WinSystemX11.cpp b/xbmc/windowing/X11/WinSystemX11.cpp
index 2acb36d..101ba98 100644
--- a/xbmc/windowing/X11/WinSystemX11.cpp
+++ b/xbmc/windowing/X11/WinSystemX11.cpp
@@ -268,9 +268,9 @@ void CWinSystemX11::UpdateResolutions()
XMode mode = g_xrandr.GetCurrentMode(currentMonitor);
m_bIsRotated = out->isRotated;
if (!m_bIsRotated)
- UpdateDesktopResolution(CDisplaySettings::Get().GetResolutionInfo(RES_DESKTOP), out->screen, mode.w, mode.h, mode.hz);
+ UpdateDesktopResolution(CDisplaySettings::Get().GetResolutionInfo(RES_DESKTOP), 0, mode.w, mode.h, mode.hz);
else
- UpdateDesktopResolution(CDisplaySettings::Get().GetResolutionInfo(RES_DESKTOP), out->screen, mode.h, mode.w, mode.hz);
+ UpdateDesktopResolution(CDisplaySettings::Get().GetResolutionInfo(RES_DESKTOP), 0, mode.h, mode.w, mode.hz);
CDisplaySettings::Get().GetResolutionInfo(RES_DESKTOP).strId = mode.id;
CDisplaySettings::Get().GetResolutionInfo(RES_DESKTOP).strOutput = currentMonitor;
}
@@ -305,6 +305,7 @@ void CWinSystemX11::UpdateResolutions()
CLog::Log(LOGINFO, "ID:%s Name:%s Refresh:%f Width:%d Height:%d",
mode.id.c_str(), mode.name.c_str(), mode.hz, mode.w, mode.h);
RESOLUTION_INFO res;
+ res.iScreen = 0; // not used by X11
res.iWidth = mode.w;
res.iHeight = mode.h;
res.iScreenWidth = mode.w;
--
1.9.0
From 836500221bf270ed628d35468a28873c96d41764 Mon Sep 17 00:00:00 2001
From: Rainer Hochecker <fernetmenta@online.de>
Date: Thu, 9 May 2013 12:07:09 +0200
Subject: [PATCH 57/93] X11: do not overwrite user selected monitor with
fallback
---
xbmc/windowing/X11/WinSystemX11.cpp | 31 ++++++++++++++-----------------
xbmc/windowing/X11/WinSystemX11.h | 1 +
2 files changed, 15 insertions(+), 17 deletions(-)
diff --git a/xbmc/windowing/X11/WinSystemX11.cpp b/xbmc/windowing/X11/WinSystemX11.cpp
index 101ba98..c614c9b 100644
--- a/xbmc/windowing/X11/WinSystemX11.cpp
+++ b/xbmc/windowing/X11/WinSystemX11.cpp
@@ -172,7 +172,7 @@ bool CWinSystemX11::ResizeWindow(int newWidth, int newHeight, int newLeft, int n
&& m_nHeight == newHeight)
return true;
- if (!SetWindow(newWidth, newHeight, false, CSettings::Get().GetString("videoscreen.monitor")))
+ if (!SetWindow(newWidth, newHeight, false, m_userOutput))
{
return false;
}
@@ -180,7 +180,7 @@ bool CWinSystemX11::ResizeWindow(int newWidth, int newHeight, int newLeft, int n
m_nWidth = newWidth;
m_nHeight = newHeight;
m_bFullScreen = false;
- m_currentOutput = CSettings::Get().GetString("videoscreen.monitor");
+ m_currentOutput = m_userOutput;
return false;
}
@@ -234,13 +234,13 @@ bool CWinSystemX11::SetFullScreen(bool fullScreen, RESOLUTION_INFO& res, bool bl
}
#endif
- if (!SetWindow(res.iWidth, res.iHeight, fullScreen, CSettings::Get().GetString("videoscreen.monitor")))
+ if (!SetWindow(res.iWidth, res.iHeight, fullScreen, m_userOutput))
return false;
m_nWidth = res.iWidth;
m_nHeight = res.iHeight;
m_bFullScreen = fullScreen;
- m_currentOutput = CSettings::Get().GetString("videoscreen.monitor");
+ m_currentOutput = m_userOutput;
return true;
}
@@ -250,34 +250,32 @@ void CWinSystemX11::UpdateResolutions()
CWinSystemBase::UpdateResolutions();
#if defined(HAS_XRANDR)
- CStdString currentMonitor;
int numScreens = XScreenCount(m_dpy);
g_xrandr.SetNumScreens(numScreens);
if(g_xrandr.Query(true))
{
- currentMonitor = CSettings::Get().GetString("videoscreen.monitor");
+ m_userOutput = CSettings::Get().GetString("videoscreen.monitor");
// check if the monitor is connected
- XOutput *out = g_xrandr.GetOutput(currentMonitor);
+ XOutput *out = g_xrandr.GetOutput(m_userOutput);
if (!out)
{
// choose first output
- currentMonitor = g_xrandr.GetModes()[0].name;
- out = g_xrandr.GetOutput(currentMonitor);
- CSettings::Get().SetString("videoscreen.monitor", currentMonitor);
+ m_userOutput = g_xrandr.GetModes()[0].name;
+ out = g_xrandr.GetOutput(m_userOutput);
}
- XMode mode = g_xrandr.GetCurrentMode(currentMonitor);
+ XMode mode = g_xrandr.GetCurrentMode(m_userOutput);
m_bIsRotated = out->isRotated;
if (!m_bIsRotated)
UpdateDesktopResolution(CDisplaySettings::Get().GetResolutionInfo(RES_DESKTOP), 0, mode.w, mode.h, mode.hz);
else
UpdateDesktopResolution(CDisplaySettings::Get().GetResolutionInfo(RES_DESKTOP), 0, mode.h, mode.w, mode.hz);
CDisplaySettings::Get().GetResolutionInfo(RES_DESKTOP).strId = mode.id;
- CDisplaySettings::Get().GetResolutionInfo(RES_DESKTOP).strOutput = currentMonitor;
+ CDisplaySettings::Get().GetResolutionInfo(RES_DESKTOP).strOutput = m_userOutput;
}
else
#endif
{
- CSettings::Get().SetString("videoscreen.monitor", "Default");
+ m_userOutput = "No Output";
m_nScreen = DefaultScreen(m_dpy);
int w = DisplayWidth(m_dpy, m_nScreen);
int h = DisplayHeight(m_dpy, m_nScreen);
@@ -291,7 +289,7 @@ void CWinSystemX11::UpdateResolutions()
CLog::Log(LOGINFO, "Available videomodes (xrandr):");
- XOutput *out = g_xrandr.GetOutput(currentMonitor);
+ XOutput *out = g_xrandr.GetOutput(m_userOutput);
string modename = "";
if (out != NULL)
@@ -691,9 +689,8 @@ void CWinSystemX11::NotifyXRREvent()
}
m_bIsInternalXrr = false;
- CStdString currentOutput = CSettings::Get().GetString("videoscreen.monitor");
- XOutput *out = g_xrandr.GetOutput(currentOutput);
- XMode mode = g_xrandr.GetCurrentMode(currentOutput);
+ XOutput *out = g_xrandr.GetOutput(m_userOutput);
+ XMode mode = g_xrandr.GetCurrentMode(m_userOutput);
if (out)
CLog::Log(LOGDEBUG, "%s - current output: %s, mode: %s, refresh: %.3f", __FUNCTION__
diff --git a/xbmc/windowing/X11/WinSystemX11.h b/xbmc/windowing/X11/WinSystemX11.h
index 5cccfb7..1b658e2 100644
--- a/xbmc/windowing/X11/WinSystemX11.h
+++ b/xbmc/windowing/X11/WinSystemX11.h
@@ -96,6 +96,7 @@ protected:
std::vector<IDispResource*> m_resources;
uint64_t m_dpyLostTime;
CStdString m_currentOutput;
+ CStdString m_userOutput;
bool m_windowDirty;
bool m_bIsInternalXrr;
bool m_newGlContext;
--
1.9.0
From 01061c02fe55c312e6e7e4b56f9cc29760ce547d Mon Sep 17 00:00:00 2001
From: Rainer Hochecker <fernetmenta@online.de>
Date: Sun, 12 May 2013 10:50:30 +0200
Subject: [PATCH 58/93] xrandr: add turn on/off to wrapper
---
xbmc/windowing/X11/XRandR.cpp | 78 +++++++++++++++++++++++++++++++++++++++----
xbmc/windowing/X11/XRandR.h | 6 ++--
2 files changed, 75 insertions(+), 9 deletions(-)
diff --git a/xbmc/windowing/X11/XRandR.cpp b/xbmc/windowing/X11/XRandR.cpp
index 4355ef7..223472c 100644
--- a/xbmc/windowing/X11/XRandR.cpp
+++ b/xbmc/windowing/X11/XRandR.cpp
@@ -29,6 +29,7 @@
#include "utils/XBMCTinyXML.h"
#include "utils/StringUtils.h"
#include "../xbmc/utils/log.h"
+#include "threads/SystemClock.h"
#if defined(TARGET_FREEBSD)
#include <sys/types.h>
@@ -45,7 +46,7 @@ CXRandR::CXRandR(bool query)
Query();
}
-bool CXRandR::Query(bool force)
+bool CXRandR::Query(bool force, bool ignoreoff)
{
if (!force)
if (m_bInit)
@@ -62,13 +63,13 @@ bool CXRandR::Query(bool force)
bool success = false;
for(unsigned int screennum=0; screennum<m_numScreens; ++screennum)
{
- if(Query(force, screennum))
+ if(Query(force, screennum, ignoreoff))
success = true;
}
return success;
}
-bool CXRandR::Query(bool force, int screennum)
+bool CXRandR::Query(bool force, int screennum, bool ignoreoff)
{
CStdString cmd;
cmd = getenv("XBMC_BIN_HOME");
@@ -136,11 +137,9 @@ bool CXRandR::Query(bool force, int screennum)
xmode.isCurrent = (strcasecmp(mode->Attribute("current"), "true") == 0);
xoutput.modes.push_back(xmode);
if (xmode.isCurrent)
- {
hascurrent = true;
- }
}
- if (hascurrent)
+ if (hascurrent || !ignoreoff)
m_outputs.push_back(xoutput);
else
CLog::Log(LOGWARNING, "CXRandR::Query - output %s has no current mode, assuming disconnected", xoutput.name.c_str());
@@ -148,6 +147,71 @@ bool CXRandR::Query(bool force, int screennum)
return m_outputs.size() > 0;
}
+bool CXRandR::TurnOffOutput(CStdString name)
+{
+ CStdString cmd;
+ cmd = getenv("XBMC_BIN_HOME");
+ cmd += "/xbmc-xrandr";
+ cmd.AppendFormat(" --output %s --off", name.c_str());
+
+ int status = system(cmd.c_str());
+ if (status == -1)
+ return false;
+
+ if (WEXITSTATUS(status) != 0)
+ return false;
+
+ return true;
+}
+
+bool CXRandR::TurnOnOutput(CStdString name)
+{
+ XOutput *output = GetOutput(name);
+ if (!output)
+ return false;
+
+ XMode mode = GetCurrentMode(output->name);
+ if (mode.isCurrent)
+ return true;
+
+ // get preferred mode
+ for (unsigned int j = 0; j < m_outputs.size(); j++)
+ {
+ if (m_outputs[j].name == output->name)
+ {
+ for (unsigned int i = 0; i < m_outputs[j].modes.size(); i++)
+ {
+ if (m_outputs[j].modes[i].isPreferred)
+ {
+ mode = m_outputs[j].modes[i];
+ break;
+ }
+ }
+ }
+ }
+
+ if (!mode.isPreferred)
+ return false;
+
+ if (!SetMode(*output, mode))
+ return false;
+
+ XbmcThreads::EndTime timeout(5000);
+ while (!timeout.IsTimePast())
+ {
+ if (!Query(true))
+ return false;
+
+ output = GetOutput(name);
+ if (output && output->h > 0)
+ return true;
+
+ Sleep(200);
+ }
+
+ return false;
+}
+
std::vector<XOutput> CXRandR::GetModes(void)
{
Query();
@@ -161,7 +225,7 @@ void CXRandR::SaveState()
bool CXRandR::SetMode(XOutput output, XMode mode)
{
- if ((output.name == m_currentOutput && mode.id == m_currentMode) || (output.name == "" && mode.id == ""))
+ if ((output.name == "" && mode.id == ""))
return true;
Query();
diff --git a/xbmc/windowing/X11/XRandR.h b/xbmc/windowing/X11/XRandR.h
index d37838a..059062f 100644
--- a/xbmc/windowing/X11/XRandR.h
+++ b/xbmc/windowing/X11/XRandR.h
@@ -94,8 +94,8 @@ class CXRandR
{
public:
CXRandR(bool query=false);
- bool Query(bool force=false);
- bool Query(bool force, int screennum);
+ bool Query(bool force=false, bool ignoreoff=true);
+ bool Query(bool force, int screennum, bool ignoreoff=true);
std::vector<XOutput> GetModes(void);
XMode GetCurrentMode(CStdString outputName);
XOutput *GetOutput(CStdString outputName);
@@ -104,6 +104,8 @@ public:
void SaveState();
void SetNumScreens(unsigned int num);
bool IsOutputConnected(CStdString name);
+ bool TurnOffOutput(CStdString name);
+ bool TurnOnOutput(CStdString name);
//bool Has1080i();
//bool Has1080p();
//bool Has720p();
--
1.9.0
From fa66d3ddccf1c807feea602bd334b9adbc12ffe8 Mon Sep 17 00:00:00 2001
From: Rainer Hochecker <fernetmenta@online.de>
Date: Sun, 19 May 2013 12:55:35 +0200
Subject: [PATCH 59/93] xrandr: add GetPreferredMode to wrapper
---
xbmc/windowing/X11/XRandR.cpp | 23 +++++++++++++++++++++++
xbmc/windowing/X11/XRandR.h | 1 +
2 files changed, 24 insertions(+)
diff --git a/xbmc/windowing/X11/XRandR.cpp b/xbmc/windowing/X11/XRandR.cpp
index 223472c..62003f5 100644
--- a/xbmc/windowing/X11/XRandR.cpp
+++ b/xbmc/windowing/X11/XRandR.cpp
@@ -347,6 +347,29 @@ XMode CXRandR::GetCurrentMode(CStdString outputName)
return result;
}
+XMode CXRandR::GetPreferredMode(CStdString outputName)
+{
+ Query();
+ XMode result;
+
+ for (unsigned int j = 0; j < m_outputs.size(); j++)
+ {
+ if (m_outputs[j].name == outputName || outputName == "")
+ {
+ for (unsigned int i = 0; i < m_outputs[j].modes.size(); i++)
+ {
+ if (m_outputs[j].modes[i].isPreferred)
+ {
+ result = m_outputs[j].modes[i];
+ break;
+ }
+ }
+ }
+ }
+
+ return result;
+}
+
void CXRandR::LoadCustomModeLinesToAllOutputs(void)
{
Query();
diff --git a/xbmc/windowing/X11/XRandR.h b/xbmc/windowing/X11/XRandR.h
index 059062f..ab7cc63 100644
--- a/xbmc/windowing/X11/XRandR.h
+++ b/xbmc/windowing/X11/XRandR.h
@@ -98,6 +98,7 @@ public:
bool Query(bool force, int screennum, bool ignoreoff=true);
std::vector<XOutput> GetModes(void);
XMode GetCurrentMode(CStdString outputName);
+ XMode GetPreferredMode(CStdString outputName);
XOutput *GetOutput(CStdString outputName);
bool SetMode(XOutput output, XMode mode);
void LoadCustomModeLinesToAllOutputs(void);
--
1.9.0
From 7c1b95f1c1354fbc2a32224592ba778b91b538d4 Mon Sep 17 00:00:00 2001
From: Rainer Hochecker <fernetmenta@online.de>
Date: Sat, 11 May 2013 17:12:12 +0200
Subject: [PATCH 60/93] X11: multi-head improvement - poll for desired output
if we do not get an xrr event
---
language/English/strings.po | 9 +++-
system/settings/settings.xml | 8 +++-
xbmc/settings/DisplaySettings.cpp | 4 ++
xbmc/windowing/WinEventsX11.cpp | 6 +++
xbmc/windowing/WinEventsX11.h | 1 +
xbmc/windowing/X11/WinSystemX11.cpp | 83 +++++++++++++++++++++++++++++++++----
xbmc/windowing/X11/WinSystemX11.h | 2 +-
xbmc/windowing/X11/XRandR.cpp | 6 ++-
8 files changed, 106 insertions(+), 13 deletions(-)
diff --git a/language/English/strings.po b/language/English/strings.po
index d9b34e1..516c5c1 100755
--- a/language/English/strings.po
+++ b/language/English/strings.po
@@ -6558,7 +6558,7 @@ msgctxt "#14071"
msgid "Allow file renaming and deletion"
msgstr ""
-#empty strings from id 14072 to 14073
+#empty strings from id 14073 to 14073
msgctxt "#14074"
msgid "Set timezone"
@@ -6696,7 +6696,12 @@ msgctxt "#14101"
msgid "Acceleration"
msgstr ""
-#empty strings from id 14102 to 15011
+#: xbmc/settings/settings.xml
+msgctxt "#14102"
+msgid "Switch off other Monitor"
+msgstr ""
+
+#empty strings from id 14103 to 15011
#: xbmc/video/VideoDatabase.cpp
msgctxt "#15012"
diff --git a/system/settings/settings.xml b/system/settings/settings.xml
index 4882978..fafabf4 100644
--- a/system/settings/settings.xml
+++ b/system/settings/settings.xml
@@ -2251,7 +2251,7 @@
<category id="videoscreen" label="21373" help="36603">
<group id="1">
<setting id="videoscreen.monitor" type="string" label="246" help="">
- <visible>HAS_GLX</visible>
+ <requirement>HAS_GLX</requirement>
<level>0</level>
<default>Default</default>
<constraints>
@@ -2259,6 +2259,11 @@
</constraints>
<control type="spinner" format="string" delayed="true" />
</setting>
+ <setting id="videoscreen.monitorsingle" type="boolean" label="14102" help="">
+ <requirement>HAS_GLX</requirement>
+ <level>0</level>
+ <default>false</default>
+ </setting>
<setting id="videoscreen.screen" type="integer" label="240" help="36351">
<level>0</level>
<default>0</default>
@@ -2311,6 +2316,7 @@
<control type="toggle" />
</setting>
<setting id="videoscreen.blankdisplays" type="boolean" parent="videoscreen.screen" label="13130" help="36355">
+ <requirement>!HAS_GLX</requirement>
<level>1</level>
<default>false</default>
<dependencies>
diff --git a/xbmc/settings/DisplaySettings.cpp b/xbmc/settings/DisplaySettings.cpp
index 966d08f..40bc3b3 100644
--- a/xbmc/settings/DisplaySettings.cpp
+++ b/xbmc/settings/DisplaySettings.cpp
@@ -265,6 +265,10 @@ bool CDisplaySettings::OnSettingChanging(const CSetting *setting)
m_resolutionChangeAborted = false;
}
}
+ else if (settingId == "videoscreen.monitorsingle")
+ {
+ g_Windowing.UpdateResolutions();
+ }
return true;
}
diff --git a/xbmc/windowing/WinEventsX11.cpp b/xbmc/windowing/WinEventsX11.cpp
index 09f56ff..908c8b6 100644
--- a/xbmc/windowing/WinEventsX11.cpp
+++ b/xbmc/windowing/WinEventsX11.cpp
@@ -213,6 +213,7 @@ bool CWinEventsX11Imp::Init(Display *dpy, Window win)
WinEvents->m_wmDeleteMessage = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
WinEvents->m_structureChanged = false;
WinEvents->m_xrrEventPending = false;
+ WinEvents->m_xrrPollTimer.Set(3000);
// open input method
char *old_locale = NULL, *old_modifiers = NULL;
@@ -591,6 +592,11 @@ bool CWinEventsX11Imp::MessagePump()
g_Windowing.NotifyXRREvent();
WinEvents->m_xrrEventPending = false;
}
+ else if (!g_application.m_pPlayer->IsPlaying() && WinEvents && WinEvents->m_xrrPollTimer.IsTimePast())
+ {
+ g_Windowing.NotifyXRREvent(true);
+ WinEvents->m_xrrPollTimer.Set(3000);
+ }
#endif
#ifdef HAS_SDL_JOYSTICK
diff --git a/xbmc/windowing/WinEventsX11.h b/xbmc/windowing/WinEventsX11.h
index 6429291..91a604f 100644
--- a/xbmc/windowing/WinEventsX11.h
+++ b/xbmc/windowing/WinEventsX11.h
@@ -62,5 +62,6 @@ protected:
bool m_structureChanged;
int m_RREventBase;
XbmcThreads::EndTime m_xrrFailSafeTimer;
+ XbmcThreads::EndTime m_xrrPollTimer;
bool m_xrrEventPending;
};
diff --git a/xbmc/windowing/X11/WinSystemX11.cpp b/xbmc/windowing/X11/WinSystemX11.cpp
index c614c9b..b3fe510 100644
--- a/xbmc/windowing/X11/WinSystemX11.cpp
+++ b/xbmc/windowing/X11/WinSystemX11.cpp
@@ -252,18 +252,62 @@ void CWinSystemX11::UpdateResolutions()
#if defined(HAS_XRANDR)
int numScreens = XScreenCount(m_dpy);
g_xrandr.SetNumScreens(numScreens);
- if(g_xrandr.Query(true))
+
+ bool switchOnOff = CSettings::Get().GetBool("videoscreen.monitorsingle");
+ m_userOutput = CSettings::Get().GetString("videoscreen.monitor");
+ if (m_userOutput.Equals("Default"))
+ switchOnOff = false;
+
+ if(g_xrandr.Query(true, !switchOnOff))
{
- m_userOutput = CSettings::Get().GetString("videoscreen.monitor");
// check if the monitor is connected
- XOutput *out = g_xrandr.GetOutput(m_userOutput);
+ // might take a while when connected to a receiver
+ XbmcThreads::EndTime timeout(3000);
+ XOutput *out = NULL;
+ while (!m_userOutput.Equals("Default") && !timeout.IsTimePast())
+ {
+ out = g_xrandr.GetOutput(m_userOutput);
+ if (out)
+ {
+ XMode mode = g_xrandr.GetCurrentMode(m_userOutput);
+ if (mode.isCurrent || switchOnOff)
+ break;
+ else
+ {
+ out = NULL;
+ break;
+ }
+ }
+
+ Sleep(500);
+ if (!g_xrandr.Query(true, !switchOnOff))
+ break;
+ }
if (!out)
{
- // choose first output
m_userOutput = g_xrandr.GetModes()[0].name;
out = g_xrandr.GetOutput(m_userOutput);
}
+
+ // switch on output
+ if(switchOnOff)
+ g_xrandr.TurnOnOutput(m_userOutput);
+
+ // switch off other outputs if desired
+ if (switchOnOff)
+ {
+ std::vector<XOutput> outputs = g_xrandr.GetModes();
+ for (int i=0; i<outputs.size(); i++)
+ {
+ if (outputs[i].name.Equals(m_userOutput))
+ continue;
+ g_xrandr.TurnOffOutput(outputs[i].name);
+ }
+ }
+
XMode mode = g_xrandr.GetCurrentMode(m_userOutput);
+ if (mode.id.empty())
+ mode = g_xrandr.GetPreferredMode(m_userOutput);
m_bIsRotated = out->isRotated;
if (!m_bIsRotated)
UpdateDesktopResolution(CDisplaySettings::Get().GetResolutionInfo(RES_DESKTOP), 0, mode.w, mode.h, mode.hz);
@@ -382,7 +426,9 @@ bool CWinSystemX11::HasCalibration(const RESOLUTION_INFO &resInfo)
void CWinSystemX11::GetConnectedOutputs(std::vector<CStdString> *outputs)
{
vector<XOutput> outs;
+ g_xrandr.Query(true);
outs = g_xrandr.GetModes();
+ outputs->push_back("Default");
for(unsigned int i=0; i<outs.size(); ++i)
{
outputs->push_back(outs[i].name);
@@ -669,14 +715,34 @@ void CWinSystemX11::CheckDisplayEvents()
#endif
}
-void CWinSystemX11::NotifyXRREvent()
+void CWinSystemX11::NotifyXRREvent(bool poll)
{
- CLog::Log(LOGDEBUG, "%s - notify display reset event", __FUNCTION__);
+ // we may not get an event if desired monitor becomes available
+ // hence we need to poll
+ if (poll)
+ {
+ CStdString output = CSettings::Get().GetString("videoscreen.monitor");
+ if (output.Equals(m_currentOutput) || m_userOutput.Equals("Default"))
+ return;
+
+ int numScreens = XScreenCount(m_dpy);
+ g_xrandr.SetNumScreens(numScreens);
+ g_xrandr.Query(true);
+ if (!g_xrandr.IsOutputConnected(output))
+ return;
+
+ // if output is turned off by user, respect it
+ XMode mode = g_xrandr.GetCurrentMode(output);
+ if (!mode.isCurrent)
+ return;
+ }
+
+ CLog::Log(LOGDEBUG, "%s - notify display reset event, poll: %d", __FUNCTION__, poll);
m_windowDirty = true;
CSingleLock lock(g_graphicsContext);
- if (!g_xrandr.Query(true))
+ if (!g_xrandr.Query(!poll))
{
CLog::Log(LOGERROR, "WinSystemX11::RefreshWindow - failed to query xrandr");
return;
@@ -703,7 +769,8 @@ void CWinSystemX11::NotifyXRREvent()
bool found(false);
for (i = RES_DESKTOP; i < CDisplaySettings::Get().ResolutionInfoSize(); ++i)
{
- if (CDisplaySettings::Get().GetResolutionInfo(i).strId == mode.id)
+ res = CDisplaySettings::Get().GetResolutionInfo(i);
+ if (CDisplaySettings::Get().GetResolutionInfo(i).strId.Equals(mode.id))
{
found = true;
break;
diff --git a/xbmc/windowing/X11/WinSystemX11.h b/xbmc/windowing/X11/WinSystemX11.h
index 1b658e2..7ec5be4 100644
--- a/xbmc/windowing/X11/WinSystemX11.h
+++ b/xbmc/windowing/X11/WinSystemX11.h
@@ -70,7 +70,7 @@ public:
Display* GetDisplay() { return m_dpy; }
GLXWindow GetWindow() { return m_glWindow; }
GLXContext GetGlxContext() { return m_glContext; }
- void NotifyXRREvent();
+ void NotifyXRREvent(bool poll = false);
void GetConnectedOutputs(std::vector<CStdString> *outputs);
bool IsCurrentOutput(CStdString output);
void NotifyMouseCoverage(bool covered);
diff --git a/xbmc/windowing/X11/XRandR.cpp b/xbmc/windowing/X11/XRandR.cpp
index 62003f5..8525ede 100644
--- a/xbmc/windowing/X11/XRandR.cpp
+++ b/xbmc/windowing/X11/XRandR.cpp
@@ -149,10 +149,14 @@ bool CXRandR::Query(bool force, int screennum, bool ignoreoff)
bool CXRandR::TurnOffOutput(CStdString name)
{
+ XOutput *output = GetOutput(name);
+ if (!output)
+ return false;
+
CStdString cmd;
cmd = getenv("XBMC_BIN_HOME");
cmd += "/xbmc-xrandr";
- cmd.AppendFormat(" --output %s --off", name.c_str());
+ cmd.AppendFormat(" --screen %d --output %s --off", output->screen, name.c_str());
int status = system(cmd.c_str());
if (status == -1)
--
1.9.0
From 08ec19f07d729af80bc81487a445ffd6794d82ed Mon Sep 17 00:00:00 2001
From: Rainer Hochecker <fernetmenta@online.de>
Date: Wed, 15 May 2013 09:14:34 +0200
Subject: [PATCH 61/93] X11: ignore mouse move event form other windows
---
xbmc/windowing/WinEventsX11.cpp | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/xbmc/windowing/WinEventsX11.cpp b/xbmc/windowing/WinEventsX11.cpp
index 908c8b6..938ad26 100644
--- a/xbmc/windowing/WinEventsX11.cpp
+++ b/xbmc/windowing/WinEventsX11.cpp
@@ -328,7 +328,7 @@ bool CWinEventsX11Imp::MessagePump()
memset(&xevent, 0, sizeof (XEvent));
XNextEvent(WinEvents->m_display, &xevent);
- if (XFilterEvent(&xevent, None))
+ if (XFilterEvent(&xevent, WinEvents->m_window))
continue;
switch (xevent.type)
@@ -529,6 +529,8 @@ bool CWinEventsX11Imp::MessagePump()
case MotionNotify:
{
+ if (xevent.xmotion.window != WinEvents->m_window)
+ break;
XBMC_Event newEvent;
memset(&newEvent, 0, sizeof(newEvent));
newEvent.type = XBMC_MOUSEMOTION;
--
1.9.0
From 1f153f70a4adc06e1b23c09bfee4daa6f59ff1db Mon Sep 17 00:00:00 2001
From: Rainer Hochecker <fernetmenta@online.de>
Date: Tue, 11 Jun 2013 16:20:29 +0200
Subject: [PATCH 62/93] renderer: allow some lateness within vblank interval
---
xbmc/cores/VideoRenderers/RenderManager.cpp | 12 ++++++++++--
xbmc/cores/VideoRenderers/RenderManager.h | 1 +
2 files changed, 11 insertions(+), 2 deletions(-)
diff --git a/xbmc/cores/VideoRenderers/RenderManager.cpp b/xbmc/cores/VideoRenderers/RenderManager.cpp
index 9e2c055..8dc8a91 100644
--- a/xbmc/cores/VideoRenderers/RenderManager.cpp
+++ b/xbmc/cores/VideoRenderers/RenderManager.cpp
@@ -378,6 +378,8 @@ void CXBMCRenderManager::FrameFinish()
if(g_graphicsContext.IsFullScreenVideo())
WaitPresentTime(m.timestamp);
+ m_clock_framefinish = GetPresentTime();
+
{ CSingleLock lock(m_presentlock);
if(m_presentstep == PRESENT_FRAME)
@@ -1030,6 +1032,12 @@ void CXBMCRenderManager::PrepareNextRender()
double clocktime = GetPresentTime();
double frametime = 1.0 / GetMaximumFPS();
+ double correction = 0.0;
+ int fps = g_VideoReferenceClock.GetRefreshRate();
+ if((fps > 0) && g_graphicsContext.IsFullScreenVideo() && (clocktime != m_clock_framefinish))
+ {
+ correction = frametime;
+ }
/* see if any future queued frames are already due */
std::deque<int>::reverse_iterator curr, prev;
@@ -1038,8 +1046,8 @@ void CXBMCRenderManager::PrepareNextRender()
++prev;
while (prev != m_queued.rend())
{
- if(clocktime > m_Queue[*prev].timestamp /* previous frame is late */
- && clocktime > m_Queue[*curr].timestamp - frametime) /* selected frame is close to it's display time */
+ if(clocktime > m_Queue[*prev].timestamp + correction /* previous frame is late */
+ && clocktime > m_Queue[*curr].timestamp - frametime + correction) /* selected frame is close to it's display time */
break;
++curr;
++prev;
diff --git a/xbmc/cores/VideoRenderers/RenderManager.h b/xbmc/cores/VideoRenderers/RenderManager.h
index 949c652..d84ff6c 100644
--- a/xbmc/cores/VideoRenderers/RenderManager.h
+++ b/xbmc/cores/VideoRenderers/RenderManager.h
@@ -252,6 +252,7 @@ protected:
XbmcThreads::ConditionVariable m_presentevent;
CCriticalSection m_presentlock;
CEvent m_flushEvent;
+ double m_clock_framefinish;
OVERLAY::CRenderer m_overlays;
--
1.9.0
From 0505eab3a4d5a351fb5700e919e190674472675d Mon Sep 17 00:00:00 2001
From: xbmc <fernetmenta@online.de>
Date: Sun, 16 Jun 2013 13:22:58 +0200
Subject: [PATCH 63/93] X11: another fix for mouse coverage
---
xbmc/windowing/WinEventsX11.cpp | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/xbmc/windowing/WinEventsX11.cpp b/xbmc/windowing/WinEventsX11.cpp
index 938ad26..e4ca56d 100644
--- a/xbmc/windowing/WinEventsX11.cpp
+++ b/xbmc/windowing/WinEventsX11.cpp
@@ -515,14 +515,16 @@ bool CWinEventsX11Imp::MessagePump()
case EnterNotify:
{
- g_Windowing.NotifyMouseCoverage(true);
+ if (xevent.xcrossing.mode == NotifyNormal)
+ g_Windowing.NotifyMouseCoverage(true);
break;
}
// lose mouse coverage
case LeaveNotify:
{
- g_Windowing.NotifyMouseCoverage(false);
+ if (xevent.xcrossing.mode == NotifyNormal)
+ g_Windowing.NotifyMouseCoverage(false);
g_Mouse.SetActive(false);
break;
}
--
1.9.0
From 3479849f9941a74852f8057de0352f52775168fc Mon Sep 17 00:00:00 2001
From: Rainer Hochecker <fernetmenta@online.de>
Date: Fri, 5 Jul 2013 12:14:00 +0200
Subject: [PATCH 64/93] X11: set windows class name
---
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 b3fe510..df5fe9b 100644
--- a/xbmc/windowing/X11/WinSystemX11.cpp
+++ b/xbmc/windowing/X11/WinSystemX11.cpp
@@ -982,8 +982,10 @@ bool CWinSystemX11::SetWindow(int width, int height, bool fullscreen, const CStd
{
CreateIconPixmap();
XWMHints *wm_hints;
+ XClassHint *class_hints;
XTextProperty windowName, iconName;
std::string titleString = "XBMC Media Center";
+ std::string classString = "xbmc.bin";
char *title = (char*)titleString.c_str();
XStringListToTextProperty(&title, 1, &windowName);
@@ -994,10 +996,15 @@ bool CWinSystemX11::SetWindow(int width, int height, bool fullscreen, const CStd
wm_hints->icon_pixmap = m_icon;
wm_hints->flags = StateHint | IconPixmapHint;
+ class_hints = XAllocClassHint();
+ class_hints->res_class = (char*)classString.c_str();
+ class_hints->res_name = (char*)classString.c_str();
+
XSync(m_dpy,False);
XSetWMProperties(m_dpy, m_mainWindow, &windowName, &iconName,
NULL, 0, NULL, wm_hints,
- NULL);
+ class_hints);
+ XFree(class_hints);
XFree(wm_hints);
// register interest in the delete window message
--
1.9.0
From 25a211eaa8d5125fc99353198b2a2caff23bf13c Mon Sep 17 00:00:00 2001
From: Rainer Hochecker <fernetmenta@online.de>
Date: Thu, 25 Jul 2013 17:18:13 +0200
Subject: [PATCH 65/93] ActiveAE: slightly reduce buffer size
---
xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAE.cpp | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAE.cpp b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAE.cpp
index 6709993..6ca2cf4 100644
--- a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAE.cpp
+++ b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAE.cpp
@@ -30,8 +30,8 @@ using namespace ActiveAE;
#include "settings/AdvancedSettings.h"
#include "windowing/WindowingFactory.h"
-#define MAX_CACHE_LEVEL 0.5 // total cache time of stream in seconds
-#define MAX_WATER_LEVEL 0.25 // buffered time after stream stages in seconds
+#define MAX_CACHE_LEVEL 0.4 // total cache time of stream in seconds
+#define MAX_WATER_LEVEL 0.2 // buffered time after stream stages in seconds
#define MAX_BUFFER_TIME 0.1 // max time of a buffer in seconds
void CEngineStats::Reset(unsigned int sampleRate)
--
1.9.0
From 0153f224e0288a2fd3d2ea6066b53fa142435580 Mon Sep 17 00:00:00 2001
From: Rainer Hochecker <fernetmenta@online.de>
Date: Sun, 4 Aug 2013 10:11:16 +0200
Subject: [PATCH 66/93] Revert "vdpau: comment some features that will be added
later"
This reverts commit e00b4f65864d623ab4d2e9e5c06db138e661f1cf.
---
xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp | 12 ++++--------
1 file changed, 4 insertions(+), 8 deletions(-)
diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp
index cd72cc6..351586a 100644
--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp
+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp
@@ -1117,8 +1117,7 @@ int CDecoder::Decode(AVCodecContext *avctx, AVFrame *pFrame)
m_bufferStats.IncDecoded();
m_vdpauOutput.m_dataPort.SendOutMessage(COutputDataProtocol::NEWFRAME, &pic, sizeof(pic));
- //TODO
- // m_codecControl = pic.DVDPic.iFlags & (DVP_FLAG_DRAIN | DVP_FLAG_NO_POSTPROC);
+ m_codecControl = pic.DVDPic.iFlags & (DVP_FLAG_DRAIN | DVP_FLAG_NO_POSTPROC);
}
int retval = 0;
@@ -2311,8 +2310,7 @@ void CMixer::InitCycle()
int flags;
uint64_t latency;
m_config.stats->GetParams(latency, flags);
- // TODO
- if (0) //flags & DVP_FLAG_NO_POSTPROC)
+ if (flags & DVP_FLAG_NO_POSTPROC)
SetPostProcFeatures(false);
else
SetPostProcFeatures(true);
@@ -2324,8 +2322,7 @@ void CMixer::InitCycle()
bool interlaced = m_mixerInput[1].DVDPic.iFlags & DVP_FLAG_INTERLACED;
m_SeenInterlaceFlag |= interlaced;
- // TODO
- if (//!(flags & DVP_FLAG_NO_POSTPROC) &&
+ if (!(flags & DVP_FLAG_NO_POSTPROC) &&
(mode == VS_DEINTERLACEMODE_FORCE ||
(mode == VS_DEINTERLACEMODE_AUTO && interlaced)))
{
@@ -2347,8 +2344,7 @@ void CMixer::InitCycle()
m_config.stats->SetCanSkipDeint(true);
}
- // TODO
- if (0) //m_mixerInput[1].DVDPic.iFlags & DVP_FLAG_DROPDEINT)
+ if (m_mixerInput[1].DVDPic.iFlags & DVP_FLAG_DROPDEINT)
{
m_mixersteps = 1;
}
--
1.9.0
From 59ce2ef98300a41255d4d860c62d3dde6f9b3272 Mon Sep 17 00:00:00 2001
From: Rainer Hochecker <fernetmenta@online.de>
Date: Fri, 9 Aug 2013 18:01:40 +0200
Subject: [PATCH 67/93] X11: fix keysyms
---
xbmc/windowing/WinEventsX11.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/xbmc/windowing/WinEventsX11.cpp b/xbmc/windowing/WinEventsX11.cpp
index e4ca56d..b20130c 100644
--- a/xbmc/windowing/WinEventsX11.cpp
+++ b/xbmc/windowing/WinEventsX11.cpp
@@ -461,7 +461,7 @@ bool CWinEventsX11Imp::MessagePump()
if (keys.length() > 0)
{
newEvent.key.keysym.scancode = xevent.xkey.keycode;
- xkeysym = XLookupKeysym(&xevent.xkey, 0);
+ XLookupString(&xevent.xkey, NULL, 0, &xkeysym, NULL);
newEvent.key.keysym.sym = LookupXbmcKeySym(xkeysym);
newEvent.key.keysym.unicode = keys[keys.length() - 1];
newEvent.key.state = xevent.xkey.state;
--
1.9.0
From 9cec1f9aa579e00c1e22d67ff0fbb7a9466035b2 Mon Sep 17 00:00:00 2001
From: Rainer Hochecker <fernetmenta@online.de>
Date: Fri, 9 Aug 2013 18:42:36 +0200
Subject: [PATCH 68/93] X11: fix keysym for non-IM
---
xbmc/windowing/WinEventsX11.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/xbmc/windowing/WinEventsX11.cpp b/xbmc/windowing/WinEventsX11.cpp
index b20130c..a38890c 100644
--- a/xbmc/windowing/WinEventsX11.cpp
+++ b/xbmc/windowing/WinEventsX11.cpp
@@ -408,7 +408,7 @@ bool CWinEventsX11Imp::MessagePump()
{
static XComposeStatus state;
char keybuf[32];
- xkeysym = XLookupKeysym(&xevent.xkey, 0);
+ XLookupString(&xevent.xkey, NULL, 0, &xkeysym, NULL);
newEvent.key.keysym.sym = LookupXbmcKeySym(xkeysym);
newEvent.key.keysym.scancode = xevent.xkey.keycode;
newEvent.key.state = xevent.xkey.state;
--
1.9.0
From 7c9b3dd5116848f8b4140450cc7e635870c91c35 Mon Sep 17 00:00:00 2001
From: Rainer Hochecker <fernetmenta@online.de>
Date: Sat, 10 Aug 2013 11:18:16 +0200
Subject: [PATCH 69/93] add some missing multi media keys
---
system/keymaps/keyboard.xml | 3 +++
xbmc/input/XBMC_keytable.cpp | 4 ++++
xbmc/input/XBMC_vkeys.h | 3 +++
3 files changed, 10 insertions(+)
diff --git a/system/keymaps/keyboard.xml b/system/keymaps/keyboard.xml
index 45682a2..01f7904 100644
--- a/system/keymaps/keyboard.xml
+++ b/system/keymaps/keyboard.xml
@@ -119,6 +119,9 @@
<prev_track>SkipPrevious</prev_track>
<stop>Stop</stop>
<play_pause>Pause</play_pause>
+ <fastforward>FastForward</fastforward>
+ <rewind>Rewind</rewind>
+ <record/>
<launch_mail></launch_mail>
<launch_media_select>XBMC.ActivateWindow(MyMusic)</launch_media_select>
<launch_app1_pc_icon>ActivateWindow(MyPrograms)</launch_app1_pc_icon>
diff --git a/xbmc/input/XBMC_keytable.cpp b/xbmc/input/XBMC_keytable.cpp
index b807897..30bad46 100644
--- a/xbmc/input/XBMC_keytable.cpp
+++ b/xbmc/input/XBMC_keytable.cpp
@@ -182,6 +182,10 @@ static const XBMCKEYTABLE XBMCKeyTable[] =
, { 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" }
+, { XBMCK_REWIND, 0, 0, XBMCVK_MEDIA_REWIND, "rewind" }
+, { XBMCK_FASTFORWARD, 0, 0, XBMCVK_MEDIA_FASTFORWARD, "fastforward" }
+, { XBMCK_RECORD, 0, 0, XBMCVK_MEDIA_RECORD, "record" }
+
// Function keys
, { XBMCK_F1, 0, 0, XBMCVK_F1, "f1"}
diff --git a/xbmc/input/XBMC_vkeys.h b/xbmc/input/XBMC_vkeys.h
index ee6bb69..364b45a 100644
--- a/xbmc/input/XBMC_vkeys.h
+++ b/xbmc/input/XBMC_vkeys.h
@@ -188,6 +188,9 @@ typedef enum {
XBMCVK_LAUNCH_APP2 = 0xC1,
XBMCVK_LAUNCH_FILE_BROWSER = 0xC2,
XBMCVK_LAUNCH_MEDIA_CENTER = 0xC3,
+ XBMCVK_MEDIA_RECORD = 0xC4,
+ XBMCVK_MEDIA_REWIND = 0xC5,
+ XBMCVK_MEDIA_FASTFORWARD = 0xC6,
XBMCVK_LCONTROL = 0xD0,
XBMCVK_RCONTROL = 0xD1,
--
1.9.0
From de2b2ba8265aba77dee620d279a61da8d3b87a61 Mon Sep 17 00:00:00 2001
From: Rainer Hochecker <fernetmenta@online.de>
Date: Sat, 10 Aug 2013 15:53:45 +0200
Subject: [PATCH 70/93] X11: squash multi
---
xbmc/windowing/X11/WinSystemX11.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/xbmc/windowing/X11/WinSystemX11.cpp b/xbmc/windowing/X11/WinSystemX11.cpp
index df5fe9b..d8e04d6 100644
--- a/xbmc/windowing/X11/WinSystemX11.cpp
+++ b/xbmc/windowing/X11/WinSystemX11.cpp
@@ -437,7 +437,7 @@ void CWinSystemX11::GetConnectedOutputs(std::vector<CStdString> *outputs)
bool CWinSystemX11::IsCurrentOutput(CStdString output)
{
- return m_currentOutput.Equals(output);
+ return output.Equals("Default") || m_currentOutput.Equals(output);
}
bool CWinSystemX11::IsSuitableVisual(XVisualInfo *vInfo)
--
1.9.0
From cf58d7d9830ee42813d1f7e7103fed4106d34d74 Mon Sep 17 00:00:00 2001
From: Rainer Hochecker <fernetmenta@online.de>
Date: Tue, 3 Sep 2013 20:46:17 +0200
Subject: [PATCH 71/93] X11: do not poll default monitor
---
xbmc/windowing/X11/WinSystemX11.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/xbmc/windowing/X11/WinSystemX11.cpp b/xbmc/windowing/X11/WinSystemX11.cpp
index d8e04d6..01f5272 100644
--- a/xbmc/windowing/X11/WinSystemX11.cpp
+++ b/xbmc/windowing/X11/WinSystemX11.cpp
@@ -722,7 +722,7 @@ void CWinSystemX11::NotifyXRREvent(bool poll)
if (poll)
{
CStdString output = CSettings::Get().GetString("videoscreen.monitor");
- if (output.Equals(m_currentOutput) || m_userOutput.Equals("Default"))
+ if (output.Equals(m_currentOutput) || output.Equals("Default"))
return;
int numScreens = XScreenCount(m_dpy);
--
1.9.0
From 21110ddf412223af1991542b1c5573da683f99a7 Mon Sep 17 00:00:00 2001
From: Rainer Hochecker <fernetmenta@online.de>
Date: Tue, 29 Oct 2013 20:57:28 +0100
Subject: [PATCH 72/93] X11: fix broken monitor switching
---
system/settings/settings.xml | 1 -
xbmc/settings/DisplaySettings.cpp | 40 ++++++++++++++++++++++++++-------------
2 files changed, 27 insertions(+), 14 deletions(-)
diff --git a/system/settings/settings.xml b/system/settings/settings.xml
index fafabf4..b13829b 100644
--- a/system/settings/settings.xml
+++ b/system/settings/settings.xml
@@ -2303,7 +2303,6 @@
<dependency type="enable" setting="videoscreen.screen" operator="!is">-1</dependency> <!-- DM_WINDOWED -->
<dependency type="update" setting="videoscreen.screen" />
<dependency type="update" setting="videoscreen.resolution" />
- <dependency type="update" setting="videoscreen.monitor" />
</dependencies>
<control type="spinner" format="string" delayed="true" />
</setting>
diff --git a/xbmc/settings/DisplaySettings.cpp b/xbmc/settings/DisplaySettings.cpp
index 40bc3b3..1663836 100644
--- a/xbmc/settings/DisplaySettings.cpp
+++ b/xbmc/settings/DisplaySettings.cpp
@@ -219,19 +219,13 @@ bool CDisplaySettings::OnSettingChanging(const CSetting *setting)
const std::string &settingId = setting->GetId();
if (settingId == "videoscreen.resolution" ||
- settingId == "videoscreen.screen" ||
- settingId == "videoscreen.monitor")
+ settingId == "videoscreen.screen")
{
RESOLUTION newRes = RES_DESKTOP;
if (settingId == "videoscreen.resolution")
newRes = (RESOLUTION)((CSettingInt*)setting)->GetValue();
else if (settingId == "videoscreen.screen")
newRes = GetResolutionForScreen();
- else if (settingId == "videoscreen.monitor")
- {
- g_Windowing.UpdateResolutions();
- newRes = GetResolutionForScreen();
- }
string screenmode = GetStringFromResolution(newRes);
CSettings::Get().SetString("videoscreen.screenmode", screenmode);
@@ -242,11 +236,7 @@ bool CDisplaySettings::OnSettingChanging(const CSetting *setting)
RESOLUTION newRes = GetResolutionFromString(((CSettingString*)setting)->GetValue());
SetCurrentResolution(newRes, false);
- bool outputChanged = false;
-#if defined(HAS_GLX)
- outputChanged = !g_Windowing.IsCurrentOutput(CSettings::Get().GetString("videoscreen.monitor"));
-#endif
- g_graphicsContext.SetVideoResolution(newRes, outputChanged);
+ g_graphicsContext.SetVideoResolution(newRes);
// check if the old or the new resolution was/is windowed
// in which case we don't show any prompt to the user
@@ -265,6 +255,28 @@ bool CDisplaySettings::OnSettingChanging(const CSetting *setting)
m_resolutionChangeAborted = false;
}
}
+ else if (settingId == "videoscreen.monitor")
+ {
+ g_Windowing.UpdateResolutions();
+ RESOLUTION newRes = GetResolutionForScreen();
+
+ SetCurrentResolution(newRes, false);
+ g_graphicsContext.SetVideoResolution(newRes, true);
+
+ if (!m_resolutionChangeAborted)
+ {
+ bool cancelled = false;
+ if (!CGUIDialogYesNo::ShowAndGetInput(13110, 13111, 20022, 20022, -1, -1, cancelled, 10000))
+ {
+ m_resolutionChangeAborted = true;
+ return false;
+ }
+ }
+ else
+ m_resolutionChangeAborted = false;
+
+ return true;
+ }
else if (settingId == "videoscreen.monitorsingle")
{
g_Windowing.UpdateResolutions();
@@ -688,9 +700,11 @@ void CDisplaySettings::SettingOptionsMonitorsFiller(const CSetting *setting, std
#if defined(HAS_GLX)
std::vector<CStdString> monitors;
g_Windowing.GetConnectedOutputs(&monitors);
+ std::string currentMonitor = CSettings::Get().GetString("videoscreen.monitor");
for (unsigned int i=0; i<monitors.size(); ++i)
{
- if(CDisplaySettings::Get().GetResolutionInfo(RES_DESKTOP).strOutput.Equals(monitors[i]))
+ if(currentMonitor.compare("Default") != 0 &&
+ CDisplaySettings::Get().GetResolutionInfo(RES_DESKTOP).strOutput.Equals(monitors[i]))
{
current = monitors[i];
}
--
1.9.0
From e95d85f22fecbc71b04569a4ceafe4971a0e5ba0 Mon Sep 17 00:00:00 2001
From: Rainer Hochecker <fernetmenta@online.de>
Date: Tue, 29 Oct 2013 20:57:59 +0100
Subject: [PATCH 73/93] X11: remove polling for connected outputs, use xrr
events
---
xbmc/windowing/WinEventsX11.cpp | 44 +++++++++++----------
xbmc/windowing/WinEventsX11.h | 1 -
xbmc/windowing/X11/WinSystemX11.cpp | 76 ++++++++++++++-----------------------
xbmc/windowing/X11/WinSystemX11.h | 8 ++--
4 files changed, 58 insertions(+), 71 deletions(-)
diff --git a/xbmc/windowing/WinEventsX11.cpp b/xbmc/windowing/WinEventsX11.cpp
index a38890c..fe91a2b 100644
--- a/xbmc/windowing/WinEventsX11.cpp
+++ b/xbmc/windowing/WinEventsX11.cpp
@@ -213,7 +213,6 @@ bool CWinEventsX11Imp::Init(Display *dpy, Window win)
WinEvents->m_wmDeleteMessage = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
WinEvents->m_structureChanged = false;
WinEvents->m_xrrEventPending = false;
- WinEvents->m_xrrPollTimer.Set(3000);
// open input method
char *old_locale = NULL, *old_modifiers = NULL;
@@ -280,7 +279,11 @@ bool CWinEventsX11Imp::Init(Display *dpy, Window win)
#if defined(HAS_XRANDR)
int iReturn;
XRRQueryExtension(WinEvents->m_display, &WinEvents->m_RREventBase, &iReturn);
- XRRSelectInput(WinEvents->m_display, WinEvents->m_window, RRScreenChangeNotifyMask);
+ int numScreens = XScreenCount(WinEvents->m_display);
+ for (int i = 0; i < numScreens; i++)
+ {
+ XRRSelectInput(WinEvents->m_display, RootWindow(WinEvents->m_display, i), RRScreenChangeNotifyMask | RRCrtcChangeNotifyMask | RROutputChangeNotifyMask | RROutputPropertyNotifyMask);
+ }
#endif
return true;
@@ -328,6 +331,26 @@ bool CWinEventsX11Imp::MessagePump()
memset(&xevent, 0, sizeof (XEvent));
XNextEvent(WinEvents->m_display, &xevent);
+#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;
+ continue;
+ }
+ else if (WinEvents && (xevent.type == WinEvents->m_RREventBase + RRNotify))
+ {
+ if (xevent.xgeneric.serial != serial)
+ g_Windowing.NotifyXRREvent();
+ WinEvents->m_xrrEventPending = false;
+ serial = xevent.xgeneric.serial;
+ continue;
+ }
+#endif
+
if (XFilterEvent(&xevent, WinEvents->m_window))
continue;
@@ -575,18 +598,6 @@ bool CWinEventsX11Imp::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
#if defined(HAS_XRANDR)
@@ -596,11 +607,6 @@ bool CWinEventsX11Imp::MessagePump()
g_Windowing.NotifyXRREvent();
WinEvents->m_xrrEventPending = false;
}
- else if (!g_application.m_pPlayer->IsPlaying() && WinEvents && WinEvents->m_xrrPollTimer.IsTimePast())
- {
- g_Windowing.NotifyXRREvent(true);
- WinEvents->m_xrrPollTimer.Set(3000);
- }
#endif
#ifdef HAS_SDL_JOYSTICK
diff --git a/xbmc/windowing/WinEventsX11.h b/xbmc/windowing/WinEventsX11.h
index 91a604f..6429291 100644
--- a/xbmc/windowing/WinEventsX11.h
+++ b/xbmc/windowing/WinEventsX11.h
@@ -62,6 +62,5 @@ protected:
bool m_structureChanged;
int m_RREventBase;
XbmcThreads::EndTime m_xrrFailSafeTimer;
- XbmcThreads::EndTime m_xrrPollTimer;
bool m_xrrEventPending;
};
diff --git a/xbmc/windowing/X11/WinSystemX11.cpp b/xbmc/windowing/X11/WinSystemX11.cpp
index 01f5272..442efa6 100644
--- a/xbmc/windowing/X11/WinSystemX11.cpp
+++ b/xbmc/windowing/X11/WinSystemX11.cpp
@@ -168,8 +168,21 @@ bool CWinSystemX11::DestroyWindow()
bool CWinSystemX11::ResizeWindow(int newWidth, int newHeight, int newLeft, int newTop)
{
+ m_userOutput = CSettings::Get().GetString("videoscreen.monitor");
+ if (m_userOutput.compare("Default") == 0)
+ {
+ std::vector<XOutput> outputs = g_xrandr.GetModes();
+ if (outputs.size() > 0)
+ {
+ m_userOutput = outputs[0].name;
+ }
+ }
+
+ m_userOutput = g_xrandr.GetModes()[0].name;
+
if(m_nWidth == newWidth
- && m_nHeight == newHeight)
+ && m_nHeight == newHeight
+ && m_userOutput.compare(m_currentOutput) == 0)
return true;
if (!SetWindow(newWidth, newHeight, false, m_userOutput))
@@ -255,33 +268,23 @@ void CWinSystemX11::UpdateResolutions()
bool switchOnOff = CSettings::Get().GetBool("videoscreen.monitorsingle");
m_userOutput = CSettings::Get().GetString("videoscreen.monitor");
- if (m_userOutput.Equals("Default"))
+ if (m_userOutput.compare("Default") == 0)
switchOnOff = false;
if(g_xrandr.Query(true, !switchOnOff))
{
- // check if the monitor is connected
- // might take a while when connected to a receiver
- XbmcThreads::EndTime timeout(3000);
XOutput *out = NULL;
- while (!m_userOutput.Equals("Default") && !timeout.IsTimePast())
+ if (m_userOutput.compare("Default") != 0)
{
out = g_xrandr.GetOutput(m_userOutput);
if (out)
{
XMode mode = g_xrandr.GetCurrentMode(m_userOutput);
- if (mode.isCurrent || switchOnOff)
- break;
- else
+ if (!mode.isCurrent && !switchOnOff)
{
out = NULL;
- break;
}
}
-
- Sleep(500);
- if (!g_xrandr.Query(true, !switchOnOff))
- break;
}
if (!out)
{
@@ -289,17 +292,16 @@ void CWinSystemX11::UpdateResolutions()
out = g_xrandr.GetOutput(m_userOutput);
}
- // switch on output
- if(switchOnOff)
- g_xrandr.TurnOnOutput(m_userOutput);
-
- // switch off other outputs if desired
if (switchOnOff)
{
+ // switch on output
+ g_xrandr.TurnOnOutput(m_userOutput);
+
+ // switch off other outputs
std::vector<XOutput> outputs = g_xrandr.GetModes();
for (int i=0; i<outputs.size(); i++)
{
- if (outputs[i].name.Equals(m_userOutput))
+ if (outputs[i].name.Equals(m_userOutput.c_str()))
continue;
g_xrandr.TurnOffOutput(outputs[i].name);
}
@@ -437,7 +439,7 @@ void CWinSystemX11::GetConnectedOutputs(std::vector<CStdString> *outputs)
bool CWinSystemX11::IsCurrentOutput(CStdString output)
{
- return output.Equals("Default") || m_currentOutput.Equals(output);
+ return (output.Equals("Default")) || (m_currentOutput.compare(output) == 0);
}
bool CWinSystemX11::IsSuitableVisual(XVisualInfo *vInfo)
@@ -715,34 +717,14 @@ void CWinSystemX11::CheckDisplayEvents()
#endif
}
-void CWinSystemX11::NotifyXRREvent(bool poll)
+void CWinSystemX11::NotifyXRREvent()
{
- // we may not get an event if desired monitor becomes available
- // hence we need to poll
- if (poll)
- {
- CStdString output = CSettings::Get().GetString("videoscreen.monitor");
- if (output.Equals(m_currentOutput) || output.Equals("Default"))
- return;
-
- int numScreens = XScreenCount(m_dpy);
- g_xrandr.SetNumScreens(numScreens);
- g_xrandr.Query(true);
- if (!g_xrandr.IsOutputConnected(output))
- return;
-
- // if output is turned off by user, respect it
- XMode mode = g_xrandr.GetCurrentMode(output);
- if (!mode.isCurrent)
- return;
- }
-
- CLog::Log(LOGDEBUG, "%s - notify display reset event, poll: %d", __FUNCTION__, poll);
+ CLog::Log(LOGDEBUG, "%s - notify display reset event", __FUNCTION__);
m_windowDirty = true;
CSingleLock lock(g_graphicsContext);
- if (!g_xrandr.Query(!poll))
+ if (!g_xrandr.Query(true))
{
CLog::Log(LOGERROR, "WinSystemX11::RefreshWindow - failed to query xrandr");
return;
@@ -839,14 +821,14 @@ bool CWinSystemX11::EnableFrameLimiter()
return m_minimized;
}
-bool CWinSystemX11::SetWindow(int width, int height, bool fullscreen, const CStdString &output)
+bool CWinSystemX11::SetWindow(int width, int height, bool fullscreen, const std::string &output)
{
bool changeWindow = false;
bool changeSize = false;
bool mouseActive = false;
float mouseX, mouseY;
- if (m_mainWindow && ((m_bFullScreen != fullscreen) || !m_currentOutput.Equals(output) || m_windowDirty))
+ if (m_mainWindow && ((m_bFullScreen != fullscreen) || m_currentOutput.compare(output) != 0 || m_windowDirty))
{
mouseActive = g_Mouse.IsActive();
if (mouseActive)
@@ -1035,7 +1017,7 @@ bool CWinSystemX11::SetWindow(int width, int height, bool fullscreen, const CStd
m_bIsGrabbed = false;
CDirtyRegionList dr;
- RefreshGlxContext(!m_currentOutput.Equals(output));
+ RefreshGlxContext(m_currentOutput.compare(output) != 0);
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 7ec5be4..14622cb 100644
--- a/xbmc/windowing/X11/WinSystemX11.h
+++ b/xbmc/windowing/X11/WinSystemX11.h
@@ -70,7 +70,7 @@ public:
Display* GetDisplay() { return m_dpy; }
GLXWindow GetWindow() { return m_glWindow; }
GLXContext GetGlxContext() { return m_glContext; }
- void NotifyXRREvent(bool poll = false);
+ void NotifyXRREvent();
void GetConnectedOutputs(std::vector<CStdString> *outputs);
bool IsCurrentOutput(CStdString output);
void NotifyMouseCoverage(bool covered);
@@ -79,7 +79,7 @@ protected:
bool RefreshGlxContext(bool force);
void CheckDisplayEvents();
void OnLostDevice();
- bool SetWindow(int width, int height, bool fullscreen, const CStdString &output);
+ bool SetWindow(int width, int height, bool fullscreen, const std::string &output);
Window m_glWindow, m_mainWindow;
GLXContext m_glContext;
@@ -95,8 +95,8 @@ protected:
CCriticalSection m_resourceSection;
std::vector<IDispResource*> m_resources;
uint64_t m_dpyLostTime;
- CStdString m_currentOutput;
- CStdString m_userOutput;
+ std::string m_currentOutput;
+ std::string m_userOutput;
bool m_windowDirty;
bool m_bIsInternalXrr;
bool m_newGlContext;
--
1.9.0
From 953a0ecd6ee55b1ef2842bb92d35e4e874f6b859 Mon Sep 17 00:00:00 2001
From: Rainer Hochecker <fernetmenta@online.de>
Date: Thu, 31 Oct 2013 09:37:13 +0100
Subject: [PATCH 74/93] X11: remove grabbing of keyboard and mouse
---
xbmc/windowing/WinEventsX11.cpp | 4 ----
xbmc/windowing/X11/WinSystemX11.cpp | 40 -------------------------------------
xbmc/windowing/X11/WinSystemX11.h | 2 --
3 files changed, 46 deletions(-)
diff --git a/xbmc/windowing/WinEventsX11.cpp b/xbmc/windowing/WinEventsX11.cpp
index fe91a2b..550c84d 100644
--- a/xbmc/windowing/WinEventsX11.cpp
+++ b/xbmc/windowing/WinEventsX11.cpp
@@ -538,16 +538,12 @@ bool CWinEventsX11Imp::MessagePump()
case EnterNotify:
{
- if (xevent.xcrossing.mode == NotifyNormal)
- g_Windowing.NotifyMouseCoverage(true);
break;
}
// lose mouse coverage
case LeaveNotify:
{
- if (xevent.xcrossing.mode == NotifyNormal)
- g_Windowing.NotifyMouseCoverage(false);
g_Mouse.SetActive(false);
break;
}
diff --git a/xbmc/windowing/X11/WinSystemX11.cpp b/xbmc/windowing/X11/WinSystemX11.cpp
index 442efa6..695b352 100644
--- a/xbmc/windowing/X11/WinSystemX11.cpp
+++ b/xbmc/windowing/X11/WinSystemX11.cpp
@@ -153,8 +153,6 @@ bool CWinSystemX11::DestroyWindow()
XUnmapWindow(m_dpy, m_mainWindow);
XSync(m_dpy,TRUE);
- XUngrabKeyboard(m_dpy, CurrentTime);
- XUngrabPointer(m_dpy, CurrentTime);
XDestroyWindow(m_dpy, m_glWindow);
XDestroyWindow(m_dpy, m_mainWindow);
m_glWindow = 0;
@@ -628,30 +626,6 @@ void CWinSystemX11::NotifyAppFocusChange(bool bGaining)
m_bIgnoreNextFocusMessage = false;
}
-void CWinSystemX11::NotifyMouseCoverage(bool covered)
-{
- if (!m_bFullScreen || !m_mainWindow)
- return;
-
- if (covered && !m_bIsGrabbed)
- {
- int result = -1;
- while (result != GrabSuccess && result != AlreadyGrabbed)
- {
- result = XGrabPointer(m_dpy, m_mainWindow, True, ButtonPressMask, GrabModeAsync, GrabModeAsync, None, None, CurrentTime);
- XbmcThreads::ThreadSleep(100);
- }
- XGrabKeyboard(m_dpy, m_mainWindow, True, GrabModeAsync, GrabModeAsync, CurrentTime);
- m_bIsGrabbed = true;
- }
- else if (!covered && m_bIsGrabbed)
- {
- XUngrabKeyboard(m_dpy, CurrentTime);
- XUngrabPointer(m_dpy, CurrentTime);
- m_bIsGrabbed = false;
- }
-}
-
bool CWinSystemX11::Minimize()
{
m_bWasFullScreenBeforeMinimize = m_bFullScreen;
@@ -1002,20 +976,6 @@ bool CWinSystemX11::SetWindow(int width, int height, bool fullscreen, const std:
XWarpPointer(m_dpy, None, m_mainWindow, 0, 0, 0, 0, mouseX*width, mouseY*height);
}
- if (fullscreen)
- {
- int result = -1;
- while (result != GrabSuccess && result != AlreadyGrabbed)
- {
- result = XGrabPointer(m_dpy, m_mainWindow, True, ButtonPressMask, GrabModeAsync, GrabModeAsync, None, None, CurrentTime);
- XbmcThreads::ThreadSleep(100);
- }
- XGrabKeyboard(m_dpy, m_mainWindow, True, GrabModeAsync, GrabModeAsync, CurrentTime);
- m_bIsGrabbed = true;
- }
- else
- m_bIsGrabbed = false;
-
CDirtyRegionList dr;
RefreshGlxContext(m_currentOutput.compare(output) != 0);
XSync(m_dpy, FALSE);
diff --git a/xbmc/windowing/X11/WinSystemX11.h b/xbmc/windowing/X11/WinSystemX11.h
index 14622cb..d1c8729 100644
--- a/xbmc/windowing/X11/WinSystemX11.h
+++ b/xbmc/windowing/X11/WinSystemX11.h
@@ -73,7 +73,6 @@ public:
void NotifyXRREvent();
void GetConnectedOutputs(std::vector<CStdString> *outputs);
bool IsCurrentOutput(CStdString output);
- void NotifyMouseCoverage(bool covered);
protected:
bool RefreshGlxContext(bool force);
@@ -90,7 +89,6 @@ protected:
bool m_bWasFullScreenBeforeMinimize;
bool m_minimized;
bool m_bIgnoreNextFocusMessage;
- bool m_bIsGrabbed;
int m_RREventBase;
CCriticalSection m_resourceSection;
std::vector<IDispResource*> m_resources;
--
1.9.0
From 039e80014380b831d46199301999e27b1d40df96 Mon Sep 17 00:00:00 2001
From: Rainer Hochecker <fernetmenta@online.de>
Date: Thu, 31 Oct 2013 10:46:40 +0100
Subject: [PATCH 75/93] X11: set ExposureMask on gl window, fixes not updated
areas
---
xbmc/windowing/X11/WinSystemX11.cpp | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/xbmc/windowing/X11/WinSystemX11.cpp b/xbmc/windowing/X11/WinSystemX11.cpp
index 695b352..e55583c 100644
--- a/xbmc/windowing/X11/WinSystemX11.cpp
+++ b/xbmc/windowing/X11/WinSystemX11.cpp
@@ -884,8 +884,8 @@ bool CWinSystemX11::SetWindow(int width, int height, bool fullscreen, const std:
swa.override_redirect = False;
swa.border_pixel = 0;
- swa.event_mask = 0;
- mask = CWBackPixel | CWBorderPixel | CWColormap | CWOverrideRedirect | CWColormap;
+ swa.event_mask = ExposureMask;
+ mask = CWBackPixel | CWBorderPixel | CWColormap | CWOverrideRedirect | CWColormap | CWEventMask;
m_glWindow = XCreateWindow(m_dpy, m_mainWindow,
0, 0, width, height, 0, vi->depth,
--
1.9.0
From 4469a824b82534d92692717e6f510a84c816eb46 Mon Sep 17 00:00:00 2001
From: Rainer Hochecker <fernetmenta@online.de>
Date: Thu, 31 Oct 2013 11:25:19 +0100
Subject: [PATCH 76/93] X11: drop shortcuts, have WM do this
---
xbmc/windowing/WinEventsX11.cpp | 21 ---------------------
xbmc/windowing/WinEventsX11.h | 1 -
2 files changed, 22 deletions(-)
diff --git a/xbmc/windowing/WinEventsX11.cpp b/xbmc/windowing/WinEventsX11.cpp
index 550c84d..a5b4ba2 100644
--- a/xbmc/windowing/WinEventsX11.cpp
+++ b/xbmc/windowing/WinEventsX11.cpp
@@ -678,10 +678,6 @@ bool CWinEventsX11Imp::ProcessKey(XBMC_Event &event)
break;
}
event.key.keysym.mod = (XBMCMod)WinEvents->m_keymodState;
-
- bool ret = ProcessShortcuts(event);
- if (ret)
- return ret;
}
else if (event.type == XBMC_KEYUP)
{
@@ -723,23 +719,6 @@ bool CWinEventsX11Imp::ProcessKey(XBMC_Event &event)
return g_application.OnEvent(event);
}
-bool CWinEventsX11Imp::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;
-}
-
XBMCKey CWinEventsX11Imp::LookupXbmcKeySym(KeySym keysym)
{
// try direct mapping first
diff --git a/xbmc/windowing/WinEventsX11.h b/xbmc/windowing/WinEventsX11.h
index 6429291..4334d21 100644
--- a/xbmc/windowing/WinEventsX11.h
+++ b/xbmc/windowing/WinEventsX11.h
@@ -48,7 +48,6 @@ public:
protected:
static XBMCKey LookupXbmcKeySym(KeySym keysym);
static bool ProcessKey(XBMC_Event &event);
- static bool ProcessShortcuts(XBMC_Event& event);
static CWinEventsX11Imp *WinEvents;
Display *m_display;
Window m_window;
--
1.9.0
From 386745d4d1e4ea4b5bde6cfad26b719e45168beb Mon Sep 17 00:00:00 2001
From: Rainer Hochecker <fernetmenta@online.de>
Date: Thu, 7 Nov 2013 15:02:00 +0100
Subject: [PATCH 77/93] X11: adapt to new settings
---
system/settings/settings.xml | 1 +
1 file changed, 1 insertion(+)
diff --git a/system/settings/settings.xml b/system/settings/settings.xml
index b13829b..b756fca 100644
--- a/system/settings/settings.xml
+++ b/system/settings/settings.xml
@@ -2263,6 +2263,7 @@
<requirement>HAS_GLX</requirement>
<level>0</level>
<default>false</default>
+ <control type="toggle" />
</setting>
<setting id="videoscreen.screen" type="integer" label="240" help="36351">
<level>0</level>
--
1.9.0
From c4292a4b8577828802204b56c4fc448dd9bd76f5 Mon Sep 17 00:00:00 2001
From: Rainer Hochecker <fernetmenta@online.de>
Date: Thu, 14 Nov 2013 09:28:24 +0100
Subject: [PATCH 78/93] X11: adapt to changes in cstdstring
---
xbmc/windowing/X11/WinSystemX11.cpp | 4 ++--
xbmc/windowing/X11/XRandR.cpp | 4 ++--
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/xbmc/windowing/X11/WinSystemX11.cpp b/xbmc/windowing/X11/WinSystemX11.cpp
index e55583c..9962f08 100644
--- a/xbmc/windowing/X11/WinSystemX11.cpp
+++ b/xbmc/windowing/X11/WinSystemX11.cpp
@@ -369,8 +369,8 @@ void CWinSystemX11::UpdateResolutions()
CLog::Log(LOGINFO, "Pixel Ratio: %f", res.fPixelRatio);
- res.strMode = StringUtils::Format("%s: %s @ %.2fHz", out.name.c_str(), mode.name.c_str(), mode.hz);
- res.strOutput = out.name;
+ res.strMode = StringUtils::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.965*mode.h);
res.fRefreshRate = mode.hz;
diff --git a/xbmc/windowing/X11/XRandR.cpp b/xbmc/windowing/X11/XRandR.cpp
index 8525ede..c94f2e3 100644
--- a/xbmc/windowing/X11/XRandR.cpp
+++ b/xbmc/windowing/X11/XRandR.cpp
@@ -74,7 +74,7 @@ bool CXRandR::Query(bool force, int screennum, bool ignoreoff)
CStdString cmd;
cmd = getenv("XBMC_BIN_HOME");
cmd += "/xbmc-xrandr";
- cmd.AppendFormat(" -q --screen %d", screennum);
+ cmd = StringUtils::Format("%s -q --screen %d", cmd.c_str(), screennum);
FILE* file = popen(cmd.c_str(),"r");
if (!file)
@@ -156,7 +156,7 @@ bool CXRandR::TurnOffOutput(CStdString name)
CStdString cmd;
cmd = getenv("XBMC_BIN_HOME");
cmd += "/xbmc-xrandr";
- cmd.AppendFormat(" --screen %d --output %s --off", output->screen, name.c_str());
+ cmd = StringUtils::Format("%s --screen %d --output %s --off", cmd.c_str(), output->screen, name.c_str());
int status = system(cmd.c_str());
if (status == -1)
--
1.9.0
From 029c809c1c28b7163ab02406668f176f49282626 Mon Sep 17 00:00:00 2001
From: Rainer Hochecker <fernetmenta@online.de>
Date: Mon, 18 Nov 2013 17:44:31 +0100
Subject: [PATCH 79/93] ActiveAE: correct time of buffered samples by resample
ratio
---
xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAE.cpp | 2 +-
xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEStream.cpp | 1 +
2 files changed, 2 insertions(+), 1 deletion(-)
diff --git a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAE.cpp b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAE.cpp
index 6ca2cf4..e2a4b6f 100644
--- a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAE.cpp
+++ b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAE.cpp
@@ -102,7 +102,7 @@ float CEngineStats::GetDelay(CActiveAEStream *stream)
if (delay < 0)
delay = 0.0;
- delay += stream->m_bufferedTime;
+ delay += stream->m_bufferedTime / stream->m_streamResampleRatio;
return delay;
}
diff --git a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEStream.cpp b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEStream.cpp
index 99989b3..0287e73 100644
--- a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEStream.cpp
+++ b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEStream.cpp
@@ -58,6 +58,7 @@ CActiveAEStream::CActiveAEStream(AEAudioFormat *format)
m_forceResampler = false;
m_remapper = NULL;
m_remapBuffer = NULL;
+ m_streamResampleRatio = 1.0;
}
CActiveAEStream::~CActiveAEStream()
--
1.9.0
From f599ea4e785a09cae43ac3e80f9cb5eb576b9eff Mon Sep 17 00:00:00 2001
From: Marcel Groothuis <margro.xbmc@gmail.com>
Date: Thu, 5 Dec 2013 22:02:50 +0100
Subject: [PATCH 80/93] ffmpeg demuxer: faster channel change for PVR addons
without internal demuxing (such as MediaPortal, ArgusTV, MythTV, NextPVR)
Credits: FernetMenta, Davilla, Popcornmix, Whaupt
---
.../cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp | 143 ++++++++++++++++++---
xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.h | 5 +-
.../dvdplayer/DVDDemuxers/DVDFactoryDemuxer.cpp | 13 +-
3 files changed, 139 insertions(+), 22 deletions(-)
diff --git a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp
index 16efae0..6ebbb6e 100644
--- a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp
+++ b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp
@@ -51,6 +51,8 @@
#include "utils/StringUtils.h"
#include "URL.h"
+#define FF_MAX_EXTRADATA_SIZE ((1 << 28) - FF_INPUT_BUFFER_PADDING_SIZE)
+
void CDemuxStreamAudioFFmpeg::GetStreamInfo(std::string& strInfo)
{
if(!m_stream) return;
@@ -217,6 +219,7 @@ CDVDDemuxFFmpeg::CDVDDemuxFFmpeg() : CDVDDemux()
m_program = UINT_MAX;
m_pkt.result = -1;
memset(&m_pkt.pkt, 0, sizeof(AVPacket));
+ m_streaminfo = true; /* set to true if we want to look for streams before playback */
}
CDVDDemuxFFmpeg::~CDVDDemuxFFmpeg()
@@ -237,10 +240,11 @@ bool CDVDDemuxFFmpeg::Aborted()
return false;
}
-bool CDVDDemuxFFmpeg::Open(CDVDInputStream* pInput)
+bool CDVDDemuxFFmpeg::Open(CDVDInputStream* pInput, bool streaminfo)
{
AVInputFormat* iformat = NULL;
std::string strFile;
+ m_streaminfo = streaminfo;
m_iCurrentPts = DVD_NOPTS_VALUE;
m_speed = DVD_PLAYSPEED_NORMAL;
m_program = UINT_MAX;
@@ -259,8 +263,6 @@ bool CDVDDemuxFFmpeg::Open(CDVDInputStream* pInput)
m_pInput = pInput;
strFile = m_pInput->GetFileName();
- bool streaminfo = true; /* set to true if we want to look for streams before playback*/
-
if( m_pInput->GetContent().length() > 0 )
{
std::string content = m_pInput->GetContent();
@@ -450,13 +452,12 @@ bool CDVDDemuxFFmpeg::Open(CDVDInputStream* pInput)
m_bMatroska = strncmp(m_pFormatContext->iformat->name, "matroska", 8) == 0; // for "matroska.webm"
m_bAVI = strcmp(m_pFormatContext->iformat->name, "avi") == 0;
- if (streaminfo)
+ if (m_streaminfo)
{
- /* too speed up dvd switches, only analyse very short */
+ /* to speed up dvd switches, only analyse very short */
if(m_pInput->IsStreamType(DVDSTREAM_TYPE_DVD))
m_pFormatContext->max_analyze_duration = 500000;
-
CLog::Log(LOGDEBUG, "%s - avformat_find_stream_info starting", __FUNCTION__);
int iErr = m_dllAvFormat.avformat_find_stream_info(m_pFormatContext, NULL);
if (iErr < 0)
@@ -476,6 +477,9 @@ bool CDVDDemuxFFmpeg::Open(CDVDInputStream* pInput)
}
CLog::Log(LOGDEBUG, "%s - av_find_stream_info finished", __FUNCTION__);
}
+ else
+ m_program = 0;
+
// reset any timeout
m_timeout.SetInfinite();
@@ -533,7 +537,7 @@ void CDVDDemuxFFmpeg::Reset()
{
CDVDInputStream* pInputStream = m_pInput;
Dispose();
- Open(pInputStream);
+ Open(pInputStream, m_streaminfo);
}
void CDVDDemuxFFmpeg::Flush()
@@ -728,25 +732,32 @@ DemuxPacket* CDVDDemuxFFmpeg::Read()
}
else
{
+ ParsePacket(&m_pkt.pkt);
+
AVStream *stream = m_pFormatContext->streams[m_pkt.pkt.stream_index];
- if (m_program != UINT_MAX)
+ if (IsVideoReady())
{
- /* check so packet belongs to selected program */
- for (unsigned int i = 0; i < m_pFormatContext->programs[m_program]->nb_stream_indexes; i++)
+ if (m_program != UINT_MAX)
{
- if(m_pkt.pkt.stream_index == (int)m_pFormatContext->programs[m_program]->stream_index[i])
+ /* check so packet belongs to selected program */
+ for (unsigned int i = 0; i < m_pFormatContext->programs[m_program]->nb_stream_indexes; i++)
{
- pPacket = CDVDDemuxUtils::AllocateDemuxPacket(m_pkt.pkt.size);
- break;
+ if(m_pkt.pkt.stream_index == (int)m_pFormatContext->programs[m_program]->stream_index[i])
+ {
+ pPacket = CDVDDemuxUtils::AllocateDemuxPacket(m_pkt.pkt.size);
+ break;
+ }
}
- }
- if (!pPacket)
- bReturnEmpty = true;
+ if (!pPacket)
+ bReturnEmpty = true;
+ }
+ else
+ pPacket = CDVDDemuxUtils::AllocateDemuxPacket(m_pkt.pkt.size);
}
else
- pPacket = CDVDDemuxUtils::AllocateDemuxPacket(m_pkt.pkt.size);
+ bReturnEmpty = true;
if (pPacket)
{
@@ -1683,3 +1694,101 @@ bool CDVDDemuxFFmpeg::IsProgramChange()
}
return false;
}
+
+void CDVDDemuxFFmpeg::ParsePacket(AVPacket *pkt)
+{
+ AVStream *st = m_pFormatContext->streams[pkt->stream_index];
+ CDemuxStream *stream = GetStreamInternal(pkt->stream_index);
+
+ // if the stream is new, tell ffmpeg to parse the stream
+ if (!stream && !st->parser)
+ {
+ st->need_parsing = AVSTREAM_PARSE_FULL;
+ }
+
+ // split extradata
+ if(st->parser && st->parser->parser->split && !st->codec->extradata)
+ {
+ int i = st->parser->parser->split(st->codec, pkt->data, pkt->size);
+ if (i > 0 && i < FF_MAX_EXTRADATA_SIZE)
+ {
+ // Found extradata, fill it in. This will cause
+ // a new stream to be created and used.
+ st->codec->extradata_size = i;
+ st->codec->extradata = (uint8_t*)av_malloc(st->codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);
+ if (st->codec->extradata)
+ {
+ CLog::Log(LOGDEBUG, "CDVDDemuxFFmpeg::Read() fetching extradata, extradata_size(%d)", st->codec->extradata_size);
+ memcpy(st->codec->extradata, pkt->data, st->codec->extradata_size);
+ memset(st->codec->extradata + i, 0, FF_INPUT_BUFFER_PADDING_SIZE);
+ }
+ else
+ {
+ st->codec->extradata_size = 0;
+ }
+ }
+ }
+
+ // for video we need a decoder to get desired information into codec context
+ if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO &&
+ (!st->codec->width || st->codec->pix_fmt == PIX_FMT_NONE))
+ {
+ // open a decoder, it will be cleared down by ffmpeg on closing the stream
+ if (!st->codec->codec)
+ {
+ const AVCodec* codec;
+ AVDictionary *thread_opt = NULL;
+ codec = avcodec_find_decoder(st->codec->codec_id);
+ // Force thread count to 1 since the h264 decoder will not extract
+ // SPS and PPS to extradata during multi-threaded decoding
+ av_dict_set(&thread_opt, "threads", "1", 0);
+ avcodec_open2(st->codec, codec, &thread_opt);
+
+ av_dict_free(&thread_opt);
+ }
+
+ // We don't need to actually decode here
+ // we just want to transport SPS data into codec context
+ st->codec->skip_idct = AVDISCARD_ALL;
+ st->codec->skip_frame = AVDISCARD_ALL;
+ st->codec->skip_loop_filter = AVDISCARD_ALL;
+
+ // We are looking for an IDR frame
+ AVFrame picture;
+ memset(&picture, 0, sizeof(AVFrame));
+ picture.pts = picture.pkt_dts = picture.pkt_pts = picture.best_effort_timestamp = AV_NOPTS_VALUE;
+ picture.pkt_pos = -1;
+ picture.key_frame = 1;
+ picture.format = -1;
+
+ int got_picture = 0;
+ avcodec_decode_video2(st->codec, &picture, &got_picture, pkt);
+ }
+}
+
+bool CDVDDemuxFFmpeg::IsVideoReady()
+{
+ AVStream *st;
+ if(m_program != UINT_MAX)
+ {
+ for (unsigned int i = 0; i < m_pFormatContext->programs[m_program]->nb_stream_indexes; i++)
+ {
+ int idx = m_pFormatContext->programs[m_program]->stream_index[i];
+ st = m_pFormatContext->streams[idx];
+ if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO &&
+ (!st->codec->width || st->codec->pix_fmt == PIX_FMT_NONE))
+ return false;
+ }
+ }
+ else
+ {
+ for (unsigned int i = 0; i < m_pFormatContext->nb_streams; i++)
+ {
+ st = m_pFormatContext->streams[i];
+ if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO &&
+ (!st->codec->width || st->codec->pix_fmt == PIX_FMT_NONE))
+ return false;
+ }
+ }
+ return true;
+}
diff --git a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.h b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.h
index 35abbdf..acde9a8 100644
--- a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.h
+++ b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.h
@@ -89,7 +89,7 @@ public:
CDVDDemuxFFmpeg();
virtual ~CDVDDemuxFFmpeg();
- bool Open(CDVDInputStream* pInput);
+ bool Open(CDVDInputStream* pInput, bool streaminfo = true);
void Dispose();
void Reset();
void Flush();
@@ -128,6 +128,8 @@ protected:
CDemuxStream* GetStreamInternal(int iStreamId);
void CreateStreams(unsigned int program = UINT_MAX);
void DisposeStreams();
+ void ParsePacket(AVPacket *pkt);
+ bool IsVideoReady();
AVDictionary *GetFFMpegOptionsFromURL(const CURL &url);
double ConvertTimestamp(int64_t pts, int den, int num);
@@ -162,5 +164,6 @@ protected:
bool m_bPtsWrap, m_bPtsWrapChecked;
int64_t m_iStartTime, m_iMaxTime, m_iEndTime;
+ bool m_streaminfo;
};
diff --git a/xbmc/cores/dvdplayer/DVDDemuxers/DVDFactoryDemuxer.cpp b/xbmc/cores/dvdplayer/DVDDemuxers/DVDFactoryDemuxer.cpp
index ca689d0..f383563 100644
--- a/xbmc/cores/dvdplayer/DVDDemuxers/DVDFactoryDemuxer.cpp
+++ b/xbmc/cores/dvdplayer/DVDDemuxers/DVDFactoryDemuxer.cpp
@@ -99,26 +99,31 @@ CDVDDemux* CDVDFactoryDemuxer::CreateDemuxer(CDVDInputStream* pInputStream)
}
#endif
+ bool streaminfo = true; /* Look for streams before playback */
if (pInputStream->IsStreamType(DVDSTREAM_TYPE_PVRMANAGER))
{
CDVDInputStreamPVRManager* pInputStreamPVR = (CDVDInputStreamPVRManager*)pInputStream;
CDVDInputStream* pOtherStream = pInputStreamPVR->GetOtherStream();
+
+ /* Don't parse the streaminfo for live streams to reduce the channel switch time */
+ bool liveStream = (pInputStream->GetFileName().substr(0, 14) == "pvr://channels");
+ streaminfo = !liveStream;
+
if(pOtherStream)
{
/* Used for MediaPortal PVR addon (uses PVR otherstream for playback of rtsp streams) */
if (pOtherStream->IsStreamType(DVDSTREAM_TYPE_FFMPEG))
{
auto_ptr<CDVDDemuxFFmpeg> demuxer(new CDVDDemuxFFmpeg());
- if(demuxer->Open(pOtherStream))
+ if(demuxer->Open(pOtherStream, streaminfo))
return demuxer.release();
else
return NULL;
}
}
- std::string filename = pInputStream->GetFileName();
/* Use PVR demuxer only for live streams */
- if (filename.substr(0, 14) == "pvr://channels")
+ if (liveStream)
{
boost::shared_ptr<CPVRClient> client;
if (g_PVRClients->GetPlayingClient(client) &&
@@ -134,7 +139,7 @@ CDVDDemux* CDVDFactoryDemuxer::CreateDemuxer(CDVDInputStream* pInputStream)
}
auto_ptr<CDVDDemuxFFmpeg> demuxer(new CDVDDemuxFFmpeg());
- if(demuxer->Open(pInputStream))
+ if(demuxer->Open(pInputStream, streaminfo))
return demuxer.release();
else
return NULL;
--
1.9.0
From 51bc8b6305c3774d0967737d87abd35e6a4634a9 Mon Sep 17 00:00:00 2001
From: Rainer Hochecker <fernetmenta@online.de>
Date: Thu, 14 Nov 2013 20:35:04 +0100
Subject: [PATCH 81/93] ffmpeg demuxer: make sure we start mpegts video with an
i-frame
---
.../cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp | 31 +++++++++++++++++++++-
xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.h | 1 +
2 files changed, 31 insertions(+), 1 deletion(-)
diff --git a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp
index 6ebbb6e..782fb3d 100644
--- a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp
+++ b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp
@@ -448,6 +448,13 @@ bool CDVDDemuxFFmpeg::Open(CDVDInputStream* pInput, bool streaminfo)
if (iformat && (strcmp(iformat->name, "mjpeg") == 0) && m_ioContext->seekable == 0)
m_pFormatContext->max_analyze_duration = 500000;
+ bool short_analyze = false;
+ if (iformat && (strcmp(iformat->name, "mpegts") == 0))
+ {
+ m_pFormatContext->max_analyze_duration = 500000;
+ short_analyze = true;
+ }
+
// we need to know if this is matroska or avi later
m_bMatroska = strncmp(m_pFormatContext->iformat->name, "matroska", 8) == 0; // for "matroska.webm"
m_bAVI = strcmp(m_pFormatContext->iformat->name, "avi") == 0;
@@ -476,6 +483,12 @@ bool CDVDDemuxFFmpeg::Open(CDVDInputStream* pInput, bool streaminfo)
}
}
CLog::Log(LOGDEBUG, "%s - av_find_stream_info finished", __FUNCTION__);
+
+ if (short_analyze)
+ {
+ // make sure we start video with an i-frame
+ ResetVideoStreams();
+ }
}
else
m_program = 0;
@@ -1730,7 +1743,7 @@ void CDVDDemuxFFmpeg::ParsePacket(AVPacket *pkt)
}
// for video we need a decoder to get desired information into codec context
- if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO &&
+ if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO && st->codec->extradata &&
(!st->codec->width || st->codec->pix_fmt == PIX_FMT_NONE))
{
// open a decoder, it will be cleared down by ffmpeg on closing the stream
@@ -1792,3 +1805,19 @@ bool CDVDDemuxFFmpeg::IsVideoReady()
}
return true;
}
+
+void CDVDDemuxFFmpeg::ResetVideoStreams()
+{
+ AVStream *st;
+ for (unsigned int i = 0; i < m_pFormatContext->nb_streams; i++)
+ {
+ st = m_pFormatContext->streams[i];
+ if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO)
+ {
+ if (st->codec->extradata)
+ m_dllAvUtil.av_free(st->codec->extradata);
+ st->codec->extradata = NULL;
+ st->codec->width = 0;
+ }
+ }
+}
diff --git a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.h b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.h
index acde9a8..9ec0877 100644
--- a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.h
+++ b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.h
@@ -130,6 +130,7 @@ protected:
void DisposeStreams();
void ParsePacket(AVPacket *pkt);
bool IsVideoReady();
+ void ResetVideoStreams();
AVDictionary *GetFFMpegOptionsFromURL(const CURL &url);
double ConvertTimestamp(int64_t pts, int den, int num);
--
1.9.0
From 24a3fa6f5b58a3c2c9bf4b53a778ca503143c6c6 Mon Sep 17 00:00:00 2001
From: Wolfgang Haupt <w.haupt@at-visions.com>
Date: Thu, 5 Dec 2013 22:11:57 +0100
Subject: [PATCH 82/93] DVDFactoryDemuxer: skip streaminfo for udp tcp and
pvr-channels
---
.../dvdplayer/DVDDemuxers/DVDFactoryDemuxer.cpp | 14 ++++++---
xbmc/utils/URIUtils.cpp | 35 ++++++++++++++++++++++
xbmc/utils/URIUtils.h | 4 +++
3 files changed, 49 insertions(+), 4 deletions(-)
diff --git a/xbmc/cores/dvdplayer/DVDDemuxers/DVDFactoryDemuxer.cpp b/xbmc/cores/dvdplayer/DVDDemuxers/DVDFactoryDemuxer.cpp
index f383563..d6580fd 100644
--- a/xbmc/cores/dvdplayer/DVDDemuxers/DVDFactoryDemuxer.cpp
+++ b/xbmc/cores/dvdplayer/DVDDemuxers/DVDFactoryDemuxer.cpp
@@ -105,9 +105,9 @@ CDVDDemux* CDVDFactoryDemuxer::CreateDemuxer(CDVDInputStream* pInputStream)
CDVDInputStreamPVRManager* pInputStreamPVR = (CDVDInputStreamPVRManager*)pInputStream;
CDVDInputStream* pOtherStream = pInputStreamPVR->GetOtherStream();
- /* Don't parse the streaminfo for live streams to reduce the channel switch time */
- bool liveStream = (pInputStream->GetFileName().substr(0, 14) == "pvr://channels");
- streaminfo = !liveStream;
+ /* Don't parse the streaminfo for some cases of streams to reduce the channel switch time */
+ bool useFastswitch = URIUtils::IsUsingFastSwitch(pInputStream->GetFileName());
+ streaminfo = !useFastswitch;
if(pOtherStream)
{
@@ -123,7 +123,7 @@ CDVDDemux* CDVDFactoryDemuxer::CreateDemuxer(CDVDInputStream* pInputStream)
}
/* Use PVR demuxer only for live streams */
- if (liveStream)
+ if (URIUtils::IsPVRChannel(pInputStream->GetFileName()))
{
boost::shared_ptr<CPVRClient> client;
if (g_PVRClients->GetPlayingClient(client) &&
@@ -138,6 +138,12 @@ CDVDDemux* CDVDFactoryDemuxer::CreateDemuxer(CDVDInputStream* pInputStream)
}
}
+ if (pInputStream->IsStreamType(DVDSTREAM_TYPE_FFMPEG))
+ {
+ bool useFastswitch = URIUtils::IsUsingFastSwitch(pInputStream->GetFileName());
+ streaminfo = !useFastswitch;
+ }
+
auto_ptr<CDVDDemuxFFmpeg> demuxer(new CDVDDemuxFFmpeg());
if(demuxer->Open(pInputStream, streaminfo))
return demuxer.release();
diff --git a/xbmc/utils/URIUtils.cpp b/xbmc/utils/URIUtils.cpp
index 12dadba..bca61a1 100644
--- a/xbmc/utils/URIUtils.cpp
+++ b/xbmc/utils/URIUtils.cpp
@@ -788,6 +788,36 @@ bool URIUtils::IsFTP(const CStdString& strFile)
StringUtils::StartsWithNoCase(strFile2, "ftps:");
}
+bool URIUtils::IsUDP(const CStdString& strFile)
+{
+ CStdString strFile2(strFile);
+
+ if (IsStack(strFile))
+ strFile2 = CStackDirectory::GetFirstStackedFile(strFile);
+
+ return StringUtils::StartsWithNoCase(strFile2, "udp:");
+}
+
+bool URIUtils::IsTCP(const CStdString& strFile)
+{
+ CStdString strFile2(strFile);
+
+ if (IsStack(strFile))
+ strFile2 = CStackDirectory::GetFirstStackedFile(strFile);
+
+ return StringUtils::StartsWithNoCase(strFile2, "tcp:");
+}
+
+bool URIUtils::IsPVRChannel(const CStdString& strFile)
+{
+ CStdString strFile2(strFile);
+
+ if (IsStack(strFile))
+ strFile2 = CStackDirectory::GetFirstStackedFile(strFile);
+
+ return StringUtils::StartsWithNoCase(strFile2, "pvr://channels");
+}
+
bool URIUtils::IsDAV(const CStdString& strFile)
{
CStdString strFile2(strFile);
@@ -1285,3 +1315,8 @@ bool URIUtils::UpdateUrlEncoding(std::string &strFilename)
strFilename = newFilename;
return true;
}
+
+bool URIUtils::IsUsingFastSwitch(const CStdString& strFile)
+{
+ return IsUDP(strFile) || IsTCP(strFile) || IsPVRChannel(strFile);
+}
diff --git a/xbmc/utils/URIUtils.h b/xbmc/utils/URIUtils.h
index b94e94c..b45630f 100644
--- a/xbmc/utils/URIUtils.h
+++ b/xbmc/utils/URIUtils.h
@@ -88,6 +88,8 @@ public:
static bool IsDOSPath(const CStdString &path);
static bool IsDVD(const CStdString& strFile);
static bool IsFTP(const CStdString& strFile);
+ static bool IsUDP(const CStdString& strFile);
+ static bool IsTCP(const CStdString& strFile);
static bool IsHD(const CStdString& strFileName);
static bool IsHDHomeRun(const CStdString& strFile);
static bool IsSlingbox(const CStdString& strFile);
@@ -127,6 +129,8 @@ public:
static bool IsAndroidApp(const CStdString& strFile);
static bool IsLibraryFolder(const CStdString& strFile);
static bool IsLibraryContent(const std::string& strFile);
+ static bool IsPVRChannel(const CStdString& strFile);
+ static bool IsUsingFastSwitch(const CStdString& strFile);
static void AddSlashAtEnd(std::string& strFolder);
static bool HasSlashAtEnd(const std::string& strFile, bool checkURL = false);
--
1.9.0
From 93d15cd098d70bdc0629d6e550f27877ab0dd63e Mon Sep 17 00:00:00 2001
From: Rainer Hochecker <fernetmenta@online.de>
Date: Tue, 28 Jan 2014 08:43:29 +0100
Subject: [PATCH 83/93] squash fast switch
---
xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp
index 782fb3d..b57b391 100644
--- a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp
+++ b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp
@@ -1815,7 +1815,7 @@ void CDVDDemuxFFmpeg::ResetVideoStreams()
if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO)
{
if (st->codec->extradata)
- m_dllAvUtil.av_free(st->codec->extradata);
+ av_free(st->codec->extradata);
st->codec->extradata = NULL;
st->codec->width = 0;
}
--
1.9.0
From 1228259650fdf7fd118787abf1f6c934c46097d6 Mon Sep 17 00:00:00 2001
From: Rainer Hochecker <fernetmenta@online.de>
Date: Sun, 9 Mar 2014 00:15:35 +0200
Subject: [PATCH 84/93] linux: add shared lib for sse4 operations
Conflicts:
configure.in
---
Makefile.in | 8 ++-
configure.in | 18 +++++++
xbmc/DllPaths_generated.h.in | 3 ++
xbmc/linux/sse4/CopyFrame.cpp | 115 ++++++++++++++++++++++++++++++++++++++++++
xbmc/linux/sse4/DllLibSSE4.h | 43 ++++++++++++++++
xbmc/linux/sse4/Makefile.in | 20 ++++++++
6 files changed, 206 insertions(+), 1 deletion(-)
create mode 100644 xbmc/linux/sse4/CopyFrame.cpp
create mode 100644 xbmc/linux/sse4/DllLibSSE4.h
create mode 100644 xbmc/linux/sse4/Makefile.in
diff --git a/Makefile.in b/Makefile.in
index 8eda3c4..b0b5c24 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -317,6 +317,12 @@ CHECK_LIBADD=@WAYLAND_TEST_LIBS@
endif
endif
+ifeq (@USE_SSE4@,1)
+LIBSSE4+=sse4
+sse4 : force
+ $(MAKE) -C xbmc/linux/sse4
+endif
+
CHECK_PROGRAMS = xbmc-test
CLEAN_FILES += $(CHECK_PROGRAMS) $(CHECK_EXTENSIONS)
@@ -446,7 +452,7 @@ endif
codecs: papcodecs dvdpcodecs dvdpextcodecs
-libs: libhdhomerun imagelib libexif system/libcpluff-@ARCH@.so $(CMYTH)
+libs: $(LIBSSE4) libhdhomerun imagelib libexif system/libcpluff-@ARCH@.so $(CMYTH)
externals: codecs libs visualizations screensavers libaddon pvraddons
diff --git a/configure.in b/configure.in
index 1cd6b2e..8756b20 100644
--- a/configure.in
+++ b/configure.in
@@ -883,6 +883,19 @@ if test "$use_static_ffmpeg" = "yes"; then
VORBISENC_ALL_LIBS=`${PKG_CONFIG} --static --libs-only-l --silence-errors vorbisenc`
fi
+use_sse4=no
+if test "$ARCH" = "x86_64-linux" || test "$ARCH" = "i486-linux"; then
+ SAVE_CFLAGS="$CFLAGS"
+ CFLAGS="-msse4.1"
+ AC_COMPILE_IFELSE(
+ [AC_LANG_SOURCE([int foo;])],
+ [ use_sse4=yes
+ USE_SSE4=1],
+ [ use_sse=no
+ USE_SSE4=0])
+ CFLAGS="$SAVE_CFLAGS"
+fi
+
# Checks for library functions.
AC_FUNC_ALLOCA
AC_FUNC_CHOWN
@@ -2591,6 +2604,10 @@ if test "$use_codec_libstagefright" = "yes"; then
OUTPUT_FILES="$OUTPUT_FILES xbmc/cores/dvdplayer/DVDCodecs/Video/libstagefrightICS/Makefile"
fi
+if test "$use_sse4" = "yes"; then
+OUTPUT_FILES="$OUTPUT_FILES xbmc/linux/sse4/Makefile"
+fi
+
OUTPUT_FILES="$OUTPUT_FILES \
xbmc/interfaces/python/Makefile \
xbmc/interfaces/python/test/Makefile"
@@ -2669,6 +2686,7 @@ AC_SUBST(USE_DOXYGEN)
AC_SUBST(USE_PVR_ADDONS)
AC_SUBST(GNUTLS_ALL_LIBS)
AC_SUBST(VORBISENC_ALL_LIBS)
+AC_SUBST(USE_SSE4)
# pushd and popd are not available in other shells besides bash, so implement
# our own pushd/popd functions
diff --git a/xbmc/DllPaths_generated.h.in b/xbmc/DllPaths_generated.h.in
index d35ea97..3bf8f96 100644
--- a/xbmc/DllPaths_generated.h.in
+++ b/xbmc/DllPaths_generated.h.in
@@ -104,4 +104,7 @@
/* xkbcommon */
#define DLL_PATH_XKBCOMMON "@XKBCOMMON_LIBRARY_SONAME@"
+/* sse4 */
+#define DLL_PATH_LIBSSE4 "special://xbmcbin/system/libsse4-@ARCH@.so"
+
#endif
diff --git a/xbmc/linux/sse4/CopyFrame.cpp b/xbmc/linux/sse4/CopyFrame.cpp
new file mode 100644
index 0000000..6d23d83
--- /dev/null
+++ b/xbmc/linux/sse4/CopyFrame.cpp
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2005-2013 Team XBMC
+ * http://xbmc.org
+ *
+ * This library 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.
+ *
+ * This library 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 General Public License
+ * along with XBMC; see the file COPYING. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "smmintrin.h"
+
+#define CACHED_BUFFER_SIZE 4096
+typedef unsigned int UINT;
+
+extern "C"
+{
+
+/*
+ * http://software.intel.com/en-us/articles/copying-accelerated-video-decode-frame-buffers
+ * COPIES VIDEO FRAMES FROM USWC MEMORY TO WB SYSTEM MEMORY VIA CACHED BUFFER
+ * ASSUMES PITCH IS A MULTIPLE OF 64B CACHE LINE SIZE, WIDTH MAY NOT BE
+ */
+void copy_frame( void * pSrc, void * pDest, void * pCacheBlock,
+ UINT width, UINT height, UINT pitch )
+{
+ __m128i x0, x1, x2, x3;
+ __m128i *pLoad;
+ __m128i *pStore;
+ __m128i *pCache;
+ UINT x, y, yLoad, yStore;
+ UINT rowsPerBlock;
+ UINT width64;
+ UINT extraPitch;
+
+
+ rowsPerBlock = CACHED_BUFFER_SIZE / pitch;
+ width64 = (width + 63) & ~0x03f;
+ extraPitch = (pitch - width64) / 16;
+
+ pLoad = (__m128i *)pSrc;
+ pStore = (__m128i *)pDest;
+
+ // COPY THROUGH 4KB CACHED BUFFER
+ for( y = 0; y < height; y += rowsPerBlock )
+ {
+ // ROWS LEFT TO COPY AT END
+ if( y + rowsPerBlock > height )
+ rowsPerBlock = height - y;
+
+ pCache = (__m128i *)pCacheBlock;
+
+ _mm_mfence();
+
+ // LOAD ROWS OF PITCH WIDTH INTO CACHED BLOCK
+ for( yLoad = 0; yLoad < rowsPerBlock; yLoad++ )
+ {
+ // COPY A ROW, CACHE LINE AT A TIME
+ for( x = 0; x < pitch; x +=64 )
+ {
+ x0 = _mm_stream_load_si128( pLoad +0 );
+ x1 = _mm_stream_load_si128( pLoad +1 );
+ x2 = _mm_stream_load_si128( pLoad +2 );
+ x3 = _mm_stream_load_si128( pLoad +3 );
+
+ _mm_store_si128( pCache +0, x0 );
+ _mm_store_si128( pCache +1, x1 );
+ _mm_store_si128( pCache +2, x2 );
+ _mm_store_si128( pCache +3, x3 );
+
+ pCache += 4;
+ pLoad += 4;
+ }
+ }
+
+ _mm_mfence();
+
+ pCache = (__m128i *)pCacheBlock;
+
+ // STORE ROWS OF FRAME WIDTH FROM CACHED BLOCK
+ for( yStore = 0; yStore < rowsPerBlock; yStore++ )
+ {
+ // copy a row, cache line at a time
+ for( x = 0; x < width64; x +=64 )
+ {
+ x0 = _mm_load_si128( pCache );
+ x1 = _mm_load_si128( pCache +1 );
+ x2 = _mm_load_si128( pCache +2 );
+ x3 = _mm_load_si128( pCache +3 );
+
+ _mm_stream_si128( pStore, x0 );
+ _mm_stream_si128( pStore +1, x1 );
+ _mm_stream_si128( pStore +2, x2 );
+ _mm_stream_si128( pStore +3, x3 );
+
+ pCache += 4;
+ pStore += 4;
+ }
+
+ pCache += extraPitch;
+ pStore += extraPitch;
+ }
+ }
+}
+}
diff --git a/xbmc/linux/sse4/DllLibSSE4.h b/xbmc/linux/sse4/DllLibSSE4.h
new file mode 100644
index 0000000..01424ac
--- /dev/null
+++ b/xbmc/linux/sse4/DllLibSSE4.h
@@ -0,0 +1,43 @@
+#pragma once
+/*
+ * Copyright (C) 2005-2013 Team XBMC
+ * http://xbmc.org
+ *
+ * This Program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This Program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with XBMC; see the file COPYING. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "DynamicDll.h"
+
+extern "C" {
+
+}
+
+class DllLibSSE4Interface
+{
+public:
+ virtual ~DllLibSSE4Interface() {}
+ virtual void copy_frame(void * pSrc, void * pDest, void * pCacheBlock, UINT width, UINT height, UINT pitch) = 0;
+};
+
+class DllLibSSE4 : public DllDynamic, DllLibSSE4Interface
+{
+ DECLARE_DLL_WRAPPER(DllLibSSE4, DLL_PATH_LIBSSE4)
+ DEFINE_METHOD6(void, copy_frame, (void *p1, void *p2, void *p3, UINT p4, UINT p5, UINT p6))
+
+ BEGIN_METHOD_RESOLVE()
+ RESOLVE_METHOD(copy_frame)
+ END_METHOD_RESOLVE()
+};
diff --git a/xbmc/linux/sse4/Makefile.in b/xbmc/linux/sse4/Makefile.in
new file mode 100644
index 0000000..45aa826
--- /dev/null
+++ b/xbmc/linux/sse4/Makefile.in
@@ -0,0 +1,20 @@
+ARCH=@ARCH@
+DEFINES+=
+CXXFLAGS=-fPIC -msse4.1
+LIBNAME=libsse4
+OBJS=CopyFrame.o
+
+LIB_SHARED=@abs_top_srcdir@/system/$(LIBNAME)-$(ARCH).so
+
+all: $(LIB_SHARED)
+
+$(LIB_SHARED): $(OBJS)
+ $(CXX) $(CFLAGS) $(LDFLAGS) -shared -g -o $(LIB_SHARED) $(OBJS)
+
+CLEAN_FILES = \
+ $(LIB_SHARED) \
+
+DISTCLEAN_FILES= \
+ Makefile \
+
+include ../../../Makefile.include
--
1.9.0
From 05f30fe9aa91c0b69d0e71490d73bdc34e0bf0af Mon Sep 17 00:00:00 2001
From: Rainer Hochecker <fernetmenta@online.de>
Date: Sun, 9 Mar 2014 00:16:57 +0200
Subject: [PATCH 85/93] vaapi: option to enable sw filters
Conflicts:
xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.cpp
xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.h
---
language/English/strings.po | 17 ++-
system/settings/settings.xml | 15 ++
xbmc/cores/VideoRenderers/RenderManager.cpp | 4 +-
xbmc/cores/dvdplayer/DVDCodecs/DVDCodecUtils.cpp | 1 +
.../DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp | 76 ++++++++--
.../DVDCodecs/Video/DVDVideoCodecFFmpeg.h | 3 +
xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.cpp | 154 +++++++++++++++++++++
xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.h | 36 ++++-
xbmc/cores/dvdplayer/DVDPlayerVideo.cpp | 32 ++---
9 files changed, 296 insertions(+), 42 deletions(-)
diff --git a/language/English/strings.po b/language/English/strings.po
index 516c5c1..47ac883 100755
--- a/language/English/strings.po
+++ b/language/English/strings.po
@@ -6092,7 +6092,13 @@ msgctxt "#13456"
msgid "Hardware accelerated"
msgstr ""
-#empty strings from id 13457 to 13499
+#. Option for video related setting #13454: sw filter
+#: system/settings/settings.xml
+msgctxt "#13457"
+msgid "Use SW Filter for VAAPI"
+msgstr ""
+
+#empty strings from id 13458 to 13499
#: system/settings/settings.xml
msgctxt "#13500"
@@ -15177,7 +15183,14 @@ msgctxt "#36431"
msgid "Defines whether video decoding should be performed in software (requires more CPU) or with hardware acceleration where possible."
msgstr ""
-#empty strings from id 36432 to 36499
+#. Description for video related setting #13457: vaapi sw filter
+#: system/settings/settings.xml
+msgctxt "#36432"
+msgid "This option enables the deinterlacing methods available for software decoding. It gives the possiblity to use high quality deinterlacers in combination with VAAPI."
+msgstr ""
+
+#empty strings from id 36433 to 36499
+
#end reservation
#: system/settings/settings.xml
diff --git a/system/settings/settings.xml b/system/settings/settings.xml
index b756fca..3a9325e 100644
--- a/system/settings/settings.xml
+++ b/system/settings/settings.xml
@@ -715,6 +715,21 @@
<default>false</default>
<control type="toggle" />
</setting>
+ <setting id="videoplayer.usevaapiswfilter" type="boolean" parent="videoplayer.usevaapi" label="13457" help="36432">
+ <requirement>HAVE_LIBVA</requirement>
+ <dependencies>
+ <dependency type="enable">
+ <and>
+ <condition setting="videoplayer.usevaapi" operator="is">true</condition>
+ <condition setting="videoplayer.decodingmethod" operator="is">1</condition>
+ </and>
+ </dependency>
+ <dependency type="visible" on="property" name="codecoptionvisible" setting="videoplayer.usevaapivc1" operator="is">true</dependency>
+ </dependencies>
+ <level>3</level>
+ <default>false</default>
+ <control type="toggle" />
+ </setting>
<setting id="videoplayer.usedxva2" type="boolean" label="13427" help="36158">
<requirement>HasDXVA2</requirement>
<dependencies>
diff --git a/xbmc/cores/VideoRenderers/RenderManager.cpp b/xbmc/cores/VideoRenderers/RenderManager.cpp
index 8dc8a91..c15f559 100644
--- a/xbmc/cores/VideoRenderers/RenderManager.cpp
+++ b/xbmc/cores/VideoRenderers/RenderManager.cpp
@@ -986,10 +986,10 @@ EINTERLACEMETHOD CXBMCRenderManager::AutoInterlaceMethodInternal(EINTERLACEMETHO
if (mInt == VS_INTERLACEMETHOD_NONE)
return VS_INTERLACEMETHOD_NONE;
- if(!m_pRenderer->Supports(mInt))
+ if(m_pRenderer && !m_pRenderer->Supports(mInt))
mInt = VS_INTERLACEMETHOD_AUTO;
- if (mInt == VS_INTERLACEMETHOD_AUTO)
+ if (m_pRenderer && mInt == VS_INTERLACEMETHOD_AUTO)
return m_pRenderer->AutoInterlaceMethod();
return mInt;
diff --git a/xbmc/cores/dvdplayer/DVDCodecs/DVDCodecUtils.cpp b/xbmc/cores/dvdplayer/DVDCodecs/DVDCodecUtils.cpp
index 5443cb3..002c8e1 100644
--- a/xbmc/cores/dvdplayer/DVDCodecs/DVDCodecUtils.cpp
+++ b/xbmc/cores/dvdplayer/DVDCodecs/DVDCodecUtils.cpp
@@ -456,6 +456,7 @@ static const EFormatMap g_format_map[] = {
, { PIX_FMT_YUV420P16, RENDER_FMT_YUV420P16 }
, { PIX_FMT_UYVY422, RENDER_FMT_UYVY422 }
, { PIX_FMT_YUYV422, RENDER_FMT_YUYV422 }
+, { PIX_FMT_NV12, RENDER_FMT_NV12 }
, { PIX_FMT_VAAPI_VLD, RENDER_FMT_VAAPI }
, { PIX_FMT_DXVA2_VLD, RENDER_FMT_DXVA }
, { PIX_FMT_NONE , RENDER_FMT_NONE }
diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp
index b59c1ee..2df9de9 100644
--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp
+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp
@@ -38,6 +38,7 @@
#include "utils/log.h"
#include "boost/shared_ptr.hpp"
#include "threads/Atomics.h"
+#include "settings/MediaSettings.h"
#ifndef TARGET_POSIX
#define RINT(x) ((x) >= 0 ? ((int)((x) + 0.5)) : ((int)((x) - 0.5)))
@@ -165,6 +166,7 @@ CDVDVideoCodecFFmpeg::CDVDVideoCodecFFmpeg() : CDVDVideoCodec()
m_dts = DVD_NOPTS_VALUE;
m_started = false;
m_decoderPts = DVD_NOPTS_VALUE;
+ m_interlace = false;
}
CDVDVideoCodecFFmpeg::~CDVDVideoCodecFFmpeg()
@@ -388,7 +390,7 @@ unsigned int CDVDVideoCodecFFmpeg::SetFilters(unsigned int flags)
{
m_filters_next.clear();
- if(m_pHardware)
+ if(m_pHardware && !m_pHardware->UseFilter())
return 0;
if(flags & FILTER_ROTATE)
@@ -462,10 +464,10 @@ int CDVDVideoCodecFFmpeg::Decode(uint8_t* pData, int iSize, double dts, double p
if(section)
lock = shared_ptr<CSingleLock>(new CSingleLock(*section));
- int result;
+ int result = 0;
if(pData)
result = m_pHardware->Check(m_pCodecContext);
- else
+ else if (!m_pHardware->UseFilter())
result = m_pHardware->Decode(m_pCodecContext, NULL);
if(result)
@@ -520,19 +522,60 @@ int CDVDVideoCodecFFmpeg::Decode(uint8_t* pData, int iSize, double dts, double p
|| m_pCodecContext->codec_id == AV_CODEC_ID_SVQ3)
m_started = true;
- if(m_pHardware == NULL)
+ m_interlace = m_pFrame->interlaced_frame;
+
+ if(m_pHardware == NULL || m_pHardware->UseFilter())
{
+ if (m_pHardware)
+ {
+ m_pFrame->pkt_dts = pts_dtoi(m_dts);
+ int result = m_pHardware->Decode(m_pCodecContext, m_pFrame);
+ if (result == VC_BUFFER)
+ return result;
+ m_pHardware->MapFrame(m_pCodecContext, m_pFrame);
+ m_dts = pts_itod(m_pFrame->pkt_dts);
+ m_pFrame->pkt_dts = 0;
+ }
+
bool need_scale = std::find( m_formats.begin()
, m_formats.end()
- , m_pCodecContext->pix_fmt) == m_formats.end();
+ , m_pFrame->format) == m_formats.end();
bool need_reopen = false;
+
+
+ // ask codec to do deinterlacing if possible
+ EDEINTERLACEMODE mDeintMode = CMediaSettings::Get().GetCurrentVideoSettings().m_DeinterlaceMode;
+ EINTERLACEMETHOD mInt = g_renderManager.AutoInterlaceMethod(CMediaSettings::Get().GetCurrentVideoSettings().m_InterlaceMethod);
+
+ unsigned int mFilters = 0;
+
+ if (mDeintMode != VS_DEINTERLACEMODE_OFF)
+ {
+ if (mDeintMode == VS_DEINTERLACEMODE_FORCE ||
+ m_pFrame->interlaced_frame)
+ {
+ if (mInt == VS_INTERLACEMETHOD_DEINTERLACE)
+ mFilters = CDVDVideoCodec::FILTER_DEINTERLACE_ANY;
+ else if(mInt == VS_INTERLACEMETHOD_DEINTERLACE_HALF)
+ mFilters = CDVDVideoCodec::FILTER_DEINTERLACE_ANY | CDVDVideoCodec::FILTER_DEINTERLACE_HALFED;
+
+ if (mDeintMode == VS_DEINTERLACEMODE_AUTO && mFilters)
+ mFilters |= CDVDVideoCodec::FILTER_DEINTERLACE_FLAGGED;
+ }
+ }
+
+ if (!g_renderManager.Supports(RENDERFEATURE_ROTATION))
+ mFilters |= CDVDVideoCodec::FILTER_ROTATE;
+
+ SetFilters(mFilters);
+
if(!m_filters.Equals(m_filters_next))
need_reopen = true;
if(m_pFilterIn)
{
- if(m_pFilterIn->outputs[0]->format != m_pCodecContext->pix_fmt
+ if(m_pFilterIn->outputs[0]->format != m_pFrame->format
|| m_pFilterIn->outputs[0]->w != m_pCodecContext->width
|| m_pFilterIn->outputs[0]->h != m_pCodecContext->height)
need_reopen = true;
@@ -549,7 +592,7 @@ int CDVDVideoCodecFFmpeg::Decode(uint8_t* pData, int iSize, double dts, double p
}
int result;
- if(m_pHardware)
+ if(m_pHardware && !m_pHardware->UseFilter())
result = m_pHardware->Decode(m_pCodecContext, m_pFrame);
else if(m_pFilterGraph)
result = FilterProcess(m_pFrame);
@@ -645,6 +688,7 @@ bool CDVDVideoCodecFFmpeg::GetPictureCommon(DVDVideoPicture* pDvdVideoPicture)
pDvdVideoPicture->chroma_position = m_pCodecContext->chroma_sample_location;
pDvdVideoPicture->color_primaries = m_pCodecContext->color_primaries;
pDvdVideoPicture->color_transfer = m_pCodecContext->color_trc;
+ pDvdVideoPicture->color_matrix = m_pCodecContext->colorspace;
if(m_pCodecContext->color_range == AVCOL_RANGE_JPEG
|| m_pCodecContext->pix_fmt == PIX_FMT_YUVJ420P)
pDvdVideoPicture->color_range = 1;
@@ -668,7 +712,11 @@ bool CDVDVideoCodecFFmpeg::GetPictureCommon(DVDVideoPicture* pDvdVideoPicture)
pDvdVideoPicture->qscale_type = DVP_QSCALE_UNKNOWN;
}
- pDvdVideoPicture->dts = m_dts;
+ if (pDvdVideoPicture->iRepeatPicture)
+ pDvdVideoPicture->dts = DVD_NOPTS_VALUE;
+ else
+ pDvdVideoPicture->dts = m_dts;
+
m_dts = DVD_NOPTS_VALUE;
if (m_pFrame->reordered_opaque)
pDvdVideoPicture->pts = pts_itod(m_pFrame->reordered_opaque);
@@ -699,7 +747,7 @@ bool CDVDVideoCodecFFmpeg::GetPictureCommon(DVDVideoPicture* pDvdVideoPicture)
bool CDVDVideoCodecFFmpeg::GetPicture(DVDVideoPicture* pDvdVideoPicture)
{
- if(m_pHardware)
+ if(m_pHardware && !m_pHardware->UseFilter())
return m_pHardware->GetPicture(m_pCodecContext, m_pFrame, pDvdVideoPicture);
if(!GetPictureCommon(pDvdVideoPicture))
@@ -724,6 +772,7 @@ bool CDVDVideoCodecFFmpeg::GetPicture(DVDVideoPicture* pDvdVideoPicture)
pix_fmt = (PixelFormat)m_pFrame->format;
pDvdVideoPicture->format = CDVDCodecUtils::EFormatFromPixfmt(pix_fmt);
+
return true;
}
@@ -738,7 +787,7 @@ int CDVDVideoCodecFFmpeg::FilterOpen(const CStdString& filters, bool scale)
if (filters.empty() && !scale)
return 0;
- if (m_pHardware)
+ if (m_pHardware && !m_pHardware->UseFilter())
{
CLog::Log(LOGWARNING, "CDVDVideoCodecFFmpeg::FilterOpen - skipped opening filters on hardware decode");
return 0;
@@ -756,7 +805,7 @@ int CDVDVideoCodecFFmpeg::FilterOpen(const CStdString& filters, bool scale)
CStdString args = StringUtils::Format("%d:%d:%d:%d:%d:%d:%d",
m_pCodecContext->width,
m_pCodecContext->height,
- m_pCodecContext->pix_fmt,
+ m_pFrame->format,
m_pCodecContext->time_base.num,
m_pCodecContext->time_base.den,
m_pCodecContext->sample_aspect_ratio.num,
@@ -955,10 +1004,7 @@ bool CDVDVideoCodecFFmpeg::GetCodecStats(double &pts, int &skippedDeint, int &in
{
pts = m_decoderPts;
skippedDeint = m_skippedDeint;
- if (m_pFrame)
- interlaced = m_pFrame->interlaced_frame;
- else
- interlaced = 0;
+ interlaced = m_interlace;
return true;
}
diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.h
index c0ce198..4f88532 100644
--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.h
+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.h
@@ -48,6 +48,8 @@ public:
virtual bool CanSkipDeint() {return false; }
virtual const std::string Name() = 0;
virtual CCriticalSection* Section() { return NULL; }
+ virtual bool UseFilter() { return false; }
+ virtual bool MapFrame(AVCodecContext* avctx, AVFrame* frame) { return false; }
};
CDVDVideoCodecFFmpeg();
@@ -134,4 +136,5 @@ protected:
int m_skippedDeint;
bool m_requestSkipDeint;
int m_codecControlFlags;
+ bool m_interlace;
};
diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.cpp
index bfefc9d..51f9bed 100644
--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.cpp
+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.cpp
@@ -24,6 +24,17 @@
#include "DVDVideoCodec.h"
#include <boost/scoped_array.hpp>
#include <boost/weak_ptr.hpp>
+#include "utils/log.h"
+#include "threads/SingleLock.h"
+#include "XMemUtils.h"
+#include "utils/CPUInfo.h"
+#include "settings/Settings.h"
+
+extern "C" {
+#include "libavutil/avutil.h"
+}
+
+#define CACHED_BUFFER_SIZE 4096
#define CHECK(a) \
do { \
@@ -166,12 +177,17 @@ CDecoder::CDecoder()
m_context = 0;
m_hwaccel = (vaapi_context*)calloc(1, sizeof(vaapi_context));
memset(m_surfaces, 0, sizeof(*m_surfaces));
+ m_frame_buffer = NULL;
+ m_cache = NULL;
}
CDecoder::~CDecoder()
{
Close();
free(m_hwaccel);
+ _aligned_free(m_frame_buffer);
+ _aligned_free(m_cache);
+ m_dllSSE4.Unload();
}
void CDecoder::RelBuffer(AVCodecContext *avctx, AVFrame *pic)
@@ -388,6 +404,11 @@ bool CDecoder::Open(AVCodecContext *avctx, enum PixelFormat fmt, unsigned int su
if (!EnsureContext(avctx))
return false;
+ if (avctx->width <= 1920 && avctx->height <= 1088)
+ CheckUseFilter();
+ else
+ m_use_filter = false;
+
m_hwaccel->display = m_display->get();
avctx->hwaccel_context = m_hwaccel;
@@ -472,7 +493,35 @@ int CDecoder::Decode(AVCodecContext* avctx, AVFrame* frame)
return status;
if(frame)
+ {
+ if (m_use_filter)
+ {
+ VASurfaceID surface = GetSurfaceID(frame);
+ std::list<CSurfacePtr>::iterator it;
+ for(it = m_surfaces_used.begin(); it != m_surfaces_used.end(); ++it)
+ {
+ if((*it)->m_id == surface)
+ {
+ m_holder.surface = *it;
+ break;
+ }
+ }
+ if (it == m_surfaces_used.end())
+ {
+ CLog::Log(LOGERROR, "VAAPI::Decode - surface not found");
+ return VC_ERROR;
+ }
+ CProcPic pic;
+ memset(&pic.frame, 0, sizeof(AVFrame));
+ av_frame_ref(&pic.frame, frame);
+ pic.surface = *it;
+ m_surfaces_proc.push_back(pic);
+ if (m_surfaces_proc.size() < m_renderbuffers_count)
+ return VC_BUFFER;
+ }
+
return VC_BUFFER | VC_PICTURE;
+ }
else
return VC_BUFFER;
}
@@ -550,4 +599,109 @@ unsigned CDecoder::GetAllowedReferences()
return m_renderbuffers_count;
}
+void CDecoder::Reset()
+{
+ m_surfaces_proc.clear();
+}
+
+void CDecoder::CheckUseFilter()
+{
+ m_use_filter = true;
+ _aligned_free(m_frame_buffer);
+ _aligned_free(m_cache);
+ if (CSettings::Get().GetBool("videoplayer.usevaapiswfilter"))
+ {
+ if (!(g_cpuInfo.GetCPUFeatures() & CPU_FEATURE_SSE4))
+ {
+ CLog::Log(LOGNOTICE,"VAAPI::CheckUseFilter cpu does not support SSE4");
+ m_use_filter = false;
+ return;
+ }
+ if (!m_dllSSE4.Load())
+ {
+ CLog::Log(LOGNOTICE,"VAAPI::CheckUseFilter failed loading sse4 lib");
+ m_use_filter = false;
+ return;
+ }
+ VAImage image;
+ VASurfaceID surface = m_surfaces_free.front()->m_id;
+ VAStatus status = vaDeriveImage(m_display->get(), surface, &image);
+ m_use_filter = true;
+ if (status != VA_STATUS_SUCCESS)
+ {
+ CLog::Log(LOGNOTICE,"VAAPI::CheckUseFilter vaDeriveImage not supported");
+ m_use_filter = false;
+ }
+ if (image.format.fourcc != VA_FOURCC_NV12)
+ {
+ CLog::Log(LOGNOTICE,"VAAPI::CheckUseFilter image format not NV12");
+ m_use_filter = false;
+ }
+ if ((image.pitches[0] % 64) || (image.pitches[1] % 64))
+ {
+ CLog::Log(LOGNOTICE,"VAAPI::CheckUseFilter patches no multiple of 64");
+ m_use_filter = false;
+ }
+ if (m_use_filter)
+ {
+ m_frame_buffer = (uint8_t*)_aligned_malloc(image.height*image.width*2 + 256, 64);
+ m_cache = (uint8_t*)_aligned_malloc(CACHED_BUFFER_SIZE, 64);
+ }
+ vaDestroyImage(m_display->get(),image.image_id);
+ }
+ else
+ {
+ m_use_filter = false;
+ }
+}
+
+bool CDecoder::MapFrame(AVCodecContext* avctx, AVFrame* frame)
+{
+ if (m_surfaces_proc.empty())
+ {
+ return false;
+ }
+ if(frame)
+ {
+ CProcPic pic = m_surfaces_proc.front();
+ m_surfaces_proc.pop_front();
+ VASurfaceID surface = pic.surface->m_id;
+ VASurfaceStatus surf_status;
+ VAImage image;
+ uint8_t *buf;
+ CHECK(vaQuerySurfaceStatus(m_display->get(), surface, &surf_status))
+ while (surf_status != VASurfaceReady)
+ {
+ Sleep(1);
+ CHECK(vaQuerySurfaceStatus(m_display->get(), surface, &surf_status))
+ }
+ CHECK(vaDeriveImage(m_display->get(), surface, &image));
+ CHECK(vaMapBuffer(m_display->get(), image.buf, (void**)&buf))
+
+ uint8_t *src, *dst;
+ src = buf + image.offsets[0];
+ dst = m_frame_buffer + image.offsets[0];
+ m_dllSSE4.copy_frame(src, dst, m_cache, image.width, image.height, image.pitches[0]);
+ src = buf + image.offsets[1];
+ dst = m_frame_buffer + image.offsets[1];
+ m_dllSSE4.copy_frame(src, dst, m_cache, image.width, image.height/2, image.pitches[1]);
+
+ av_frame_unref(frame);
+ av_frame_move_ref(frame, &pic.frame);
+
+ frame->format = AV_PIX_FMT_NV12;
+ frame->data[0] = m_frame_buffer + image.offsets[0];
+ frame->linesize[0] = image.pitches[0];
+ frame->data[1] = m_frame_buffer + image.offsets[1];
+ frame->linesize[1] = image.pitches[1];
+ frame->data[2] = NULL;
+ frame->data[3] = NULL;
+ frame->pkt_size = image.data_size;
+
+ CHECK(vaUnmapBuffer(m_display->get(), image.buf))
+ CHECK(vaDestroyImage(m_display->get(),image.image_id))
+ }
+ return true;
+}
+
#endif
diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.h
index a520e42..3541c9c 100644
--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.h
+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.h
@@ -22,14 +22,19 @@
#include "system_gl.h"
#include "DllAvCodec.h"
+
#include "DVDVideoCodecFFmpeg.h"
-#include <libavcodec/vaapi.h>
#include <va/va.h>
#include <va/va_x11.h>
#include <va/va_glx.h>
#include <list>
#include <boost/shared_ptr.hpp>
+#include "linux/sse4/DllLibSSE4.h"
+extern "C" {
+#include "libavcodec/vaapi.h"
+#include "libavcodec/avcodec.h"
+}
namespace VAAPI {
@@ -101,11 +106,31 @@ struct CHolder
{}
};
+struct CProcPic
+{
+ AVFrame frame;
+ CSurfacePtr surface;
+ CProcPic()
+ {}
+ CProcPic(const CProcPic &other)
+ {
+ memcpy(&this->frame, &other.frame, sizeof(AVFrame));
+ surface = other.surface;
+ }
+ CProcPic & operator= (const CProcPic &other)
+ {
+ memcpy(&this->frame, &other.frame, sizeof(AVFrame));
+ surface = other.surface;
+ return *this;
+ }
+};
+
class CDecoder
: public CDVDVideoCodecFFmpeg::IHardwareDecoder
{
bool EnsureContext(AVCodecContext *avctx);
bool EnsureSurfaces(AVCodecContext *avctx, unsigned n_surfaces_count);
+ void CheckUseFilter();
public:
CDecoder();
~CDecoder();
@@ -114,9 +139,12 @@ public:
virtual bool GetPicture(AVCodecContext* avctx, AVFrame* frame, DVDVideoPicture* picture);
virtual int Check (AVCodecContext* avctx);
virtual void Close();
+ virtual void Reset();
virtual const std::string Name() { return "vaapi"; }
virtual CCriticalSection* Section() { if(m_display) return m_display.get(); else return NULL; }
virtual unsigned GetAllowedReferences();
+ virtual bool UseFilter() { return m_use_filter; }
+ virtual bool MapFrame(AVCodecContext* avctx, AVFrame* frame);
int GetBuffer(AVCodecContext *avctx, AVFrame *pic);
void RelBuffer(AVCodecContext *avctx, AVFrame *pic);
@@ -132,14 +160,20 @@ protected:
int m_refs;
std::list<CSurfacePtr> m_surfaces_used;
std::list<CSurfacePtr> m_surfaces_free;
+ std::list<CProcPic> m_surfaces_proc;
CDisplayPtr m_display;
VAConfigID m_config;
VAContextID m_context;
+ bool m_use_filter;
+ uint8_t *m_frame_buffer;
+ uint8_t *m_cache;
vaapi_context *m_hwaccel;
CHolder m_holder; // silly struct to pass data to renderer
+
+ DllLibSSE4 m_dllSSE4;
};
}
diff --git a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp
index 9c5469b..b30e450 100644
--- a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp
+++ b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp
@@ -554,28 +554,6 @@ void CDVDPlayerVideo::Process()
// decoder still needs to provide an empty image structure, with correct flags
m_pVideoCodec->SetDropState(bRequestDrop);
- // ask codec to do deinterlacing if possible
- EDEINTERLACEMODE mDeintMode = CMediaSettings::Get().GetCurrentVideoSettings().m_DeinterlaceMode;
- EINTERLACEMETHOD mInt = g_renderManager.AutoInterlaceMethod(CMediaSettings::Get().GetCurrentVideoSettings().m_InterlaceMethod);
-
- unsigned int mFilters = 0;
-
- if (mDeintMode != VS_DEINTERLACEMODE_OFF)
- {
- if (mInt == VS_INTERLACEMETHOD_DEINTERLACE)
- mFilters = CDVDVideoCodec::FILTER_DEINTERLACE_ANY;
- else if(mInt == VS_INTERLACEMETHOD_DEINTERLACE_HALF)
- mFilters = CDVDVideoCodec::FILTER_DEINTERLACE_ANY | CDVDVideoCodec::FILTER_DEINTERLACE_HALFED;
-
- if (mDeintMode == VS_DEINTERLACEMODE_AUTO && mFilters)
- mFilters |= CDVDVideoCodec::FILTER_DEINTERLACE_FLAGGED;
- }
-
- if (!g_renderManager.Supports(RENDERFEATURE_ROTATION))
- mFilters |= CDVDVideoCodec::FILTER_ROTATE;
-
- mFilters = m_pVideoCodec->SetFilters(mFilters);
-
int iDecoderState = m_pVideoCodec->Decode(pPacket->pData, pPacket->iSize, pPacket->dts, pPacket->pts);
// buffer packets so we can recover should decoder flush for some reason
@@ -662,6 +640,8 @@ void CDVDPlayerVideo::Process()
//Deinterlace if codec said format was interlaced or if we have selected we want to deinterlace
//this video
+ EDEINTERLACEMODE mDeintMode = CMediaSettings::Get().GetCurrentVideoSettings().m_DeinterlaceMode;
+ EINTERLACEMETHOD mInt = g_renderManager.AutoInterlaceMethod(CMediaSettings::Get().GetCurrentVideoSettings().m_InterlaceMethod);
if ((mDeintMode == VS_DEINTERLACEMODE_AUTO && (picture.iFlags & DVP_FLAG_INTERLACED)) || mDeintMode == VS_DEINTERLACEMODE_FORCE)
{
if(mInt == VS_INTERLACEMETHOD_SW_BLEND)
@@ -704,7 +684,15 @@ void CDVDPlayerVideo::Process()
}
if (picture.iRepeatPicture)
+ {
+ double pts;
+ int skipped, deint;
+ m_pVideoCodec->GetCodecStats(pts, skipped, deint);
+ picture.iDuration = frametime;
+ if (deint && (frametime <= 0.02*DVD_TIME_BASE))
+ picture.iDuration *= 2;
picture.iDuration *= picture.iRepeatPicture + 1;
+ }
int iResult = OutputPicture(&picture, pts);
--
1.9.0
From eb235f0541bef993a9db30642ed451b723b7953e Mon Sep 17 00:00:00 2001
From: Rainer Hochecker <fernetmenta@online.de>
Date: Fri, 3 Jan 2014 20:50:46 +0100
Subject: [PATCH 86/93] X11: check for user output on resize window
---
xbmc/windowing/X11/WinSystemX11.cpp | 17 ++++++++++++++---
1 file changed, 14 insertions(+), 3 deletions(-)
diff --git a/xbmc/windowing/X11/WinSystemX11.cpp b/xbmc/windowing/X11/WinSystemX11.cpp
index 9962f08..c95f4ec 100644
--- a/xbmc/windowing/X11/WinSystemX11.cpp
+++ b/xbmc/windowing/X11/WinSystemX11.cpp
@@ -167,7 +167,20 @@ bool CWinSystemX11::DestroyWindow()
bool CWinSystemX11::ResizeWindow(int newWidth, int newHeight, int newLeft, int newTop)
{
m_userOutput = CSettings::Get().GetString("videoscreen.monitor");
- if (m_userOutput.compare("Default") == 0)
+ XOutput *out = NULL;
+ if (m_userOutput.compare("Default") != 0)
+ {
+ out = g_xrandr.GetOutput(m_userOutput);
+ if (out)
+ {
+ XMode mode = g_xrandr.GetCurrentMode(m_userOutput);
+ if (!mode.isCurrent)
+ {
+ out = NULL;
+ }
+ }
+ }
+ if (!out)
{
std::vector<XOutput> outputs = g_xrandr.GetModes();
if (outputs.size() > 0)
@@ -176,8 +189,6 @@ bool CWinSystemX11::ResizeWindow(int newWidth, int newHeight, int newLeft, int n
}
}
- m_userOutput = g_xrandr.GetModes()[0].name;
-
if(m_nWidth == newWidth
&& m_nHeight == newHeight
&& m_userOutput.compare(m_currentOutput) == 0)
--
1.9.0
From cf354441917e2066e406fad51200f20d762f09d2 Mon Sep 17 00:00:00 2001
From: Rainer Hochecker <fernetmenta@online.de>
Date: Fri, 24 Jan 2014 18:29:33 +0100
Subject: [PATCH 87/93] dvdplayer: flush ffmpeg after hw decoder returned an
error
---
xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp
index 2df9de9..f4c9929 100644
--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp
+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp
@@ -471,7 +471,12 @@ int CDVDVideoCodecFFmpeg::Decode(uint8_t* pData, int iSize, double dts, double p
result = m_pHardware->Decode(m_pCodecContext, NULL);
if(result)
+ {
+ if (result & VC_ERROR)
+ avcodec_flush_buffers(m_pCodecContext);
+
return result;
+ }
}
if(m_pFilterGraph)
@@ -593,7 +598,11 @@ int CDVDVideoCodecFFmpeg::Decode(uint8_t* pData, int iSize, double dts, double p
int result;
if(m_pHardware && !m_pHardware->UseFilter())
+ {
result = m_pHardware->Decode(m_pCodecContext, m_pFrame);
+ if (result & VC_ERROR)
+ avcodec_flush_buffers(m_pCodecContext);
+ }
else if(m_pFilterGraph)
result = FilterProcess(m_pFrame);
else
--
1.9.0
From 8184d80ea878672e0ad27ef24bc0daab05bf6397 Mon Sep 17 00:00:00 2001
From: Rainer Hochecker <fernetmenta@online.de>
Date: Tue, 28 Jan 2014 10:05:26 +0100
Subject: [PATCH 88/93] xbmc pr 3080
---
.../dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp | 14 ++++++++++++--
1 file changed, 12 insertions(+), 2 deletions(-)
diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp
index f4c9929..283af9e 100644
--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp
+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp
@@ -495,6 +495,14 @@ int CDVDVideoCodecFFmpeg::Decode(uint8_t* pData, int iSize, double dts, double p
m_dllAvCodec.av_init_packet(&avpkt);
avpkt.data = pData;
avpkt.size = iSize;
+#define SET_PKT_TS(ts) \
+ if(ts != DVD_NOPTS_VALUE)\
+ avpkt.ts = (ts / DVD_TIME_BASE) * AV_TIME_BASE;\
+ else\
+ avpkt.ts = AV_NOPTS_VALUE
+ SET_PKT_TS(pts);
+ SET_PKT_TS(dts);
+#undef SET_PKT_TS
/* We lie, but this flag is only used by pngdec.c.
* Setting it correctly would allow CorePNG decoding. */
avpkt.flags = AV_PKT_FLAG_KEY;
@@ -727,8 +735,10 @@ bool CDVDVideoCodecFFmpeg::GetPictureCommon(DVDVideoPicture* pDvdVideoPicture)
pDvdVideoPicture->dts = m_dts;
m_dts = DVD_NOPTS_VALUE;
- if (m_pFrame->reordered_opaque)
- pDvdVideoPicture->pts = pts_itod(m_pFrame->reordered_opaque);
+
+ int64_t bpts = av_frame_get_best_effort_timestamp(m_pFrame);
+ if(bpts != AV_NOPTS_VALUE)
+ pDvdVideoPicture->pts = (double)bpts * DVD_TIME_BASE / AV_TIME_BASE;
else
pDvdVideoPicture->pts = DVD_NOPTS_VALUE;
--
1.9.0
From dbfcb8af2d7aa02dd5de3227e226493e80e7be4d Mon Sep 17 00:00:00 2001
From: Rainer Hochecker <fernetmenta@online.de>
Date: Tue, 28 Jan 2014 17:24:58 +0100
Subject: [PATCH 89/93] set preatpicture if pts is equal to last frame
---
xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp
index 283af9e..ff18b73 100644
--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp
+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp
@@ -738,7 +738,15 @@ bool CDVDVideoCodecFFmpeg::GetPictureCommon(DVDVideoPicture* pDvdVideoPicture)
int64_t bpts = av_frame_get_best_effort_timestamp(m_pFrame);
if(bpts != AV_NOPTS_VALUE)
+ {
pDvdVideoPicture->pts = (double)bpts * DVD_TIME_BASE / AV_TIME_BASE;
+ if (pDvdVideoPicture->pts == m_decoderPts)
+ {
+ pDvdVideoPicture->iRepeatPicture = -0.5;
+ pDvdVideoPicture->pts = DVD_NOPTS_VALUE;
+ pDvdVideoPicture->dts = DVD_NOPTS_VALUE;
+ }
+ }
else
pDvdVideoPicture->pts = DVD_NOPTS_VALUE;
--
1.9.0
From 4ae7d07c09a3d2e3fe0dc7042f37a11c89622357 Mon Sep 17 00:00:00 2001
From: fritsch <Peter.Fruehberger@gmail.com>
Date: Mon, 27 Jan 2014 19:49:03 +0100
Subject: [PATCH 90/93] Introduce SWCodec - these are codecs that don't have
any GPU acceleration (yet) - add HVEC
---
.../dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp | 15 +++++++++------
.../cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.h | 2 +-
xbmc/settings/AdvancedSettings.cpp | 4 ++--
xbmc/settings/AdvancedSettings.h | 2 +-
4 files changed, 13 insertions(+), 10 deletions(-)
diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp
index ff18b73..354e206 100644
--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp
+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp
@@ -160,7 +160,7 @@ CDVDVideoCodecFFmpeg::CDVDVideoCodecFFmpeg() : CDVDVideoCodec()
m_iScreenHeight = 0;
m_iOrientation = 0;
m_bSoftware = false;
- m_isHi10p = false;
+ m_isSWCodec = false;
m_pHardware = NULL;
m_iLastKeyframe = 0;
m_dts = DVD_NOPTS_VALUE;
@@ -216,10 +216,12 @@ bool CDVDVideoCodecFFmpeg::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options
// this is needed to not open the decoders
m_bSoftware = true;
// this we need to enable multithreading for hi10p via advancedsettings
- m_isHi10p = true;
+ m_isSWCodec = true;
break;
}
}
+ else if (hints.codec == AV_CODEC_ID_HEVC)
+ m_isSWCodec = true;
if(pCodec == NULL)
pCodec = m_dllAvCodec.avcodec_find_decoder(hints.codec);
@@ -245,12 +247,12 @@ bool CDVDVideoCodecFFmpeg::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options
* sensitive to changes in frame sizes, and it causes crashes
* during HW accell - so we unset it in this case.
*
- * When we detect Hi10p and user did not disable hi10pmultithreading
+ * When we detect a pure SW codec and user did not disable SWmultithreading
* via advancedsettings.xml we keep the ffmpeg default thread type.
* */
- if(m_isHi10p && !g_advancedSettings.m_videoDisableHi10pMultithreading)
+ if(m_isSWCodec && !g_advancedSettings.m_videoDisableSWMultithreading)
{
- CLog::Log(LOGDEBUG,"CDVDVideoCodecFFmpeg::Open() Keep default threading for Hi10p: %d",
+ CLog::Log(LOGDEBUG,"CDVDVideoCodecFFmpeg::Open() Keep default threading for swcodec: %d",
m_pCodecContext->thread_type);
}
else if ((EDECODEMETHOD) CSettings::Get().GetInt("videoplayer.decodingmethod") == VS_DECODEMETHOD_SOFTWARE && CSettings::Get().GetBool("videoplayer.useframemtdec"))
@@ -302,7 +304,8 @@ bool CDVDVideoCodecFFmpeg::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options
int num_threads = std::min(8 /*MAX_THREADS*/, g_cpuInfo.getCPUCount());
if( num_threads > 1 && !hints.software && m_pHardware == NULL // thumbnail extraction fails when run threaded
&& ( pCodec->id == AV_CODEC_ID_H264
- || pCodec->id == AV_CODEC_ID_MPEG4 ))
+ || pCodec->id == AV_CODEC_ID_MPEG4
+ || pCodec->id == AV_CODEC_ID_HEVC))
m_pCodecContext->thread_count = num_threads;
if (m_dllAvCodec.avcodec_open2(m_pCodecContext, pCodec, NULL) < 0)
diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.h
index 4f88532..e301aa8 100644
--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.h
+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.h
@@ -126,7 +126,7 @@ protected:
std::string m_name;
bool m_bSoftware;
- bool m_isHi10p;
+ bool m_isSWCodec;
IHardwareDecoder *m_pHardware;
int m_iLastKeyframe;
double m_dts;
diff --git a/xbmc/settings/AdvancedSettings.cpp b/xbmc/settings/AdvancedSettings.cpp
index 7532914..0d5e546 100644
--- a/xbmc/settings/AdvancedSettings.cpp
+++ b/xbmc/settings/AdvancedSettings.cpp
@@ -182,7 +182,7 @@ void CAdvancedSettings::Initialize()
m_stagefrightConfig.useInputDTS = false;
m_videoDefaultLatency = 0.0;
- m_videoDisableHi10pMultithreading = false;
+ m_videoDisableSWMultithreading = false;
m_musicUseTimeSeeking = true;
m_musicTimeSeekForward = 10;
@@ -599,7 +599,7 @@ void CAdvancedSettings::ParseSettingsFile(const CStdString &file)
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);
- XMLUtils::GetBoolean(pElement,"disablehi10pmultithreading",m_videoDisableHi10pMultithreading);
+ XMLUtils::GetBoolean(pElement,"disableswmultithreading",m_videoDisableSWMultithreading);
XMLUtils::GetBoolean(pElement, "disablebackgrounddeinterlace", m_videoDisableBackgroundDeinterlace);
XMLUtils::GetInt(pElement, "useocclusionquery", m_videoCaptureUseOcclusionQuery, -1, 1);
XMLUtils::GetInt(pElement,"vdpauHDdeint",m_videoVDPAUdeintHD);
diff --git a/xbmc/settings/AdvancedSettings.h b/xbmc/settings/AdvancedSettings.h
index c43351d..7075f05 100644
--- a/xbmc/settings/AdvancedSettings.h
+++ b/xbmc/settings/AdvancedSettings.h
@@ -194,7 +194,7 @@ class CAdvancedSettings : public ISettingCallback, public ISettingsHandler
bool m_DXVANoDeintProcForProgressive;
int m_videoFpsDetect;
int m_videoBusyDialogDelay_ms;
- bool m_videoDisableHi10pMultithreading;
+ bool m_videoDisableSWMultithreading;
StagefrightConfig m_stagefrightConfig;
CStdString m_videoDefaultPlayer;
--
1.9.0
From 0f809b66ecb03c219083ea821f4dbba543e818f5 Mon Sep 17 00:00:00 2001
From: Rainer Hochecker <fernetmenta@online.de>
Date: Tue, 11 Feb 2014 18:15:06 +0100
Subject: [PATCH 91/93] ActiveAE: add some debug logging
---
xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEStream.cpp | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEStream.cpp b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEStream.cpp
index 0287e73..6904cb9 100644
--- a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEStream.cpp
+++ b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEStream.cpp
@@ -276,7 +276,13 @@ unsigned int CActiveAEStream::AddData(void *data, unsigned int size)
}
}
if (!m_inMsgEvent.WaitMSec(200))
+ {
+ double cachetime = GetCacheTime();
+ CSingleLock lock(m_streamLock);
+ CLog::Log(LOGWARNING, "CActiveAEStream::AddData - timeout waiting for buffer, paused: %d, cache time: %f, free buffers: %d",
+ m_paused, cachetime, m_streamFreeBuffers);
break;
+ }
}
return copied;
}
--
1.9.0
From 513134b092630d3d59ee738a2761b93c08e3312f Mon Sep 17 00:00:00 2001
From: Stefan Saraev <stefan@saraev.ca>
Date: Mon, 24 Feb 2014 20:49:47 +0200
Subject: [PATCH 92/93] vaapi: fix build
---
xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.cpp | 13 ++-----------
xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.h | 6 +-----
2 files changed, 3 insertions(+), 16 deletions(-)
diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.cpp
index 51f9bed..f957393 100644
--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.cpp
+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.cpp
@@ -24,16 +24,10 @@
#include "DVDVideoCodec.h"
#include <boost/scoped_array.hpp>
#include <boost/weak_ptr.hpp>
-#include "utils/log.h"
-#include "threads/SingleLock.h"
#include "XMemUtils.h"
#include "utils/CPUInfo.h"
#include "settings/Settings.h"
-extern "C" {
-#include "libavutil/avutil.h"
-}
-
#define CACHED_BUFFER_SIZE 4096
#define CHECK(a) \
@@ -512,8 +506,7 @@ int CDecoder::Decode(AVCodecContext* avctx, AVFrame* frame)
return VC_ERROR;
}
CProcPic pic;
- memset(&pic.frame, 0, sizeof(AVFrame));
- av_frame_ref(&pic.frame, frame);
+ memcpy(&pic.frame, frame, sizeof(AVFrame));
pic.surface = *it;
m_surfaces_proc.push_back(pic);
if (m_surfaces_proc.size() < m_renderbuffers_count)
@@ -686,9 +679,7 @@ bool CDecoder::MapFrame(AVCodecContext* avctx, AVFrame* frame)
dst = m_frame_buffer + image.offsets[1];
m_dllSSE4.copy_frame(src, dst, m_cache, image.width, image.height/2, image.pitches[1]);
- av_frame_unref(frame);
- av_frame_move_ref(frame, &pic.frame);
-
+ memcpy(frame, &pic.frame, sizeof(AVFrame));
frame->format = AV_PIX_FMT_NV12;
frame->data[0] = m_frame_buffer + image.offsets[0];
frame->linesize[0] = image.pitches[0];
diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.h
index 3541c9c..49d3117 100644
--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.h
+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.h
@@ -22,8 +22,8 @@
#include "system_gl.h"
#include "DllAvCodec.h"
-
#include "DVDVideoCodecFFmpeg.h"
+#include <libavcodec/vaapi.h>
#include <va/va.h>
#include <va/va_x11.h>
#include <va/va_glx.h>
@@ -31,10 +31,6 @@
#include <boost/shared_ptr.hpp>
#include "linux/sse4/DllLibSSE4.h"
-extern "C" {
-#include "libavcodec/vaapi.h"
-#include "libavcodec/avcodec.h"
-}
namespace VAAPI {
--
1.9.0
From f0b8551028faafa5bb3c5880263759a6239e836a Mon Sep 17 00:00:00 2001
From: Stefan Saraev <stefan@saraev.ca>
Date: Mon, 24 Feb 2014 20:58:52 +0200
Subject: [PATCH 93/93] no hevc in ffmpeg 1.2
---
xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp
index 354e206..6bc35b1 100644
--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp
+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp
@@ -220,8 +220,11 @@ bool CDVDVideoCodecFFmpeg::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options
break;
}
}
+ #ifdef AV_CODEC_ID_HEVC
else if (hints.codec == AV_CODEC_ID_HEVC)
m_isSWCodec = true;
+ #endif
+
if(pCodec == NULL)
pCodec = m_dllAvCodec.avcodec_find_decoder(hints.codec);
@@ -304,8 +307,7 @@ bool CDVDVideoCodecFFmpeg::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options
int num_threads = std::min(8 /*MAX_THREADS*/, g_cpuInfo.getCPUCount());
if( num_threads > 1 && !hints.software && m_pHardware == NULL // thumbnail extraction fails when run threaded
&& ( pCodec->id == AV_CODEC_ID_H264
- || pCodec->id == AV_CODEC_ID_MPEG4
- || pCodec->id == AV_CODEC_ID_HEVC))
+ || pCodec->id == AV_CODEC_ID_MPEG4 ))
m_pCodecContext->thread_count = num_threads;
if (m_dllAvCodec.avcodec_open2(m_pCodecContext, pCodec, NULL) < 0)
--
1.9.0