diff --git a/packages/mediacenter/xbmc-theme-Confluence/package.mk b/packages/mediacenter/xbmc-theme-Confluence/package.mk index 0d7f5f4834..a2ffecc094 100644 --- a/packages/mediacenter/xbmc-theme-Confluence/package.mk +++ b/packages/mediacenter/xbmc-theme-Confluence/package.mk @@ -17,7 +17,7 @@ ################################################################################ PKG_NAME="xbmc-theme-Confluence" -PKG_VERSION="14-a29b21a" +PKG_VERSION="14-0b1a6eb" PKG_REV="1" PKG_ARCH="any" PKG_LICENSE="GPL" diff --git a/packages/mediacenter/xbmc/package.mk b/packages/mediacenter/xbmc/package.mk index ff1ff545c3..2f7bfcd54b 100644 --- a/packages/mediacenter/xbmc/package.mk +++ b/packages/mediacenter/xbmc/package.mk @@ -17,7 +17,7 @@ ################################################################################ PKG_NAME="xbmc" -PKG_VERSION="14-a29b21a" +PKG_VERSION="14-0b1a6eb" PKG_REV="1" PKG_ARCH="any" PKG_LICENSE="GPL" diff --git a/packages/mediacenter/xbmc/patches/xbmc-995.01-fernetmenta.patch b/packages/mediacenter/xbmc/patches/xbmc-995.01-fernetmenta.patch index 2d986efdcc..5a06613efa 100644 --- a/packages/mediacenter/xbmc/patches/xbmc-995.01-fernetmenta.patch +++ b/packages/mediacenter/xbmc/patches/xbmc-995.01-fernetmenta.patch @@ -1,7 +1,7 @@ -From ab3ed171e0f2d3539455b8479b72204b0b935145 Mon Sep 17 00:00:00 2001 +From efd0ef52581dd291a55847867545d97b9b2b7eb2 Mon Sep 17 00:00:00 2001 From: xbmc Date: Mon, 28 May 2012 10:34:39 +0200 -Subject: [PATCH 01/31] videoplayer: adapt lateness detection and dropping to +Subject: [PATCH 01/24] videoplayer: adapt lateness detection and dropping to buffering --- @@ -15,10 +15,10 @@ Subject: [PATCH 01/31] videoplayer: adapt lateness detection and dropping to 7 files changed, 288 insertions(+), 48 deletions(-) diff --git a/xbmc/cores/VideoRenderers/RenderManager.cpp b/xbmc/cores/VideoRenderers/RenderManager.cpp -index b6fb1a3..61e1fe3 100644 +index 7f04949..1ae5c9f 100644 --- a/xbmc/cores/VideoRenderers/RenderManager.cpp +++ b/xbmc/cores/VideoRenderers/RenderManager.cpp -@@ -286,6 +286,8 @@ bool CXBMCRenderManager::Configure(unsigned int width, unsigned int height, unsi +@@ -290,6 +290,8 @@ bool CXBMCRenderManager::Configure(unsigned int width, unsigned int height, unsi m_bIsStarted = true; m_bReconfigured = true; m_presentstep = PRESENT_IDLE; @@ -27,7 +27,7 @@ index b6fb1a3..61e1fe3 100644 m_presentevent.notifyAll(); m_firstFlipPage = false; // tempfix -@@ -631,7 +633,7 @@ void CXBMCRenderManager::SetViewMode(int iViewMode) +@@ -635,7 +637,7 @@ void CXBMCRenderManager::SetViewMode(int iViewMode) m_pRenderer->SetViewMode(iViewMode); } @@ -36,7 +36,7 @@ index b6fb1a3..61e1fe3 100644 { { CSharedLock lock(m_sharedSection); -@@ -699,6 +701,7 @@ void CXBMCRenderManager::FlipPage(volatile bool& bStop, double timestamp /* = 0L +@@ -703,6 +705,7 @@ void CXBMCRenderManager::FlipPage(volatile bool& bStop, double timestamp /* = 0L m.timestamp = timestamp; m.presentfield = sync; m.presentmethod = presentmethod; @@ -44,7 +44,7 @@ index b6fb1a3..61e1fe3 100644 requeue(m_queued, m_free); /* signal to any waiters to check state */ -@@ -1073,6 +1076,8 @@ void CXBMCRenderManager::PrepareNextRender() +@@ -1082,6 +1085,8 @@ void CXBMCRenderManager::PrepareNextRender() m_discard.push_back(m_presentsource); m_presentsource = idx; m_queued.pop_front(); @@ -53,7 +53,7 @@ index b6fb1a3..61e1fe3 100644 m_presentevent.notifyAll(); } } -@@ -1089,3 +1094,12 @@ void CXBMCRenderManager::DiscardBuffer() +@@ -1098,3 +1103,12 @@ void CXBMCRenderManager::DiscardBuffer() m_presentstep = PRESENT_IDLE; m_presentevent.notifyAll(); } @@ -114,7 +114,7 @@ index 8b237fb..e8d4ca2 100644 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 741017d..c5b24d6 100644 +index 3fdfba1..69ff8c9 100644 --- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h +++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h @@ -136,6 +136,10 @@ struct DVDVideoUserData @@ -182,7 +182,7 @@ index 741017d..c5b24d6 100644 + virtual void SetCodecControl(int flags) {} }; diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp -index 2db5d99..6920db2 100644 +index aea738e..2481b66 100644 --- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp +++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp @@ -167,6 +167,7 @@ CDVDVideoCodecFFmpeg::CDVDVideoCodecFFmpeg() : CDVDVideoCodec() @@ -289,7 +289,7 @@ index 1f564bb..48564d1 100644 + int m_codecControlFlags; }; diff --git a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp -index ac78f18..a3edad2 100644 +index b5d9ebd..d88dd7f 100644 --- a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp +++ b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp @@ -38,6 +38,7 @@ @@ -397,7 +397,7 @@ index ac78f18..a3edad2 100644 // reset the request, the following while loop may break before // setting the flag to a new value bRequestDrop = false; -@@ -1168,45 +1186,17 @@ int CDVDPlayerVideo::OutputPicture(const DVDVideoPicture* src, double pts) +@@ -1169,45 +1187,17 @@ int CDVDPlayerVideo::OutputPicture(const DVDVideoPicture* src, double pts) , "CDVDPlayerVideo::OutputPicture"); } @@ -447,7 +447,7 @@ index ac78f18..a3edad2 100644 // set fieldsync if picture is interlaced EFIELDSYNC mDisplayField = FS_NONE; -@@ -1239,7 +1229,7 @@ int CDVDPlayerVideo::OutputPicture(const DVDVideoPicture* src, double pts) +@@ -1240,7 +1230,7 @@ int CDVDPlayerVideo::OutputPicture(const DVDVideoPicture* src, double pts) if (index < 0) return EOS_DROPPED; @@ -456,7 +456,7 @@ index ac78f18..a3edad2 100644 return result; #else -@@ -1539,3 +1529,124 @@ void CDVDPlayerVideo::CalcFrameRate() +@@ -1540,3 +1530,124 @@ void CDVDPlayerVideo::CalcFrameRate() m_iFrameRateCount = 0; } } @@ -642,14 +642,11 @@ index 37a37c4..be14832 100644 + CDroppingStats m_droppingStats; }; --- -2.0.4 - -From 487e9680440879f01fe0732325748aa519164419 Mon Sep 17 00:00:00 2001 +From 727bd33ebf4a7ed4b947635992ade215bbaf150a Mon Sep 17 00:00:00 2001 From: xbmc Date: Sun, 2 Sep 2012 16:05:21 +0200 -Subject: [PATCH 02/31] video player: present correct pts to user for a/v sync +Subject: [PATCH 02/24] video player: present correct pts to user for a/v sync (after buffering in renderer) --- @@ -658,10 +655,10 @@ Subject: [PATCH 02/31] video player: present correct pts to user for a/v sync 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp -index a3edad2..1e70fca 100644 +index d88dd7f..072296b 100644 --- a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp +++ b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp -@@ -1449,6 +1449,22 @@ void CDVDPlayerVideo::ResetFrameRateCalc() +@@ -1450,6 +1450,22 @@ void CDVDPlayerVideo::ResetFrameRateCalc() g_advancedSettings.m_videoFpsDetect == 0; } @@ -697,14 +694,11 @@ index be14832..ad99987 100644 double GetOutputDelay(); /* returns the expected delay, from that a packet is put in queue */ std::string GetPlayerInfo(); --- -2.0.4 - -From c5368ddfb731ef967e3dbc635d325285e4368bed Mon Sep 17 00:00:00 2001 +From f799e89b13acad9888e58960f09d43bcc99329ea Mon Sep 17 00:00:00 2001 From: Rainer Hochecker Date: Sat, 1 Jun 2013 11:21:19 +0200 -Subject: [PATCH 03/31] renderer: bump buffers to 5 +Subject: [PATCH 03/24] renderer: bump buffers to 5 --- xbmc/cores/VideoRenderers/BaseRenderer.h | 2 +- @@ -723,14 +717,11 @@ index fb41ccf..f5e5677 100644 class CSetting; --- -2.0.4 - -From dcba98d63da19d9a620da5a66a90711289344afd Mon Sep 17 00:00:00 2001 +From f8b7c7ba155b99abf768bc390889a081c4dcdde1 Mon Sep 17 00:00:00 2001 From: xbmc Date: Mon, 28 May 2012 10:41:31 +0200 -Subject: [PATCH 04/31] videoplayer: update frametime, it might change due to +Subject: [PATCH 04/24] videoplayer: update frametime, it might change due to fps detection --- @@ -738,7 +729,7 @@ Subject: [PATCH 04/31] videoplayer: update frametime, it might change due to 1 file changed, 2 insertions(+) diff --git a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp -index 1e70fca..5761270 100644 +index 072296b..3ac3673 100644 --- a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp +++ b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp @@ -706,6 +706,8 @@ void CDVDPlayerVideo::Process() @@ -750,14 +741,11 @@ index 1e70fca..5761270 100644 if(m_started == false) { m_codecname = m_pVideoCodec->GetName(); --- -2.0.4 - -From de6543284447f8185c4df494e3e48df71eb16349 Mon Sep 17 00:00:00 2001 +From d7b6e5b20722c0829fbbb44609baaf80a3a52c2e Mon Sep 17 00:00:00 2001 From: xbmc Date: Mon, 28 May 2012 10:43:06 +0200 -Subject: [PATCH 05/31] videoplayer: give streams with invalid fps a chance for +Subject: [PATCH 05/24] videoplayer: give streams with invalid fps a chance for fps detection --- @@ -765,10 +753,10 @@ Subject: [PATCH 05/31] videoplayer: give streams with invalid fps a chance for 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp -index 5761270..e8d855f 100644 +index 3ac3673..94d520d 100644 --- a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp +++ b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp -@@ -1491,7 +1491,7 @@ void CDVDPlayerVideo::CalcFrameRate() +@@ -1492,7 +1492,7 @@ void CDVDPlayerVideo::CalcFrameRate() double frameduration = m_pullupCorrection.GetFrameDuration(); if (frameduration == DVD_NOPTS_VALUE || @@ -777,14 +765,11 @@ index 5761270..e8d855f 100644 { //reset the stored framerates if no good framerate was detected m_fStableFrameRate = 0.0; --- -2.0.4 - -From 0598187613227e589871a06df9a6637df4b8ef59 Mon Sep 17 00:00:00 2001 +From 1526b8b63fe59e1ba8de0e7b8d00ccea63a5cb3d Mon Sep 17 00:00:00 2001 From: xbmc Date: Mon, 28 May 2012 10:49:05 +0200 -Subject: [PATCH 06/31] dvdplayer: allow rewinding at end of stream, do a seek +Subject: [PATCH 06/24] dvdplayer: allow rewinding at end of stream, do a seek after rewind --- @@ -817,14 +802,11 @@ index 8de1e96..19e90f5 100644 // 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 --- -2.0.4 - -From 9b5fcc9f82be2d8a93b3fbedbf8709a72e82ec96 Mon Sep 17 00:00:00 2001 +From 1d83f91d19328c078b3302368fc02a571932bbdd Mon Sep 17 00:00:00 2001 From: xbmc Date: Mon, 20 Aug 2012 16:06:39 +0200 -Subject: [PATCH 07/31] dvdplayer: observe pts counter overflow +Subject: [PATCH 07/24] dvdplayer: observe pts counter overflow --- .../cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp | 197 ++++++++++++++++++++- @@ -1103,14 +1085,11 @@ index 08eb3df..dd89584 100644 + int64_t m_iStartTime, m_iMaxTime, m_iEndTime; }; --- -2.0.4 - -From 430589bc82a13e4b457b84862fed5d80c2c9c8e5 Mon Sep 17 00:00:00 2001 +From fe4263eda2d683a88f483e85c79ebec32b6e06f9 Mon Sep 17 00:00:00 2001 From: xbmc Date: Tue, 2 Oct 2012 13:02:10 +0200 -Subject: [PATCH 08/31] dvdplayer: avoid short screen flicker caused by +Subject: [PATCH 08/24] dvdplayer: avoid short screen flicker caused by unnecessary reconfigure of renderer --- @@ -1118,10 +1097,10 @@ Subject: [PATCH 08/31] dvdplayer: avoid short screen flicker caused by 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp -index e8d855f..5bff37e 100644 +index 94d520d..e4c5b92 100644 --- a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp +++ b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp -@@ -1050,13 +1050,16 @@ int CDVDPlayerVideo::OutputPicture(const DVDVideoPicture* src, double pts) +@@ -1051,13 +1051,16 @@ int CDVDPlayerVideo::OutputPicture(const DVDVideoPicture* src, double pts) #ifdef HAS_VIDEO_PLAYBACK double config_framerate = m_bFpsInvalid ? 0.0 : m_fFrameRate; @@ -1139,14 +1118,11 @@ index e8d855f..5bff37e 100644 || ( 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 --- -2.0.4 - -From df1c231838244764acbf84142261d5f67f6f89b0 Mon Sep 17 00:00:00 2001 +From c024275b8c80f33bd2438f60688a743cb7d0de00 Mon Sep 17 00:00:00 2001 From: xbmc Date: Thu, 11 Oct 2012 12:05:50 +0200 -Subject: [PATCH 09/31] vdpau: advanced settings for auto deinterlacing +Subject: [PATCH 09/24] vdpau: advanced settings for auto deinterlacing --- xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp | 8 ++++---- @@ -1174,7 +1150,7 @@ index 94c9188..1845198 100644 if (deint != -1) { diff --git a/xbmc/settings/AdvancedSettings.cpp b/xbmc/settings/AdvancedSettings.cpp -index 5f3f2d8..f42970c 100644 +index 4af3c7a..f2ad5c8 100644 --- a/xbmc/settings/AdvancedSettings.cpp +++ b/xbmc/settings/AdvancedSettings.cpp @@ -156,6 +156,8 @@ void CAdvancedSettings::Initialize() @@ -1208,14 +1184,11 @@ index 7e50a63..980138e 100644 bool m_videoVDPAUtelecine; bool m_videoVDPAUdeintSkipChromaHD; bool m_musicUseTimeSeeking; --- -2.0.4 - -From d320919872492797709fc2226eccddae470d53dc Mon Sep 17 00:00:00 2001 +From 7db7164107b9eb4e75a834712a6fbc101b20e517 Mon Sep 17 00:00:00 2001 From: xbmc Date: Fri, 2 Nov 2012 13:20:03 +0100 -Subject: [PATCH 10/31] player: fix rewind +Subject: [PATCH 10/24] player: fix rewind --- xbmc/cores/dvdplayer/DVDMessage.h | 5 ++++- @@ -1393,10 +1366,10 @@ index 2b16a90..68d68a1 100644 int m_errorCount; diff --git a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp -index 5bff37e..f530567 100644 +index e4c5b92..f9a45e8 100644 --- a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp +++ b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp -@@ -1464,7 +1464,7 @@ double CDVDPlayerVideo::GetCurrentPts() +@@ -1465,7 +1465,7 @@ double CDVDPlayerVideo::GetCurrentPts() if( m_stalled ) iRenderPts = DVD_NOPTS_VALUE; @@ -1405,7 +1378,7 @@ index 5bff37e..f530567 100644 iRenderPts = iRenderPts - max(0.0, iSleepTime); return iRenderPts; -@@ -1563,6 +1563,8 @@ int CDVDPlayerVideo::CalcDropRequirement(double pts) +@@ -1564,6 +1564,8 @@ int CDVDPlayerVideo::CalcDropRequirement(double pts) int iDroppedPics = -1; int iBufferLevel; @@ -1426,14 +1399,11 @@ index ad99987..4d2b2c7 100644 unsigned int m_lateFrames; unsigned int m_dropRequests; }; --- -2.0.4 - -From 53c0dbd9f211b6b2d9934a9c4e2a26da265fcc01 Mon Sep 17 00:00:00 2001 +From 34227aead45596a55387780ae5763d35f935bdcc Mon Sep 17 00:00:00 2001 From: xbmc Date: Thu, 28 Mar 2013 15:18:53 +0100 -Subject: [PATCH 11/31] OMXPlayer: some caching fixes for pvr +Subject: [PATCH 11/24] OMXPlayer: some caching fixes for pvr --- xbmc/cores/omxplayer/OMXPlayer.cpp | 3 ++- @@ -1453,21 +1423,18 @@ index 53fe37d..182314f 100644 m_clock.SetSpeed(speed); m_av_clock.OMXSetSpeed(speed); m_av_clock.OMXPause(); --- -2.0.4 - -From 6b4eb294ef8c3d13736cbdec6093c4d5d6ace4b7 Mon Sep 17 00:00:00 2001 +From eb4229d5cb216ac1a520601c7926a847fcaafeaf Mon Sep 17 00:00:00 2001 From: xbmc Date: Thu, 28 Mar 2013 20:50:59 +0100 -Subject: [PATCH 12/31] fix incorrect display of fps when dr kicks in +Subject: [PATCH 12/24] 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 479b54a..6ef5bdb 100644 +index 94ee013..851a380 100644 --- a/xbmc/Application.cpp +++ b/xbmc/Application.cpp @@ -2325,10 +2325,11 @@ void CApplication::Render() @@ -1483,14 +1450,11 @@ index 479b54a..6ef5bdb 100644 CTimeUtils::UpdateFrameTime(flip); g_renderManager.UpdateResolution(); --- -2.0.4 - -From 51aac4a2916cd7fdd2da52cb71dbbd4e47c0b8db Mon Sep 17 00:00:00 2001 +From c5a0dafc36be783b147d647ed3afdf68437cee50 Mon Sep 17 00:00:00 2001 From: Rainer Hochecker Date: Thu, 25 Jul 2013 17:18:13 +0200 -Subject: [PATCH 13/31] ActiveAE: slightly reduce buffer size +Subject: [PATCH 13/24] ActiveAE: slightly reduce buffer size --- xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAE.cpp | 4 ++-- @@ -1511,14 +1475,11 @@ index fe5e893..c98c73b 100644 #define MAX_BUFFER_TIME 0.1 // max time of a buffer in seconds void CEngineStats::Reset(unsigned int sampleRate) --- -2.0.4 - -From 0cec3ff65e750280264d058c3d9e75c6e76a8419 Mon Sep 17 00:00:00 2001 +From 9986529bed77a4fbc8ffd9c6c52c46c3384ba17e Mon Sep 17 00:00:00 2001 From: Rainer Hochecker Date: Sun, 4 Aug 2013 10:11:16 +0200 -Subject: [PATCH 14/31] Revert "vdpau: comment some features that will be added +Subject: [PATCH 14/24] Revert "vdpau: comment some features that will be added later" This reverts commit e00b4f65864d623ab4d2e9e5c06db138e661f1cf. @@ -1570,14 +1531,11 @@ index 1845198..2bfea1a 100644 { m_mixersteps = 1; } --- -2.0.4 - -From f93e7631df21c85ad5c512de3247562115ed9ee2 Mon Sep 17 00:00:00 2001 +From 236002d2c8be8e22f791be14c1e5288b7ba36cb2 Mon Sep 17 00:00:00 2001 From: Marcel Groothuis Date: Thu, 5 Dec 2013 22:02:50 +0100 -Subject: [PATCH 15/31] ffmpeg demuxer: faster channel change for PVR addons +Subject: [PATCH 15/24] ffmpeg demuxer: faster channel change for PVR addons without internal demuxing (such as MediaPortal, ArgusTV, MythTV, NextPVR) Credits: FernetMenta, Davilla, Popcornmix, Whaupt @@ -1933,14 +1891,11 @@ index ca689d0..f383563 100644 return demuxer.release(); else return NULL; --- -2.0.4 - -From d6b8a9eaed29fe9e7cc52fcd3e337a374f86187c Mon Sep 17 00:00:00 2001 +From bad5185bcf6e73fbeb706f08d5651f18dd184e95 Mon Sep 17 00:00:00 2001 From: Wolfgang Haupt Date: Thu, 5 Dec 2013 22:11:57 +0100 -Subject: [PATCH 16/31] DVDFactoryDemuxer: skip streaminfo for udp tcp and +Subject: [PATCH 16/24] DVDFactoryDemuxer: skip streaminfo for udp tcp and pvr-channels --- @@ -1989,7 +1944,7 @@ index f383563..d6580fd 100644 if(demuxer->Open(pInputStream, streaminfo)) return demuxer.release(); diff --git a/xbmc/utils/URIUtils.cpp b/xbmc/utils/URIUtils.cpp -index 8278867..8040591 100644 +index 6346cee..ab12a4f 100644 --- a/xbmc/utils/URIUtils.cpp +++ b/xbmc/utils/URIUtils.cpp @@ -814,6 +814,36 @@ bool URIUtils::IsFTP(const CStdString& strFile) @@ -2029,7 +1984,7 @@ index 8278867..8040591 100644 bool URIUtils::IsDAV(const CStdString& strFile) { CStdString strFile2(strFile); -@@ -1296,3 +1326,8 @@ bool URIUtils::UpdateUrlEncoding(std::string &strFilename) +@@ -1297,3 +1327,8 @@ bool URIUtils::UpdateUrlEncoding(std::string &strFilename) strFilename = newFilename; return true; } @@ -2060,14 +2015,11 @@ index 667f6d3..0094709 100644 static void AddSlashAtEnd(std::string& strFolder); static bool HasSlashAtEnd(const std::string& strFile, bool checkURL = false); --- -2.0.4 - -From fa733c748a2a9259dc8032614df4182f8ed8125c Mon Sep 17 00:00:00 2001 +From b93ef4aa291333043a0d24e10cb99168e28b9fde Mon Sep 17 00:00:00 2001 From: Rainer Hochecker Date: Fri, 18 Jul 2014 10:39:07 +0200 -Subject: [PATCH 17/31] fast channel switch, make sure extradata is decoded +Subject: [PATCH 17/24] fast channel switch, make sure extradata is decoded --- xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp | 3 ++- @@ -2087,14 +2039,11 @@ index c01bc11..d38bfab 100644 st->codec->skip_loop_filter = AVDISCARD_ALL; // We are looking for an IDR frame --- -2.0.4 - -From 5bb5b183f8969475db282ff90a8d5382920f4546 Mon Sep 17 00:00:00 2001 +From 79903fad6805be1422b75116ea339780ac67be53 Mon Sep 17 00:00:00 2001 From: Rainer Hochecker Date: Wed, 23 Jul 2014 15:07:37 +0200 -Subject: [PATCH 18/31] ffmpeg demuxer: allow a stream change if pat/pmt was +Subject: [PATCH 18/24] ffmpeg demuxer: allow a stream change if pat/pmt was not seen on open --- @@ -2153,319 +2102,18 @@ index d38bfab..2332b1b 100644 if(m_program != UINT_MAX) { for (unsigned int i = 0; i < m_pFormatContext->programs[m_program]->nb_stream_indexes; i++) --- -2.0.4 - -From 75f483190ef00aed904023a1dce5c803d228804c Mon Sep 17 00:00:00 2001 -From: Rainer Hochecker -Date: Sun, 22 Dec 2013 14:52:29 +0100 -Subject: [PATCH 19/31] linux: add shared lib for sse4 operations - ---- - 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 27a9de0..75d79a6 100644 ---- a/Makefile.in -+++ b/Makefile.in -@@ -320,6 +320,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) -@@ -447,7 +453,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 725a271..5eb8465 100644 ---- a/configure.in -+++ b/configure.in -@@ -827,6 +827,19 @@ elif test "$use_arch" = "arm"; then - fi - 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 -@@ -2474,6 +2487,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" -@@ -2550,6 +2567,7 @@ AC_SUBST(GTEST_CONFIGURED) - AC_SUBST(USE_DOXYGEN) - AC_SUBST(USE_PVR_ADDONS) - AC_SUBST(UPNP_DEFINES) -+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 37a179b..1387cd4 100644 ---- a/xbmc/DllPaths_generated.h.in -+++ b/xbmc/DllPaths_generated.h.in -@@ -83,4 +83,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 -+ * . -+ * -+ */ -+ -+#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 -+ * . -+ * -+ */ -+ -+#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 --- -2.0.4 - - -From 955cd049218bfa250cb4331af4e96cc3e5f647af Mon Sep 17 00:00:00 2001 +From 224a0b9b80767ed6ce369594550f8470734ae2e2 Mon Sep 17 00:00:00 2001 From: Rainer Hochecker Date: Tue, 28 Jan 2014 10:05:26 +0100 -Subject: [PATCH 20/31] xbmc pr 3080 +Subject: [PATCH 19/24] xbmc pr 3080 --- 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 6920db2..d72e256 100644 +index 2481b66..40816e3 100644 --- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp +++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp @@ -477,6 +477,14 @@ int CDVDVideoCodecFFmpeg::Decode(uint8_t* pData, int iSize, double dts, double p @@ -2483,14 +2131,11 @@ index 6920db2..d72e256 100644 /* We lie, but this flag is only used by pngdec.c. * Setting it correctly would allow CorePNG decoding. */ avpkt.flags = AV_PKT_FLAG_KEY; --- -2.0.4 - -From ea66a597e55c5e96aa50e5f6c1ad3e116ea73f94 Mon Sep 17 00:00:00 2001 +From 3175f930c2edbea02b2e563e802fa4c9c837f2f0 Mon Sep 17 00:00:00 2001 From: Rainer Hochecker Date: Tue, 11 Feb 2014 18:15:06 +0100 -Subject: [PATCH 21/31] ActiveAE: add some debug logging +Subject: [PATCH 20/24] ActiveAE: add some debug logging --- xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEStream.cpp | 6 ++++++ @@ -2514,4783 +2159,11 @@ index ec10397..3b67fc0 100644 } return copied; } --- -2.0.4 - -From cb2f5af4e3804880785a5670857541dfce5795a0 Mon Sep 17 00:00:00 2001 -From: Rainer Hochecker -Date: Fri, 13 Jun 2014 14:37:16 +0200 -Subject: [PATCH 22/31] VAAPI: rewrite with VPP and ffmpeg filter - ---- - configure.in | 16 +- - language/English/strings.po | 34 +- - system/settings/settings.xml | 15 + - xbmc/cores/VideoRenderers/LinuxRendererGL.cpp | 262 +- - xbmc/cores/VideoRenderers/LinuxRendererGL.h | 9 +- - xbmc/cores/VideoRenderers/RenderFormats.h | 1 + - xbmc/cores/VideoRenderers/RenderManager.cpp | 15 +- - .../VideoRenderers/VideoShaders/YUV2RGBShader.cpp | 5 +- - .../dvdplayer/DVDCodecs/Video/DVDVideoCodec.h | 4 +- - .../DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp | 21 +- - xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.cpp | 3240 +++++++++++++++++--- - xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.h | 540 +++- - xbmc/cores/dvdplayer/DVDPlayerVideo.cpp | 1 + - xbmc/settings/VideoSettings.h | 4 + - xbmc/video/dialogs/GUIDialogVideoSettings.cpp | 3 + - 15 files changed, 3499 insertions(+), 671 deletions(-) - -diff --git a/configure.in b/configure.in -index 5eb8465..b4e4a5d 100644 ---- a/configure.in -+++ b/configure.in -@@ -1826,21 +1826,15 @@ if test "x$use_vaapi" != "xno"; then - USE_VAAPI=0 - else - initial_val=$use_vaapi -- AC_CHECK_LIB([va], main, :, use_vaapi=no) - if test "x$use_vaapi" != "xno"; then -- AC_CHECK_LIB([va-glx], main, LIBS="-lva -lva-glx $LIBS", use_vaapi=no, -lva) -- fi -- -- if test "x$use_vaapi" = "xno"; then -+ PKG_CHECK_MODULES([LIBVA], [libva libva-x11], -+ [INCLUDES="$INCLUDES $LIBVA_CFLAGS"; LIBS="$LIBS $LIBVA_LIBS"; USE_VAAPI=1; -+ AC_DEFINE([HAVE_LIBVA], [1], [Define to 1 if you have the 'vaapi' libraries])], -+ [use_vaapi="no"; USE_VAAPI=0; AC_MSG_RESULT($vaapi_not_found)]) -+ else - if test "x$initial_val" = "xyes"; then - AC_MSG_ERROR($vaapi_not_found) -- else -- AC_MSG_RESULT($vaapi_not_found) - fi -- USE_VAAPI=0 -- else -- AC_DEFINE([HAVE_LIBVA], [1], [Define to 1 if you have the 'vaapi' libraries (-lva AND -lva-glx)]) -- USE_VAAPI=1 - fi - fi - else -diff --git a/language/English/strings.po b/language/English/strings.po -index 6e7c98c..1ff8f13 100755 ---- a/language/English/strings.po -+++ b/language/English/strings.po -@@ -6190,7 +6190,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 "Prefer VAAPI render method" -+msgstr "" -+ -+#empty strings from id 13458 to 13499 - - #: system/settings/settings.xml - msgctxt "#13500" -@@ -7356,7 +7362,22 @@ msgctxt "#16326" - msgid "DXVA-HD" - msgstr "" - --#empty strings from id 16327 to 16399 -+#: xbmc/video/dialogs/GUIDialogVideoSettings.cpp -+msgctxt "#16327" -+msgid "VAAPI Bob" -+msgstr "" -+ -+#: xbmc/video/dialogs/GUIDialogVideoSettings.cpp -+msgctxt "#16328" -+msgid "VAAPI Motion Adaptive" -+msgstr "" -+ -+#: xbmc/video/dialogs/GUIDialogVideoSettings.cpp -+msgctxt "#16329" -+msgid "VAAPI Motion Compensated" -+msgstr "" -+ -+#empty strings from id 16330 to 16399 - - #: xbmc/video/dialogs/GUIDialogVideoSettings.cpp - msgctxt "#16400" -@@ -15369,7 +15390,14 @@ msgctxt "#36432" - msgid "Select virtual keyboard layouts." - msgstr "" - --#empty strings from id 36433 to 36499 -+#. Description for video related setting #13457: vaapi sw filter -+#: system/settings/settings.xml -+msgctxt "#36433" -+msgid "If enabled VAAPI render method is prefered. This puts less load on the CPU but driver may hang!" -+msgstr "" -+ -+#empty strings from id 36434 to 36499 -+ - #end reservation - - #: system/settings/settings.xml -diff --git a/system/settings/settings.xml b/system/settings/settings.xml -index d69ffc0..f604b30 100644 ---- a/system/settings/settings.xml -+++ b/system/settings/settings.xml -@@ -728,6 +728,21 @@ - false - - -+ -+ HAVE_LIBVA -+ -+ -+ -+ true -+ 1 -+ -+ -+ true -+ -+ 3 -+ true -+ -+ - - HasDXVA2 - -diff --git a/xbmc/cores/VideoRenderers/LinuxRendererGL.cpp b/xbmc/cores/VideoRenderers/LinuxRendererGL.cpp -index 987b276..1dcc33e 100644 ---- a/xbmc/cores/VideoRenderers/LinuxRendererGL.cpp -+++ b/xbmc/cores/VideoRenderers/LinuxRendererGL.cpp -@@ -62,13 +62,6 @@ extern "C" { - #include - #include "cores/dvdplayer/DVDCodecs/Video/VAAPI.h" - --#define USE_VAAPI_GLX_BIND \ -- (VA_MAJOR_VERSION == 0 && \ -- ((VA_MINOR_VERSION == 30 && \ -- VA_MICRO_VERSION == 4 && VA_SDS_VERSION >= 5) || \ -- (VA_MINOR_VERSION == 31 && \ -- VA_MICRO_VERSION == 0 && VA_SDS_VERSION < 5))) -- - #endif - - #ifdef TARGET_DARWIN -@@ -128,9 +121,6 @@ static const GLubyte stipple_weave[] = { - }; - - CLinuxRendererGL::YUVBUFFER::YUVBUFFER() --#ifdef HAVE_LIBVA -- : vaapi(*(new VAAPI::CHolder())) --#endif - { - memset(&fields, 0, sizeof(fields)); - memset(&image , 0, sizeof(image)); -@@ -139,6 +129,9 @@ CLinuxRendererGL::YUVBUFFER::YUVBUFFER() - #ifdef HAVE_LIBVDPAU - vdpau = NULL; - #endif -+#ifdef HAVE_LIBVA -+ vaapi = NULL; -+#endif - #ifdef TARGET_DARWIN_OSX - cvBufferRef = NULL; - #endif -@@ -146,9 +139,6 @@ CLinuxRendererGL::YUVBUFFER::YUVBUFFER() - - CLinuxRendererGL::YUVBUFFER::~YUVBUFFER() - { --#ifdef HAVE_LIBVA -- delete &vaapi; --#endif - #ifdef TARGET_DARWIN_OSX - if (cvBufferRef) - CVBufferRelease(cvBufferRef); -@@ -573,7 +563,7 @@ void CLinuxRendererGL::ReleaseBuffer(int idx) - SAFE_RELEASE(buf.vdpau); - #endif - #ifdef HAVE_LIBVA -- buf.vaapi.surface.reset(); -+ SAFE_RELEASE(buf.vaapi); - #endif - #ifdef TARGET_DARWIN - if (buf.cvBufferRef) -@@ -1056,7 +1046,8 @@ void CLinuxRendererGL::LoadShaders(int field) - m_pboUsed = false; - - // Now that we now the render method, setup texture function handlers -- if (m_format == RENDER_FMT_NV12) -+ if (m_format == RENDER_FMT_NV12 || -+ m_format == RENDER_FMT_VAAPINV12) - { - m_textureUpload = &CLinuxRendererGL::UploadNV12Texture; - m_textureCreate = &CLinuxRendererGL::CreateNV12Texture; -@@ -1193,14 +1184,14 @@ void CLinuxRendererGL::Render(DWORD flags, int renderBuffer) - else if (m_renderMethod & RENDER_VDPAU) - { - UpdateVideoFilter(); -- RenderVDPAU(renderBuffer, m_currentField); -+ RenderRGB(renderBuffer, m_currentField); - } - #endif - #ifdef HAVE_LIBVA - else if (m_renderMethod & RENDER_VAAPI) - { - UpdateVideoFilter(); -- RenderVAAPI(renderBuffer, m_currentField); -+ RenderRGB(renderBuffer, m_currentField); - } - #endif - else -@@ -1220,6 +1211,16 @@ void CLinuxRendererGL::Render(DWORD flags, int renderBuffer) - } - } - #endif -+#ifdef HAVE_LIBVA -+ if (m_format == RENDER_FMT_VAAPI) -+ { -+ YUVBUFFER &buf = m_buffers[renderBuffer]; -+ if (buf.vaapi) -+ { -+ buf.vaapi->Sync(); -+ } -+ } -+#endif - } - - void CLinuxRendererGL::RenderSinglePass(int index, int field) -@@ -1562,9 +1563,9 @@ void CLinuxRendererGL::RenderProgressiveWeave(int index, int field) - } - } - --void CLinuxRendererGL::RenderVDPAU(int index, int field) -+void CLinuxRendererGL::RenderRGB(int index, int field) - { --#ifdef HAVE_LIBVDPAU -+#if defined(HAVE_LIBVDPAU) || defined(HAVE_LIBVA) - YUVPLANE &plane = m_buffers[index].fields[FIELD_FULL][0]; - - glEnable(m_textureTarget); -@@ -1636,99 +1637,6 @@ void CLinuxRendererGL::RenderVDPAU(int index, int field) - #endif - } - --void CLinuxRendererGL::RenderVAAPI(int index, int field) --{ --#ifdef HAVE_LIBVA -- YUVPLANE &plane = m_buffers[index].fields[0][0]; -- VAAPI::CHolder &va = m_buffers[index].vaapi; -- -- if(!va.surface) -- { -- CLog::Log(LOGINFO, "CLinuxRendererGL::RenderVAAPI - no vaapi object"); -- return; -- } -- VAAPI::CDisplayPtr& display(va.surface->m_display); -- CSingleLock lock(*display); -- -- glEnable(m_textureTarget); -- glActiveTextureARB(GL_TEXTURE0); -- glBindTexture(m_textureTarget, plane.id); -- --#if USE_VAAPI_GLX_BIND -- VAStatus status; -- status = vaBeginRenderSurfaceGLX(display->get(), va.surfglx->m_id); -- if(status != VA_STATUS_SUCCESS) -- { -- CLog::Log(LOGERROR, "CLinuxRendererGL::RenderVAAPI - vaBeginRenderSurfaceGLX failed (%d)", status); -- return; -- } --#endif -- -- // make sure we know the correct texture size -- GetPlaneTextureSize(plane); -- CalculateTextureSourceRects(index, 1); -- -- // Try some clamping or wrapping -- glTexParameteri(m_textureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); -- glTexParameteri(m_textureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); -- -- if (m_pVideoFilterShader) -- { -- GLint filter; -- if (!m_pVideoFilterShader->GetTextureFilter(filter)) -- filter = m_scalingMethod == VS_SCALINGMETHOD_NEAREST ? GL_NEAREST : GL_LINEAR; -- -- glTexParameteri(m_textureTarget, GL_TEXTURE_MAG_FILTER, filter); -- glTexParameteri(m_textureTarget, GL_TEXTURE_MIN_FILTER, filter); -- m_pVideoFilterShader->SetSourceTexture(0); -- m_pVideoFilterShader->SetWidth(m_sourceWidth); -- m_pVideoFilterShader->SetHeight(m_sourceHeight); -- -- //disable non-linear stretch when a dvd menu is shown, parts of the menu are rendered through the overlay renderer -- //having non-linear stretch on breaks the alignment -- if (g_application.m_pPlayer->IsInMenu()) -- m_pVideoFilterShader->SetNonLinStretch(1.0); -- else -- m_pVideoFilterShader->SetNonLinStretch(pow(CDisplaySettings::Get().GetPixelRatio(), g_advancedSettings.m_videoNonLinStretchRatio)); -- -- m_pVideoFilterShader->Enable(); -- } -- else -- { -- GLint filter = m_scalingMethod == VS_SCALINGMETHOD_NEAREST ? GL_NEAREST : GL_LINEAR; -- glTexParameteri(m_textureTarget, GL_TEXTURE_MAG_FILTER, filter); -- glTexParameteri(m_textureTarget, GL_TEXTURE_MIN_FILTER, filter); -- } -- -- glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); -- VerifyGLState(); -- -- glBegin(GL_QUADS); -- glTexCoord2f(plane.rect.x1, plane.rect.y1); glVertex2f(m_rotatedDestCoords[0].x, m_rotatedDestCoords[0].y); -- glTexCoord2f(plane.rect.x2, plane.rect.y1); glVertex2f(m_rotatedDestCoords[1].x, m_rotatedDestCoords[1].y); -- glTexCoord2f(plane.rect.x2, plane.rect.y2); glVertex2f(m_rotatedDestCoords[2].x, m_rotatedDestCoords[2].y); -- glTexCoord2f(plane.rect.x1, plane.rect.y2); glVertex2f(m_rotatedDestCoords[3].x, m_rotatedDestCoords[3].y); -- glEnd(); -- -- VerifyGLState(); -- -- if (m_pVideoFilterShader) -- m_pVideoFilterShader->Disable(); -- --#if USE_VAAPI_GLX_BIND -- status = vaEndRenderSurfaceGLX(display->get(), va.surfglx->m_id); -- if(status != VA_STATUS_SUCCESS) -- { -- CLog::Log(LOGERROR, "CLinuxRendererGL::RenderVAAPI - vaEndRenderSurfaceGLX failed (%d)", status); -- return; -- } --#endif -- -- glBindTexture (m_textureTarget, 0); -- glDisable(m_textureTarget); --#endif --} -- - void CLinuxRendererGL::RenderSoftware(int index, int field) - { - // used for textues uploaded from rgba or CVPixelBuffers. -@@ -2593,17 +2501,9 @@ bool CLinuxRendererGL::UploadVDPAUTexture420(int index) - void CLinuxRendererGL::DeleteVAAPITexture(int index) - { - #ifdef HAVE_LIBVA -- YUVPLANE &plane = m_buffers[index].fields[0][0]; -- VAAPI::CHolder &va = m_buffers[index].vaapi; -- -- va.display.reset(); -- va.surface.reset(); -- va.surfglx.reset(); -- -- if(plane.id && glIsTexture(plane.id)) -- glDeleteTextures(1, &plane.id); -+ YUVPLANE &plane = m_buffers[index].fields[FIELD_FULL][0]; -+ SAFE_RELEASE(m_buffers[index].vaapi); - plane.id = 0; -- - #endif - } - -@@ -2653,83 +2553,44 @@ bool CLinuxRendererGL::CreateVAAPITexture(int index) - bool CLinuxRendererGL::UploadVAAPITexture(int index) - { - #ifdef HAVE_LIBVA -- YUVPLANE &plane = m_buffers[index].fields[0][0]; -- VAAPI::CHolder &va = m_buffers[index].vaapi; -- VAStatus status; -+ VAAPI::CVaapiRenderPicture *vaapi = m_buffers[index].vaapi; - -- if(!va.surface) -- return false; -+ YV12Image &im = m_buffers[index].image; -+ YUVFIELDS &fields = m_buffers[index].fields; -+ YUVPLANE &plane = fields[FIELD_FULL][0]; - -- if(va.display && va.surface->m_display != va.display) -+ if (!vaapi || !vaapi->valid) - { -- CLog::Log(LOGDEBUG, "CLinuxRendererGL::UploadVAAPITexture - context changed %d", index); -- va.surfglx.reset(); -+ return false; - } -- va.display = va.surface->m_display; -- -- CSingleLock lock(*va.display); - -- if(va.display->lost()) -- return false; -+ plane.id = vaapi->texture; - -- if(!va.surfglx) -- { -- CLog::Log(LOGDEBUG, "CLinuxRendererGL::UploadVAAPITexture - creating vaapi surface for texture %d", index); -- void* surface; -- status = vaCreateSurfaceGLX(va.display->get() -- , m_textureTarget -- , plane.id -- , &surface); -- if(status != VA_STATUS_SUCCESS) -- { -- CLog::Log(LOGERROR, "CLinuxRendererGL::UploadVAAPITexture - failed to create vaapi glx surface (%d)", status); -- return false; -- } -- va.surfglx = VAAPI::CSurfaceGLPtr(new VAAPI::CSurfaceGL(surface, va.display)); -- } -- int colorspace; -- if(CONF_FLAGS_YUVCOEF_MASK(m_iFlags) == CONF_FLAGS_YUVCOEF_BT709) -- colorspace = VA_SRC_BT709; -- else -- colorspace = VA_SRC_BT601; -+ // in stereoscopic mode sourceRect may only -+ // be a part of the source video surface -+ plane.rect = m_sourceRect; - -- int field; -- if (m_currentField == FIELD_TOP) -- field = VA_TOP_FIELD; -- else if (m_currentField == FIELD_BOT) -- field = VA_BOTTOM_FIELD; -- else -- field = VA_FRAME_PICTURE; -- --#if USE_VAAPI_GLX_BIND -- status = vaAssociateSurfaceGLX(va.display->get() -- , va.surfglx->m_id -- , va.surface->m_id -- , field | colorspace); --#else -- glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); -- status = vaCopySurfaceGLX(va.display->get() -- , va.surfglx->m_id -- , va.surface->m_id -- , field | colorspace); --#endif -+ // clip rect -+ if (vaapi->crop.x1 > plane.rect.x1) -+ plane.rect.x1 = vaapi->crop.x1; -+ if (vaapi->crop.x2 < plane.rect.x2) -+ plane.rect.x2 = vaapi->crop.x2; -+ if (vaapi->crop.y1 > plane.rect.y1) -+ plane.rect.y1 = vaapi->crop.y1; -+ if (vaapi->crop.y2 < plane.rect.y2) -+ plane.rect.y2 = vaapi->crop.y2; -+ -+ plane.texheight = vaapi->texHeight; -+ plane.texwidth = vaapi->texWidth; - -- // when a vaapi backend is lost (vdpau), we start getting these errors -- if(status == VA_STATUS_ERROR_INVALID_SURFACE -- || status == VA_STATUS_ERROR_INVALID_DISPLAY) -+ if (m_textureTarget == GL_TEXTURE_2D) - { -- va.display->lost(true); -- for(int i = 0; i < m_NumYV12Buffers; i++) -- { -- m_buffers[i].vaapi.display.reset(); -- m_buffers[i].vaapi.surface.reset(); -- m_buffers[i].vaapi.surfglx.reset(); -- } -+ plane.rect.y1 /= plane.texheight; -+ plane.rect.y2 /= plane.texheight; -+ plane.rect.x1 /= plane.texwidth; -+ plane.rect.x2 /= plane.texwidth; - } - -- if(status != VA_STATUS_SUCCESS) -- CLog::Log(LOGERROR, "CLinuxRendererGL::UploadVAAPITexture - failed to copy surface to glx %d - %s", status, vaErrorStr(status)); -- - #endif - return true; - } -@@ -3527,21 +3388,13 @@ bool CLinuxRendererGL::Supports(EINTERLACEMETHOD method) - return false; - } - -- if(m_renderMethod & RENDER_VAAPI) -+ if(m_format == RENDER_FMT_VAAPI || -+ m_format == RENDER_FMT_VAAPINV12) - { - #ifdef HAVE_LIBVA -- VAAPI::CDisplayPtr disp = m_buffers[m_iYV12RenderBuffer].vaapi.display; -- if(disp) -- { -- CSingleLock lock(*disp); -- -- if(disp->support_deinterlace()) -- { -- if( method == VS_INTERLACEMETHOD_RENDER_BOB_INVERTED -- || method == VS_INTERLACEMETHOD_RENDER_BOB ) -- return true; -- } -- } -+ VAAPI::CVaapiRenderPicture *vaapiPic = m_buffers[m_iYV12RenderBuffer].vaapi; -+ if(vaapiPic && vaapiPic->vaapi) -+ return vaapiPic->vaapi->Supports(method); - #endif - return false; - } -@@ -3662,6 +3515,7 @@ unsigned int CLinuxRendererGL::GetProcessorSize() - if(m_format == RENDER_FMT_VDPAU - || m_format == RENDER_FMT_VDPAU_420 - || m_format == RENDER_FMT_VAAPI -+ || m_format == RENDER_FMT_VAAPINV12 - || m_format == RENDER_FMT_CVBREF) - return 1; - else -@@ -3679,10 +3533,12 @@ void CLinuxRendererGL::AddProcessor(VDPAU::CVdpauRenderPicture *vdpau, int index - #endif - - #ifdef HAVE_LIBVA --void CLinuxRendererGL::AddProcessor(VAAPI::CHolder& holder, int index) -+void CLinuxRendererGL::AddProcessor(VAAPI::CVaapiRenderPicture *vaapi, int index) - { - YUVBUFFER &buf = m_buffers[index]; -- buf.vaapi.surface = holder.surface; -+ VAAPI::CVaapiRenderPicture *pic = vaapi->Acquire(); -+ SAFE_RELEASE(buf.vaapi); -+ buf.vaapi = pic; - } - #endif - -diff --git a/xbmc/cores/VideoRenderers/LinuxRendererGL.h b/xbmc/cores/VideoRenderers/LinuxRendererGL.h -index 304017f..1e46940 100644 ---- a/xbmc/cores/VideoRenderers/LinuxRendererGL.h -+++ b/xbmc/cores/VideoRenderers/LinuxRendererGL.h -@@ -41,7 +41,7 @@ class CRenderCapture; - class CBaseTexture; - namespace Shaders { class BaseYUV2RGBShader; } - namespace Shaders { class BaseVideoFilterShader; } --namespace VAAPI { struct CHolder; } -+namespace VAAPI { class CVaapiRenderPicture; } - namespace VDPAU { class CVdpauRenderPicture; } - - #undef ALIGN -@@ -142,7 +142,7 @@ class CLinuxRendererGL : public CBaseRenderer - virtual void AddProcessor(VDPAU::CVdpauRenderPicture* vdpau, int index); - #endif - #ifdef HAVE_LIBVA -- virtual void AddProcessor(VAAPI::CHolder& holder, int index); -+ virtual void AddProcessor(VAAPI::CVaapiRenderPicture* vaapi, int index); - #endif - #ifdef TARGET_DARWIN - virtual void AddProcessor(struct __CVBuffer *cvBufferRef, int index); -@@ -218,9 +218,8 @@ class CLinuxRendererGL : public CBaseRenderer - void RenderFromFBO(); - void RenderSinglePass(int renderBuffer, int field); // single pass glsl renderer - void RenderSoftware(int renderBuffer, int field); // single pass s/w yuv2rgb renderer -- void RenderVDPAU(int renderBuffer, int field); // render using vdpau hardware -+ void RenderRGB(int renderBuffer, int field); // render using vdpau/vaapi hardware - void RenderProgressiveWeave(int renderBuffer, int field); // render using vdpau hardware -- void RenderVAAPI(int renderBuffer, int field); // render using vdpau hardware - - struct - { -@@ -282,7 +281,7 @@ class CLinuxRendererGL : public CBaseRenderer - VDPAU::CVdpauRenderPicture *vdpau; - #endif - #ifdef HAVE_LIBVA -- VAAPI::CHolder& vaapi; -+ VAAPI::CVaapiRenderPicture *vaapi; - #endif - #ifdef TARGET_DARWIN_OSX - struct __CVBuffer *cvBufferRef; -diff --git a/xbmc/cores/VideoRenderers/RenderFormats.h b/xbmc/cores/VideoRenderers/RenderFormats.h -index f15e80d..15e1d76 100644 ---- a/xbmc/cores/VideoRenderers/RenderFormats.h -+++ b/xbmc/cores/VideoRenderers/RenderFormats.h -@@ -32,6 +32,7 @@ enum ERenderFormat { - RENDER_FMT_YUYV422, - RENDER_FMT_DXVA, - RENDER_FMT_VAAPI, -+ RENDER_FMT_VAAPINV12, - RENDER_FMT_OMXEGL, - RENDER_FMT_CVBREF, - RENDER_FMT_BYPASS, -diff --git a/xbmc/cores/VideoRenderers/RenderManager.cpp b/xbmc/cores/VideoRenderers/RenderManager.cpp -index 61e1fe3..1ae5c9f 100644 ---- a/xbmc/cores/VideoRenderers/RenderManager.cpp -+++ b/xbmc/cores/VideoRenderers/RenderManager.cpp -@@ -56,6 +56,10 @@ - #include "../dvdplayer/DVDCodecs/Video/DVDVideoCodec.h" - #include "../dvdplayer/DVDCodecs/DVDCodecUtils.h" - -+#ifdef HAVE_LIBVA -+ #include "../dvdplayer/DVDCodecs/Video/VAAPI.h" -+#endif -+ - #define MAXPRESENTDELAY 0.500 - - /* at any point we want an exclusive lock on rendermanager */ -@@ -925,7 +929,12 @@ int CXBMCRenderManager::AddVideoPicture(DVDVideoPicture& pic) - #endif - #ifdef HAVE_LIBVA - else if(pic.format == RENDER_FMT_VAAPI) -- m_pRenderer->AddProcessor(*pic.vaapi, index); -+ m_pRenderer->AddProcessor(pic.vaapi, index); -+ else if(pic.format == RENDER_FMT_VAAPINV12) -+ { -+ m_pRenderer->AddProcessor(pic.vaapi, index); -+ CDVDCodecUtils::CopyNV12Picture(&image, &pic.vaapi->DVDPic); -+ } - #endif - #ifdef HAS_LIBSTAGEFRIGHT - else if(pic.format == RENDER_FMT_EGLIMG) -@@ -988,10 +997,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/VideoRenderers/VideoShaders/YUV2RGBShader.cpp b/xbmc/cores/VideoRenderers/VideoShaders/YUV2RGBShader.cpp -index 21a4ee2..b675995 100644 ---- a/xbmc/cores/VideoRenderers/VideoShaders/YUV2RGBShader.cpp -+++ b/xbmc/cores/VideoRenderers/VideoShaders/YUV2RGBShader.cpp -@@ -208,13 +208,14 @@ BaseYUV2RGBGLSLShader::BaseYUV2RGBGLSLShader(bool rect, unsigned flags, ERenderF - m_format == RENDER_FMT_YUV420P10 || - m_format == RENDER_FMT_YUV420P16) - m_defines += "#define XBMC_YV12\n"; -- else if (m_format == RENDER_FMT_NV12) -+ else if (m_format == RENDER_FMT_NV12 || -+ m_format == RENDER_FMT_VAAPINV12) - m_defines += "#define XBMC_NV12\n"; - else if (m_format == RENDER_FMT_YUYV422) - m_defines += "#define XBMC_YUY2\n"; - else if (m_format == RENDER_FMT_UYVY422) - m_defines += "#define XBMC_UYVY\n"; -- else if (RENDER_FMT_VDPAU_420) -+ else if (m_format == RENDER_FMT_VDPAU_420) - m_defines += "#define XBMC_VDPAU_NV12\n"; - else - CLog::Log(LOGERROR, "GL: BaseYUV2RGBGLSLShader - unsupported format %d", m_format); -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h -index c5b24d6..69ff8c9 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h -@@ -46,7 +46,7 @@ struct DVDCodecAvailableType - #define FRAME_TYPE_D 4 - - namespace DXVA { class CSurfaceContext; } --namespace VAAPI { struct CHolder; } -+namespace VAAPI { class CVaapiRenderPicture; } - namespace VDPAU { class CVdpauRenderPicture; } - class COpenMax; - class COpenMaxVideo; -@@ -75,7 +75,7 @@ struct DVDVideoPicture - VDPAU::CVdpauRenderPicture* vdpau; - }; - struct { -- VAAPI::CHolder* vaapi; -+ VAAPI::CVaapiRenderPicture* vaapi; - }; - - struct { -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp -index d72e256..a4ebcd8 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp -@@ -630,6 +630,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; -@@ -653,10 +654,24 @@ 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); -+ -+ 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; - -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.cpp -index e1637fa..9aec0c9 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.cpp -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.cpp -@@ -22,534 +22,3046 @@ - #include "windowing/WindowingFactory.h" - #include "VAAPI.h" - #include "DVDVideoCodec.h" --#include --#include -+#include "cores/dvdplayer/DVDCodecs/DVDCodecUtils.h" -+#include "cores/dvdplayer/DVDClock.h" - #include "utils/log.h" -+#include "utils/StringUtils.h" - #include "threads/SingleLock.h" -- --#define CHECK(a) \ --do { \ -- VAStatus res = a; \ -- if(res != VA_STATUS_SUCCESS) \ -- { \ -- CLog::Log(LOGERROR, "VAAPI - failed executing "#a" at line %d with error %x:%s", __LINE__, res, vaErrorStr(res)); \ -- return false; \ -- } \ --} while(0); -- --#define WARN(a) \ --do { \ -- VAStatus res = a; \ -- if(res != VA_STATUS_SUCCESS) \ -- CLog::Log(LOGWARNING, "VAAPI - failed executing "#a" at line %d with error %x:%s", __LINE__, res, vaErrorStr(res)); \ --} while(0); -+#include "settings/Settings.h" -+#include "guilib/GraphicContext.h" -+#include "settings/MediaSettings.h" -+#include -+ -+extern "C" { -+#include "libavutil/avutil.h" -+#include "libavutil/opt.h" -+#include "libavfilter/buffersink.h" -+#include "libavfilter/buffersrc.h" -+} - - #ifndef VA_SURFACE_ATTRIB_SETTABLE - #define vaCreateSurfaces(d, f, w, h, s, ns, a, na) \ -- vaCreateSurfaces(d, w, h, f, ns, s) -+vaCreateSurfaces(d, w, h, f, ns, s) -+#endif -+ -+#if VA_CHECK_VERSION(0,34,0) -+#include -+#define HAVE_VPP 1 - #endif - --using namespace std; --using namespace boost; - using namespace VAAPI; -+#define NUM_RENDER_PICS 7 - --// settings codecs mapping --DVDCodecAvailableType g_vaapi_available[] = { -- { AV_CODEC_ID_H263, "videoplayer.usevaapimpeg4" }, -- { AV_CODEC_ID_MPEG4, "videoplayer.usevaapimpeg4" }, -- { AV_CODEC_ID_WMV3, "videoplayer.usevaapivc1" }, -- { AV_CODEC_ID_VC1, "videoplayer.usevaapivc1" }, -- { AV_CODEC_ID_MPEG2VIDEO, "videoplayer.usevaapimpeg2" }, --}; --const size_t settings_count = sizeof(g_vaapi_available) / sizeof(DVDCodecAvailableType); -+//----------------------------------------------------------------------------- -+//----------------------------------------------------------------------------- -+ -+CVAAPIContext *CVAAPIContext::m_context = 0; -+CCriticalSection CVAAPIContext::m_section; -+Display *CVAAPIContext::m_X11dpy = 0; - --static int compare_version(int major_l, int minor_l, int micro_l, int major_r, int minor_r, int micro_r) -+CVAAPIContext::CVAAPIContext() - { -- if(major_l < major_r) return -1; -- if(major_l > major_r) return 1; -- if(minor_l < minor_r) return -1; -- if(minor_l > minor_r) return 1; -- if(micro_l < micro_r) return -1; -- if(micro_l > micro_r) return 1; -- return 0; -+ m_context = 0; -+ m_refCount = 0; -+ m_attributes = NULL; -+ m_profiles = NULL; -+ m_display = NULL; - } - --static void RelBufferS(void *opaque, uint8_t *data) --{ ((CDecoder*)((CDVDVideoCodecFFmpeg*)opaque)->GetHardware())->RelBuffer(data); } -+void CVAAPIContext::Release(CDecoder *decoder) -+{ -+ CSingleLock lock(m_section); -+ -+ std::vector::iterator it; -+ it = find(m_decoders.begin(), m_decoders.end(), decoder); -+ if (it != m_decoders.end()) -+ m_decoders.erase(it); - --static int GetBufferS(AVCodecContext *avctx, AVFrame *pic, int flags) --{ return ((CDecoder*)((CDVDVideoCodecFFmpeg*)avctx->opaque)->GetHardware())->GetBuffer(avctx, pic, flags); } -+ m_refCount--; -+ if (m_refCount <= 0) -+ { -+ Close(); -+ delete this; -+ m_context = 0; -+ } -+} - --static inline VASurfaceID GetSurfaceID(AVFrame *pic) --{ return (VASurfaceID)(uintptr_t)pic->data[3]; } -+void CVAAPIContext::Close() -+{ -+ CLog::Log(LOGNOTICE, "VAAPI::Close - closing decoder context"); -+ DestroyContext(); -+} - --static CDisplayPtr GetGlobalDisplay() -+bool CVAAPIContext::EnsureContext(CVAAPIContext **ctx, CDecoder *decoder) - { -- static boost::weak_ptr display_global; -+ CSingleLock lock(m_section); - -- CDisplayPtr display(display_global.lock()); -- if(display) -+ if (m_context) - { -- if(display->lost()) -+ m_context->m_refCount++; -+ *ctx = m_context; -+ if (!m_context->IsValidDecoder(decoder)) -+ m_context->m_decoders.push_back(decoder); -+ return true; -+ } -+ -+ m_context = new CVAAPIContext(); -+ *ctx = m_context; -+ { -+ CSingleLock gLock(g_graphicsContext); -+ if (!m_context->CreateContext()) - { -- CLog::Log(LOGERROR, "VAAPI - vaapi display is in lost state"); -- display.reset(); -- } -- return display; -+ delete m_context; -+ m_context = 0; -+ *ctx = NULL; -+ return false; -+ } -+ } -+ -+ m_context->m_refCount++; -+ -+ if (!m_context->IsValidDecoder(decoder)) -+ m_context->m_decoders.push_back(decoder); -+ *ctx = m_context; -+ return true; -+} -+ -+bool CVAAPIContext::CreateContext() -+{ -+ { CSingleLock lock(g_graphicsContext); -+ if (!m_X11dpy) -+ m_X11dpy = XOpenDisplay(NULL); - } - -- VADisplay disp; -- disp = vaGetDisplayGLX(g_Windowing.GetDisplay()); -+ m_display = vaGetDisplay(m_X11dpy); - - int major_version, minor_version; -- VAStatus res = vaInitialize(disp, &major_version, &minor_version); -+ if (!CheckSuccess(vaInitialize(m_display, &major_version, &minor_version))) -+ { -+ m_display = NULL; -+ return false; -+ } - - CLog::Log(LOGDEBUG, "VAAPI - initialize version %d.%d", major_version, minor_version); - -- if(res != VA_STATUS_SUCCESS) -+ -+ QueryCaps(); -+ if (!m_profileCount || !m_attributeCount) -+ return false; -+ -+ return true; -+} -+ -+void CVAAPIContext::DestroyContext() -+{ -+ delete[] m_attributes; -+ delete[] m_profiles; -+ if (m_display) -+ CheckSuccess(vaTerminate(m_display)); -+} -+ -+void CVAAPIContext::QueryCaps() -+{ -+ m_attributeCount = 0; -+ m_profileCount = 0; -+ -+ int max_attributes = vaMaxNumDisplayAttributes(m_display); -+ m_attributes = new VADisplayAttribute[max_attributes]; -+ -+ if (!CheckSuccess(vaQueryDisplayAttributes(m_display, m_attributes, &m_attributeCount))) -+ return; -+ -+ for(int i = 0; i < m_attributeCount; i++) - { -- CLog::Log(LOGERROR, "VAAPI - unable to initialize display %d - %s", res, vaErrorStr(res)); -- return display; -+ VADisplayAttribute * const display_attr = &m_attributes[i]; -+ CLog::Log(LOGDEBUG, "VAAPI - attrib %d (%s/%s) min %d max %d value 0x%x\n" -+ , display_attr->type -+ ,(display_attr->flags & VA_DISPLAY_ATTRIB_GETTABLE) ? "get" : "---" -+ ,(display_attr->flags & VA_DISPLAY_ATTRIB_SETTABLE) ? "set" : "---" -+ , display_attr->min_value -+ , display_attr->max_value -+ , display_attr->value); - } - -- const char* vendor = vaQueryVendorString(disp); -- CLog::Log(LOGDEBUG, "VAAPI - vendor: %s", vendor); -+ int max_profiles = vaMaxNumProfiles(m_display); -+ m_profiles = new VAProfile[max_profiles]; -+ -+ if (!CheckSuccess(vaQueryConfigProfiles(m_display, m_profiles, &m_profileCount))) -+ return; -+ -+ for(int i = 0; i < m_profileCount; i++) -+ CLog::Log(LOGDEBUG, "VAAPI - profile %d", m_profiles[i]); -+} -+ -+VAConfigAttrib CVAAPIContext::GetAttrib(VAProfile profile) -+{ -+ CSingleLock lock(m_section); -+ -+ VAConfigAttrib attrib; -+ attrib.type = VAConfigAttribRTFormat; -+ CheckSuccess(vaGetConfigAttributes(m_display, profile, VAEntrypointVLD, &attrib, 1)); -+ -+ return attrib; -+} -+ -+bool CVAAPIContext::SupportsProfile(VAProfile profile) -+{ -+ CSingleLock lock(m_section); - -- bool deinterlace = true; -- int major, minor, micro; -- bool support_4k = true; -- if(sscanf(vendor, "Intel i965 driver - %d.%d.%d", &major, &minor, µ) == 3) -+ for (int i=0; isupport_4k(support_4k); -- display_global = display; -- return display; -+ VAConfigID config = VA_INVALID_ID; -+ CheckSuccess(vaCreateConfig(m_display, profile, VAEntrypointVLD, &attrib, 1, &config)); -+ -+ return config; - } - --CDisplay::~CDisplay() -+bool CVAAPIContext::CheckSuccess(VAStatus status) - { -- CLog::Log(LOGDEBUG, "VAAPI - destroying display %p", m_display); -- WARN(vaTerminate(m_display)) -+ if (status != VA_STATUS_SUCCESS) -+ { -+ CLog::Log(LOGERROR, "VAAPI error: %s", vaErrorStr(status)); -+ return false; -+ } -+ return true; - } - --CSurface::~CSurface() -+VADisplay CVAAPIContext::GetDisplay() - { -- CLog::Log(LOGDEBUG, "VAAPI - destroying surface 0x%x", (int)m_id); -- CSingleLock lock(*m_display); -- WARN(vaDestroySurfaces(m_display->get(), &m_id, 1)) -+ return m_display; - } - --CSurfaceGL::~CSurfaceGL() -+bool CVAAPIContext::IsValidDecoder(CDecoder *decoder) - { -- CLog::Log(LOGDEBUG, "VAAPI - destroying glx surface %p", m_id); -- CSingleLock lock(*m_display); -- WARN(vaDestroySurfaceGLX(m_display->get(), m_id)) -+ std::vector::iterator it; -+ it = find(m_decoders.begin(), m_decoders.end(), decoder); -+ if (it != m_decoders.end()) -+ return true; -+ -+ return false; - } - --CDecoder::CDecoder() -+void CVAAPIContext::FFReleaseBuffer(void *opaque, uint8_t *data) - { -- m_refs = 0; -- m_surfaces_count = 0; -- m_config = 0; -- m_context = 0; -- m_hwaccel = (vaapi_context*)calloc(1, sizeof(vaapi_context)); -- memset(m_surfaces, 0, sizeof(*m_surfaces)); -+ CDecoder *va = (CDecoder*)opaque; -+ if (m_context && m_context->IsValidDecoder(va)) -+ { -+ va->FFReleaseBuffer(data); -+ } - } - --CDecoder::~CDecoder() -+//----------------------------------------------------------------------------- -+// VAAPI Video Surface states -+//----------------------------------------------------------------------------- -+ -+#define SURFACE_USED_FOR_REFERENCE 0x01 -+#define SURFACE_USED_FOR_RENDER 0x02 -+ -+void CVideoSurfaces::AddSurface(VASurfaceID surf) - { -- Close(); -- free(m_hwaccel); -+ CSingleLock lock(m_section); -+ m_state[surf] = 0; -+ m_freeSurfaces.push_back(surf); - } - --void CDecoder::RelBuffer(uint8_t *data) -+void CVideoSurfaces::ClearReference(VASurfaceID surf) - { -- VASurfaceID surface = (VASurfaceID)(uintptr_t)data; -+ CSingleLock lock(m_section); -+ if (m_state.find(surf) == m_state.end()) -+ { -+ CLog::Log(LOGWARNING, "CVideoSurfaces::ClearReference - surface invalid"); -+ return; -+ } -+ m_state[surf] &= ~SURFACE_USED_FOR_REFERENCE; -+ if (m_state[surf] == 0) -+ { -+ m_freeSurfaces.push_back(surf); -+ } -+} - -- for(std::list::iterator it = m_surfaces_used.begin(); it != m_surfaces_used.end(); ++it) -- { -- if((*it)->m_id == surface) -- { -- m_surfaces_free.push_back(*it); -- m_surfaces_used.erase(it); -- break; -- } -+bool CVideoSurfaces::MarkRender(VASurfaceID surf) -+{ -+ CSingleLock lock(m_section); -+ if (m_state.find(surf) == m_state.end()) -+ { -+ CLog::Log(LOGWARNING, "CVideoSurfaces::MarkRender - surface invalid"); -+ return false; - } -+ std::list::iterator it; -+ it = std::find(m_freeSurfaces.begin(), m_freeSurfaces.end(), surf); -+ if (it != m_freeSurfaces.end()) -+ { -+ m_freeSurfaces.erase(it); -+ } -+ m_state[surf] |= SURFACE_USED_FOR_RENDER; -+ return true; -+} -+ -+void CVideoSurfaces::ClearRender(VASurfaceID surf) -+{ -+ CSingleLock lock(m_section); -+ if (m_state.find(surf) == m_state.end()) -+ { -+ CLog::Log(LOGWARNING, "CVideoSurfaces::ClearRender - surface invalid"); -+ return; -+ } -+ m_state[surf] &= ~SURFACE_USED_FOR_RENDER; -+ if (m_state[surf] == 0) -+ { -+ m_freeSurfaces.push_back(surf); -+ } -+} -+ -+bool CVideoSurfaces::IsValid(VASurfaceID surf) -+{ -+ CSingleLock lock(m_section); -+ if (m_state.find(surf) != m_state.end()) -+ return true; -+ else -+ return false; - } - --int CDecoder::GetBuffer(AVCodecContext *avctx, AVFrame *pic, int flags) -+VASurfaceID CVideoSurfaces::GetFree(VASurfaceID surf) - { -- VASurfaceID surface = GetSurfaceID(pic); -- CSurface* wrapper = NULL; -- std::list::iterator it = m_surfaces_free.begin(); -- if(surface) -+ CSingleLock lock(m_section); -+ if (m_state.find(surf) != m_state.end()) - { -- /* reget call */ -- for(; it != m_surfaces_free.end(); ++it) -+ std::list::iterator it; -+ it = std::find(m_freeSurfaces.begin(), m_freeSurfaces.end(), surf); -+ if (it == m_freeSurfaces.end()) - { -- if((*it)->m_id == surface) -- { -- wrapper = it->get(); -- m_surfaces_used.push_back(*it); -- m_surfaces_free.erase(it); -- break; -- } -+ CLog::Log(LOGWARNING, "CVideoSurfaces::GetFree - surface not free"); - } -- if(!wrapper) -+ else - { -- CLog::Log(LOGERROR, "VAAPI - unable to find requested surface"); -- return -1; -+ m_freeSurfaces.erase(it); -+ m_state[surf] = SURFACE_USED_FOR_REFERENCE; -+ return surf; - } - } -- else -+ -+ if (!m_freeSurfaces.empty()) - { -- // To avoid stutter, we scan the free surface pool (provided by decoder) for surfaces -- // that are 100% not in use by renderer. The pointers to these surfaces have a use_count of 1. -- for (; it != m_surfaces_free.end() && it->use_count() > 1; ++it) {} -+ VASurfaceID freeSurf = m_freeSurfaces.front(); -+ m_freeSurfaces.pop_front(); -+ m_state[freeSurf] = SURFACE_USED_FOR_REFERENCE; -+ return freeSurf; -+ } - -- // If we have zero free surface from decoder OR all free surfaces are in use by renderer, we allocate a new surface -- if (it == m_surfaces_free.end()) -- { -- if (!m_surfaces_free.empty()) CLog::Log(LOGERROR, "VAAPI - renderer still using all freed up surfaces by decoder"); -- CLog::Log(LOGERROR, "VAAPI - unable to find free surface, trying to allocate a new one"); -- if(!EnsureSurfaces(avctx, m_surfaces_count+1) || m_surfaces_free.empty()) -- { -- CLog::Log(LOGERROR, "VAAPI - unable to find free surface"); -- return -1; -- } -- // Set itarator position to the newly allocated surface (end-1) -- it = m_surfaces_free.end(); --it; -- } -- /* getbuffer call */ -- wrapper = it->get(); -- surface = wrapper->m_id; -- m_surfaces_used.push_back(*it); -- m_surfaces_free.erase(it); -- } -- -- pic->data[0] = (uint8_t*)wrapper; -- pic->data[1] = NULL; -- pic->data[2] = NULL; -- pic->data[3] = (uint8_t*)(uintptr_t)surface; -- pic->linesize[0] = 0; -- pic->linesize[1] = 0; -- pic->linesize[2] = 0; -- pic->linesize[3] = 0; -- pic->reordered_opaque= avctx->reordered_opaque; -+ return VA_INVALID_SURFACE; -+} - -- AVBufferRef *buffer = av_buffer_create(pic->data[3], 0, RelBufferS, avctx->opaque, 0); -- if (!buffer) -+VASurfaceID CVideoSurfaces::GetAtIndex(int idx) -+{ -+ if (idx >= m_state.size()) -+ return VA_INVALID_SURFACE; -+ -+ std::map::iterator it = m_state.begin(); -+ for(int i = 0; i < idx; i++) -+ ++it; -+ return it->first; -+} -+ -+VASurfaceID CVideoSurfaces::RemoveNext(bool skiprender) -+{ -+ CSingleLock lock(m_section); -+ VASurfaceID surf; -+ std::map::iterator it; -+ for(it = m_state.begin(); it != m_state.end(); ++it) - { -- CLog::Log(LOGERROR, "VAAPI::%s - error creating buffer", __FUNCTION__); -- return -1; -+ if (skiprender && it->second & SURFACE_USED_FOR_RENDER) -+ continue; -+ surf = it->first; -+ m_state.erase(surf); -+ -+ std::list::iterator it2; -+ it2 = std::find(m_freeSurfaces.begin(), m_freeSurfaces.end(), surf); -+ if (it2 != m_freeSurfaces.end()) -+ m_freeSurfaces.erase(it2); -+ return surf; - } -- pic->buf[0] = buffer; -- return 0; -+ return VA_INVALID_SURFACE; - } - --void CDecoder::Close() --{ -- if(m_context) -- WARN(vaDestroyContext(m_display->get(), m_context)) -- m_context = 0; -+void CVideoSurfaces::Reset() -+{ -+ CSingleLock lock(m_section); -+ m_freeSurfaces.clear(); -+ m_state.clear(); -+} -+ -+int CVideoSurfaces::Size() -+{ -+ CSingleLock lock(m_section); -+ return m_state.size(); -+} -+ -+bool CVideoSurfaces::HasFree() -+{ -+ CSingleLock lock(m_section); -+ return !m_freeSurfaces.empty(); -+} - -- if(m_config) -- WARN(vaDestroyConfig(m_display->get(), m_config)) -- m_config = 0; -- -- m_surfaces_free.clear(); -- m_surfaces_used.clear(); -- m_surfaces_count = 0; -- m_refs = 0; -- memset(m_hwaccel , 0, sizeof(*m_hwaccel)); -- memset(m_surfaces, 0, sizeof(*m_surfaces)); -- m_display.reset(); -- m_holder.surface.reset(); -+//----------------------------------------------------------------------------- -+// VAAPI -+//----------------------------------------------------------------------------- -+ -+// settings codecs mapping -+DVDCodecAvailableType g_vaapi_available[] = { -+ { AV_CODEC_ID_H263, "videoplayer.usevaapimpeg4" }, -+ { AV_CODEC_ID_MPEG4, "videoplayer.usevaapimpeg4" }, -+ { AV_CODEC_ID_WMV3, "videoplayer.usevaapivc1" }, -+ { AV_CODEC_ID_VC1, "videoplayer.usevaapivc1" }, -+ { AV_CODEC_ID_MPEG2VIDEO, "videoplayer.usevaapimpeg2" }, -+}; -+const size_t settings_count = sizeof(g_vaapi_available) / sizeof(DVDCodecAvailableType); -+ -+CDecoder::CDecoder() : m_vaapiOutput(&m_inMsgEvent) -+{ -+ m_vaapiConfig.videoSurfaces = &m_videoSurfaces; -+ -+ m_vaapiConfigured = false; -+ m_DisplayState = VAAPI_OPEN; -+ m_vaapiConfig.context = 0; -+ m_vaapiConfig.contextId = VA_INVALID_ID; -+ m_vaapiConfig.configId = VA_INVALID_ID; -+} -+ -+CDecoder::~CDecoder() -+{ -+ Close(); - } - --bool CDecoder::Open(AVCodecContext *avctx, enum PixelFormat fmt, unsigned int surfaces) -+bool CDecoder::Open(AVCodecContext* avctx, const enum PixelFormat fmt, unsigned int surfaces) - { -+ // don't support broken wrappers -+ // nvidia cards with a vaapi to vdpau wrapper -+ // fglrx cards with xvba-va-driver -+ std::string gpuvendor = g_Windowing.GetRenderVendor(); -+ std::transform(gpuvendor.begin(), gpuvendor.end(), gpuvendor.begin(), ::tolower); -+ if (gpuvendor.compare(0, 5, "intel") != 0) -+ { -+ CLog::Log(LOGNOTICE, "VAAPI is not correctly supported on your hardware - will close the decoder."); -+ return false; -+ } -+ - // check if user wants to decode this format with VAAPI - if (CDVDVideoCodec::IsCodecDisabled(g_vaapi_available, settings_count, avctx->codec_id)) - return false; - -- VAEntrypoint entrypoint = VAEntrypointVLD; -- VAProfile profile; -+ CLog::Log(LOGDEBUG,"VAAPI - open decoder"); -+ -+ if (!CVAAPIContext::EnsureContext(&m_vaapiConfig.context, this)) -+ return false; - -- CLog::Log(LOGDEBUG, "VAAPI - attempting to open codec %d with profile %d at level %d with %d reference frames", avctx->codec_id, avctx->profile, avctx->level, avctx->refs); -+ if(avctx->coded_width == 0 -+ || avctx->coded_height == 0) -+ { -+ CLog::Log(LOGWARNING,"VAAPI::Open: no width/height available, can't init"); -+ return false; -+ } - -- vector accepted; -- switch (avctx->codec_id) { -+ m_vaapiConfig.vidWidth = avctx->width; -+ m_vaapiConfig.vidHeight = avctx->height; -+ m_vaapiConfig.outWidth = avctx->width; -+ m_vaapiConfig.outHeight = avctx->height; -+ m_vaapiConfig.surfaceWidth = avctx->width; -+ m_vaapiConfig.surfaceHeight = avctx->height; -+ m_vaapiConfig.aspect = avctx->sample_aspect_ratio; -+ m_vaapiConfig.numRenderBuffers = surfaces; -+ m_decoderThread = CThread::GetCurrentThreadId(); -+ m_DisplayState = VAAPI_OPEN; -+ m_vaapiConfigured = false; -+ m_presentPicture = 0; -+ -+ VAProfile profile; -+ switch (avctx->codec_id) -+ { - case AV_CODEC_ID_MPEG2VIDEO: -- accepted.push_back(VAProfileMPEG2Main); -+ profile = VAProfileMPEG2Main; -+ if (!m_vaapiConfig.context->SupportsProfile(profile)) -+ return false; - break; - case AV_CODEC_ID_MPEG4: - case AV_CODEC_ID_H263: -- accepted.push_back(VAProfileMPEG4AdvancedSimple); -+ profile = VAProfileMPEG4AdvancedSimple; -+ if (!m_vaapiConfig.context->SupportsProfile(profile)) -+ return false; - break; - case AV_CODEC_ID_H264: - { --#ifdef FF_PROFILE_H264_BASELINE -- if (avctx->profile == FF_PROFILE_H264_BASELINE) -- accepted.push_back(VAProfileH264Baseline); -+ if (avctx->profile == FF_PROFILE_H264_BASELINE) -+ { -+ profile = VAProfileH264Baseline; -+ if (!m_vaapiConfig.context->SupportsProfile(profile)) -+ return false; -+ } - else - { - if(avctx->profile == FF_PROFILE_H264_MAIN) -- accepted.push_back(VAProfileH264Main); --#else -- { -- // fallback to high profile if libavcodec is too old to export -- // profile information; it will likely work --#endif -- // fallback to high profile if main profile is not available -- accepted.push_back(VAProfileH264High); -+ { -+ profile = VAProfileH264Main; -+ if (m_vaapiConfig.context->SupportsProfile(profile)) -+ break; -+ } -+ profile = VAProfileH264High; -+ if (!m_vaapiConfig.context->SupportsProfile(profile)) -+ return false; - } - break; - } - case AV_CODEC_ID_WMV3: -- accepted.push_back(VAProfileVC1Main); -+ profile = VAProfileVC1Main; -+ if (!m_vaapiConfig.context->SupportsProfile(profile)) -+ return false; - break; - case AV_CODEC_ID_VC1: -- accepted.push_back(VAProfileVC1Advanced); -+ profile = VAProfileVC1Advanced; -+ if (!m_vaapiConfig.context->SupportsProfile(profile)) -+ return false; - break; - default: - return false; - } - -- m_display = GetGlobalDisplay(); -- if(!m_display) -- return false; -- -- if(!m_display->support_4k() && (avctx->width > 1920 || avctx->height > 1088)) -+ m_vaapiConfig.profile = profile; -+ m_vaapiConfig.attrib = m_vaapiConfig.context->GetAttrib(profile); -+ if ((m_vaapiConfig.attrib.value & VA_RT_FORMAT_YUV420) == 0) - { -- CLog::Log(LOGDEBUG, "VAAPI - frame size (%dx%d) too large - disallowing", avctx->width, avctx->height); -+ CLog::Log(LOGERROR, "VAAPI - invalid yuv format %x", m_vaapiConfig.attrib.value); - return false; - } - -- int num_display_attrs = 0; -- scoped_array display_attrs(new VADisplayAttribute[vaMaxNumDisplayAttributes(m_display->get())]); -- -- CHECK(vaQueryDisplayAttributes(m_display->get(), display_attrs.get(), &num_display_attrs)) -- -- for(int i = 0; i < num_display_attrs; i++) -+ if(avctx->codec_id == AV_CODEC_ID_H264) - { -- VADisplayAttribute * const display_attr = &display_attrs[i]; -- CLog::Log(LOGDEBUG, "VAAPI - attrib %d (%s/%s) min %d max %d value 0x%x\n" -- , display_attr->type -- ,(display_attr->flags & VA_DISPLAY_ATTRIB_GETTABLE) ? "get" : "---" -- ,(display_attr->flags & VA_DISPLAY_ATTRIB_SETTABLE) ? "set" : "---" -- , display_attr->min_value -- , display_attr->max_value -- , display_attr->value); -+ m_vaapiConfig.maxReferences = avctx->refs; -+ if (m_vaapiConfig.maxReferences > 16) -+ m_vaapiConfig.maxReferences = 16; -+ if (m_vaapiConfig.maxReferences < 5) -+ m_vaapiConfig.maxReferences = 5; - } -+ else -+ m_vaapiConfig.maxReferences = 2; - -- int num_profiles = 0; -- scoped_array profiles(new VAProfile[vaMaxNumProfiles(m_display->get())]); -- CHECK(vaQueryConfigProfiles(m_display->get(), profiles.get(), &num_profiles)) -- -- for(int i = 0; i < num_profiles; i++) -- CLog::Log(LOGDEBUG, "VAAPI - profile %d", profiles[i]); -+ m_vaapiConfig.maxReferences += surfaces; - -- vector::iterator selected = find_first_of(accepted.begin() -- , accepted.end() -- , profiles.get() -- , profiles.get()+num_profiles); -- if(selected == accepted.end()) -+ if (!ConfigVAAPI()) - { -- CLog::Log(LOGDEBUG, "VAAPI - unable to find a suitable profile"); - return false; - } - -- profile = *selected; -- -- VAConfigAttrib attrib; -- attrib.type = VAConfigAttribRTFormat; -- CHECK(vaGetConfigAttributes(m_display->get(), profile, entrypoint, &attrib, 1)) -- -- if ((attrib.value & VA_RT_FORMAT_YUV420) == 0) -- { -- CLog::Log(LOGERROR, "VAAPI - invalid yuv format %x", attrib.value); -- return false; -- } -+ avctx->hwaccel_context = &m_hwContext; -+ avctx->get_buffer2 = CDecoder::FFGetBuffer; -+ avctx->slice_flags = SLICE_FLAG_CODED_ORDER|SLICE_FLAG_ALLOW_FIELD; -+ return true; -+} - -- CHECK(vaCreateConfig(m_display->get(), profile, entrypoint, &attrib, 1, &m_hwaccel->config_id)) -- m_config = m_hwaccel->config_id; -+void CDecoder::Close() -+{ -+ CLog::Log(LOGNOTICE, "VAAPI::%s", __FUNCTION__); - -- m_renderbuffers_count = surfaces; -- if (!EnsureContext(avctx)) -- return false; -+ CSingleLock lock(m_DecoderSection); - -- m_hwaccel->display = m_display->get(); -+ FiniVAAPIOutput(); - -- avctx->hwaccel_context = m_hwaccel; -- avctx->get_buffer2 = GetBufferS; -- avctx->draw_horiz_band = NULL; -- avctx->slice_flags = SLICE_FLAG_CODED_ORDER|SLICE_FLAG_ALLOW_FIELD; -- return true; -+ if (m_vaapiConfig.context) -+ m_vaapiConfig.context->Release(this); -+ m_vaapiConfig.context = 0; - } - --bool CDecoder::EnsureContext(AVCodecContext *avctx) -+long CDecoder::Release() - { -- if(avctx->refs && avctx->refs <= m_refs) -- return true; -- -- if(m_refs > 0) -- CLog::Log(LOGWARNING, "VAAPI - reference frame count increasing, reiniting decoder"); -- -- m_refs = avctx->refs; -- if(m_refs == 0) -+ // check if we should do some pre-cleanup here -+ // a second decoder might need resources -+ if (m_vaapiConfigured == true) - { -- if(avctx->codec_id == AV_CODEC_ID_H264) -- m_refs = 16; -+ CSingleLock lock(m_DecoderSection); -+ CLog::Log(LOGNOTICE,"VAAPI::Release pre-cleanup"); -+ -+ Message *reply; -+ if (m_vaapiOutput.m_controlPort.SendOutMessageSync(COutputControlProtocol::PRECLEANUP, -+ &reply, -+ 2000)) -+ { -+ bool success = reply->signal == COutputControlProtocol::ACC ? true : false; -+ reply->Release(); -+ if (!success) -+ { -+ CLog::Log(LOGERROR, "VAAPI::%s - pre-cleanup returned error", __FUNCTION__); -+ m_DisplayState = VAAPI_ERROR; -+ } -+ } - else -- m_refs = 2; -+ { -+ CLog::Log(LOGERROR, "VAAPI::%s - pre-cleanup timed out", __FUNCTION__); -+ m_DisplayState = VAAPI_ERROR; -+ } -+ -+ VASurfaceID surf; -+ while((surf = m_videoSurfaces.RemoveNext(true)) != VA_INVALID_SURFACE) -+ { -+ CheckSuccess(vaDestroySurfaces(m_vaapiConfig.dpy, &surf, 1)); -+ } - } -- return EnsureSurfaces(avctx, m_refs + m_renderbuffers_count + 1); -+ return IHardwareDecoder::Release(); - } - --bool CDecoder::EnsureSurfaces(AVCodecContext *avctx, unsigned n_surfaces_count) -+long CDecoder::ReleasePicReference() - { -- CLog::Log(LOGDEBUG, "VAAPI - making sure %d surfaces are allocated for given %d references", n_surfaces_count, avctx->refs); -- -- if(n_surfaces_count > m_surfaces_max) -- { -- CLog::Log(LOGERROR, "VAAPI - Failed to ensure surfaces! Requested %d surfaces. Maximum possible count is %d!", n_surfaces_count, m_surfaces_max); -- return false; -- } -+ return IHardwareDecoder::Release(); -+} - -- if(n_surfaces_count <= m_surfaces_count) -- return true; -+int CDecoder::FFGetBuffer(AVCodecContext *avctx, AVFrame *pic, int flags) -+{ -+ CDVDVideoCodecFFmpeg* ctx = (CDVDVideoCodecFFmpeg*)avctx->opaque; -+ CDecoder* va = (CDecoder*)ctx->GetHardware(); - -- const unsigned old_surfaces_count = m_surfaces_count; -- m_surfaces_count = n_surfaces_count; -+ // while we are waiting to recover we can't do anything -+ CSingleLock lock(va->m_DecoderSection); - -- CHECK(vaCreateSurfaces(m_display->get() -- , VA_RT_FORMAT_YUV420 -- , avctx->width -- , avctx->height -- , &m_surfaces[old_surfaces_count] -- , m_surfaces_count - old_surfaces_count -- , NULL -- , 0)) -+ if(va->m_DisplayState != VAAPI_OPEN) -+ { -+ CLog::Log(LOGWARNING, "VAAPI::FFGetBuffer - returning due to awaiting recovery"); -+ return -1; -+ } - -- for(unsigned i = old_surfaces_count; i < m_surfaces_count; i++) -- m_surfaces_free.push_back(CSurfacePtr(new CSurface(m_surfaces[i], m_display))); -+ VASurfaceID surf = (VASurfaceID)(uintptr_t)pic->data[3]; -+ surf = va->m_videoSurfaces.GetFree(surf != 0 ? surf : VA_INVALID_SURFACE); - -- //shared_ptr test = VASurfaceIDPtr(m_surfaces[0], m_display); -+ if (surf == VA_INVALID_SURFACE) -+ { -+ uint16_t decoded, processed, render; -+ va->m_bufferStats.Get(decoded, processed, render); -+ CLog::Log(LOGERROR, "VAAPI::FFGetBuffer - no surface available - dec: %d, render: %d", -+ decoded, render); -+ return -1; -+ } - -- if(m_context) -- WARN(vaDestroyContext(m_display->get(), m_context)) -- m_context = 0; -+ pic->data[1] = pic->data[2] = NULL; -+ pic->data[0] = (uint8_t*)(uintptr_t)surf; -+ pic->data[3] = (uint8_t*)(uintptr_t)surf; -+ pic->linesize[0] = pic->linesize[1] = pic->linesize[2] = 0; -+ AVBufferRef *buffer = av_buffer_create(pic->data[3], 0, CVAAPIContext::FFReleaseBuffer, va, 0); -+ if (!buffer) -+ { -+ CLog::Log(LOGERROR, "VAAPI::%s - error creating buffer", __FUNCTION__); -+ return -1; -+ } -+ pic->buf[0] = buffer; - -- CHECK(vaCreateContext(m_display->get() -- , m_config -- , avctx->width -- , avctx->height -- , VA_PROGRESSIVE -- , m_surfaces -- , m_surfaces_count -- , &m_hwaccel->context_id)) -- m_context = m_hwaccel->context_id; -- return true; -+ pic->reordered_opaque= avctx->reordered_opaque; -+ return 0; - } - --int CDecoder::Decode(AVCodecContext* avctx, AVFrame* frame) -+void CDecoder::FFReleaseBuffer(uint8_t *data) - { -- int status = Check(avctx); -- if(status) -- return status; -+ VASurfaceID surf; -+ unsigned int i; - -- if(frame) -- return VC_BUFFER | VC_PICTURE; -- else -- return VC_BUFFER; -+ CSingleLock lock(m_DecoderSection); -+ -+ surf = (VASurfaceID)(uintptr_t)data; -+ m_videoSurfaces.ClearReference(surf); - } - --bool CDecoder::GetPicture(AVCodecContext* avctx, AVFrame* frame, DVDVideoPicture* picture) -+int CDecoder::Decode(AVCodecContext* avctx, AVFrame* pFrame) - { -- ((CDVDVideoCodecFFmpeg*)avctx->opaque)->GetPictureCommon(picture); -- VASurfaceID surface = GetSurfaceID(frame); -+ int result = Check(avctx); -+ if (result) -+ return result; -+ -+ CSingleLock lock(m_DecoderSection); - -+ if (!m_vaapiConfigured) -+ return VC_ERROR; - -- m_holder.surface.reset(); -+ if(pFrame) -+ { // we have a new frame from decoder - -- std::list::iterator it; -- for(it = m_surfaces_used.begin(); it != m_surfaces_used.end() && !m_holder.surface; ++it) -- { -- if((*it)->m_id == surface) -+ VASurfaceID surf = (VASurfaceID)(uintptr_t)pFrame->data[3]; -+ // ffmpeg vc-1 decoder does not flush, make sure the data buffer is still valid -+ if (!m_videoSurfaces.IsValid(surf)) - { -- m_holder.surface = *it; -- break; -+ CLog::Log(LOGWARNING, "VAAPI::Decode - ignoring invalid buffer"); -+ return VC_BUFFER; - } -+ m_videoSurfaces.MarkRender(surf); -+ -+ // send frame to output for processing -+ CVaapiDecodedPicture pic; -+ memset(&pic.DVDPic, 0, sizeof(pic.DVDPic)); -+ ((CDVDVideoCodecFFmpeg*)avctx->opaque)->GetPictureCommon(&pic.DVDPic); -+ pic.videoSurface = surf; -+ pic.DVDPic.color_matrix = avctx->colorspace; -+ m_bufferStats.IncDecoded(); -+ m_vaapiOutput.m_dataPort.SendOutMessage(COutputDataProtocol::NEWFRAME, &pic, sizeof(pic)); -+ -+// m_codecControl = pic.DVDPic.iFlags & (DVP_FLAG_DRAIN | DVP_FLAG_NO_POSTPROC); - } - -- for(it = m_surfaces_free.begin(); it != m_surfaces_free.end() && !m_holder.surface; ++it) -- { -- if((*it)->m_id == surface) -+ int retval = 0; -+ uint16_t decoded, processed, render; -+ Message *msg; -+ while (m_vaapiOutput.m_controlPort.ReceiveInMessage(&msg)) -+ { -+ if (msg->signal == COutputControlProtocol::ERROR) - { -- m_holder.surface = *it; -- break; -+ m_DisplayState = VAAPI_ERROR; -+ retval |= VC_ERROR; - } -- } -- if(!m_holder.surface) -- { -- CLog::Log(LOGERROR, "VAAPI - Unable to find surface"); -- return false; -+ msg->Release(); - } - -- picture->format = RENDER_FMT_VAAPI; -- picture->vaapi = &m_holder; -- return true; --} -+ m_bufferStats.Get(decoded, processed, render); - --int CDecoder::Check(AVCodecContext* avctx) --{ -- if (m_display == NULL) -+ bool hasfree = m_videoSurfaces.HasFree(); -+ while (!retval) - { -- if(!Open(avctx, avctx->pix_fmt)) -+ // first fill the buffers to keep vaapi busy -+ if (decoded < 3 && processed < 3 && m_videoSurfaces.HasFree()) - { -- CLog::Log(LOGERROR, "VAAPI - Unable to recover device after display was closed"); -- Close(); -- return VC_ERROR; -+ retval |= VC_BUFFER; - } -- } -- -- if (m_display->lost()) -- { -- Close(); -- if(!Open(avctx, avctx->pix_fmt)) -+ else if (m_vaapiOutput.m_dataPort.ReceiveInMessage(&msg)) - { -- CLog::Log(LOGERROR, "VAAPI - Unable to recover device after display was lost"); -- Close(); -- return VC_ERROR; -+ if (msg->signal == COutputDataProtocol::PICTURE) -+ { -+ if (m_presentPicture) -+ { -+ m_presentPicture->ReturnUnused(); -+ m_presentPicture = 0; -+ } -+ -+ m_presentPicture = *(CVaapiRenderPicture**)msg->data; -+ m_presentPicture->vaapi = this; -+ m_bufferStats.DecRender(); -+ m_bufferStats.Get(decoded, processed, render); -+ retval |= VC_PICTURE; -+ msg->Release(); -+ break; -+ } -+ msg->Release(); - } -- return VC_FLUSHED; -+ else if (m_vaapiOutput.m_controlPort.ReceiveInMessage(&msg)) -+ { -+ if (msg->signal == COutputControlProtocol::STATS) -+ { -+ m_bufferStats.Get(decoded, processed, render); -+ } -+ else -+ { -+ m_DisplayState = VAAPI_ERROR; -+ retval |= VC_ERROR; -+ } -+ msg->Release(); -+ } -+ -+ if (decoded < 3 && processed < 3 && m_videoSurfaces.HasFree()) -+ { -+ retval |= VC_BUFFER; -+ } -+ -+ if (!retval && !m_inMsgEvent.WaitMSec(2000)) -+ break; -+ } -+ if (retval & VC_PICTURE) -+ { -+ m_bufferStats.SetParams(0, m_codecControl); - } - -- if (!EnsureContext(avctx)) -- return VC_ERROR; -+ if (!retval) -+ { -+ CLog::Log(LOGERROR, "VAAPI::%s - timed out waiting for output message - decoded: %d, proc: %d, has free surface: %s", -+ __FUNCTION__, decoded, processed, m_videoSurfaces.HasFree() ? "yes" : "no"); -+ m_DisplayState = VAAPI_ERROR; -+ retval |= VC_ERROR; -+ } -+ -+ return retval; -+} -+ -+int CDecoder::Check(AVCodecContext* avctx) -+{ -+ EDisplayState state; -+ -+ { CSingleLock lock(m_DecoderSection); -+ state = m_DisplayState; -+ } -+ -+ if (state == VAAPI_LOST) -+ { -+ CLog::Log(LOGNOTICE,"VAAPI::Check waiting for display reset event"); -+ if (!m_DisplayEvent.WaitMSec(4000)) -+ { -+ CLog::Log(LOGERROR, "VAAPI::Check - device didn't reset in reasonable time"); -+ state = VAAPI_RESET; -+ } -+ else -+ { -+ CSingleLock lock(m_DecoderSection); -+ state = m_DisplayState; -+ } -+ } -+ if (state == VAAPI_RESET || state == VAAPI_ERROR) -+ { -+ CSingleLock lock(m_DecoderSection); -+ -+ avcodec_flush_buffers(avctx); -+ FiniVAAPIOutput(); -+ if (m_vaapiConfig.context) -+ m_vaapiConfig.context->Release(this); -+ m_vaapiConfig.context = 0; -+ -+ if (CVAAPIContext::EnsureContext(&m_vaapiConfig.context, this) && ConfigVAAPI()) -+ { -+ m_DisplayState = VAAPI_OPEN; -+ } - -- m_holder.surface.reset(); -+ if (state == VAAPI_RESET) -+ return VC_FLUSHED; -+ else -+ return VC_ERROR; -+ } - return 0; - } - --unsigned CDecoder::GetAllowedReferences() -+bool CDecoder::GetPicture(AVCodecContext* avctx, AVFrame* frame, DVDVideoPicture* picture) -+{ -+ CSingleLock lock(m_DecoderSection); -+ -+ if (m_DisplayState != VAAPI_OPEN) -+ return false; -+ -+ *picture = m_presentPicture->DVDPic; -+ picture->vaapi = m_presentPicture; -+ -+ return true; -+} -+ -+void CDecoder::Reset() -+{ -+ CSingleLock lock(m_DecoderSection); -+ -+ if (!m_vaapiConfigured) -+ return; -+ -+ Message *reply; -+ if (m_vaapiOutput.m_controlPort.SendOutMessageSync(COutputControlProtocol::FLUSH, -+ &reply, -+ 2000)) -+ { -+ bool success = reply->signal == COutputControlProtocol::ACC ? true : false; -+ reply->Release(); -+ if (!success) -+ { -+ CLog::Log(LOGERROR, "VAAPI::%s - flush returned error", __FUNCTION__); -+ m_DisplayState = VAAPI_ERROR; -+ } -+ else -+ m_bufferStats.Reset(); -+ } -+ else -+ { -+ CLog::Log(LOGERROR, "VAAPI::%s - flush timed out", __FUNCTION__); -+ m_DisplayState = VAAPI_ERROR; -+ } -+} -+ -+bool CDecoder::CanSkipDeint() -+{ -+ return m_bufferStats.CanSkipDeint(); -+} -+ -+bool CDecoder::CheckSuccess(VAStatus status) -+{ -+ if (status != VA_STATUS_SUCCESS) -+ { -+ CLog::Log(LOGERROR, "VAAPI - error: %s", vaErrorStr(status)); -+ m_ErrorCount++; -+ -+ if(m_DisplayState == VAAPI_OPEN) -+ { -+ if (m_ErrorCount > 2) -+ m_DisplayState = VAAPI_ERROR; -+ } -+ return false; -+ } -+ m_ErrorCount = 0; -+ return true; -+} -+ -+bool CDecoder::Supports(EINTERLACEMETHOD method) -+{ -+ if(method == VS_INTERLACEMETHOD_AUTO) -+ return true; -+ -+ for (int i=0; iGetDisplay(); -+ m_vaapiConfig.attrib = m_vaapiConfig.context->GetAttrib(m_vaapiConfig.profile); -+ if ((m_vaapiConfig.attrib.value & VA_RT_FORMAT_YUV420) == 0) -+ { -+ CLog::Log(LOGERROR, "VAAPI - invalid yuv format %x", m_vaapiConfig.attrib.value); -+ return false; -+ } -+ -+ m_vaapiConfig.configId = m_vaapiConfig.context->CreateConfig(m_vaapiConfig.profile, -+ m_vaapiConfig.attrib); -+ if (m_vaapiConfig.configId == VA_INVALID_ID) -+ return false; -+ -+ // create surfaces -+ VASurfaceID surfaces[32]; -+ int nb_surfaces = m_vaapiConfig.maxReferences; -+ if (!CheckSuccess(vaCreateSurfaces(m_vaapiConfig.dpy, -+ VA_RT_FORMAT_YUV420, -+ m_vaapiConfig.surfaceWidth, -+ m_vaapiConfig.surfaceHeight, -+ surfaces, -+ nb_surfaces, -+ NULL, 0))) -+ { -+ return false; -+ } -+ for (int i=0; isignal == COutputControlProtocol::ACC ? true : false; -+ if (!success) -+ { -+ reply->Release(); -+ CLog::Log(LOGERROR, "VAAPI::%s - vaapi output returned error", __FUNCTION__); -+ m_vaapiOutput.Dispose(); -+ return false; -+ } -+ SDiMethods *diMethods = NULL; -+ diMethods = (SDiMethods*)reply->data; -+ if (diMethods) -+ { -+ m_diMethods.clear(); -+ for (int i=0; inumDiMethods; i++) -+ { -+ m_diMethods.push_back(diMethods->diMethods[i]); -+ } -+ } -+ reply->Release(); -+ } -+ else -+ { -+ CLog::Log(LOGERROR, "VAAPI::%s - failed to init output", __FUNCTION__); -+ m_vaapiOutput.Dispose(); -+ return false; -+ } -+ -+ -+ m_hwContext.config_id = m_vaapiConfig.configId; -+ m_hwContext.context_id = m_vaapiConfig.contextId; -+ m_hwContext.display = m_vaapiConfig.dpy; -+ -+ m_inMsgEvent.Reset(); -+ m_vaapiConfigured = true; -+ m_ErrorCount = 0; -+ -+ return true; -+} -+ -+void CDecoder::FiniVAAPIOutput() -+{ -+ if (!m_vaapiConfigured) -+ return; -+ -+ memset(&m_hwContext, 0, sizeof(vaapi_context)); -+ -+ // uninit output -+ m_vaapiOutput.Dispose(); -+ m_vaapiConfigured = false; -+ -+ VAStatus status; -+ -+ // destroy decoder context -+ if (m_vaapiConfig.contextId != VA_INVALID_ID) -+ CheckSuccess(vaDestroyContext(m_vaapiConfig.dpy, m_vaapiConfig.contextId)); -+ m_vaapiConfig.contextId = VA_INVALID_ID; -+ -+ // detroy surfaces -+ CLog::Log(LOGDEBUG, "VAAPI::FiniVAAPIOutput destroying %d video surfaces", m_videoSurfaces.Size()); -+ VASurfaceID surf; -+ while((surf = m_videoSurfaces.RemoveNext()) != VA_INVALID_SURFACE) -+ { -+ CheckSuccess(vaDestroySurfaces(m_vaapiConfig.dpy, &surf, 1)); -+ } -+ m_videoSurfaces.Reset(); -+ -+ // destroy vaapi config -+ if (m_vaapiConfig.configId != VA_INVALID_ID) -+ CheckSuccess(vaDestroyConfig(m_vaapiConfig.dpy, m_vaapiConfig.configId)); -+ m_vaapiConfig.configId = VA_INVALID_ID; -+} -+ -+void CDecoder::ReturnRenderPicture(CVaapiRenderPicture *renderPic) -+{ -+ m_vaapiOutput.m_dataPort.SendOutMessage(COutputDataProtocol::RETURNPIC, &renderPic, sizeof(renderPic)); -+} -+ -+ -+//----------------------------------------------------------------------------- -+// RenderPicture -+//----------------------------------------------------------------------------- -+ -+CVaapiRenderPicture* CVaapiRenderPicture::Acquire() -+{ -+ CSingleLock lock(renderPicSection); -+ -+ if (refCount == 0) -+ vaapi->Acquire(); -+ -+ refCount++; -+ return this; -+} -+ -+long CVaapiRenderPicture::Release() -+{ -+ CSingleLock lock(renderPicSection); -+ -+ refCount--; -+ if (refCount > 0) -+ return refCount; -+ -+ lock.Leave(); -+ vaapi->ReturnRenderPicture(this); -+ vaapi->ReleasePicReference(); -+ -+ return refCount; -+} -+ -+void CVaapiRenderPicture::ReturnUnused() -+{ -+ { CSingleLock lock(renderPicSection); -+ if (refCount > 0) -+ return; -+ } -+ if (vaapi) -+ vaapi->ReturnRenderPicture(this); -+} -+ -+void CVaapiRenderPicture::Sync() -+{ -+#ifdef GL_ARB_sync -+ CSingleLock lock(renderPicSection); -+ if (usefence) -+ { -+ if(glIsSync(fence)) -+ { -+ glDeleteSync(fence); -+ fence = None; -+ } -+ fence = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); -+ } -+#endif -+} -+ -+//----------------------------------------------------------------------------- -+// Buffer Pool -+//----------------------------------------------------------------------------- -+ -+VaapiBufferPool::VaapiBufferPool() -+{ -+ CVaapiRenderPicture *pic; -+ for (unsigned int i = 0; i < NUM_RENDER_PICS; i++) -+ { -+ pic = new CVaapiRenderPicture(renderPicSec); -+ allRenderPics.push_back(pic); -+ } -+} -+ -+VaapiBufferPool::~VaapiBufferPool() -+{ -+ CVaapiRenderPicture *pic; -+ for (unsigned int i = 0; i < NUM_RENDER_PICS; i++) -+ { -+ pic = allRenderPics[i]; -+ delete pic; -+ } -+ allRenderPics.clear(); -+} -+ -+//----------------------------------------------------------------------------- -+// Output -+//----------------------------------------------------------------------------- -+COutput::COutput(CEvent *inMsgEvent) : -+ CThread("Vaapi-Output"), -+ m_controlPort("OutputControlPort", inMsgEvent, &m_outMsgEvent), -+ m_dataPort("OutputDataPort", inMsgEvent, &m_outMsgEvent) -+{ -+ m_inMsgEvent = inMsgEvent; -+ -+ for (unsigned int i = 0; i < m_bufferPool.allRenderPics.size(); ++i) -+ { -+ m_bufferPool.freeRenderPics.push_back(i); -+ } -+} -+ -+void COutput::Start() -+{ -+ Create(); -+} -+ -+COutput::~COutput() -+{ -+ Dispose(); -+ -+ m_bufferPool.freeRenderPics.clear(); -+ m_bufferPool.usedRenderPics.clear(); -+} -+ -+void COutput::Dispose() -+{ -+ CSingleLock lock(g_graphicsContext); -+ m_bStop = true; -+ m_outMsgEvent.Set(); -+ StopThread(); -+ m_controlPort.Purge(); -+ m_dataPort.Purge(); -+} -+ -+void COutput::OnStartup() -+{ -+ CLog::Log(LOGNOTICE, "COutput::OnStartup: Output Thread created"); -+} -+ -+void COutput::OnExit() - { -- return m_renderbuffers_count; -+ CLog::Log(LOGNOTICE, "COutput::OnExit: Output Thread terminated"); -+} -+ -+enum OUTPUT_STATES -+{ -+ O_TOP = 0, // 0 -+ O_TOP_ERROR, // 1 -+ O_TOP_UNCONFIGURED, // 2 -+ O_TOP_CONFIGURED, // 3 -+ O_TOP_CONFIGURED_IDLE, // 4 -+ O_TOP_CONFIGURED_WORK, // 5 -+ O_TOP_CONFIGURED_STEP1, // 6 -+ O_TOP_CONFIGURED_STEP2, // 7 -+ O_TOP_CONFIGURED_OUTPUT, // 8 -+}; -+ -+int VAAPI_OUTPUT_parentStates[] = { -+ -1, -+ 0, //TOP_ERROR -+ 0, //TOP_UNCONFIGURED -+ 0, //TOP_CONFIGURED -+ 3, //TOP_CONFIGURED_IDLE -+ 3, //TOP_CONFIGURED_WORK -+ 3, //TOP_CONFIGURED_STEP1 -+ 3, //TOP_CONFIGURED_STEP2 -+ 3, //TOP_CONFIGURED_OUTPUT -+}; -+ -+void COutput::StateMachine(int signal, Protocol *port, Message *msg) -+{ -+ for (int state = m_state; ; state = VAAPI_OUTPUT_parentStates[state]) -+ { -+ switch (state) -+ { -+ case O_TOP: // TOP -+ if (port == &m_controlPort) -+ { -+ switch (signal) -+ { -+ case COutputControlProtocol::FLUSH: -+ msg->Reply(COutputControlProtocol::ACC); -+ return; -+ case COutputControlProtocol::PRECLEANUP: -+ msg->Reply(COutputControlProtocol::ACC); -+ return; -+ default: -+ break; -+ } -+ } -+ else if (port == &m_dataPort) -+ { -+ switch (signal) -+ { -+ case COutputDataProtocol::RETURNPIC: -+ CVaapiRenderPicture *pic; -+ pic = *((CVaapiRenderPicture**)msg->data); -+ QueueReturnPicture(pic); -+ return; -+ default: -+ break; -+ } -+ } -+ { -+ std::string portName = port == NULL ? "timer" : port->portName; -+ CLog::Log(LOGWARNING, "COutput::%s - signal: %d form port: %s not handled for state: %d", __FUNCTION__, signal, portName.c_str(), m_state); -+ } -+ return; -+ -+ case O_TOP_ERROR: -+ break; -+ -+ case O_TOP_UNCONFIGURED: -+ if (port == &m_controlPort) -+ { -+ switch (signal) -+ { -+ case COutputControlProtocol::INIT: -+ CVaapiConfig *data; -+ data = (CVaapiConfig*)msg->data; -+ if (data) -+ { -+ m_config = *data; -+ } -+ Init(); -+ -+ // set initial number of -+ EnsureBufferPool(); -+ if (!m_vaError) -+ { -+ m_state = O_TOP_CONFIGURED_IDLE; -+ msg->Reply(COutputControlProtocol::ACC, &m_diMethods, sizeof(m_diMethods)); -+ } -+ else -+ { -+ m_state = O_TOP_ERROR; -+ msg->Reply(COutputControlProtocol::ERROR); -+ } -+ return; -+ default: -+ break; -+ } -+ } -+ break; -+ -+ case O_TOP_CONFIGURED: -+ if (port == &m_controlPort) -+ { -+ switch (signal) -+ { -+ case COutputControlProtocol::FLUSH: -+ Flush(); -+ msg->Reply(COutputControlProtocol::ACC); -+ return; -+ case COutputControlProtocol::PRECLEANUP: -+ Flush(); -+ ReleaseBufferPool(true); -+ msg->Reply(COutputControlProtocol::ACC); -+ m_state = O_TOP_UNCONFIGURED; -+ return; -+ default: -+ break; -+ } -+ } -+ else if (port == &m_dataPort) -+ { -+ switch (signal) -+ { -+ case COutputDataProtocol::NEWFRAME: -+ CVaapiDecodedPicture *frame; -+ frame = (CVaapiDecodedPicture*)msg->data; -+ if (frame) -+ { -+ m_bufferPool.decodedPics.push_back(*frame); -+ m_extTimeout = 0; -+ } -+ return; -+ case COutputDataProtocol::RETURNPIC: -+ CVaapiRenderPicture *pic; -+ pic = *((CVaapiRenderPicture**)msg->data); -+ QueueReturnPicture(pic); -+ m_controlPort.SendInMessage(COutputControlProtocol::STATS); -+ m_extTimeout = 0; -+ return; -+ default: -+ break; -+ } -+ } -+ -+ case O_TOP_CONFIGURED_IDLE: -+ if (port == NULL) // timeout -+ { -+ switch (signal) -+ { -+ case COutputControlProtocol::TIMEOUT: -+ if (ProcessSyncPicture()) -+ m_extTimeout = 10; -+ else -+ m_extTimeout = 100; -+ if (HasWork()) -+ { -+ m_state = O_TOP_CONFIGURED_WORK; -+ m_extTimeout = 0; -+ } -+ return; -+ default: -+ break; -+ } -+ } -+ break; -+ -+ case O_TOP_CONFIGURED_WORK: -+ if (port == NULL) // timeout -+ { -+ switch (signal) -+ { -+ case COutputControlProtocol::TIMEOUT: -+ if (!m_bufferPool.decodedPics.empty() && -+ m_bufferPool.processedPics.size() < 4) -+ { -+ m_currentPicture = m_bufferPool.decodedPics.front(); -+ m_bufferPool.decodedPics.pop_front(); -+ InitCycle(); -+ m_state = O_TOP_CONFIGURED_STEP1; -+ m_extTimeout = 0; -+ return; -+ } -+ else if (!m_bufferPool.freeRenderPics.empty() && -+ !m_bufferPool.processedPics.empty()) -+ { -+ m_state = O_TOP_CONFIGURED_OUTPUT; -+ m_extTimeout = 0; -+ return; -+ } -+ else -+ m_state = O_TOP_CONFIGURED_IDLE; -+ m_extTimeout = 100; -+ return; -+ default: -+ break; -+ } -+ } -+ break; -+ -+ case O_TOP_CONFIGURED_STEP1: -+ if (port == NULL) // timeout -+ { -+ switch (signal) -+ { -+ case COutputControlProtocol::TIMEOUT: -+ m_pp->AddPicture(m_currentPicture); -+ CVaapiProcessedPicture outPic; -+ if (m_pp->Filter(outPic)) -+ { -+ m_config.stats->IncProcessed(); -+ m_bufferPool.processedPics.push_back(outPic); -+ m_state = O_TOP_CONFIGURED_STEP2; -+ } -+ else -+ { -+ m_state = O_TOP_CONFIGURED_IDLE; -+ } -+ m_config.stats->DecDecoded(); -+ m_controlPort.SendInMessage(COutputControlProtocol::STATS); -+ m_extTimeout = 0; -+ return; -+ default: -+ break; -+ } -+ } -+ break; -+ -+ case O_TOP_CONFIGURED_STEP2: -+ if (port == NULL) // timeout -+ { -+ switch (signal) -+ { -+ case COutputControlProtocol::TIMEOUT: -+ CVaapiProcessedPicture outPic; -+ if (m_pp->Filter(outPic)) -+ { -+ m_bufferPool.processedPics.push_back(outPic); -+ m_config.stats->IncProcessed(); -+ m_extTimeout = 0; -+ return; -+ } -+ m_state = O_TOP_CONFIGURED_IDLE; -+ m_extTimeout = 0; -+ return; -+ default: -+ break; -+ } -+ } -+ break; -+ -+ case O_TOP_CONFIGURED_OUTPUT: -+ if (port == NULL) // timeout -+ { -+ switch (signal) -+ { -+ case COutputControlProtocol::TIMEOUT: -+ if (!m_bufferPool.processedPics.empty()) -+ { -+ CVaapiRenderPicture *outPic; -+ CVaapiProcessedPicture procPic; -+ procPic = m_bufferPool.processedPics.front(); -+ m_config.stats->DecProcessed(); -+ m_bufferPool.processedPics.pop_front(); -+ outPic = ProcessPicture(procPic); -+ ReleaseProcessedPicture(procPic); -+ if (outPic) -+ { -+ m_config.stats->IncRender(); -+ m_dataPort.SendInMessage(COutputDataProtocol::PICTURE, &outPic, sizeof(outPic)); -+ } -+ if (m_vaError) -+ { -+ m_state = O_TOP_ERROR; -+ return; -+ } -+ } -+ m_state = O_TOP_CONFIGURED_IDLE; -+ m_extTimeout = 0; -+ return; -+ default: -+ break; -+ } -+ } -+ break; -+ -+ default: // we are in no state, should not happen -+ CLog::Log(LOGERROR, "COutput::%s - no valid state: %d", __FUNCTION__, m_state); -+ return; -+ } -+ } // for -+} -+ -+void COutput::Process() -+{ -+ Message *msg = NULL; -+ Protocol *port = NULL; -+ bool gotMsg; -+ -+ m_state = O_TOP_UNCONFIGURED; -+ m_extTimeout = 1000; -+ m_bStateMachineSelfTrigger = false; -+ -+ while (!m_bStop) -+ { -+ gotMsg = false; -+ -+ if (m_bStateMachineSelfTrigger) -+ { -+ m_bStateMachineSelfTrigger = false; -+ // self trigger state machine -+ StateMachine(msg->signal, port, msg); -+ if (!m_bStateMachineSelfTrigger) -+ { -+ msg->Release(); -+ msg = NULL; -+ } -+ continue; -+ } -+ // check control port -+ else if (m_controlPort.ReceiveOutMessage(&msg)) -+ { -+ gotMsg = true; -+ port = &m_controlPort; -+ } -+ // check data port -+ else if (m_dataPort.ReceiveOutMessage(&msg)) -+ { -+ gotMsg = true; -+ port = &m_dataPort; -+ } -+ if (gotMsg) -+ { -+ StateMachine(msg->signal, port, msg); -+ if (!m_bStateMachineSelfTrigger) -+ { -+ msg->Release(); -+ msg = NULL; -+ } -+ continue; -+ } -+ -+ // wait for message -+ else if (m_outMsgEvent.WaitMSec(m_extTimeout)) -+ { -+ continue; -+ } -+ // time out -+ else -+ { -+ msg = m_controlPort.GetMessage(); -+ msg->signal = COutputControlProtocol::TIMEOUT; -+ port = 0; -+ // signal timeout to state machine -+ StateMachine(msg->signal, port, msg); -+ if (!m_bStateMachineSelfTrigger) -+ { -+ msg->Release(); -+ msg = NULL; -+ } -+ } -+ } -+ Flush(); -+ Uninit(); -+} -+ -+bool COutput::Init() -+{ -+ if (!CreateGlxContext()) -+ return false; -+ -+ if (!GLInit()) -+ return false; -+ -+ m_diMethods.numDiMethods = 0; -+ -+ m_pp = new CFFmpegPostproc(); -+ m_pp->PreInit(m_config, &m_diMethods); -+ delete m_pp; -+ -+ m_pp = new CVppPostproc(); -+ m_pp->PreInit(m_config, &m_diMethods); -+ delete m_pp; -+ -+ m_pp = NULL; -+ -+ m_vaError = false; -+ -+ return true; -+} -+ -+bool COutput::Uninit() -+{ -+ glFlush(); -+ while(ProcessSyncPicture()) -+ { -+ Sleep(10); -+ } -+ ReleaseBufferPool(); -+ delete m_pp; -+ m_pp = NULL; -+ DestroyGlxContext(); -+ return true; -+} -+ -+void COutput::Flush() -+{ -+ Message *msg; -+ while (m_dataPort.ReceiveOutMessage(&msg)) -+ { -+ if (msg->signal == COutputDataProtocol::NEWFRAME) -+ { -+ CVaapiDecodedPicture pic = *(CVaapiDecodedPicture*)msg->data; -+ m_config.videoSurfaces->ClearRender(pic.videoSurface); -+ } -+ else if (msg->signal == COutputDataProtocol::RETURNPIC) -+ { -+ CVaapiRenderPicture *pic; -+ pic = *((CVaapiRenderPicture**)msg->data); -+ QueueReturnPicture(pic); -+ } -+ msg->Release(); -+ } -+ -+ while (m_dataPort.ReceiveInMessage(&msg)) -+ { -+ if (msg->signal == COutputDataProtocol::PICTURE) -+ { -+ CVaapiRenderPicture *pic; -+ pic = *((CVaapiRenderPicture**)msg->data); -+ QueueReturnPicture(pic); -+ } -+ } -+ -+ for (unsigned int i = 0; i < m_bufferPool.decodedPics.size(); i++) -+ { -+ m_config.videoSurfaces->ClearRender(m_bufferPool.decodedPics[i].videoSurface); -+ } -+ m_bufferPool.decodedPics.clear(); -+ -+ for (unsigned int i = 0; i < m_bufferPool.processedPics.size(); i++) -+ { -+ ReleaseProcessedPicture(m_bufferPool.processedPics[i]); -+ } -+ m_bufferPool.processedPics.clear(); -+ -+ if (m_pp) -+ m_pp->Flush(); -+} -+ -+bool COutput::HasWork() -+{ -+ if ((!m_bufferPool.freeRenderPics.empty() && !m_bufferPool.processedPics.empty()) || -+ !m_bufferPool.decodedPics.empty()) -+ return true; -+ -+ return false; -+} -+ -+void COutput::InitCycle() -+{ -+ uint64_t latency; -+ int speed; -+ m_config.stats->GetParams(latency, speed); -+ -+ m_config.stats->SetCanSkipDeint(false); -+ -+ EDEINTERLACEMODE mode = CMediaSettings::Get().GetCurrentVideoSettings().m_DeinterlaceMode; -+ EINTERLACEMETHOD method = CMediaSettings::Get().GetCurrentVideoSettings().m_InterlaceMethod; -+ bool interlaced = m_currentPicture.DVDPic.iFlags & DVP_FLAG_INTERLACED; -+ -+ if ((mode == VS_DEINTERLACEMODE_FORCE || -+ (mode == VS_DEINTERLACEMODE_AUTO && interlaced))) -+ { -+ if((method == VS_INTERLACEMETHOD_AUTO && interlaced) -+ || method == VS_INTERLACEMETHOD_VAAPI_BOB -+ || method == VS_INTERLACEMETHOD_VAAPI_MADI -+ || method == VS_INTERLACEMETHOD_VAAPI_MACI -+ || method == VS_INTERLACEMETHOD_DEINTERLACE -+ || method == VS_INTERLACEMETHOD_RENDER_BOB) -+ { -+ if (method == VS_INTERLACEMETHOD_AUTO) -+ method = VS_INTERLACEMETHOD_RENDER_BOB; -+ } -+ else -+ { -+ CLog::Log(LOGDEBUG,"VAAPI - deinterlace method not supported, falling back to BOB"); -+ method = VS_INTERLACEMETHOD_RENDER_BOB; -+ } -+ -+ if (m_pp && (method != m_currentDiMethod || !m_pp->Compatible(method))) -+ { -+ delete m_pp; -+ m_pp = NULL; -+ DropVppProcessedPictures(); -+ } -+ if (!m_pp) -+ { -+ if (method == VS_INTERLACEMETHOD_DEINTERLACE || -+ method == VS_INTERLACEMETHOD_RENDER_BOB) -+ m_pp = new CFFmpegPostproc(); -+ else -+ m_pp = new CVppPostproc(); -+ if (m_pp->PreInit(m_config)) -+ { -+ m_pp->Init(method); -+ m_currentDiMethod = method; -+ } -+ else -+ { -+ delete m_pp; -+ m_pp = NULL; -+ } -+ } -+ } -+ // progressive -+ else -+ { -+ method = VS_INTERLACEMETHOD_NONE; -+ if (m_pp && !m_pp->Compatible(method)) -+ { -+ delete m_pp; -+ m_pp = NULL; -+ DropVppProcessedPictures(); -+ } -+ if (!m_pp) -+ { -+ if (!CSettings::Get().GetBool("videoplayer.prefervaapirender")) -+ m_pp = new CFFmpegPostproc(); -+ else -+ m_pp = new CSkipPostproc(); -+ if (m_pp->PreInit(m_config)) -+ { -+ m_pp->Init(method); -+ } -+ else -+ { -+ delete m_pp; -+ m_pp = NULL; -+ } -+ } -+ } -+ if (!m_pp) // fallback -+ { -+ m_pp = new CSkipPostproc(); -+ if (m_pp->PreInit(m_config)) -+ m_pp->Init(method); -+ } -+} -+ -+CVaapiRenderPicture* COutput::ProcessPicture(CVaapiProcessedPicture &pic) -+{ -+ CVaapiRenderPicture *retPic; -+ int idx = m_bufferPool.freeRenderPics.front(); -+ retPic = m_bufferPool.allRenderPics[idx]; -+ retPic->DVDPic = pic.DVDPic; -+ -+ if (pic.source == CVaapiProcessedPicture::SKIP_SRC || -+ pic.source == CVaapiProcessedPicture::VPP_SRC) -+ { -+ unsigned int colorStandard; -+ switch(pic.DVDPic.color_matrix) -+ { -+ case AVCOL_SPC_BT709: -+ colorStandard = VA_SRC_BT709; -+ break; -+ case AVCOL_SPC_BT470BG: -+ case AVCOL_SPC_SMPTE170M: -+ colorStandard = VA_SRC_BT601; -+ break; -+ case AVCOL_SPC_SMPTE240M: -+ case AVCOL_SPC_FCC: -+ case AVCOL_SPC_UNSPECIFIED: -+ case AVCOL_SPC_RGB: -+ default: -+ if(m_config.surfaceWidth > 1000) -+ colorStandard = VA_SRC_BT709; -+ else -+ colorStandard = VA_SRC_BT601; -+ } -+ -+ if (!CheckSuccess(vaSyncSurface(m_config.dpy, pic.videoSurface))) -+ return NULL; -+ -+ if (!CheckSuccess(vaPutSurface(m_config.dpy, -+ pic.videoSurface, -+ retPic->pixmap, -+ 0,0, -+ m_config.surfaceWidth, m_config.surfaceHeight, -+ 0,0, -+ m_config.surfaceWidth, m_config.surfaceHeight, -+ NULL,0, -+ VA_FRAME_PICTURE | colorStandard))) -+ { -+ return NULL; -+ } -+ XSync(m_Display, false); -+ glEnable(m_textureTarget); -+ glBindTexture(m_textureTarget, retPic->texture); -+ glXBindTexImageEXT(m_Display, retPic->glPixmap, GLX_FRONT_LEFT_EXT, NULL); -+ glBindTexture(m_textureTarget, 0); -+ glDisable(m_textureTarget); -+ -+ retPic->DVDPic.format = RENDER_FMT_VAAPI; -+ } -+ else if (pic.source == CVaapiProcessedPicture::FFMPEG_SRC) -+ { -+ av_frame_move_ref(retPic->avFrame, pic.frame); -+ av_frame_free(&pic.frame); -+ retPic->DVDPic.format = RENDER_FMT_VAAPINV12; -+ } -+ else -+ return NULL; -+ -+ m_bufferPool.freeRenderPics.pop_front(); -+ m_bufferPool.usedRenderPics.push_back(idx); -+ -+ retPic->DVDPic.dts = DVD_NOPTS_VALUE; -+ retPic->DVDPic.iWidth = m_config.vidWidth; -+ retPic->DVDPic.iHeight = m_config.vidHeight; -+ -+ retPic->valid = true; -+ retPic->texWidth = m_config.outWidth; -+ retPic->texHeight = m_config.outHeight; -+ retPic->crop.x1 = 0; -+ retPic->crop.y1 = 0; -+ retPic->crop.x2 = m_config.outWidth; -+ retPic->crop.y2 = m_config.outHeight; -+ -+ return retPic; -+} -+ -+void COutput::ReleaseProcessedPicture(CVaapiProcessedPicture &pic) -+{ -+ if (pic.source == CVaapiProcessedPicture::VPP_SRC && m_pp) -+ { -+ CVppPostproc *pp = dynamic_cast(m_pp); -+ if (pp) -+ { -+ pp->ClearRef(pic.videoSurface); -+ } -+ } -+ else if (pic.source == CVaapiProcessedPicture::SKIP_SRC) -+ { -+ m_config.videoSurfaces->ClearRender(pic.videoSurface); -+ } -+ else if (pic.source == CVaapiProcessedPicture::FFMPEG_SRC) -+ { -+ av_frame_free(&pic.frame); -+ } -+} -+ -+void COutput::DropVppProcessedPictures() -+{ -+ std::deque::iterator it; -+ it = m_bufferPool.processedPics.begin(); -+ while (it != m_bufferPool.processedPics.end()) -+ { -+ if (it->source == CVaapiProcessedPicture::VPP_SRC) -+ { -+ it = m_bufferPool.processedPics.erase(it); -+ m_config.stats->DecProcessed(); -+ } -+ else -+ ++it; -+ } -+ m_controlPort.SendInMessage(COutputControlProtocol::STATS); -+} -+ -+void COutput::QueueReturnPicture(CVaapiRenderPicture *pic) -+{ -+ std::deque::iterator it; -+ for (it = m_bufferPool.usedRenderPics.begin(); it != m_bufferPool.usedRenderPics.end(); ++it) -+ { -+ if (m_bufferPool.allRenderPics[*it] == pic) -+ { -+ break; -+ } -+ } -+ -+ if (it == m_bufferPool.usedRenderPics.end()) -+ { -+ CLog::Log(LOGWARNING, "COutput::QueueReturnPicture - pic not found"); -+ return; -+ } -+ -+ // check if already queued -+ std::deque::iterator it2 = find(m_bufferPool.syncRenderPics.begin(), -+ m_bufferPool.syncRenderPics.end(), -+ *it); -+ if (it2 == m_bufferPool.syncRenderPics.end()) -+ { -+ m_bufferPool.syncRenderPics.push_back(*it); -+ } -+ -+ ProcessSyncPicture(); -+} -+ -+bool COutput::ProcessSyncPicture() -+{ -+ CVaapiRenderPicture *pic; -+ bool busy = false; -+ -+ std::deque::iterator it; -+ for (it = m_bufferPool.syncRenderPics.begin(); it != m_bufferPool.syncRenderPics.end(); ) -+ { -+ pic = m_bufferPool.allRenderPics[*it]; -+ -+#ifdef GL_ARB_sync -+ if (pic->usefence) -+ { -+ if (glIsSync(pic->fence)) -+ { -+ GLint state; -+ GLsizei length; -+ glGetSynciv(pic->fence, GL_SYNC_STATUS, 1, &length, &state); -+ if(state == GL_SIGNALED) -+ { -+ glDeleteSync(pic->fence); -+ pic->fence = None; -+ } -+ else -+ { -+ busy = true; -+ ++it; -+ continue; -+ } -+ } -+ } -+#endif -+ -+ m_bufferPool.freeRenderPics.push_back(*it); -+ -+ std::deque::iterator it2 = find(m_bufferPool.usedRenderPics.begin(), -+ m_bufferPool.usedRenderPics.end(), -+ *it); -+ if (it2 == m_bufferPool.usedRenderPics.end()) -+ { -+ CLog::Log(LOGERROR, "COutput::ProcessSyncPicture - pic not found in queue"); -+ } -+ else -+ { -+ m_bufferPool.usedRenderPics.erase(it2); -+ } -+ it = m_bufferPool.syncRenderPics.erase(it); -+ -+ if (pic->valid) -+ { -+ ProcessReturnPicture(pic); -+ } -+ else -+ { -+ CLog::Log(LOGDEBUG, "COutput::%s - return of invalid render pic", __FUNCTION__); -+ } -+ } -+ return busy; -+} -+ -+void COutput::ProcessReturnPicture(CVaapiRenderPicture *pic) -+{ -+ if (pic->avFrame) -+ av_frame_unref(pic->avFrame); -+ -+ if (pic->DVDPic.format == RENDER_FMT_VAAPI) -+ { -+ glEnable(m_textureTarget); -+ glBindTexture(m_textureTarget, pic->texture); -+ glXReleaseTexImageEXT(m_Display, pic->glPixmap, GLX_FRONT_LEFT_EXT); -+ glBindTexture(m_textureTarget, 0); -+ glDisable(m_textureTarget); -+ } -+ -+ pic->valid = false; -+} -+ -+bool COutput::EnsureBufferPool() -+{ -+ int fbConfigIndex = 0; -+ int num; -+ -+ XWindowAttributes wndattribs; -+ XGetWindowAttributes(m_Display, g_Windowing.GetWindow(), &wndattribs); -+ -+ int doubleVisAttributes[] = { -+ GLX_RENDER_TYPE, GLX_RGBA_BIT, -+ GLX_RED_SIZE, 8, -+ GLX_GREEN_SIZE, 8, -+ GLX_BLUE_SIZE, 8, -+ GLX_ALPHA_SIZE, 8, -+ GLX_DEPTH_SIZE, 8, -+ GLX_DRAWABLE_TYPE, GLX_PIXMAP_BIT, -+ GLX_BIND_TO_TEXTURE_RGBA_EXT, True, -+ GLX_DOUBLEBUFFER, False, -+ GLX_Y_INVERTED_EXT, True, -+ GLX_X_RENDERABLE, True, -+ None}; -+ -+ int pixmapAttribs[] = { -+ GLX_TEXTURE_TARGET_EXT, GLX_TEXTURE_2D_EXT, -+ GLX_TEXTURE_FORMAT_EXT, GLX_TEXTURE_FORMAT_RGBA_EXT, -+ None}; -+ -+ GLXFBConfig *fbConfigs; -+ fbConfigs = glXChooseFBConfig(m_Display, g_Windowing.GetCurrentScreen(), doubleVisAttributes, &num); -+ if (fbConfigs==NULL) -+ { -+ CLog::Log(LOGERROR, "VAAPI::EnsureBufferPool - No compatible framebuffers found"); -+ return false; -+ } -+ -+ fbConfigIndex = 0; -+ -+ // create glx surfaces and avFrames -+ CVaapiRenderPicture *pic; -+ for (unsigned int i = 0; i < m_bufferPool.allRenderPics.size(); i++) -+ { -+ pic = m_bufferPool.allRenderPics[i]; -+ -+ pic->pixmap = XCreatePixmap(m_Display, -+ m_Window, -+ m_config.surfaceWidth, -+ m_config.surfaceHeight, -+ wndattribs.depth); -+ if (!pic->pixmap) -+ { -+ CLog::Log(LOGERROR, "VAAPI::COutput::EnsureBufferPool - Unable to create XPixmap"); -+ return false; -+ } -+ -+ // create gl pixmap -+ pic->glPixmap = glXCreatePixmap(m_Display, fbConfigs[fbConfigIndex], pic->pixmap, pixmapAttribs); -+ -+ if (!pic->glPixmap) -+ { -+ CLog::Log(LOGINFO, "VAAPI::COutput::EnsureBufferPool - Could not create glPixmap"); -+ return false; -+ } -+ -+ glGenTextures(1, &pic->texture); -+ glBindTexture(m_textureTarget, pic->texture); -+ glXBindTexImageEXT(m_Display, pic->glPixmap, GLX_FRONT_LEFT_EXT, NULL); -+ glBindTexture(m_textureTarget, 0); -+ -+ pic->avFrame = av_frame_alloc(); -+ pic->valid = false; -+ } -+ -+ CLog::Log(LOGNOTICE, "VAAPI::COutput::InitBufferPool - Surfaces created"); -+ return true; -+} -+ -+void COutput::ReleaseBufferPool(bool precleanup) -+{ -+ VAStatus status; -+ CVaapiRenderPicture *pic; -+ -+ CSingleLock lock(m_bufferPool.renderPicSec); -+ -+ if (!precleanup) -+ { -+ // wait for all fences -+ XbmcThreads::EndTime timeout(1000); -+ for (unsigned int i = 0; i < m_bufferPool.allRenderPics.size(); i++) -+ { -+ pic = m_bufferPool.allRenderPics[i]; -+ if (pic->usefence) -+ { -+#ifdef GL_ARB_sync -+ while (glIsSync(pic->fence)) -+ { -+ GLint state; -+ GLsizei length; -+ glGetSynciv(pic->fence, GL_SYNC_STATUS, 1, &length, &state); -+ if(state == GL_SIGNALED || timeout.IsTimePast()) -+ { -+ glDeleteSync(pic->fence); -+ } -+ else -+ { -+ Sleep(5); -+ } -+ } -+ pic->fence = None; -+#endif -+ } -+ } -+ if (timeout.IsTimePast()) -+ { -+ CLog::Log(LOGERROR, "COutput::%s - timeout waiting for fence", __FUNCTION__); -+ } -+ } -+ -+ ProcessSyncPicture(); -+ -+ for (unsigned int i = 0; i < m_bufferPool.allRenderPics.size(); i++) -+ { -+ pic = m_bufferPool.allRenderPics[i]; -+ -+ if (precleanup && pic->valid) -+ continue; -+ -+ if (glIsTexture(pic->texture)) -+ { -+ glDeleteTextures(1, &pic->texture); -+ glXDestroyPixmap(m_Display, pic->glPixmap); -+ XFreePixmap(m_Display, pic->pixmap); -+ } -+ av_frame_free(&pic->avFrame); -+ pic->valid = false; -+ } -+ -+ for (unsigned int i = 0; i < m_bufferPool.decodedPics.size(); i++) -+ { -+ m_config.videoSurfaces->ClearRender(m_bufferPool.decodedPics[i].videoSurface); -+ } -+ m_bufferPool.decodedPics.clear(); -+ -+ for (unsigned int i = 0; i < m_bufferPool.processedPics.size(); i++) -+ { -+ ReleaseProcessedPicture(m_bufferPool.processedPics[i]); -+ } -+ m_bufferPool.processedPics.clear(); -+} -+ -+bool COutput::GLInit() -+{ -+#ifdef GL_ARB_sync -+ bool hasfence = glewIsSupported("GL_ARB_sync"); -+ for (unsigned int i = 0; i < m_bufferPool.allRenderPics.size(); i++) -+ { -+ m_bufferPool.allRenderPics[i]->usefence = hasfence; -+ } -+#endif -+ -+ if (!glewIsSupported("GL_ARB_texture_non_power_of_two") && glewIsSupported("GL_ARB_texture_rectangle")) -+ { -+ m_textureTarget = GL_TEXTURE_RECTANGLE_ARB; -+ } -+ else -+ m_textureTarget = GL_TEXTURE_2D; -+ -+ glXBindTexImageEXT = (PFNGLXBINDTEXIMAGEEXTPROC)glXGetProcAddress((GLubyte *) "glXBindTexImageEXT"); -+ glXReleaseTexImageEXT = (PFNGLXRELEASETEXIMAGEEXTPROC)glXGetProcAddress((GLubyte *) "glXReleaseTexImageEXT"); -+ -+ return true; -+} -+ -+bool COutput::CheckSuccess(VAStatus status) -+{ -+ if (status != VA_STATUS_SUCCESS) -+ { -+ CLog::Log(LOGERROR, "VAAPI - Error: %s(%d)", vaErrorStr(status), status); -+ m_vaError = true; -+ return false; -+ } -+ return true; -+} -+ -+bool COutput::CreateGlxContext() -+{ -+ GLXContext glContext; -+ -+ m_Display = g_Windowing.GetDisplay(); -+ glContext = g_Windowing.GetGlxContext(); -+ m_Window = g_Windowing.GetWindow(); -+ -+ // Get our window attribs. -+ XWindowAttributes wndattribs; -+ XGetWindowAttributes(m_Display, m_Window, &wndattribs); -+ -+ // Get visual Info -+ XVisualInfo visInfo; -+ visInfo.visualid = wndattribs.visual->visualid; -+ int nvisuals = 0; -+ XVisualInfo* visuals = XGetVisualInfo(m_Display, VisualIDMask, &visInfo, &nvisuals); -+ if (nvisuals != 1) -+ { -+ CLog::Log(LOGERROR, "VAAPI::COutput::CreateGlxContext - could not find visual"); -+ return false; -+ } -+ visInfo = visuals[0]; -+ XFree(visuals); -+ -+ m_pixmap = XCreatePixmap(m_Display, -+ m_Window, -+ 192, -+ 108, -+ visInfo.depth); -+ if (!m_pixmap) -+ { -+ CLog::Log(LOGERROR, "VAAPI::COutput::CreateGlxContext - Unable to create XPixmap"); -+ return false; -+ } -+ -+ // create gl pixmap -+ m_glPixmap = glXCreateGLXPixmap(m_Display, &visInfo, m_pixmap); -+ -+ if (!m_glPixmap) -+ { -+ CLog::Log(LOGINFO, "VAAPI::COutput::CreateGlxContext - Could not create glPixmap"); -+ return false; -+ } -+ -+ m_glContext = glXCreateContext(m_Display, &visInfo, glContext, True); -+ -+ if (!glXMakeCurrent(m_Display, m_glPixmap, m_glContext)) -+ { -+ CLog::Log(LOGINFO, "VAAPI::COutput::CreateGlxContext - Could not make Pixmap current"); -+ return false; -+ } -+ -+ CLog::Log(LOGNOTICE, "VAAPI::COutput::CreateGlxContext - created context"); -+ return true; -+} -+ -+bool COutput::DestroyGlxContext() -+{ -+ if (m_glContext) -+ { -+ glXMakeCurrent(m_Display, None, NULL); -+ glXDestroyContext(m_Display, m_glContext); -+ } -+ m_glContext = 0; -+ -+ if (m_glPixmap) -+ glXDestroyPixmap(m_Display, m_glPixmap); -+ m_glPixmap = 0; -+ -+ if (m_pixmap) -+ XFreePixmap(m_Display, m_pixmap); -+ m_pixmap = 0; -+ -+ return true; -+} -+ -+//----------------------------------------------------------------------------- -+// Postprocessing -+//----------------------------------------------------------------------------- -+ -+bool CSkipPostproc::PreInit(CVaapiConfig &config, SDiMethods *methods) -+{ -+ m_config = config; -+ return true; -+} -+ -+bool CSkipPostproc::Init(EINTERLACEMETHOD method) -+{ -+ return true; -+} -+ -+bool CSkipPostproc::AddPicture(CVaapiDecodedPicture &inPic) -+{ -+ m_pic = inPic; -+ m_step = 0; -+ return true; -+} -+ -+bool CSkipPostproc::Filter(CVaapiProcessedPicture &outPic) -+{ -+ if (m_step>0) -+ return false; -+ outPic.DVDPic = m_pic.DVDPic; -+ outPic.videoSurface = m_pic.videoSurface; -+ outPic.source = CVaapiProcessedPicture::SKIP_SRC; -+ outPic.DVDPic.iFlags &= ~(DVP_FLAG_TOP_FIELD_FIRST | -+ DVP_FLAG_REPEAT_TOP_FIELD | -+ DVP_FLAG_INTERLACED); -+ m_step++; -+ return true; -+} -+ -+void CSkipPostproc::ClearRef(VASurfaceID surf) -+{ -+ -+} -+ -+void CSkipPostproc::Flush() -+{ -+ -+} -+ -+bool CSkipPostproc::Compatible(EINTERLACEMETHOD method) -+{ -+ if (method == VS_INTERLACEMETHOD_NONE) -+ return true; -+ -+ return false; -+} -+ -+//----------------------------------------------------------------------------- -+// VPP Postprocessing -+//----------------------------------------------------------------------------- -+ -+CVppPostproc::CVppPostproc() -+{ -+ m_contextId = VA_INVALID_ID; -+ m_configId = VA_INVALID_ID; -+ m_filter = VA_INVALID_ID; -+} -+ -+CVppPostproc::~CVppPostproc() -+{ -+ Dispose(); -+} -+ -+bool CVppPostproc::PreInit(CVaapiConfig &config, SDiMethods *methods) -+{ -+#if !defined(HAVE_VPP) -+ return false; -+#else -+ -+ m_config = config; -+ -+ // create config -+ if (!CheckSuccess(vaCreateConfig(m_config.dpy, VAProfileNone, VAEntrypointVideoProc, NULL, 0, &m_configId))) -+ { -+ return false; -+ } -+ -+ // create surfaces -+ VASurfaceID surfaces[32]; -+ int nb_surfaces = 5; -+ if (!CheckSuccess(vaCreateSurfaces(m_config.dpy, -+ VA_RT_FORMAT_YUV420, -+ m_config.surfaceWidth, -+ m_config.surfaceHeight, -+ surfaces, -+ nb_surfaces, -+ NULL, 0))) -+ { -+ return false; -+ } -+ for (int i=0; idiMethods[methods->numDiMethods++] = VS_INTERLACEMETHOD_VAAPI_BOB; -+ } -+ else if (deinterlacingCaps[j].type == VAProcDeinterlacingMotionAdaptive) -+ { -+ methods->diMethods[methods->numDiMethods++] = VS_INTERLACEMETHOD_VAAPI_MADI; -+ } -+ else if (deinterlacingCaps[j].type == VAProcDeinterlacingMotionCompensated) -+ { -+ methods->diMethods[methods->numDiMethods++] = VS_INTERLACEMETHOD_VAAPI_MACI; -+ } -+ } -+ } -+ } -+ } -+#endif -+ return true; -+} -+ -+bool CVppPostproc::Init(EINTERLACEMETHOD method) -+{ -+#if !defined(HAVE_VPP) -+ return false; -+#else -+ -+ m_vppMethod = method; -+ -+ VAProcDeinterlacingType vppMethod = VAProcDeinterlacingNone; -+ switch (method) -+ { -+ case VS_INTERLACEMETHOD_VAAPI_BOB: -+ vppMethod = VAProcDeinterlacingBob; -+ break; -+ case VS_INTERLACEMETHOD_VAAPI_MADI: -+ vppMethod = VAProcDeinterlacingMotionAdaptive; -+ break; -+ case VS_INTERLACEMETHOD_VAAPI_MACI: -+ vppMethod = VAProcDeinterlacingMotionCompensated; -+ break; -+ default: -+ return false; -+ } -+ -+ VAProcFilterParameterBufferDeinterlacing filterparams; -+ filterparams.type = VAProcFilterDeinterlacing; -+ filterparams.algorithm = vppMethod; -+ filterparams.flags = 0; -+ -+ if (!CheckSuccess(vaCreateBuffer(m_config.dpy, m_contextId, -+ VAProcFilterParameterBufferType, -+ sizeof(filterparams), 1, &filterparams, &m_filter))) -+ { -+ m_filter = VA_INVALID_ID; -+ return false; -+ } -+ -+ VAProcPipelineCaps pplCaps; -+ if (!CheckSuccess(vaQueryVideoProcPipelineCaps(m_config.dpy, m_contextId, -+ &m_filter, 1, &pplCaps))) -+ { -+ return false; -+ } -+ -+ m_forwardRefs = pplCaps.num_forward_references; -+ m_backwardRefs = pplCaps.num_backward_references; -+ m_currentIdx = 0; -+ m_frameCount = 0; -+ -+#endif -+ return true; -+} -+ -+void CVppPostproc::Dispose() -+{ -+ // make sure surfaces are idle -+ for (int i=0; i1) -+ { -+ Advance(); -+ return false; -+ } -+ -+ // we need a free render target -+ VASurfaceID surf = m_videoSurfaces.GetFree(VA_INVALID_SURFACE); -+ if (surf == VA_INVALID_SURFACE) -+ { -+ CLog::Log(LOGERROR, "VAAPI - VPP - no free render target"); -+ return false; -+ } -+ // clear reference in case we return false -+ m_videoSurfaces.ClearReference(surf); -+ -+ // make sure we have all needed forward refs -+ if ((m_currentIdx - m_forwardRefs) < m_decodedPics.back().index) -+ { -+ Advance(); -+ return false; -+ } -+ -+ std::deque::iterator it; -+ for (it=m_decodedPics.begin(); it!=m_decodedPics.end(); ++it) -+ { -+ if (it->index == m_currentIdx) -+ break; -+ } -+ if (it==m_decodedPics.end()) -+ { -+ return false; -+ } -+ outPic.DVDPic = it->DVDPic; -+ -+ // vpp deinterlacing -+ VAProcFilterParameterBufferDeinterlacing *filterParams; -+ VABufferID pipelineBuf; -+ VAProcPipelineParameterBuffer *pipelineParams; -+ VARectangle inputRegion; -+ VARectangle outputRegion; -+ -+ if (!CheckSuccess(vaBeginPicture(m_config.dpy, m_contextId, surf))) -+ { -+ return false; -+ } -+ -+ if (!CheckSuccess(vaCreateBuffer(m_config.dpy, m_contextId, -+ VAProcPipelineParameterBufferType, -+ sizeof(VAProcPipelineParameterBuffer), 1, NULL, &pipelineBuf))) -+ { -+ return false; -+ } -+ if (!CheckSuccess(vaMapBuffer(m_config.dpy, pipelineBuf, (void**)&pipelineParams))) -+ { -+ return false; -+ } -+ memset(pipelineParams, 0, sizeof(VAProcPipelineParameterBuffer)); -+ -+ inputRegion.x = outputRegion.x = 0; -+ inputRegion.y = outputRegion.y = 0; -+ inputRegion.width = outputRegion.width = m_config.surfaceWidth; -+ inputRegion.height = outputRegion.height = m_config.surfaceHeight; -+ -+ pipelineParams->output_region = &outputRegion; -+ pipelineParams->surface_region = &inputRegion; -+ pipelineParams->output_background_color = 0xff000000; -+ -+ VASurfaceID forwardRefs[32]; -+ VASurfaceID backwardRefs[32]; -+ pipelineParams->forward_references = forwardRefs; -+ pipelineParams->backward_references = backwardRefs; -+ pipelineParams->num_forward_references = 0; -+ pipelineParams->num_backward_references = 0; -+ -+ int maxPic = m_currentIdx + m_backwardRefs; -+ int minPic = m_currentIdx - m_forwardRefs; -+ int curPic = m_currentIdx; -+ -+ // deinterlace flag -+ unsigned int flags = 0; -+ if (it->DVDPic.iFlags & DVP_FLAG_TOP_FIELD_FIRST) -+ flags = 0; -+ else -+ flags = VA_DEINTERLACING_BOTTOM_FIELD_FIRST | VA_DEINTERLACING_BOTTOM_FIELD; -+ -+ if (m_step) -+ { -+ if (flags & VA_DEINTERLACING_BOTTOM_FIELD) -+ flags &= ~VA_DEINTERLACING_BOTTOM_FIELD; -+ else -+ flags |= VA_DEINTERLACING_BOTTOM_FIELD; -+ } -+ if (!CheckSuccess(vaMapBuffer(m_config.dpy, m_filter, (void**)&filterParams))) -+ { -+ return false; -+ } -+ filterParams->flags = flags; -+ if (!CheckSuccess(vaUnmapBuffer(m_config.dpy, m_filter))) -+ { -+ return false; -+ } -+ -+ if (m_vppMethod == VS_INTERLACEMETHOD_VAAPI_BOB) -+ pipelineParams->filter_flags = (flags & VA_DEINTERLACING_BOTTOM_FIELD) ? VA_BOTTOM_FIELD : VA_TOP_FIELD; -+ else -+ pipelineParams->filter_flags = 0; -+ pipelineParams->filters = &m_filter; -+ pipelineParams->num_filters = 1; -+ -+ // references -+ double pts, ptsLast = DVD_NOPTS_VALUE; -+ pipelineParams->surface = VA_INVALID_SURFACE; -+ for (it=m_decodedPics.begin(); it!=m_decodedPics.end(); ++it) -+ { -+ if (it->index >= minPic && it->index <= maxPic) -+ { -+ if (it->index > curPic) -+ { -+ backwardRefs[(it->index - curPic) - 1] = it->videoSurface; -+ pipelineParams->num_backward_references++; -+ } -+ else if (it->index == curPic) -+ { -+ pipelineParams->surface = it->videoSurface; -+ pts = it->DVDPic.pts; -+ } -+ if (it->index < curPic) -+ { -+ forwardRefs[(curPic - it->index) - 1] = it->videoSurface; -+ pipelineParams->num_forward_references++; -+ if (it->index == curPic - 1) -+ ptsLast = it->DVDPic.pts; -+ } -+ } -+ } -+ -+ // set pts for 2nd frame -+ if (m_step && pts != DVD_NOPTS_VALUE && ptsLast != DVD_NOPTS_VALUE) -+ outPic.DVDPic.pts += (pts-ptsLast)/2; -+ -+ if (pipelineParams->surface == VA_INVALID_SURFACE) -+ return false; -+ -+ if (!CheckSuccess(vaUnmapBuffer(m_config.dpy, pipelineBuf))) -+ { -+ return false; -+ } -+ -+ if (!CheckSuccess(vaRenderPicture(m_config.dpy, m_contextId, -+ &pipelineBuf, 1))) -+ { -+ return false; -+ } -+ -+ if (!CheckSuccess(vaEndPicture(m_config.dpy, m_contextId))) -+ { -+ return false; -+ } -+ -+ if (!CheckSuccess(vaDestroyBuffer(m_config.dpy, pipelineBuf))) -+ { -+ return false; -+ } -+ -+ m_step++; -+ outPic.videoSurface = m_videoSurfaces.GetFree(surf); -+ outPic.source = CVaapiProcessedPicture::VPP_SRC; -+ outPic.DVDPic.iFlags &= ~(DVP_FLAG_TOP_FIELD_FIRST | -+ DVP_FLAG_REPEAT_TOP_FIELD | -+ DVP_FLAG_INTERLACED); -+ -+#endif -+ return true; -+} -+ -+void CVppPostproc::Advance() -+{ -+ m_currentIdx++; -+ -+ // release all unneeded refs -+ std::deque::iterator it; -+ it = m_decodedPics.begin(); -+ while (it != m_decodedPics.end()) -+ { -+ if (it->index < m_currentIdx - m_forwardRefs) -+ { -+ m_config.videoSurfaces->ClearRender(it->videoSurface); -+ it = m_decodedPics.erase(it); -+ } -+ else -+ ++it; -+ } -+} -+ -+void CVppPostproc::ClearRef(VASurfaceID surf) -+{ -+ m_videoSurfaces.ClearReference(surf); -+} -+ -+void CVppPostproc::Flush() -+{ -+ // release all decoded pictures -+ std::deque::iterator it; -+ it = m_decodedPics.begin(); -+ while (it != m_decodedPics.end()) -+ { -+ m_config.videoSurfaces->ClearRender(it->videoSurface); -+ it = m_decodedPics.erase(it); -+ } -+} -+ -+bool CVppPostproc::Compatible(EINTERLACEMETHOD method) -+{ -+ if (method == VS_INTERLACEMETHOD_VAAPI_BOB || -+ method == VS_INTERLACEMETHOD_VAAPI_MADI || -+ method == VS_INTERLACEMETHOD_VAAPI_MACI) -+ return true; -+ -+ return false; -+} -+ -+bool CVppPostproc::CheckSuccess(VAStatus status) -+{ -+ if (status != VA_STATUS_SUCCESS) -+ { -+ CLog::Log(LOGERROR, "VAAPI - Error: %s(%d)", vaErrorStr(status), status); -+ return false; -+ } -+ return true; -+} -+ -+//----------------------------------------------------------------------------- -+// FFmpeg Postprocessing -+//----------------------------------------------------------------------------- -+ -+#define CACHED_BUFFER_SIZE 4096 -+ -+CFFmpegPostproc::CFFmpegPostproc() -+{ -+ m_cache = NULL; -+ m_pFilterFrameIn = NULL; -+ m_pFilterFrameOut = NULL; -+ m_pFilterGraph = NULL; -+ m_DVDPic.pts = DVD_NOPTS_VALUE; -+ m_frametime = 0; -+ m_lastOutPts = DVD_NOPTS_VALUE; -+} -+ -+CFFmpegPostproc::~CFFmpegPostproc() -+{ -+ Close(); -+ _aligned_free(m_cache); -+ m_dllSSE4.Unload(); -+ av_frame_free(&m_pFilterFrameIn); -+ av_frame_free(&m_pFilterFrameOut); -+} -+ -+bool CFFmpegPostproc::PreInit(CVaapiConfig &config, SDiMethods *methods) -+{ -+ m_config = config; -+ bool use_filter = true; -+ if (!m_dllSSE4.Load()) -+ { -+ CLog::Log(LOGNOTICE,"VAAPI::SupportsFilter failed loading sse4 lib"); -+ return false; -+ } -+ -+ // copying large surfaces via sse4 is a bit slow -+ // we just return false here as the primary use case the -+ // sse4 copy method is deinterlacing of max 1080i content -+ if (m_config.vidWidth > 1920 || m_config.vidHeight > 1088) -+ return false; -+ -+ VAImage image; -+ VASurfaceID surface = config.videoSurfaces->GetAtIndex(0); -+ VAStatus status = vaDeriveImage(config.dpy, surface, &image); -+ if (status != VA_STATUS_SUCCESS) -+ { -+ CLog::Log(LOGNOTICE,"VAAPI::SupportsFilter vaDeriveImage not supported"); -+ use_filter = false; -+ } -+ if (image.format.fourcc != VA_FOURCC_NV12) -+ { -+ CLog::Log(LOGNOTICE,"VAAPI::SupportsFilter image format not NV12"); -+ use_filter = false; -+ } -+ if ((image.pitches[0] % 64) || (image.pitches[1] % 64)) -+ { -+ CLog::Log(LOGNOTICE,"VAAPI::SupportsFilter patches no multiple of 64"); -+ use_filter = false; -+ } -+ CheckSuccess(vaDestroyImage(config.dpy,image.image_id)); -+ -+ if (use_filter) -+ { -+ m_cache = (uint8_t*)_aligned_malloc(CACHED_BUFFER_SIZE, 64); -+ if (methods) -+ { -+ methods->diMethods[methods->numDiMethods++] = VS_INTERLACEMETHOD_DEINTERLACE; -+ methods->diMethods[methods->numDiMethods++] = VS_INTERLACEMETHOD_RENDER_BOB; -+ } -+ } -+ return use_filter; -+} -+ -+bool CFFmpegPostproc::Init(EINTERLACEMETHOD method) -+{ -+ if (!(m_pFilterGraph = avfilter_graph_alloc())) -+ { -+ CLog::Log(LOGERROR, "CFFmpegPostproc::Init - unable to alloc filter graph"); -+ return false; -+ } -+ -+ AVFilter* srcFilter = avfilter_get_by_name("buffer"); -+ AVFilter* outFilter = avfilter_get_by_name("buffersink"); -+ -+ std::string args = StringUtils::Format("%d:%d:%d:%d:%d:%d:%d", -+ m_config.vidWidth, -+ m_config.vidHeight, -+ AV_PIX_FMT_NV12, -+ 1, -+ 1, -+ (m_config.aspect.num != 0) ? m_config.aspect.num : 1, -+ (m_config.aspect.num != 0) ? m_config.aspect.den : 1); -+ -+ if (avfilter_graph_create_filter(&m_pFilterIn, srcFilter, "src", args.c_str(), NULL, m_pFilterGraph) < 0) -+ { -+ CLog::Log(LOGERROR, "CFFmpegPostproc::Init - avfilter_graph_create_filter: src"); -+ return false; -+ } -+ -+ if (avfilter_graph_create_filter(&m_pFilterOut, outFilter, "out", NULL, NULL, m_pFilterGraph) < 0) -+ { -+ CLog::Log(LOGERROR, "CFFmpegPostproc::Init - avfilter_graph_create_filter: out"); -+ return false; -+ } -+ -+ enum AVPixelFormat pix_fmts[] = { AV_PIX_FMT_NV12, AV_PIX_FMT_NONE }; -+ if (av_opt_set_int_list(m_pFilterOut, "pix_fmts", pix_fmts, AV_PIX_FMT_NONE, AV_OPT_SEARCH_CHILDREN) < 0) -+ { -+ CLog::Log(LOGERROR, "CFFmpegPostproc::Init - failed settings pix formats"); -+ return false; -+ } -+ -+ AVFilterInOut* outputs = avfilter_inout_alloc(); -+ AVFilterInOut* inputs = avfilter_inout_alloc(); -+ -+ outputs->name = av_strdup("in"); -+ outputs->filter_ctx = m_pFilterIn; -+ outputs->pad_idx = 0; -+ outputs->next = NULL; -+ -+ inputs->name = av_strdup("out"); -+ inputs->filter_ctx = m_pFilterOut; -+ inputs->pad_idx = 0; -+ inputs->next = NULL; -+ -+ if (method == VS_INTERLACEMETHOD_DEINTERLACE) -+ { -+ std::string filter; -+ -+ filter = "yadif=1:-1"; -+ -+ if (avfilter_graph_parse_ptr(m_pFilterGraph, filter.c_str(), &inputs, &outputs, NULL) < 0) -+ { -+ CLog::Log(LOGERROR, "CFFmpegPostproc::Init - avfilter_graph_parse"); -+ avfilter_inout_free(&outputs); -+ avfilter_inout_free(&inputs); -+ return false; -+ } -+ -+ avfilter_inout_free(&outputs); -+ avfilter_inout_free(&inputs); -+ -+ if (avfilter_graph_config(m_pFilterGraph, NULL) < 0) -+ { -+ CLog::Log(LOGERROR, "CFFmpegPostproc::Init - avfilter_graph_config"); -+ return false; -+ } -+ } -+ else if (method == VS_INTERLACEMETHOD_RENDER_BOB || -+ method == VS_INTERLACEMETHOD_NONE) -+ { -+ CLog::Log(LOGDEBUG, "CFFmpegPostproc::Init - no skip deinterlacing"); -+ } -+ else -+ { -+ avfilter_inout_free(&outputs); -+ avfilter_inout_free(&inputs); -+ return false; -+ } -+ m_diMethod = method; -+ -+ m_pFilterFrameIn = av_frame_alloc(); -+ m_pFilterFrameOut = av_frame_alloc(); -+ return true; -+} -+ -+bool CFFmpegPostproc::AddPicture(CVaapiDecodedPicture &inPic) -+{ -+ VASurfaceID surf = inPic.videoSurface; -+ VASurfaceStatus surf_status; -+ VAImage image; -+ uint8_t *buf; -+ if (m_DVDPic.pts != DVD_NOPTS_VALUE && inPic.DVDPic.pts != DVD_NOPTS_VALUE) -+ { -+ m_frametime = inPic.DVDPic.pts - m_DVDPic.pts; -+ } -+ m_DVDPic = inPic.DVDPic; -+ bool result = false; -+ -+ if (!CheckSuccess(vaSyncSurface(m_config.dpy, surf))) -+ goto error; -+ -+ if (!CheckSuccess(vaDeriveImage(m_config.dpy, surf, &image))) -+ goto error; -+ -+ if (!CheckSuccess(vaMapBuffer(m_config.dpy, image.buf, (void**)&buf))) -+ goto error; -+ -+ m_pFilterFrameIn->format = AV_PIX_FMT_NV12; -+ m_pFilterFrameIn->width = m_config.vidWidth; -+ m_pFilterFrameIn->height = m_config.vidHeight; -+ m_pFilterFrameIn->linesize[0] = image.pitches[0]; -+ m_pFilterFrameIn->linesize[1] = image.pitches[1]; -+ m_pFilterFrameIn->interlaced_frame = (inPic.DVDPic.iFlags & DVP_FLAG_INTERLACED) ? 1 : 0; -+ m_pFilterFrameIn->top_field_first = (inPic.DVDPic.iFlags & DVP_FLAG_TOP_FIELD_FIRST) ? 1 : 0; -+ -+ if (inPic.DVDPic.pts == DVD_NOPTS_VALUE) -+ m_pFilterFrameIn->pkt_pts = AV_NOPTS_VALUE; -+ else -+ m_pFilterFrameIn->pkt_pts = (inPic.DVDPic.pts / DVD_TIME_BASE) * AV_TIME_BASE; -+ -+ av_frame_get_buffer(m_pFilterFrameIn, 64); -+ -+ uint8_t *src, *dst; -+ src = buf + image.offsets[0]; -+ dst = m_pFilterFrameIn->data[0]; -+ m_dllSSE4.copy_frame(src, dst, m_cache, image.width, image.height, image.pitches[0]); -+ -+ src = buf + image.offsets[1]; -+ dst = m_pFilterFrameIn->data[1]; -+ m_dllSSE4.copy_frame(src, dst, m_cache, image.width, image.height/2, image.pitches[1]); -+ -+ m_pFilterFrameIn->linesize[0] = image.pitches[0]; -+ m_pFilterFrameIn->linesize[1] = image.pitches[1]; -+ m_pFilterFrameIn->data[2] = NULL; -+ m_pFilterFrameIn->data[3] = NULL; -+ m_pFilterFrameIn->pkt_size = image.data_size; -+ -+ CheckSuccess(vaUnmapBuffer(m_config.dpy, image.buf)); -+ CheckSuccess(vaDestroyImage(m_config.dpy,image.image_id)); -+ -+ if (m_diMethod == VS_INTERLACEMETHOD_DEINTERLACE) -+ { -+ if (av_buffersrc_add_frame(m_pFilterIn, m_pFilterFrameIn) < 0) -+ { -+ CLog::Log(LOGERROR, "CFFmpegPostproc::AddPicture - av_buffersrc_add_frame"); -+ goto error; -+ } -+ } -+ else if (m_diMethod == VS_INTERLACEMETHOD_RENDER_BOB || -+ m_diMethod == VS_INTERLACEMETHOD_NONE) -+ { -+ av_frame_move_ref(m_pFilterFrameOut, m_pFilterFrameIn); -+ m_step = 0; -+ } -+ av_frame_unref(m_pFilterFrameIn); -+ -+ result = true; -+ -+error: -+ m_config.videoSurfaces->ClearRender(surf); -+ return result; -+} -+ -+bool CFFmpegPostproc::Filter(CVaapiProcessedPicture &outPic) -+{ -+ outPic.DVDPic = m_DVDPic; -+ if (m_diMethod == VS_INTERLACEMETHOD_DEINTERLACE) -+ { -+ int result; -+ result = av_buffersink_get_frame(m_pFilterOut, m_pFilterFrameOut); -+ -+ if(result == AVERROR(EAGAIN) || result == AVERROR_EOF) -+ return false; -+ else if(result < 0) -+ { -+ CLog::Log(LOGERROR, "CFFmpegPostproc::Filter - av_buffersink_get_frame"); -+ return false; -+ } -+ outPic.DVDPic.iFlags &= ~(DVP_FLAG_TOP_FIELD_FIRST | -+ DVP_FLAG_REPEAT_TOP_FIELD | -+ DVP_FLAG_INTERLACED); -+ } -+ else if (m_diMethod == VS_INTERLACEMETHOD_RENDER_BOB || -+ m_diMethod == VS_INTERLACEMETHOD_NONE) -+ { -+ if (m_step>0) -+ return false; -+ } -+ -+ m_step++; -+ outPic.frame = av_frame_clone(m_pFilterFrameOut); -+ av_frame_unref(m_pFilterFrameOut); -+ -+ outPic.source = CVaapiProcessedPicture::FFMPEG_SRC; -+ -+ if(outPic.frame->pkt_pts != AV_NOPTS_VALUE) -+ { -+ outPic.DVDPic.pts = (double)outPic.frame->pkt_pts * DVD_TIME_BASE / AV_TIME_BASE; -+ } -+ else -+ outPic.DVDPic.pts = DVD_NOPTS_VALUE; -+ -+ double pts = outPic.DVDPic.pts; -+ if (m_lastOutPts != DVD_NOPTS_VALUE && m_lastOutPts == pts) -+ { -+ outPic.DVDPic.pts += m_frametime/2; -+ } -+ m_lastOutPts = pts; -+ -+ for (int i = 0; i < 4; i++) -+ outPic.DVDPic.data[i] = outPic.frame->data[i]; -+ for (int i = 0; i < 4; i++) -+ outPic.DVDPic.iLineSize[i] = outPic.frame->linesize[i]; -+ -+ return true; -+} -+ -+void CFFmpegPostproc::ClearRef(VASurfaceID surf) -+{ -+ -+} -+ -+void CFFmpegPostproc::Close() -+{ -+ if (m_pFilterGraph) -+ { -+ avfilter_graph_free(&m_pFilterGraph); -+ } -+} -+ -+void CFFmpegPostproc::Flush() -+{ -+ Close(); -+ Init(m_diMethod); -+ m_DVDPic.pts = DVD_NOPTS_VALUE; -+ m_frametime = 0; -+ m_lastOutPts = DVD_NOPTS_VALUE; -+} -+ -+bool CFFmpegPostproc::Compatible(EINTERLACEMETHOD method) -+{ -+ if (method == VS_INTERLACEMETHOD_DEINTERLACE) -+ return true; -+ else if (method == VS_INTERLACEMETHOD_RENDER_BOB) -+ return true; -+ else if (method == VS_INTERLACEMETHOD_NONE && -+ !CSettings::Get().GetBool("videoplayer.prefervaapirender")) -+ return true; -+ -+ return false; -+} -+ -+bool CFFmpegPostproc::CheckSuccess(VAStatus status) -+{ -+ if (status != VA_STATUS_SUCCESS) -+ { -+ CLog::Log(LOGERROR, "VAAPI - Error: %s(%d)", vaErrorStr(status), status); -+ return false; -+ } -+ return true; - } - - #endif -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.h -index ec99162..0c4fc62 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.h -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.h -@@ -20,127 +20,517 @@ - #pragma once - - #include "system_gl.h" -+#define GLX_GLXEXT_PROTOTYPES -+#include - -+#include "DVDVideoCodec.h" - #include "DVDVideoCodecFFmpeg.h" --#include --#include --#include -+#include "DVDVideoCodec.h" -+#include "DVDVideoCodecFFmpeg.h" -+#include "settings/VideoSettings.h" -+#include "threads/CriticalSection.h" -+#include "threads/SharedSection.h" -+#include "threads/Event.h" -+#include "threads/Thread.h" -+#include "utils/ActorProtocol.h" - #include --#include -+#include -+#include -+#include "linux/sse4/DllLibSSE4.h" - - extern "C" { -+#include "libavutil/avutil.h" - #include "libavcodec/vaapi.h" - } - --namespace VAAPI { -+using namespace Actor; - --typedef boost::shared_ptr VASurfacePtr; - --struct CDisplay -- : CCriticalSection -+#define FULLHD_WIDTH 1920 -+ -+namespace VAAPI - { -- CDisplay(VADisplay display, bool deinterlace) -- : m_display(display) -- , m_lost(false) -- , m_deinterlace(deinterlace) -- , m_support_4k(true) -- {} -- ~CDisplay(); - -- VADisplay get() { return m_display; } -- bool lost() { return m_lost; } -- void lost(bool lost) { m_lost = lost; } -- bool support_deinterlace() { return m_deinterlace; }; -- bool support_4k() { return m_support_4k; }; -- void support_4k(bool support_4k) { m_support_4k = support_4k; }; -+//----------------------------------------------------------------------------- -+// VAAPI data structs -+//----------------------------------------------------------------------------- -+ -+class CDecoder; -+ -+/** -+ * Buffer statistics used to control number of frames in queue -+ */ -+ -+class CVaapiBufferStats -+{ -+public: -+ uint16_t decodedPics; -+ uint16_t processedPics; -+ uint16_t renderPics; -+ uint64_t latency; // time decoder has waited for a frame, ideally there is no latency -+ int codecFlags; -+ bool canSkipDeint; -+ int processCmd; -+ -+ void IncDecoded() { CSingleLock l(m_sec); decodedPics++;} -+ void DecDecoded() { CSingleLock l(m_sec); decodedPics--;} -+ void IncProcessed() { CSingleLock l(m_sec); processedPics++;} -+ void DecProcessed() { CSingleLock l(m_sec); processedPics--;} -+ void IncRender() { CSingleLock l(m_sec); renderPics++;} -+ void DecRender() { CSingleLock l(m_sec); renderPics--;} -+ void Reset() { CSingleLock l(m_sec); decodedPics=0; processedPics=0;renderPics=0;latency=0;} -+ void Get(uint16_t &decoded, uint16_t &processed, uint16_t &render) {CSingleLock l(m_sec); decoded = decodedPics, processed=processedPics, render=renderPics;} -+ void SetParams(uint64_t time, int flags) { CSingleLock l(m_sec); latency = time; codecFlags = flags; } -+ void GetParams(uint64_t &lat, int &flags) { CSingleLock l(m_sec); lat = latency; flags = codecFlags; } -+ void SetCmd(int cmd) { CSingleLock l(m_sec); processCmd = cmd; } -+ void GetCmd(int &cmd) { CSingleLock l(m_sec); cmd = processCmd; processCmd = 0; } -+ void SetCanSkipDeint(bool canSkip) { CSingleLock l(m_sec); canSkipDeint = canSkip; } -+ bool CanSkipDeint() { CSingleLock l(m_sec); if (canSkipDeint) return true; else return false;} - private: -- VADisplay m_display; -- bool m_lost; -- bool m_deinterlace; -- bool m_support_4k; -+ CCriticalSection m_sec; - }; - --typedef boost::shared_ptr CDisplayPtr; -+/** -+ * CVaapiConfig holds all configuration parameters needed by vaapi -+ * The structure is sent to the internal classes CMixer and COutput -+ * for init. -+ */ -+ -+class CVideoSurfaces; -+class CVAAPIContext; - --struct CSurface -+struct CVaapiConfig - { -- CSurface(VASurfaceID id, CDisplayPtr& display) -- : m_id(id) -- , m_display(display) -- {} -+ int surfaceWidth; -+ int surfaceHeight; -+ int vidWidth; -+ int vidHeight; -+ int outWidth; -+ int outHeight; -+ AVRational aspect; -+ VAConfigID configId; -+ VAContextID contextId; -+ CVaapiBufferStats *stats; -+ CDecoder *vaapi; -+ int upscale; -+ CVideoSurfaces *videoSurfaces; -+ int numRenderBuffers; -+ uint32_t maxReferences; -+ bool useInteropYuv; -+ CVAAPIContext *context; -+ VADisplay dpy; -+ VAProfile profile; -+ VAConfigAttrib attrib; -+}; - -- ~CSurface(); -+/** -+ * Holds a decoded frame -+ * Input to COutput for further processing -+ */ -+struct CVaapiDecodedPicture -+{ -+ DVDVideoPicture DVDPic; -+ VASurfaceID videoSurface; -+ int index; -+}; - -- VASurfaceID m_id; -- CDisplayPtr m_display; -+/** -+ * Frame after having been processed by vpp -+ */ -+struct CVaapiProcessedPicture -+{ -+ DVDVideoPicture DVDPic; -+ VASurfaceID videoSurface; -+ AVFrame *frame; -+ enum -+ { -+ VPP_SRC, -+ FFMPEG_SRC, -+ SKIP_SRC -+ }source; -+ bool crop; - }; - --typedef boost::shared_ptr CSurfacePtr; -+/** -+ * Ready to render textures -+ * Sent from COutput back to CDecoder -+ * Objects are referenced by DVDVideoPicture and are sent -+ * to renderer -+ */ -+class CVaapiRenderPicture -+{ -+ friend class CDecoder; -+ friend class COutput; -+public: -+ CVaapiRenderPicture(CCriticalSection §ion) -+ : texture(None), avFrame(NULL), refCount(0), renderPicSection(section) { fence = None; } -+ void Sync(); -+ DVDVideoPicture DVDPic; -+ int texWidth, texHeight; -+ CRect crop; -+ GLuint texture; -+ bool valid; -+ CDecoder *vaapi; -+ AVFrame *avFrame; -+ CVaapiRenderPicture* Acquire(); -+ long Release(); -+private: -+ void ReturnUnused(); -+ bool usefence; -+ GLsync fence; -+ int refCount; -+ Pixmap pixmap; -+ GLXPixmap glPixmap; -+ CCriticalSection &renderPicSection; -+}; - --struct CSurfaceGL -+//----------------------------------------------------------------------------- -+// Output -+//----------------------------------------------------------------------------- -+ -+/** -+ * Buffer pool holds allocated vaapi and gl resources -+ * Embedded in COutput -+ */ -+struct VaapiBufferPool - { -- CSurfaceGL(void* id, CDisplayPtr& display) -- : m_id(id) -- , m_display(display) -- {} -- ~CSurfaceGL(); -- -- void* m_id; -- CDisplayPtr m_display; -+ VaapiBufferPool(); -+ virtual ~VaapiBufferPool(); -+ std::vector allRenderPics; -+ std::deque usedRenderPics; -+ std::deque freeRenderPics; -+ std::deque syncRenderPics; -+ std::deque processedPics; -+ std::deque decodedPics; -+ CCriticalSection renderPicSec; - }; - --typedef boost::shared_ptr CSurfaceGLPtr; -+class COutputControlProtocol : public Protocol -+{ -+public: -+ COutputControlProtocol(std::string name, CEvent* inEvent, CEvent *outEvent) : Protocol(name, inEvent, outEvent) {}; -+ enum OutSignal -+ { -+ INIT, -+ FLUSH, -+ PRECLEANUP, -+ TIMEOUT, -+ }; -+ enum InSignal -+ { -+ ACC, -+ ERROR, -+ STATS, -+ }; -+}; - --// silly type to avoid includes --struct CHolder -+class COutputDataProtocol : public Protocol - { -- CDisplayPtr display; -- CSurfacePtr surface; -- CSurfaceGLPtr surfglx; -+public: -+ COutputDataProtocol(std::string name, CEvent* inEvent, CEvent *outEvent) : Protocol(name, inEvent, outEvent) {}; -+ enum OutSignal -+ { -+ NEWFRAME = 0, -+ RETURNPIC, -+ }; -+ enum InSignal -+ { -+ PICTURE, -+ }; -+}; - -- CHolder() -- {} -+struct SDiMethods -+{ -+ EINTERLACEMETHOD diMethods[8]; -+ int numDiMethods; - }; - -+/** -+ * COutput is embedded in CDecoder and embeds vpp -+ * The class has its own OpenGl context which is shared with render thread -+ * COuput generated ready to render textures and passes them back to -+ * CDecoder -+ */ -+class CPostproc; -+ -+class COutput : private CThread -+{ -+public: -+ COutput(CEvent *inMsgEvent); -+ virtual ~COutput(); -+ void Start(); -+ void Dispose(); -+ COutputControlProtocol m_controlPort; -+ COutputDataProtocol m_dataPort; -+protected: -+ void OnStartup(); -+ void OnExit(); -+ void Process(); -+ void StateMachine(int signal, Protocol *port, Message *msg); -+ bool HasWork(); -+ void InitCycle(); -+ CVaapiRenderPicture* ProcessPicture(CVaapiProcessedPicture &pic); -+ void QueueReturnPicture(CVaapiRenderPicture *pic); -+ void ProcessReturnPicture(CVaapiRenderPicture *pic); -+ bool ProcessSyncPicture(); -+ void ReleaseProcessedPicture(CVaapiProcessedPicture &pic); -+ void DropVppProcessedPictures(); -+ bool Init(); -+ bool Uninit(); -+ void Flush(); -+ bool CreateGlxContext(); -+ bool DestroyGlxContext(); -+ bool EnsureBufferPool(); -+ void ReleaseBufferPool(bool precleanup = false); -+ bool GLInit(); -+ bool CheckSuccess(VAStatus status); -+ PFNGLXBINDTEXIMAGEEXTPROC glXBindTexImageEXT; -+ PFNGLXRELEASETEXIMAGEEXTPROC glXReleaseTexImageEXT; -+ CEvent m_outMsgEvent; -+ CEvent *m_inMsgEvent; -+ int m_state; -+ bool m_bStateMachineSelfTrigger; -+ -+ // extended state variables for state machine -+ int m_extTimeout; -+ bool m_vaError; -+ CVaapiConfig m_config; -+ VaapiBufferPool m_bufferPool; -+ Display *m_Display; -+ Window m_Window; -+ GLXContext m_glContext; -+ GLXWindow m_glWindow; -+ Pixmap m_pixmap; -+ GLXPixmap m_glPixmap; -+ CVaapiDecodedPicture m_currentPicture; -+ GLenum m_textureTarget; -+ CPostproc *m_pp; -+ SDiMethods m_diMethods; -+ EINTERLACEMETHOD m_currentDiMethod; -+}; -+ -+//----------------------------------------------------------------------------- -+// VAAPI Video Surface states -+//----------------------------------------------------------------------------- -+ -+class CVideoSurfaces -+{ -+public: -+ void AddSurface(VASurfaceID surf); -+ void ClearReference(VASurfaceID surf); -+ bool MarkRender(VASurfaceID surf); -+ void ClearRender(VASurfaceID surf); -+ bool IsValid(VASurfaceID surf); -+ VASurfaceID GetFree(VASurfaceID surf); -+ VASurfaceID GetAtIndex(int idx); -+ VASurfaceID RemoveNext(bool skiprender = false); -+ void Reset(); -+ int Size(); -+ bool HasFree(); -+protected: -+ std::map m_state; -+ std::list m_freeSurfaces; -+ CCriticalSection m_section; -+}; -+ -+//----------------------------------------------------------------------------- -+// VAAPI decoder -+//----------------------------------------------------------------------------- -+ -+class CVAAPIContext -+{ -+public: -+ static bool EnsureContext(CVAAPIContext **ctx, CDecoder *decoder); -+ void Release(CDecoder *decoder); -+ VADisplay GetDisplay(); -+ bool SupportsProfile(VAProfile profile); -+ VAConfigAttrib GetAttrib(VAProfile profile); -+ VAConfigID CreateConfig(VAProfile profile, VAConfigAttrib attrib); -+ static void FFReleaseBuffer(void *opaque, uint8_t *data); -+private: -+ CVAAPIContext(); -+ void Close(); -+ bool CreateContext(); -+ void DestroyContext(); -+ void QueryCaps(); -+ bool CheckSuccess(VAStatus status); -+ bool IsValidDecoder(CDecoder *decoder); -+ static CVAAPIContext *m_context; -+ static CCriticalSection m_section; -+ static Display *m_X11dpy; -+ VADisplay m_display; -+ int m_refCount; -+ int m_attributeCount; -+ VADisplayAttribute *m_attributes; -+ int m_profileCount; -+ VAProfile *m_profiles; -+ std::vector m_decoders; -+}; -+ -+/** -+ * VAAPI main class -+ */ - class CDecoder -- : public CDVDVideoCodecFFmpeg::IHardwareDecoder -+ : public CDVDVideoCodecFFmpeg::IHardwareDecoder - { -- bool EnsureContext(AVCodecContext *avctx); -- bool EnsureSurfaces(AVCodecContext *avctx, unsigned n_surfaces_count); -+ friend class CVaapiRenderPicture; -+ - public: -+ - CDecoder(); -- ~CDecoder(); -+ virtual ~CDecoder(); -+ - virtual bool Open (AVCodecContext* avctx, const enum PixelFormat, unsigned int surfaces = 0); - virtual int Decode (AVCodecContext* avctx, AVFrame* frame); - virtual bool GetPicture(AVCodecContext* avctx, AVFrame* frame, DVDVideoPicture* picture); -- virtual int Check (AVCodecContext* avctx); -+ virtual void Reset(); - virtual void Close(); -+ virtual long Release(); -+ virtual bool CanSkipDeint(); -+ virtual unsigned GetAllowedReferences() { return 5; } -+ -+ virtual int Check(AVCodecContext* avctx); - virtual const std::string Name() { return "vaapi"; } -- virtual CCriticalSection* Section() { if(m_display) return m_display.get(); else return NULL; } -- virtual unsigned GetAllowedReferences(); - -- int GetBuffer(AVCodecContext *avctx, AVFrame *pic, int flags); -- void RelBuffer(uint8_t *data); -+ bool Supports(EINTERLACEMETHOD method); -+ EINTERLACEMETHOD AutoInterlaceMethod(); -+ -+ void FFReleaseBuffer(uint8_t *data); -+ static int FFGetBuffer(AVCodecContext *avctx, AVFrame *pic, int flags); - -- VADisplay GetDisplay() { return m_display->get(); } - protected: -- -- static const unsigned m_surfaces_max = 32; -- unsigned m_surfaces_count; -- VASurfaceID m_surfaces[m_surfaces_max]; -- unsigned m_renderbuffers_count; -+ void SetWidthHeight(int width, int height); -+ bool ConfigVAAPI(); -+ bool CheckStatus(VAStatus vdp_st, int line); -+ void FiniVAAPIOutput(); -+ void ReturnRenderPicture(CVaapiRenderPicture *renderPic); -+ long ReleasePicReference(); -+ bool CheckSuccess(VAStatus status); -+ -+ enum EDisplayState -+ { VAAPI_OPEN -+ , VAAPI_RESET -+ , VAAPI_LOST -+ , VAAPI_ERROR -+ } m_DisplayState; -+ CCriticalSection m_DecoderSection; -+ CEvent m_DisplayEvent; -+ int m_ErrorCount; -+ -+ ThreadIdentifier m_decoderThread; -+ bool m_vaapiConfigured; -+ CVaapiConfig m_vaapiConfig; -+ CVideoSurfaces m_videoSurfaces; -+ vaapi_context m_hwContext; -+ -+ COutput m_vaapiOutput; -+ CVaapiBufferStats m_bufferStats; -+ CEvent m_inMsgEvent; -+ CVaapiRenderPicture *m_presentPicture; -+ -+ int m_codecControl; -+ std::vector m_diMethods; -+}; - -- int m_refs; -- std::list m_surfaces_used; -- std::list m_surfaces_free; -+//----------------------------------------------------------------------------- -+// Postprocessing -+//----------------------------------------------------------------------------- - -- CDisplayPtr m_display; -- VAConfigID m_config; -- VAContextID m_context; -+/** -+ * Base class -+ */ -+class CPostproc -+{ -+public: -+ virtual ~CPostproc() {}; -+ virtual bool PreInit(CVaapiConfig &config, SDiMethods *methods = NULL) = 0; -+ virtual bool Init(EINTERLACEMETHOD method) = 0; -+ virtual bool AddPicture(CVaapiDecodedPicture &inPic) = 0; -+ virtual bool Filter(CVaapiProcessedPicture &outPic) = 0; -+ virtual void ClearRef(VASurfaceID surf) = 0; -+ virtual void Flush() = 0; -+ virtual bool Compatible(EINTERLACEMETHOD method) = 0; -+protected: -+ CVaapiConfig m_config; -+ int m_step; -+}; - -- vaapi_context *m_hwaccel; -+/** -+ * skip post processing -+ */ -+class CSkipPostproc : public CPostproc -+{ -+public: -+ bool PreInit(CVaapiConfig &config, SDiMethods *methods = NULL); -+ bool Init(EINTERLACEMETHOD method); -+ bool AddPicture(CVaapiDecodedPicture &inPic); -+ bool Filter(CVaapiProcessedPicture &outPic); -+ void ClearRef(VASurfaceID surf); -+ void Flush(); -+ bool Compatible(EINTERLACEMETHOD method); -+protected: -+ CVaapiDecodedPicture m_pic; -+}; - -- CHolder m_holder; // silly struct to pass data to renderer -+/** -+ * VAAPI post processing -+ */ -+class CVppPostproc : public CPostproc -+{ -+public: -+ CVppPostproc(); -+ virtual ~CVppPostproc(); -+ bool PreInit(CVaapiConfig &config, SDiMethods *methods = NULL); -+ bool Init(EINTERLACEMETHOD method); -+ bool AddPicture(CVaapiDecodedPicture &inPic); -+ bool Filter(CVaapiProcessedPicture &outPic); -+ void ClearRef(VASurfaceID surf); -+ void Flush(); -+ bool Compatible(EINTERLACEMETHOD method); -+protected: -+ bool CheckSuccess(VAStatus status); -+ void Dispose(); -+ void Advance(); -+ VAConfigID m_configId; -+ VAContextID m_contextId; -+ CVideoSurfaces m_videoSurfaces; -+ std::deque m_decodedPics; -+ VABufferID m_filter; -+ int m_forwardRefs, m_backwardRefs; -+ int m_currentIdx; -+ int m_frameCount; -+ EINTERLACEMETHOD m_vppMethod; -+}; -+ -+/** -+ * ffmpeg filter -+ */ -+class CFFmpegPostproc : public CPostproc -+{ -+public: -+ CFFmpegPostproc(); -+ virtual ~CFFmpegPostproc(); -+ bool PreInit(CVaapiConfig &config, SDiMethods *methods = NULL); -+ bool Init(EINTERLACEMETHOD method); -+ bool AddPicture(CVaapiDecodedPicture &inPic); -+ bool Filter(CVaapiProcessedPicture &outPic); -+ void ClearRef(VASurfaceID surf); -+ void Flush(); -+ bool Compatible(EINTERLACEMETHOD method); -+protected: -+ bool CheckSuccess(VAStatus status); -+ void Close(); -+ DllLibSSE4 m_dllSSE4; -+ uint8_t *m_cache; -+ AVFilterGraph* m_pFilterGraph; -+ AVFilterContext* m_pFilterIn; -+ AVFilterContext* m_pFilterOut; -+ AVFrame *m_pFilterFrameIn; -+ AVFrame *m_pFilterFrameOut; -+ EINTERLACEMETHOD m_diMethod; -+ DVDVideoPicture m_DVDPic; -+ double m_frametime; -+ double m_lastOutPts; - }; - - } -diff --git a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp -index f530567..f9a45e8 100644 ---- a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp -+++ b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp -@@ -1009,6 +1009,7 @@ static std::string GetRenderFormatName(ERenderFormat format) - case RENDER_FMT_VDPAU_420: return "VDPAU_420"; - case RENDER_FMT_DXVA: return "DXVA"; - case RENDER_FMT_VAAPI: return "VAAPI"; -+ case RENDER_FMT_VAAPINV12: return "VAAPI_NV12"; - case RENDER_FMT_OMXEGL: return "OMXEGL"; - case RENDER_FMT_CVBREF: return "BGRA"; - case RENDER_FMT_EGLIMG: return "EGLIMG"; -diff --git a/xbmc/settings/VideoSettings.h b/xbmc/settings/VideoSettings.h -index 32a2e8d..88434a4 100644 ---- a/xbmc/settings/VideoSettings.h -+++ b/xbmc/settings/VideoSettings.h -@@ -63,6 +63,10 @@ enum EINTERLACEMETHOD - VS_INTERLACEMETHOD_SW_BLEND = 20, - VS_INTERLACEMETHOD_AUTO_ION = 21, - -+ VS_INTERLACEMETHOD_VAAPI_BOB = 22, -+ VS_INTERLACEMETHOD_VAAPI_MADI = 23, -+ VS_INTERLACEMETHOD_VAAPI_MACI = 24, -+ - VS_INTERLACEMETHOD_MAX // do not use and keep as last enum value. - }; - -diff --git a/xbmc/video/dialogs/GUIDialogVideoSettings.cpp b/xbmc/video/dialogs/GUIDialogVideoSettings.cpp -index 760eda5..965f297 100644 ---- a/xbmc/video/dialogs/GUIDialogVideoSettings.cpp -+++ b/xbmc/video/dialogs/GUIDialogVideoSettings.cpp -@@ -259,6 +259,9 @@ void CGUIDialogVideoSettings::InitializeSettings() - entries.push_back(make_pair(16320, VS_INTERLACEMETHOD_DXVA_BOB)); - entries.push_back(make_pair(16321, VS_INTERLACEMETHOD_DXVA_BEST)); - entries.push_back(make_pair(16325, VS_INTERLACEMETHOD_AUTO_ION)); -+ entries.push_back(make_pair(16327, VS_INTERLACEMETHOD_VAAPI_BOB)); -+ entries.push_back(make_pair(16328, VS_INTERLACEMETHOD_VAAPI_MADI)); -+ entries.push_back(make_pair(16329, VS_INTERLACEMETHOD_VAAPI_MACI)); - - /* remove unsupported methods */ - for (StaticIntegerSettingOptions::iterator it = entries.begin(); it != entries.end(); ) --- -2.0.4 - - -From cb2fc4c71d8582e83bafd036eed14ee8cbc4550a Mon Sep 17 00:00:00 2001 +From 87f7579c0c9e38f8b1763d91b845431fd87504de Mon Sep 17 00:00:00 2001 From: Rainer Hochecker Date: Sat, 26 Jul 2014 09:54:06 +0200 -Subject: [PATCH 23/31] ffmpeg: adapt depreciated attribute +Subject: [PATCH 21/24] ffmpeg: adapt depreciated attribute max_analyze_duration --- @@ -7310,189 +2183,11 @@ index 2332b1b..edaa006 100644 m_checkvideo = true; isMpegts = true; } --- -2.0.4 - -From 98f504310e967283db7b50ae5ca6d77aadfa4091 Mon Sep 17 00:00:00 2001 -From: Rainer Hochecker -Date: Sat, 16 Aug 2014 20:45:37 +0200 -Subject: [PATCH 24/31] ALSA: remove log spam by adding not ELD listed - passthrough formats after the pcm formats - ---- - xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp | 32 +++++++++++++++-------------- - 1 file changed, 17 insertions(+), 15 deletions(-) - -diff --git a/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp b/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp -index 8dee4bc..b7411b8 100644 ---- a/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp -+++ b/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp -@@ -1343,21 +1343,6 @@ void CAESinkALSA::EnumerateDevice(AEDeviceInfoList &list, const std::string &dev - /* snd_hctl_close also closes ctlhandle */ - snd_hctl_close(hctl); - -- // regarding data formats we don't trust ELD -- // push all passthrough formats to the list -- AEDataFormatList::iterator it; -- for (enum AEDataFormat i = AE_FMT_MAX; i > AE_FMT_INVALID; i = (enum AEDataFormat)((int)i - 1)) -- { -- if (!AE_IS_RAW(i)) -- continue; -- it = find(info.m_dataFormats.begin(), info.m_dataFormats.end(), i); -- if (it == info.m_dataFormats.end()) -- { -- info.m_dataFormats.push_back(i); -- CLog::Log(LOGNOTICE, "CAESinkALSA::%s data format \"%s\" on device \"%s\" seems to be not supported.", __FUNCTION__, CAEUtil::DataFormatToStr(i), device.c_str()); -- } -- } -- - if (badHDMI) - { - /* -@@ -1501,6 +1486,23 @@ void CAESinkALSA::EnumerateDevice(AEDeviceInfoList &list, const std::string &dev - info.m_dataFormats.push_back(i); - } - -+ if (info.m_deviceType == AE_DEVTYPE_HDMI) -+ { -+ // regarding data formats we don't trust ELD -+ // push all passthrough formats to the list -+ AEDataFormatList::iterator it; -+ for (enum AEDataFormat i = AE_FMT_MAX; i > AE_FMT_INVALID; i = (enum AEDataFormat)((int)i - 1)) -+ { -+ if (!AE_IS_RAW(i)) -+ continue; -+ it = find(info.m_dataFormats.begin(), info.m_dataFormats.end(), i); -+ if (it == info.m_dataFormats.end()) -+ { -+ info.m_dataFormats.push_back(i); -+ } -+ } -+ } -+ - snd_pcm_close(pcmhandle); - list.push_back(info); - } --- -2.0.4 - - -From be2aee8d283033f876438e1b24b39f1cc1d45a06 Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Tue, 19 Aug 2014 00:53:17 +0100 -Subject: [PATCH 25/31] [dvdplayer] Allow UpdateCorrection to handle audio and - video jumping asynchronously - ---- - xbmc/cores/dvdplayer/DVDPlayer.cpp | 22 ++++++++++++++++------ - xbmc/cores/dvdplayer/DVDPlayer.h | 2 ++ - 2 files changed, 18 insertions(+), 6 deletions(-) - -diff --git a/xbmc/cores/dvdplayer/DVDPlayer.cpp b/xbmc/cores/dvdplayer/DVDPlayer.cpp -index 4c4de1b..a7f59c6 100644 ---- a/xbmc/cores/dvdplayer/DVDPlayer.cpp -+++ b/xbmc/cores/dvdplayer/DVDPlayer.cpp -@@ -538,6 +538,8 @@ bool CDVDPlayer::OpenFile(const CFileItem& file, const CPlayerOptions &options) - m_State.Clear(); - m_UpdateApplication = 0; - m_offset_pts = 0; -+ m_CurrentAudio.correction = 0.0; -+ m_CurrentVideo.correction = 0.0; - - m_PlayerOptions = options; - m_item = file; -@@ -1823,12 +1825,20 @@ void CDVDPlayer::CheckContinuity(CCurrentStream& current, DemuxPacket* pPacket) - - if(correction != 0.0) - { -- /* disable detection on next packet on other stream to avoid ping pong-ing */ -- if(m_CurrentAudio.player != current.player) m_CurrentAudio.dts = DVD_NOPTS_VALUE; -- if(m_CurrentVideo.player != current.player) m_CurrentVideo.dts = DVD_NOPTS_VALUE; -- -- m_offset_pts += correction; -- UpdateCorrection(pPacket, correction); -+ current.correction = correction; -+ if (m_CurrentAudio.correction != 0.0 && m_CurrentVideo.correction != 0.0 && fabs(m_CurrentAudio.correction - m_CurrentVideo.correction) < DVD_MSEC_TO_TIME(1000)) -+ { -+ m_offset_pts += correction; -+ UpdateCorrection(pPacket, correction); -+ m_CurrentAudio.correction = 0.0; -+ m_CurrentVideo.correction = 0.0; -+ } -+ else -+ { -+ // not sure yet - flags the packets as unknown until we get confirmation on another audio/video packet -+ pPacket->dts = DVD_NOPTS_VALUE; -+ pPacket->pts = DVD_NOPTS_VALUE; -+ } - } - } - -diff --git a/xbmc/cores/dvdplayer/DVDPlayer.h b/xbmc/cores/dvdplayer/DVDPlayer.h -index 68d68a1..fdc25af 100644 ---- a/xbmc/cores/dvdplayer/DVDPlayer.h -+++ b/xbmc/cores/dvdplayer/DVDPlayer.h -@@ -77,6 +77,7 @@ class CCurrentStream - const int player; - // stuff to handle starting after seek - double startpts; -+ double correction; - - CCurrentStream(StreamType t, int i) - : type(t) -@@ -98,6 +99,7 @@ class CCurrentStream - inited = false; - started = false; - startpts = DVD_NOPTS_VALUE; -+ correction = 0.0; - } - - double dts_end() --- -2.0.4 - - -From bb47c72dd0ed6aaced0a8980c15835b8737303c7 Mon Sep 17 00:00:00 2001 -From: Rainer Hochecker -Date: Wed, 20 Aug 2014 20:33:57 +0200 -Subject: [PATCH 26/31] VAAPI: fixes - ---- - xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.cpp | 5 ++++- - 1 file changed, 4 insertions(+), 1 deletion(-) - -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.cpp -index 9aec0c9..913063c 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.cpp -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.cpp -@@ -1303,6 +1303,7 @@ void COutput::StateMachine(int signal, Protocol *port, Message *msg) - ReleaseBufferPool(true); - msg->Reply(COutputControlProtocol::ACC); - m_state = O_TOP_UNCONFIGURED; -+ m_extTimeout = 10000; - return; - default: - break; -@@ -2872,7 +2873,9 @@ bool CFFmpegPostproc::Init(EINTERLACEMETHOD method) - else if (method == VS_INTERLACEMETHOD_RENDER_BOB || - method == VS_INTERLACEMETHOD_NONE) - { -- CLog::Log(LOGDEBUG, "CFFmpegPostproc::Init - no skip deinterlacing"); -+ CLog::Log(LOGDEBUG, "CFFmpegPostproc::Init - skip deinterlacing"); -+ avfilter_inout_free(&outputs); -+ avfilter_inout_free(&inputs); - } - else - { --- -2.0.4 - - -From b2723c955373788b3e410fe4cc68d508c54e12a4 Mon Sep 17 00:00:00 2001 +From 498ba25e06ab62786cc120d16b4366d4a149b4b2 Mon Sep 17 00:00:00 2001 From: Rainer Hochecker Date: Sat, 23 Aug 2014 11:42:31 +0200 -Subject: [PATCH 27/31] dvdplayer: rename codec ctrl flags +Subject: [PATCH 23/24] dvdplayer: rename codec ctrl flags --- xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h | 14 ++++++++------ @@ -7535,10 +2230,10 @@ index 69ff8c9..22b9b99 100644 * this is signaled to codec. Codec can wait for post-proc * to be finished instead of returning empty and getting another diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp -index a4ebcd8..65edae0 100644 +index 40816e3..8715d21 100644 --- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp +++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp -@@ -682,7 +682,7 @@ bool CDVDVideoCodecFFmpeg::GetPictureCommon(DVDVideoPicture* pDvdVideoPicture) +@@ -667,7 +667,7 @@ bool CDVDVideoCodecFFmpeg::GetPictureCommon(DVDVideoPicture* pDvdVideoPicture) if (m_requestSkipDeint) { @@ -7603,33 +2298,71 @@ index f9a45e8..755f0a1 100644 m_pVideoCodec->SetCodecControl(codecControl); if (iDropDirective & EOS_DROPPED) { --- -2.0.4 - -From 30fd6e3b6c87c4126a05c1e674c38db7c6c8ec61 Mon Sep 17 00:00:00 2001 +From 420c399eba6793265a59963907320f35615c6e7c Mon Sep 17 00:00:00 2001 From: Rainer Hochecker -Date: Sat, 23 Aug 2014 12:21:43 +0200 -Subject: [PATCH 28/31] VAAPI: implement codec control flags +Date: Fri, 13 Jun 2014 14:37:16 +0200 +Subject: [PATCH 24/24] VAAPI: implement codec control flags --- - xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.cpp | 17 +++++++++++++---- - 1 file changed, 13 insertions(+), 4 deletions(-) + .../DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp | 21 ++++++++++++++++++--- + xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.cpp | 17 ++++++++++++++--- + 2 files changed, 32 insertions(+), 6 deletions(-) +diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp +index 8715d21..467a802 100644 +--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp ++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp +@@ -630,6 +630,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; +@@ -653,10 +654,24 @@ 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); ++ ++ 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; + diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.cpp -index 913063c..d1e9654 100644 +index 40fbcd8..70eda1a 100644 --- a/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.cpp +++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.cpp -@@ -706,7 +706,7 @@ int CDecoder::Decode(AVCodecContext* avctx, AVFrame* pFrame) +@@ -708,6 +708,8 @@ int CDecoder::Decode(AVCodecContext* avctx, AVFrame* pFrame) + pic.DVDPic.color_matrix = avctx->colorspace; m_bufferStats.IncDecoded(); m_vaapiOutput.m_dataPort.SendOutMessage(COutputDataProtocol::NEWFRAME, &pic, sizeof(pic)); - --// m_codecControl = pic.DVDPic.iFlags & (DVP_FLAG_DRAIN | DVP_FLAG_NO_POSTPROC); ++ + m_codecControl = pic.DVDPic.iFlags & (DVD_CODEC_CTRL_DRAIN | DVD_CODEC_CTRL_NO_POSTPROC); } int retval = 0; -@@ -1651,8 +1651,8 @@ bool COutput::HasWork() +@@ -1652,8 +1654,8 @@ bool COutput::HasWork() void COutput::InitCycle() { uint64_t latency; @@ -7640,7 +2373,7 @@ index 913063c..d1e9654 100644 m_config.stats->SetCanSkipDeint(false); -@@ -1660,7 +1660,8 @@ void COutput::InitCycle() +@@ -1661,7 +1663,8 @@ void COutput::InitCycle() EINTERLACEMETHOD method = CMediaSettings::Get().GetCurrentVideoSettings().m_InterlaceMethod; bool interlaced = m_currentPicture.DVDPic.iFlags & DVP_FLAG_INTERLACED; @@ -7650,7 +2383,7 @@ index 913063c..d1e9654 100644 (mode == VS_DEINTERLACEMODE_AUTO && interlaced))) { if((method == VS_INTERLACEMETHOD_AUTO && interlaced) -@@ -2481,6 +2482,7 @@ bool CVppPostproc::AddPicture(CVaapiDecodedPicture &pic) +@@ -2482,6 +2485,7 @@ bool CVppPostproc::AddPicture(CVaapiDecodedPicture &pic) m_decodedPics.push_front(pic); m_frameCount++; m_step = 0; @@ -7658,7 +2391,7 @@ index 913063c..d1e9654 100644 } bool CVppPostproc::Filter(CVaapiProcessedPicture &outPic) -@@ -2524,6 +2526,13 @@ bool CVppPostproc::Filter(CVaapiProcessedPicture &outPic) +@@ -2525,6 +2529,13 @@ bool CVppPostproc::Filter(CVaapiProcessedPicture &outPic) } outPic.DVDPic = it->DVDPic; @@ -7672,230 +2405,3 @@ index 913063c..d1e9654 100644 // vpp deinterlacing VAProcFilterParameterBufferDeinterlacing *filterParams; VABufferID pipelineBuf; --- -2.0.4 - - -From fea09af18ef403b4656ec1c3b1e0ee088a0d83db Mon Sep 17 00:00:00 2001 -From: Rainer Hochecker -Date: Fri, 22 Aug 2014 17:12:24 +0200 -Subject: [PATCH 29/31] pvr: fix deadlock caused by pollling channel group name - ---- - xbmc/GUIInfoManager.cpp | 2 +- - xbmc/pvr/PVRGUIInfo.cpp | 7 +++++++ - xbmc/pvr/PVRGUIInfo.h | 6 ++++++ - xbmc/pvr/PVRManager.cpp | 5 +++++ - xbmc/pvr/PVRManager.h | 6 ++++++ - 5 files changed, 25 insertions(+), 1 deletion(-) - -diff --git a/xbmc/GUIInfoManager.cpp b/xbmc/GUIInfoManager.cpp -index 617faa6..c262c1b 100644 ---- a/xbmc/GUIInfoManager.cpp -+++ b/xbmc/GUIInfoManager.cpp -@@ -3829,7 +3829,7 @@ CStdString CGUIInfoManager::GetVideoLabel(int item) - case VIDEOPLAYER_CHANNEL_GROUP: - { - if (tag && !tag->IsRadio()) -- return g_PVRManager.GetPlayingGroup(false)->GroupName(); -+ return g_PVRManager.GetPlayingTVGroupName(); - } - } - } -diff --git a/xbmc/pvr/PVRGUIInfo.cpp b/xbmc/pvr/PVRGUIInfo.cpp -index 1487282..4c6cfdb 100644 ---- a/xbmc/pvr/PVRGUIInfo.cpp -+++ b/xbmc/pvr/PVRGUIInfo.cpp -@@ -258,6 +258,7 @@ void CPVRGUIInfo::UpdateMisc(void) - bool bIsPlayingEncryptedStream = bStarted && g_PVRClients->IsEncrypted(); - bool bHasTVChannels = bStarted && g_PVRChannelGroups->GetGroupAllTV()->HasChannels(); - bool bHasRadioChannels = bStarted && g_PVRChannelGroups->GetGroupAllRadio()->HasChannels(); -+ std::string strPlayingTVGroup = (bStarted && bIsPlayingTV) ? g_PVRManager.GetPlayingGroup(false)->GroupName() : ""; - - /* safe to fetch these unlocked, since they're updated from the same thread as this one */ - bool bHasNonRecordingTimers = bStarted && m_iTimerAmount - m_iRecordingTimerAmount > 0; -@@ -272,6 +273,7 @@ void CPVRGUIInfo::UpdateMisc(void) - m_bIsPlayingEncryptedStream = bIsPlayingEncryptedStream; - m_bHasTVChannels = bHasTVChannels; - m_bHasRadioChannels = bHasRadioChannels; -+ m_strPlayingTVGroup = strPlayingTVGroup; - } - - bool CPVRGUIInfo::TranslateCharInfo(DWORD dwInfo, std::string &strValue) const -@@ -898,3 +900,8 @@ void CPVRGUIInfo::UpdatePlayingTag(void) - m_iDuration = recording.GetDuration() * 1000; - } - } -+ -+std::string CPVRGUIInfo::GetPlayingTVGroup() -+{ -+ return m_strPlayingTVGroup; -+} -diff --git a/xbmc/pvr/PVRGUIInfo.h b/xbmc/pvr/PVRGUIInfo.h -index 0d1500e..c8f8f43 100644 ---- a/xbmc/pvr/PVRGUIInfo.h -+++ b/xbmc/pvr/PVRGUIInfo.h -@@ -77,6 +77,11 @@ namespace PVR - - bool GetPlayingTag(EPG::CEpgInfoTag &tag) const; - -+ /*! -+ * @brief Get playing TV group. -+ */ -+ std::string GetPlayingTVGroup(); -+ - private: - void ResetProperties(void); - void ClearQualityInfo(PVR_SIGNAL_STATUS &qualityInfo); -@@ -162,6 +167,7 @@ namespace PVR - bool m_bIsPlayingEncryptedStream; - bool m_bHasTVChannels; - bool m_bHasRadioChannels; -+ std::string m_strPlayingTVGroup; - //@} - - PVR_SIGNAL_STATUS m_qualityInfo; /*!< stream quality information */ -diff --git a/xbmc/pvr/PVRManager.cpp b/xbmc/pvr/PVRManager.cpp -index dc5a85e..ee7770f 100644 ---- a/xbmc/pvr/PVRManager.cpp -+++ b/xbmc/pvr/PVRManager.cpp -@@ -1614,3 +1614,8 @@ bool CPVRManager::CreateChannelEpgs(void) - m_bEpgsCreated = m_channelGroups->CreateChannelEpgs(); - return m_bEpgsCreated; - } -+ -+std::string CPVRManager::GetPlayingTVGroupName() -+{ -+ return IsStarted() && m_guiInfo ? m_guiInfo->GetPlayingTVGroup() : ""; -+} -diff --git a/xbmc/pvr/PVRManager.h b/xbmc/pvr/PVRManager.h -index 67ff282..652e5e5 100644 ---- a/xbmc/pvr/PVRManager.h -+++ b/xbmc/pvr/PVRManager.h -@@ -548,6 +548,12 @@ namespace PVR - */ - bool CreateChannelEpgs(void); - -+ /*! -+ * @brief get the name of the channel group of the current playing channel -+ * @return name of channel if tv channel is playing -+ */ -+ std::string GetPlayingTVGroupName(); -+ - protected: - /*! - * @brief PVR update and control thread. --- -2.0.4 - - -From 36718552e55e53199ec1f916a7e3e36d515f2a02 Mon Sep 17 00:00:00 2001 -From: Rainer Hochecker -Date: Sun, 24 Aug 2014 14:03:04 +0200 -Subject: [PATCH 30/31] X11: fix window placement on multi-monitor setups - ---- - xbmc/windowing/X11/WinSystemX11.cpp | 17 ++++++----------- - 1 file changed, 6 insertions(+), 11 deletions(-) - -diff --git a/xbmc/windowing/X11/WinSystemX11.cpp b/xbmc/windowing/X11/WinSystemX11.cpp -index 60761ec..281e0d8 100644 ---- a/xbmc/windowing/X11/WinSystemX11.cpp -+++ b/xbmc/windowing/X11/WinSystemX11.cpp -@@ -776,8 +776,6 @@ bool CWinSystemX11::SetWindow(int width, int height, bool fullscreen, const std: - bool mouseActive = false; - float mouseX = 0; - float mouseY = 0; -- int x0 = 0; -- int y0 = 0; - - if (m_mainWindow && ((m_bFullScreen != fullscreen) || m_currentOutput.compare(output) != 0 || m_windowDirty)) - { -@@ -825,6 +823,8 @@ bool CWinSystemX11::SetWindow(int width, int height, bool fullscreen, const std: - Colormap cmap; - XSetWindowAttributes swa; - XVisualInfo *vi; -+ int x0 = 0; -+ int y0 = 0; - - XOutput *out = g_xrandr.GetOutput(output); - if (!out) -@@ -942,19 +942,14 @@ bool CWinSystemX11::SetWindow(int width, int height, bool fullscreen, const std: - Atom wmDeleteMessage = XInternAtom(m_dpy, "WM_DELETE_WINDOW", False); - XSetWMProtocols(m_dpy, m_mainWindow, &wmDeleteMessage, 1); - } -- XMapRaised(m_dpy, m_glWindow); -- XMapRaised(m_dpy, m_mainWindow); - -- if (fullscreen) -- XMoveWindow(m_dpy, m_mainWindow, x0, y0); -+ // placement of window may follow mouse -+ XWarpPointer(m_dpy, None, m_mainWindow, 0, 0, 0, 0, mouseX*width, mouseY*height); - -+ XMapRaised(m_dpy, m_glWindow); -+ XMapRaised(m_dpy, m_mainWindow); - XSync(m_dpy,TRUE); - -- if (changeWindow && mouseActive) -- { -- XWarpPointer(m_dpy, None, m_mainWindow, 0, 0, 0, 0, mouseX*width, mouseY*height); -- } -- - CDirtyRegionList dr; - RefreshGlxContext(m_currentOutput.compare(output) != 0); - XSync(m_dpy, FALSE); --- -2.0.4 - - -From b9aebeb781cc718099e8daf87cb4ea365d6a97e7 Mon Sep 17 00:00:00 2001 -From: Rainer Hochecker -Date: Sun, 24 Aug 2014 14:40:00 +0200 -Subject: [PATCH 31/31] VAAPI: fix buffer handing - ---- - xbmc/cores/VideoRenderers/LinuxRendererGL.cpp | 3 +++ - xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.cpp | 5 ++++- - 2 files changed, 7 insertions(+), 1 deletion(-) - -diff --git a/xbmc/cores/VideoRenderers/LinuxRendererGL.cpp b/xbmc/cores/VideoRenderers/LinuxRendererGL.cpp -index 1dcc33e..767e15a 100644 ---- a/xbmc/cores/VideoRenderers/LinuxRendererGL.cpp -+++ b/xbmc/cores/VideoRenderers/LinuxRendererGL.cpp -@@ -1125,7 +1125,10 @@ void CLinuxRendererGL::UnInit() - - // YV12 textures - for (int i = 0; i < NUM_BUFFERS; ++i) -+ { - (this->*m_textureDelete)(i); -+ DeleteVAAPITexture(i); -+ } - - // cleanup framebuffer object if it was in use - m_fbo.fbo.Cleanup(); -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.cpp -index d1e9654..2b60f0e 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.cpp -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.cpp -@@ -659,7 +659,8 @@ int CDecoder::FFGetBuffer(AVCodecContext *avctx, AVFrame *pic, int flags) - } - pic->buf[0] = buffer; - -- pic->reordered_opaque= avctx->reordered_opaque; -+ pic->reordered_opaque = avctx->reordered_opaque; -+ va->Acquire(); - return 0; - } - -@@ -672,6 +673,8 @@ void CDecoder::FFReleaseBuffer(uint8_t *data) - - surf = (VASurfaceID)(uintptr_t)data; - m_videoSurfaces.ClearReference(surf); -+ -+ IHardwareDecoder::Release(); - } - - int CDecoder::Decode(AVCodecContext* avctx, AVFrame* pFrame) --- -2.0.4 - diff --git a/packages/mediacenter/xbmc/patches/xbmc-999.91-PR5275.patch b/packages/mediacenter/xbmc/patches/xbmc-999.91-PR5275.patch deleted file mode 100644 index d97bb75cbb..0000000000 --- a/packages/mediacenter/xbmc/patches/xbmc-999.91-PR5275.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 7f2c28112179d6a1336dbc48f70bec927e2820f1 Mon Sep 17 00:00:00 2001 -From: fritsch -Date: Sun, 24 Aug 2014 15:05:17 +0200 -Subject: [PATCH] PaP: Support DSD Format - ---- - xbmc/cores/paplayer/CodecFactory.cpp | 2 ++ - xbmc/settings/AdvancedSettings.cpp | 2 +- - 2 files changed, 3 insertions(+), 1 deletion(-) - -diff --git a/xbmc/cores/paplayer/CodecFactory.cpp b/xbmc/cores/paplayer/CodecFactory.cpp -index 72750a0..f7a157e 100644 ---- a/xbmc/cores/paplayer/CodecFactory.cpp -+++ b/xbmc/cores/paplayer/CodecFactory.cpp -@@ -111,6 +111,8 @@ ICodec* CodecFactory::CreateCodec(const std::string& strFileType) - return new DVDPlayerCodec(); - else if (fileType == "opus") - return new DVDPlayerCodec(); -+ else if (fileType == "dff" || fileType == "dsf") -+ return new DVDPlayerCodec(); - - return NULL; - } -diff --git a/xbmc/settings/AdvancedSettings.cpp b/xbmc/settings/AdvancedSettings.cpp -index 5f3f2d8..4af3c7a 100644 ---- a/xbmc/settings/AdvancedSettings.cpp -+++ b/xbmc/settings/AdvancedSettings.cpp -@@ -387,7 +387,7 @@ void CAdvancedSettings::Initialize() - m_databaseVideo.Reset(); - - m_pictureExtensions = ".png|.jpg|.jpeg|.bmp|.gif|.ico|.tif|.tiff|.tga|.pcx|.cbz|.zip|.cbr|.rar|.dng|.nef|.cr2|.crw|.orf|.arw|.erf|.3fr|.dcr|.x3f|.mef|.raf|.mrw|.pef|.sr2|.rss"; -- m_musicExtensions = ".nsv|.m4a|.flac|.aac|.strm|.pls|.rm|.rma|.mpa|.wav|.wma|.ogg|.mp3|.mp2|.m3u|.mod|.amf|.669|.dmf|.dsm|.far|.gdm|.imf|.it|.m15|.med|.okt|.s3m|.stm|.sfx|.ult|.uni|.xm|.sid|.ac3|.dts|.cue|.aif|.aiff|.wpl|.ape|.mac|.mpc|.mp+|.mpp|.shn|.zip|.rar|.wv|.nsf|.spc|.gym|.adx|.dsp|.adp|.ymf|.ast|.afc|.hps|.xsp|.xwav|.waa|.wvs|.wam|.gcm|.idsp|.mpdsp|.mss|.spt|.rsd|.mid|.kar|.sap|.cmc|.cmr|.dmc|.mpt|.mpd|.rmt|.tmc|.tm8|.tm2|.oga|.url|.pxml|.tta|.rss|.cm3|.cms|.dlt|.brstm|.wtv|.mka|.tak|.opus"; -+ m_musicExtensions = ".nsv|.m4a|.flac|.aac|.strm|.pls|.rm|.rma|.mpa|.wav|.wma|.ogg|.mp3|.mp2|.m3u|.mod|.amf|.669|.dmf|.dsm|.far|.gdm|.imf|.it|.m15|.med|.okt|.s3m|.stm|.sfx|.ult|.uni|.xm|.sid|.ac3|.dts|.cue|.aif|.aiff|.wpl|.ape|.mac|.mpc|.mp+|.mpp|.shn|.zip|.rar|.wv|.nsf|.spc|.gym|.adx|.dsp|.adp|.ymf|.ast|.afc|.hps|.xsp|.xwav|.waa|.wvs|.wam|.gcm|.idsp|.mpdsp|.mss|.spt|.rsd|.mid|.kar|.sap|.cmc|.cmr|.dmc|.mpt|.mpd|.rmt|.tmc|.tm8|.tm2|.oga|.url|.pxml|.tta|.rss|.cm3|.cms|.dlt|.brstm|.wtv|.mka|.tak|.opus|.dff|.dsf"; - m_videoExtensions = ".m4v|.3g2|.3gp|.nsv|.tp|.ts|.ty|.strm|.pls|.rm|.rmvb|.m3u|.m3u8|.ifo|.mov|.qt|.divx|.xvid|.bivx|.vob|.nrg|.img|.iso|.pva|.wmv|.asf|.asx|.ogm|.m2v|.avi|.bin|.dat|.mpg|.mpeg|.mp4|.mkv|.avc|.vp3|.svq3|.nuv|.viv|.dv|.fli|.flv|.rar|.001|.wpl|.zip|.vdr|.dvr-ms|.xsp|.mts|.m2t|.m2ts|.evo|.ogv|.sdp|.avs|.rec|.url|.pxml|.vc1|.h264|.rcv|.rss|.mpls|.webm|.bdmv|.wtv"; - m_subtitlesExtensions = ".utf|.utf8|.utf-8|.sub|.srt|.smi|.rt|.txt|.ssa|.text|.ssa|.aqt|.jss|.ass|.idx|.ifo|.rar|.zip"; - m_discStubExtensions = ".disc"; --- -2.0.4 - diff --git a/packages/mediacenter/xbmc/patches/xbmc-999.91-PR5306.patch b/packages/mediacenter/xbmc/patches/xbmc-999.91-PR5306.patch new file mode 100644 index 0000000000..d82ec13274 --- /dev/null +++ b/packages/mediacenter/xbmc/patches/xbmc-999.91-PR5306.patch @@ -0,0 +1,23 @@ +From 0be29d9a6e30b1cf1c50e12a9dea28f7dce6f1f7 Mon Sep 17 00:00:00 2001 +From: Stephan Raue +Date: Mon, 1 Sep 2014 03:16:37 +0200 +Subject: [PATCH] add support to read frequency output if using intel's pstate + driver + +--- + xbmc/utils/CPUInfo.cpp | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/xbmc/utils/CPUInfo.cpp b/xbmc/utils/CPUInfo.cpp +index 93ca784..31b27ba 100644 +--- a/xbmc/utils/CPUInfo.cpp ++++ b/xbmc/utils/CPUInfo.cpp +@@ -267,6 +267,8 @@ CCPUInfo::CCPUInfo(void) + m_fProcTemperature = fopen("/sys/class/thermal/thermal_zone0/temp", "r"); // On Raspberry PIs + + m_fCPUFreq = fopen ("/sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq", "r"); ++ if (m_fCPUFreq == NULL) ++ m_fCPUFreq = fopen ("/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_cur_freq", "r"); + if (!m_fCPUFreq) + { + m_cpuInfoForFreq = true; diff --git a/packages/mediacenter/xbmc/patches/xbmc-999.93-pstate_support.patch b/packages/mediacenter/xbmc/patches/xbmc-999.93-pstate_support.patch deleted file mode 100644 index 11d3ccaa1b..0000000000 --- a/packages/mediacenter/xbmc/patches/xbmc-999.93-pstate_support.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff -Naur xbmc-14-a29b21a/xbmc/utils/CPUInfo.cpp xbmc-14-a29b21a.patch/xbmc/utils/CPUInfo.cpp ---- xbmc-14-a29b21a/xbmc/utils/CPUInfo.cpp 2014-08-24 17:41:38.000000000 +0200 -+++ xbmc-14-a29b21a.patch/xbmc/utils/CPUInfo.cpp 2014-08-29 23:32:55.958602554 +0200 -@@ -266,7 +266,8 @@ - m_fProcTemperature = fopen("/sys/class/thermal/thermal_zone0/temp", "r"); // On Raspberry PIs - - m_fCPUFreq = fopen ("/sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq", "r"); -- -+ if (m_fCPUFreq == NULL) -+ m_fCPUFreq = fopen ("/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_cur_freq", "r"); - - FILE* fCPUInfo = fopen("/proc/cpuinfo", "r"); - m_cpuCount = 0; diff --git a/projects/RPi/patches/xbmc/xbmc-001-newclock3.patch b/projects/RPi/patches/xbmc/xbmc-001-newclock3.patch index ae3ea9b972..7844a6299c 100644 --- a/projects/RPi/patches/xbmc/xbmc-001-newclock3.patch +++ b/projects/RPi/patches/xbmc/xbmc-001-newclock3.patch @@ -8418,70 +8418,6 @@ index 01aafe3..5ab83a2 100644 2.0.4 -From eb1f529be51c71cce01c09bce707fcb8464e2219 Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Sat, 14 Dec 2013 16:55:05 +0000 -Subject: [PATCH 46/98] logging: Add microsecond timer to log messages - ---- - xbmc/utils/log.cpp | 12 +++++++++--- - 1 file changed, 9 insertions(+), 3 deletions(-) - -diff --git a/xbmc/utils/log.cpp b/xbmc/utils/log.cpp -index dd6ef26..8edf2fd 100644 ---- a/xbmc/utils/log.cpp -+++ b/xbmc/utils/log.cpp -@@ -32,6 +32,7 @@ - #elif defined(TARGET_WINDOWS) - #include "win32/WIN32Util.h" - #endif -+#include "utils/TimeUtils.cpp" - - #define critSec XBMC_GLOBAL_USE(CLog::CLogGlobals).critSec - #define m_file XBMC_GLOBAL_USE(CLog::CLogGlobals).m_file -@@ -64,7 +65,7 @@ void CLog::Close() - - void CLog::Log(int loglevel, const char *format, ... ) - { -- static const char* prefixFormat = "%02.2d:%02.2d:%02.2d T:%" PRIu64" %7s: "; -+ static const char* prefixFormat = "%02.2d:%02.2d:%02.2d %10.6f T:%" PRIu64" %7s: "; - CSingleLock waitLock(critSec); - int extras = (loglevel >> LOGMASKBIT) << LOGMASKBIT; - loglevel = loglevel & LOGMASK; -@@ -90,6 +91,11 @@ void CLog::Log(int loglevel, const char *format, ... ) - strData = StringUtils::FormatV(format,va); - va_end(va); - -+ -+ struct timespec now; -+ clock_gettime(CLOCK_MONOTONIC, &now); -+ float Now = now.tv_sec + now.tv_nsec * 1e-9; -+ - if (m_repeatLogLevel == loglevel && m_repeatLine == strData) - { - m_repeatCount++; -@@ -100,7 +106,7 @@ void CLog::Log(int loglevel, const char *format, ... ) - strPrefix = StringUtils::Format(prefixFormat, - time.wHour, - time.wMinute, -- time.wSecond, -+ time.wSecond, Now, - (uint64_t)CThread::GetCurrentThreadId(), - levelNames[m_repeatLogLevel]); - -@@ -129,7 +135,7 @@ void CLog::Log(int loglevel, const char *format, ... ) - strPrefix = StringUtils::Format(prefixFormat, - time.wHour, - time.wMinute, -- time.wSecond, -+ time.wSecond, Now, - (uint64_t)CThread::GetCurrentThreadId(), - levelNames[loglevel]); - --- -2.0.4 - - From 6829c44375784e0ee43fb88901af699a283e09f9 Mon Sep 17 00:00:00 2001 From: Jonathan Marshall Date: Sat, 2 Nov 2013 23:49:17 +1300 @@ -11882,34 +11818,6 @@ index 2929a37..53873f6 100644 2.0.4 -From 316d15895273f66fa2a39906b534fb59f770a9d7 Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Mon, 16 Jun 2014 19:05:14 +0100 -Subject: [PATCH 65/98] sqlite: Bump to 3080500 - ---- - tools/depends/target/sqlite3/Makefile | 4 +++- - 1 file changed, 3 insertions(+), 1 deletion(-) - -diff --git a/tools/depends/target/sqlite3/Makefile b/tools/depends/target/sqlite3/Makefile -index 87f7eaa..8fe61e8 100644 ---- a/tools/depends/target/sqlite3/Makefile -+++ b/tools/depends/target/sqlite3/Makefile -@@ -3,7 +3,9 @@ DEPS= ../../Makefile.include Makefile - - # lib name, version - LIBNAME=sqlite --VERSION=3071000 -+VERSION=3080500 -+BASE_URL=https://www.sqlite.org/2014 -+ - SOURCE=$(LIBNAME)-autoconf-$(VERSION) - ARCHIVE=$(SOURCE).tar.gz - --- -2.0.4 - - From f4d8961a71c00b39e1e7fdf23c2fe3c56adf2a92 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Mon, 16 Jun 2014 19:06:00 +0100