Merge pull request #2830 from fritsch/master

Drop VPP support
This commit is contained in:
Stephan Raue 2013-12-24 05:56:45 -08:00
commit 46dc2db4df
6 changed files with 0 additions and 1707 deletions

View File

@ -1,694 +0,0 @@
From d9739fe6ee21362f196bf4641e38c39a6f0c1eb7 Mon Sep 17 00:00:00 2001
From: BtbN <btbn@btbn.de>
Date: Thu, 3 Oct 2013 14:49:25 +0200
Subject: [PATCH 1/2] VAAPI: Add class which handles VPP deinterlacing
---
xbmc/cores/dvdplayer/DVDCodecs/Video/Makefile.in | 1 +
xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI_VPP.cpp | 540 +++++++++++++++++++++
xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI_VPP.h | 114 +++++
3 files changed, 655 insertions(+)
create mode 100644 xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI_VPP.cpp
create mode 100644 xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI_VPP.h
diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/Makefile.in b/xbmc/cores/dvdplayer/DVDCodecs/Video/Makefile.in
index 23261f1..cfa05ec 100644
--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/Makefile.in
+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/Makefile.in
@@ -9,6 +9,7 @@ SRCS += VDPAU.cpp
endif
ifeq (@USE_VAAPI@,1)
SRCS += VAAPI.cpp
+SRCS += VAAPI_VPP.cpp
endif
ifeq (@USE_CRYSTALHD@,1)
SRCS += CrystalHD.cpp
diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI_VPP.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI_VPP.cpp
new file mode 100644
index 0000000..78e786a
--- /dev/null
+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI_VPP.cpp
@@ -0,0 +1,540 @@
+/*
+ * Copyright (C) 2013 Team XBMC
+ * http://xbmc.org
+ *
+ * This Program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This Program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with XBMC; see the file COPYING. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "system.h"
+#ifdef HAVE_LIBVA
+
+#include "VAAPI_VPP.h"
+#if VA_CHECK_VERSION(0,34,0)
+# define VPP_AVAIL 1
+#endif
+
+#ifdef VPP_AVAIL
+#include <va/va_vpp.h>
+#endif
+
+#include "utils/log.h"
+#include "threads/SingleLock.h"
+
+#include <algorithm>
+#include <boost/scoped_array.hpp>
+
+#ifndef VA_SURFACE_ATTRIB_SETTABLE
+#define vaCreateSurfaces(d, f, w, h, s, ns, a, na) \
+ vaCreateSurfaces(d, w, h, f, ns, s)
+#endif
+
+using namespace VAAPI;
+
+
+CVPP::SupportState CVPP::g_supported = CVPP::Unknown;
+CVPP::SupportState CVPP::g_deintSupported[VAAPI::Deinterlacing_Count] = {CVPP::Unknown};
+
+CVPP::CVPP()
+ :m_width(0)
+ ,m_height(0)
+ ,m_configId(VA_INVALID_ID)
+ ,m_vppReady(CVPP::InitFailed)
+ ,m_deintReady(CVPP::InitFailed)
+ ,m_deintContext(VA_INVALID_ID)
+ ,m_deintFilter(VA_INVALID_ID)
+{}
+
+CVPP::CVPP(CDisplayPtr& display, int width, int height)
+ :m_usedMethod(VAAPI::DeinterlacingNone)
+ ,m_display(display)
+ ,m_width(width)
+ ,m_height(height)
+ ,m_configId(VA_INVALID_ID)
+ ,m_vppReady(CVPP::NotReady)
+ ,m_deintReady(CVPP::NotReady)
+ ,m_deintContext(VA_INVALID_ID)
+ ,m_deintFilter(VA_INVALID_ID)
+{
+ assert(display.get() && display->get());
+ assert(width > 0 && height > 0);
+
+ CLog::Log(LOGDEBUG, "VAAPI_VPP - Probing available methods");
+ for(int i = 1; i < VAAPI::Deinterlacing_Count; ++i)
+ {
+ if(VppSupported() && g_deintSupported[i] == Unknown && InitVpp())
+ {
+ if(InitDeint((DeintMethod)i, 1))
+ CLog::Log(LOGDEBUG, "VAAPI_VPP - Method %d is supported!", i);
+ else
+ CLog::Log(LOGDEBUG, "VAAPI_VPP - Method %d is NOT supported!", i);
+ Deinit();
+ }
+ }
+ CLog::Log(LOGDEBUG, "VAAPI_VPP - Done probing available methods");
+}
+
+CVPP::~CVPP()
+{
+ Deinit();
+}
+
+bool CVPP::VppSupported()
+{
+#ifdef VPP_AVAIL
+ return g_supported != Unsupported;
+#else
+ return false;
+#endif
+}
+
+bool CVPP::DeintSupported(DeintMethod method)
+{
+#ifdef VPP_AVAIL
+ if(method == DeinterlacingNone)
+ return false;
+
+ return VppSupported() && g_deintSupported[method] != Unsupported;
+#else
+ return false;
+#endif
+}
+
+void CVPP::Deinit()
+{
+#ifdef VPP_AVAIL
+ CLog::Log(LOGDEBUG, "VAAPI_VPP - Deinitializing");
+
+ DeinitDeint();
+ DeinitVpp();
+#endif
+}
+
+void CVPP::DeinitVpp()
+{
+#ifdef VPP_AVAIL
+ CSingleLock lock(m_deint_lock);
+
+ if(VppReady())
+ {
+ vaDestroyConfig(m_display->get(), m_configId);
+ m_vppReady = NotReady;
+
+ CLog::Log(LOGDEBUG, "VAAPI_VPP - Deinitialized vpp");
+ }
+#endif
+}
+
+void CVPP::DeinitDeint()
+{
+#ifdef VPP_AVAIL
+ CSingleLock lock(m_deint_lock);
+
+ if(DeintReady() || m_deintReady == RuntimeFailed)
+ {
+ vaDestroyBuffer(m_display->get(), m_deintFilter);
+ vaDestroyContext(m_display->get(), m_deintContext);
+ m_deintTargets.clear();
+ m_deintReady = NotReady;
+ m_usedMethod = DeinterlacingNone;
+
+ m_forwardReferences.clear();
+ m_backwardReferences.clear();
+
+ CLog::Log(LOGDEBUG, "VAAPI_VPP - Deinitialized deint");
+ }
+#endif
+}
+
+bool CVPP::InitVpp()
+{
+#ifdef VPP_AVAIL
+ CSingleLock lock(m_deint_lock);
+
+ if(VppFailed() || VppReady())
+ return false;
+
+ int numEntrypoints = vaMaxNumEntrypoints(m_display->get());
+ boost::scoped_array<VAEntrypoint> entrypoints(new VAEntrypoint[numEntrypoints]);
+
+ if(vaQueryConfigEntrypoints(m_display->get(), VAProfileNone, entrypoints.get(), &numEntrypoints) != VA_STATUS_SUCCESS)
+ {
+ CLog::Log(LOGERROR, "VAAPI_VPP - failed querying entrypoints");
+
+ m_vppReady = InitFailed;
+ return false;
+ }
+
+ int i;
+ for(i = 0; i < numEntrypoints; ++i)
+ if(entrypoints[i] == VAEntrypointVideoProc)
+ break;
+
+ if(i >= numEntrypoints)
+ {
+ CLog::Log(LOGDEBUG, "VAAPI_VPP - Entrypoint VideoProc not supported");
+ m_vppReady = InitFailed;
+ g_supported = Unsupported;
+ return false;
+ }
+
+ if(vaCreateConfig(m_display->get(), VAProfileNone, VAEntrypointVideoProc, NULL, 0, &m_configId) != VA_STATUS_SUCCESS)
+ {
+ CLog::Log(LOGERROR, "VAAPI_VPP - failed creating va config");
+ m_vppReady = InitFailed;
+ return false;
+ }
+
+ CLog::Log(LOGDEBUG, "VAAPI_VPP - Successfully initialized VPP");
+
+ m_vppReady = Ready;
+ g_supported = Supported;
+ return true;
+#else
+ g_supported = Unsupported;
+ m_vppReady = InitFailed;
+ return false;
+#endif
+}
+
+bool CVPP::InitDeint(DeintMethod method, int num_surfaces)
+{
+#ifdef VPP_AVAIL
+ CSingleLock lock(m_deint_lock);
+
+ assert(VppReady());
+
+ if(DeintReady())
+ return false;
+
+ VAProcDeinterlacingType selectedMethod = VAProcDeinterlacingNone;
+ switch(method)
+ {
+ case DeinterlacingBob:
+ selectedMethod = VAProcDeinterlacingBob;
+ break;
+ case DeinterlacingWeave:
+ selectedMethod = VAProcDeinterlacingWeave;
+ break;
+ case DeinterlacingMotionAdaptive:
+ selectedMethod = VAProcDeinterlacingMotionAdaptive;
+ break;
+ case DeinterlacingMotionCompensated:
+ selectedMethod = VAProcDeinterlacingMotionCompensated;
+ break;
+ default:
+ selectedMethod = VAProcDeinterlacingNone;
+ break;
+ }
+
+ if(selectedMethod == VAProcDeinterlacingNone)
+ {
+ CLog::Log(LOGERROR, "VAAPI_VPP - invalid deinterlacing method requested!");
+ m_deintReady = InitFailed;
+ return false;
+ }
+
+ boost::scoped_array<VASurfaceID> deintTargetsInternal(new VASurfaceID[num_surfaces]);
+ if(vaCreateSurfaces(m_display->get(), VA_RT_FORMAT_YUV420, m_width, m_height, deintTargetsInternal.get(), num_surfaces, NULL, 0) != VA_STATUS_SUCCESS)
+ {
+ CLog::Log(LOGERROR, "VAAPI_VPP - failed creating deint target surfaces");
+ m_deintReady = InitFailed;
+ return false;
+ }
+
+ if(vaCreateContext(m_display->get(), m_configId, m_width, m_height, VA_PROGRESSIVE, deintTargetsInternal.get(), num_surfaces, &m_deintContext) != VA_STATUS_SUCCESS)
+ {
+ CLog::Log(LOGERROR, "VAAPI_VPP - failed creating deint context");
+ vaDestroySurfaces(m_display->get(), deintTargetsInternal.get(), num_surfaces);
+ m_deintReady = InitFailed;
+ return false;
+ }
+
+ VAProcFilterType filters[VAProcFilterCount];
+ unsigned int numFilters = VAProcFilterCount;
+ VAProcFilterCapDeinterlacing deinterlacingCaps[VAProcDeinterlacingCount];
+ unsigned int numDeinterlacingCaps = VAProcDeinterlacingCount;
+
+ if(
+ vaQueryVideoProcFilters(m_display->get(), m_deintContext, filters, &numFilters) != VA_STATUS_SUCCESS
+ || vaQueryVideoProcFilterCaps(m_display->get(), m_deintContext, VAProcFilterDeinterlacing, deinterlacingCaps, &numDeinterlacingCaps) != VA_STATUS_SUCCESS)
+ {
+ vaDestroyContext(m_display->get(), m_deintContext);
+ vaDestroySurfaces(m_display->get(), deintTargetsInternal.get(), num_surfaces);
+ CLog::Log(LOGERROR, "VAAPI_VPP - failed querying filter caps");
+ m_deintReady = InitFailed;
+ g_deintSupported[method] = Unsupported;
+ return false;
+ }
+
+ bool methodSupported = false;
+ for(unsigned int fi = 0; fi < numFilters; ++fi)
+ if(filters[fi] == VAProcFilterDeinterlacing)
+ for(unsigned int ci = 0; ci < numDeinterlacingCaps; ++ci)
+ {
+ if(deinterlacingCaps[ci].type != selectedMethod)
+ continue;
+ methodSupported = true;
+ break;
+ }
+
+ if(!methodSupported)
+ {
+ vaDestroyContext(m_display->get(), m_deintContext);
+ vaDestroySurfaces(m_display->get(), deintTargetsInternal.get(), num_surfaces);
+ CLog::Log(LOGDEBUG, "VAAPI_VPP - deinterlacing filter is not supported");
+ m_deintReady = InitFailed;
+ g_deintSupported[method] = Unsupported;
+ return false;
+ }
+
+ VAProcFilterParameterBufferDeinterlacing deint;
+ deint.type = VAProcFilterDeinterlacing;
+ deint.algorithm = selectedMethod;
+ deint.flags = 0;
+
+ if(vaCreateBuffer(m_display->get(), m_deintContext, VAProcFilterParameterBufferType, sizeof(deint), 1, &deint, &m_deintFilter) != VA_STATUS_SUCCESS)
+ {
+ vaDestroyContext(m_display->get(), m_deintContext);
+ vaDestroySurfaces(m_display->get(), deintTargetsInternal.get(), num_surfaces);
+ CLog::Log(LOGERROR, "VAAPI_VPP - creating ProcFilterParameterBuffer failed");
+ m_deintReady = InitFailed;
+ return false;
+ }
+
+ VAProcPipelineCaps pplCaps;
+ if(vaQueryVideoProcPipelineCaps(m_display->get(), m_deintContext, &m_deintFilter, 1, &pplCaps) != VA_STATUS_SUCCESS)
+ {
+ vaDestroyBuffer(m_display->get(), m_deintFilter);
+ vaDestroyContext(m_display->get(), m_deintContext);
+ vaDestroySurfaces(m_display->get(), deintTargetsInternal.get(), num_surfaces);
+ CLog::Log(LOGERROR, "VAAPI_VPP - querying ProcPipelineCaps failed");
+ m_deintReady = InitFailed;
+ return false;
+ }
+
+ m_forwardReferencesCount = pplCaps.num_forward_references;
+ m_backwardReferencesCount = pplCaps.num_backward_references;
+
+ CLog::Log(LOGDEBUG, "VAAPI_VPP - Successfully initialized deinterlacer %d. Need %d forward and %d backward refs.", (int)method, m_forwardReferencesCount, m_backwardReferencesCount);
+
+ m_deintTargets.resize(num_surfaces);
+ for(int i = 0; i < num_surfaces; ++i)
+ m_deintTargets[i] = CSurfacePtr(new CSurface(deintTargetsInternal[i], m_display));
+
+ m_deintReady = Ready;
+ m_usedMethod = method;
+ g_deintSupported[method] = Supported;
+ m_forwardReferences.clear();
+ return true;
+#else
+ m_deintReady = InitFailed;
+ return false;
+#endif
+}
+
+#define CHECK_VA(s, b) \
+{\
+ VAStatus res = s;\
+ if(res != VA_STATUS_SUCCESS)\
+ {\
+ CLog::Log(LOGERROR, "VAAPI_VPP - failed executing "#s" at line %d with error 0x%x:%s", __LINE__, res, vaErrorStr(res));\
+ VABufferID buf = b;\
+ if(buf != 0)\
+ vaDestroyBuffer(m_display->get(), buf);\
+ if(forwRefs != 0)\
+ delete[] forwRefs;\
+ m_forwardReferences.clear();\
+ return CVPPPicture();\
+ }\
+}
+
+CVPPPicture CVPP::DoDeint(const CVPPPicture& input, bool topFieldFirst, bool firstCall)
+{
+#ifdef VPP_AVAIL
+ CSingleLock lock(m_deint_lock);
+
+ assert(input.valid);
+
+ if(!DeintReady())
+ return CVPPPicture();
+
+ VAStatus syncStatus = vaSyncSurface(m_display->get(), input.surface->m_id);
+ if(syncStatus != VA_STATUS_SUCCESS)
+ {
+ CLog::Log(LOGDEBUG, "VAAPI_VPP - failed syncing surface with error 0x%x:%s", syncStatus, vaErrorStr(syncStatus));
+
+ if(syncStatus != VA_STATUS_ERROR_DECODING_ERROR)
+ return CVPPPicture();
+
+ VASurfaceDecodeMBErrors *errors;
+ if(vaQuerySurfaceError(m_display->get(), input.surface->m_id, syncStatus, (void**)&errors) != VA_STATUS_SUCCESS)
+ return CVPPPicture();
+
+ while(errors != 0 && errors->status == 1)
+ {
+ CLog::Log(LOGDEBUG, "VAAPI_VPP - detected decode error: start_mb: %d, end_mb: %d, error_type: %d", errors->start_mb, errors->end_mb, (int)errors->decode_error_type);
+ ++errors;
+ }
+
+ return CVPPPicture();
+ }
+
+ CVPPPicture procPic = input;
+
+ if(firstCall && m_forwardReferences.size() < m_forwardReferencesCount)
+ return CVPPPicture();
+
+ CSurfacePtr deintTarget = getFreeSurface();
+ if(!deintTarget.get())
+ return CVPPPicture();
+
+ VAProcFilterParameterBufferDeinterlacing *deint;
+ VABufferID pipelineBuf;
+ VAProcPipelineParameterBuffer *pipelineParam;
+ VARectangle inputRegion;
+ VARectangle outputRegion;
+
+ VASurfaceID *forwRefs = 0;
+
+ CHECK_VA(vaBeginPicture(m_display->get(), m_deintContext, deintTarget->m_id), 0);
+
+ CHECK_VA(vaMapBuffer(m_display->get(), m_deintFilter, (void**)&deint), 0);
+
+ if(firstCall || m_forwardReferences.size() < m_forwardReferencesCount)
+ {
+ if(!topFieldFirst)
+ deint->flags = VA_DEINTERLACING_BOTTOM_FIELD_FIRST | VA_DEINTERLACING_BOTTOM_FIELD;
+ else
+ deint->flags = 0;
+ }
+ else
+ {
+ if(topFieldFirst)
+ deint->flags = VA_DEINTERLACING_BOTTOM_FIELD;
+ else
+ deint->flags = VA_DEINTERLACING_BOTTOM_FIELD_FIRST;
+ }
+
+ CHECK_VA(vaUnmapBuffer(m_display->get(), m_deintFilter), 0);
+
+ CHECK_VA(vaCreateBuffer(m_display->get(), m_deintContext, VAProcPipelineParameterBufferType, sizeof(VAProcPipelineParameterBuffer), 1, NULL, &pipelineBuf), 0);
+ CHECK_VA(vaMapBuffer(m_display->get(), pipelineBuf, (void**)&pipelineParam), pipelineBuf);
+
+ memset(pipelineParam, 0, sizeof(VAProcPipelineParameterBuffer));
+
+ // This input/output regions crop two the top and bottom pixel rows
+ // It removes the flickering pixels caused by bob
+ const int vcrop = 1;
+ const int hcrop = 0;
+ inputRegion.x = outputRegion.x = hcrop;
+ inputRegion.y = outputRegion.y = vcrop;
+ inputRegion.width = outputRegion.width = m_width - (2 * hcrop);
+ inputRegion.height = outputRegion.height = m_height - (2 * vcrop);
+
+ pipelineParam->surface = procPic.surface->m_id;
+ pipelineParam->output_region = &outputRegion;
+ pipelineParam->surface_region = &inputRegion;
+ pipelineParam->output_background_color = 0xff000000;
+
+ pipelineParam->filter_flags = 0;
+
+ pipelineParam->filters = &m_deintFilter;
+ pipelineParam->num_filters = 1;
+
+ if(m_forwardReferencesCount > 0)
+ {
+ forwRefs = new VASurfaceID[m_forwardReferencesCount];
+
+ unsigned int i;
+
+ if(m_forwardReferences.size() < m_forwardReferencesCount)
+ {
+ for(i = 0; i < m_forwardReferencesCount; ++i)
+ forwRefs[i] = VA_INVALID_SURFACE;
+ }
+ else
+ {
+ i = 0;
+ for(std::list<CVPPPicture>::iterator it = m_forwardReferences.begin(); it != m_forwardReferences.end(); ++it, ++i)
+ forwRefs[i] = it->surface->m_id;
+ }
+ }
+
+ pipelineParam->num_forward_references = m_forwardReferences.size();
+ pipelineParam->forward_references = forwRefs;
+ pipelineParam->num_backward_references = 0;
+ pipelineParam->backward_references = NULL;
+
+ CHECK_VA(vaUnmapBuffer(m_display->get(), pipelineBuf), pipelineBuf);
+
+ CHECK_VA(vaRenderPicture(m_display->get(), m_deintContext, &pipelineBuf, 1), pipelineBuf);
+ CHECK_VA(vaEndPicture(m_display->get(), m_deintContext), pipelineBuf);
+
+ CHECK_VA(vaDestroyBuffer(m_display->get(), pipelineBuf), 0);
+
+ CHECK_VA(vaSyncSurface(m_display->get(), deintTarget->m_id), 0);
+
+ if(!firstCall && m_forwardReferencesCount > 0)
+ {
+ if(m_forwardReferences.size() >= m_forwardReferencesCount)
+ m_forwardReferences.pop_front();
+
+ if(m_forwardReferences.size() < m_forwardReferencesCount)
+ m_forwardReferences.push_back(input);
+ }
+
+ if(forwRefs)
+ delete[] forwRefs;
+
+ CVPPPicture res;
+ res.valid = true;
+ res.DVDPic = procPic.DVDPic;
+ res.surface = deintTarget;
+
+ return res;
+#else
+ return CVPPPicture();
+#endif
+}
+
+void CVPP::Flush()
+{
+#ifdef VPP_AVAIL
+ CSingleLock lock(m_deint_lock);
+
+ m_forwardReferences.clear();
+ m_backwardReferences.clear();
+#endif
+}
+
+CSurfacePtr CVPP::getFreeSurface()
+{
+#ifdef VPP_AVAIL
+ for(int i = 0; i < m_deintTargets.size(); ++i)
+ {
+ if(m_deintTargets[i].unique())
+ {
+ return m_deintTargets[i];
+ }
+ }
+
+ CLog::Log(LOGWARNING, "VAAPI_VPP - Running out of surfaces");
+#endif
+
+ return CSurfacePtr();
+}
+
+#endif
diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI_VPP.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI_VPP.h
new file mode 100644
index 0000000..093e270
--- /dev/null
+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI_VPP.h
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2013 Team XBMC
+ * http://xbmc.org
+ *
+ * This Program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This Program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with XBMC; see the file COPYING. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#pragma once
+
+#include "VAAPI.h"
+#include "threads/CriticalSection.h"
+
+#include <boost/shared_ptr.hpp>
+#include <vector>
+#include <list>
+
+namespace VAAPI
+{
+ struct CVPPPicture
+ {
+ CVPPPicture():valid(false) {}
+
+ bool valid;
+ DVDVideoPicture DVDPic;
+ CSurfacePtr surface;
+ };
+
+ class CVPP
+ {
+ CVPP();
+
+ public:
+ enum ReadyState
+ {
+ NotReady = 0,
+ Ready,
+ InitFailed,
+ RuntimeFailed
+ };
+ enum SupportState
+ {
+ Unknown = 0,
+ Supported,
+ Unsupported
+ };
+
+ CVPP(CDisplayPtr& display, int width, int height);
+ ~CVPP();
+
+ static bool VppSupported();
+ static bool DeintSupported(DeintMethod method);
+
+ void Deinit();
+ void DeinitVpp();
+ void DeinitDeint();
+
+ bool InitVpp();
+ bool InitDeint(DeintMethod method, int num_surfaces);
+
+ inline bool VppReady() { return m_vppReady == Ready; }
+ inline bool VppFailed() { return m_vppReady == InitFailed || m_vppReady == RuntimeFailed; }
+ inline bool DeintReady() { return m_deintReady == Ready; }
+ inline bool DeintFailed() { return m_deintReady == InitFailed || m_deintReady == RuntimeFailed; }
+ inline DeintMethod getUsedMethod() { return m_usedMethod; }
+
+ CVPPPicture DoDeint(const CVPPPicture& input, bool topFieldFirst, bool firstCall);
+
+ void Flush();
+
+ private:
+ CSurfacePtr getFreeSurface();
+
+
+ static SupportState g_supported;
+ static SupportState g_deintSupported[VAAPI::Deinterlacing_Count];
+
+
+ DeintMethod m_usedMethod;
+ unsigned int m_forwardReferencesCount;
+ unsigned int m_backwardReferencesCount;
+ std::list<CVPPPicture> m_forwardReferences;
+ std::list<CVPPPicture> m_backwardReferences;
+
+ CDisplayPtr m_display;
+ int m_width;
+ int m_height;
+
+ VAConfigID m_configId;
+
+ ReadyState m_vppReady;
+ ReadyState m_deintReady;
+
+ //VPP Deinterlacing
+ CCriticalSection m_deint_lock;
+ VAContextID m_deintContext;
+ std::vector<CSurfacePtr> m_deintTargets;
+ VABufferID m_deintFilter;
+ };
+
+}
+
--
1.8.3.2

View File

@ -1,850 +0,0 @@
From 0de5c323cee26d565fcd84eda803d3c92b4e6b37 Mon Sep 17 00:00:00 2001
From: BtbN <btbn@btbn.de>
Date: Thu, 3 Oct 2013 14:49:38 +0200
Subject: [PATCH] VAAPI: Integrate VPP into existing vaapi code
---
language/English/strings.po | 27 +-
xbmc/cores/VideoRenderers/LinuxRendererGL.cpp | 28 ++
xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.cpp | 399 ++++++++++++++++++++++---
xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.h | 85 +++++-
xbmc/settings/AdvancedSettings.cpp | 2 +
xbmc/settings/AdvancedSettings.h | 1 +
xbmc/settings/VideoSettings.h | 6 +
xbmc/video/dialogs/GUIDialogVideoSettings.cpp | 5 +
8 files changed, 513 insertions(+), 40 deletions(-)
diff --git a/language/English/strings.po b/language/English/strings.po
index bab2c12..ea38e13 100755
--- a/language/English/strings.po
+++ b/language/English/strings.po
@@ -7150,7 +7150,32 @@ msgctxt "#16326"
msgid "DXVA-HD"
msgstr ""
-#empty strings from id 16327 to 16399
+#: xbmc/video/dialogs/GUIDialogVideoSettings.cpp
+msgctxt "#16327"
+msgid "VAAPI Auto"
+msgstr ""
+
+#: xbmc/video/dialogs/GUIDialogVideoSettings.cpp
+msgctxt "#16328"
+msgid "VAAPI Weave"
+msgstr ""
+
+#: xbmc/video/dialogs/GUIDialogVideoSettings.cpp
+msgctxt "#16329"
+msgid "VAAPI Bob"
+msgstr ""
+
+#: xbmc/video/dialogs/GUIDialogVideoSettings.cpp
+msgctxt "#16330"
+msgid "VAAPI Motion Adaptive"
+msgstr ""
+
+#: xbmc/video/dialogs/GUIDialogVideoSettings.cpp
+msgctxt "#16331"
+msgid "VAAPI Motion Compensated"
+msgstr ""
+
+#empty strings from id 16332 to 16399
#: xbmc/video/dialogs/GUIDialogVideoSettings.cpp
msgctxt "#16400"
diff --git a/xbmc/cores/VideoRenderers/LinuxRendererGL.cpp b/xbmc/cores/VideoRenderers/LinuxRendererGL.cpp
index aa52f72..c4a7455 100644
--- a/xbmc/cores/VideoRenderers/LinuxRendererGL.cpp
+++ b/xbmc/cores/VideoRenderers/LinuxRendererGL.cpp
@@ -3488,6 +3488,26 @@ bool CLinuxRendererGL::Supports(EINTERLACEMETHOD method)
if(m_renderMethod & RENDER_VAAPI)
{
#ifdef HAVE_LIBVA
+ if(method == VS_INTERLACEMETHOD_VAAPI_AUTO)
+ return VAAPI::VppSupported();
+
+ if(method == VS_INTERLACEMETHOD_VAAPI_BOB)
+ return VAAPI::DeintSupported(VAAPI::DeinterlacingBob);
+
+ // MADI and MACI still produce problems
+ // disable them completely by now
+ if(g_advancedSettings.m_useVAAPIAdvancedDeinterlacing)
+ {
+ if(method == VS_INTERLACEMETHOD_VAAPI_WEAVE)
+ return VAAPI::DeintSupported(VAAPI::DeinterlacingWeave);
+
+ if(method == VS_INTERLACEMETHOD_VAAPI_MOTION_ADAPTIVE)
+ return VAAPI::DeintSupported(VAAPI::DeinterlacingMotionAdaptive);
+
+ if(method == VS_INTERLACEMETHOD_VAAPI_MOTION_COMPENSATED)
+ return VAAPI::DeintSupported(VAAPI::DeinterlacingMotionCompensated);
+ }
+
VAAPI::CDisplayPtr disp = m_buffers[m_iYV12RenderBuffer].vaapi.display;
if(disp)
{
@@ -3575,6 +3595,14 @@ EINTERLACEMETHOD CLinuxRendererGL::AutoInterlaceMethod()
if(m_renderMethod & RENDER_VDPAU)
return VS_INTERLACEMETHOD_NONE;
+ if(m_renderMethod & RENDER_VAAPI)
+ {
+#ifdef HAVE_LIBVA
+ if(VAAPI::VppSupported())
+ return VS_INTERLACEMETHOD_VAAPI_AUTO;
+#endif
+ }
+
if(Supports(VS_INTERLACEMETHOD_RENDER_BOB))
return VS_INTERLACEMETHOD_RENDER_BOB;
diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.cpp
index 3facfce..e7304e0 100644
--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.cpp
+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.cpp
@@ -20,8 +20,11 @@
#include "system.h"
#ifdef HAVE_LIBVA
#include "windowing/WindowingFactory.h"
+#include "settings/MediaSettings.h"
#include "settings/Settings.h"
+#include "cores/dvdplayer/DVDClock.h"
#include "VAAPI.h"
+#include "VAAPI_VPP.h"
#include "DVDVideoCodec.h"
#include <boost/scoped_array.hpp>
#include <boost/weak_ptr.hpp>
@@ -66,7 +69,7 @@ static int compare_version(int major_l, int minor_l, int micro_l, int major_r, i
static void RelBufferS(AVCodecContext *avctx, AVFrame *pic)
{ ((CDecoder*)((CDVDVideoCodecFFmpeg*)avctx->opaque)->GetHardware())->RelBuffer(avctx, pic); }
-static int GetBufferS(AVCodecContext *avctx, AVFrame *pic)
+static int GetBufferS(AVCodecContext *avctx, AVFrame *pic)
{ return ((CDecoder*)((CDVDVideoCodecFFmpeg*)avctx->opaque)->GetHardware())->GetBuffer(avctx, pic); }
static inline VASurfaceID GetSurfaceID(AVFrame *pic)
@@ -83,7 +86,7 @@ static CDisplayPtr GetGlobalDisplay()
{
CLog::Log(LOGERROR, "VAAPI - vaapi display is in lost state");
display.reset();
- }
+ }
return display;
}
@@ -151,6 +154,9 @@ static CDisplayPtr GetGlobalDisplay()
CDecoder::CDecoder()
{
+ // Buffer size passed to VPP Init
+ m_buffer_size = 9;
+
m_refs = 0;
m_surfaces_count = 0;
m_config = 0;
@@ -170,7 +176,7 @@ void CDecoder::RelBuffer(AVCodecContext *avctx, AVFrame *pic)
VASurfaceID surface = GetSurfaceID(pic);
for(std::list<CSurfacePtr>::iterator it = m_surfaces_used.begin(); it != m_surfaces_used.end(); ++it)
- {
+ {
if((*it)->m_id == surface)
{
m_surfaces_free.push_back(*it);
@@ -205,19 +211,19 @@ int CDecoder::GetBuffer(AVCodecContext *avctx, AVFrame *pic)
if(!wrapper)
{
CLog::Log(LOGERROR, "VAAPI - unable to find requested surface");
- return -1;
+ return -1;
}
}
else
{
// 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) {}
+ // that are 100% not in use by renderer or vpp. The pointers to these surfaces are unique(use_count() == 1).
+ for (; it != m_surfaces_free.end() && !it->unique(); ++it) {}
// 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");
+ if (!m_surfaces_free.empty()) CLog::Log(LOGERROR, "VAAPI - renderer/vpp 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())
{
@@ -238,7 +244,7 @@ int CDecoder::GetBuffer(AVCodecContext *avctx, AVFrame *pic)
pic->data[0] = (uint8_t*)wrapper;
pic->data[1] = NULL;
pic->data[2] = NULL;
- pic->data[3] = (uint8_t*)surface;
+ pic->data[3] = (uint8_t*)(uintptr_t)surface;
pic->linesize[0] = 0;
pic->linesize[1] = 0;
pic->linesize[2] = 0;
@@ -248,7 +254,9 @@ int CDecoder::GetBuffer(AVCodecContext *avctx, AVFrame *pic)
}
void CDecoder::Close()
-{
+{
+ m_vppth.reset();
+
if(m_context)
WARN(vaDestroyContext(m_display->get(), m_context))
m_context = 0;
@@ -256,7 +264,7 @@ void CDecoder::Close()
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;
@@ -291,7 +299,7 @@ bool CDecoder::Open(AVCodecContext *avctx, enum PixelFormat fmt, unsigned int su
else
{
if(avctx->profile == FF_PROFILE_H264_MAIN)
- accepted.push_back(VAProfileH264Main);
+ accepted.push_back(VAProfileH264Main);
#else
{
// fallback to high profile if libavcodec is too old to export
@@ -371,10 +379,15 @@ bool CDecoder::Open(AVCodecContext *avctx, enum PixelFormat fmt, unsigned int su
CHECK(vaCreateConfig(m_display->get(), profile, entrypoint, &attrib, 1, &m_hwaccel->config_id))
m_config = m_hwaccel->config_id;
+ m_vppth = CVPPThreadPtr(new CVPPThread(m_display, avctx->width, avctx->height));
+
m_renderbuffers_count = surfaces;
if (!EnsureContext(avctx))
return false;
+ m_vppth->Init(m_buffer_size); // Ignore result, VPPThread just passes frames if init failed
+ m_vppth->Start();
+
m_hwaccel->display = m_display->get();
avctx->hwaccel_context = m_hwaccel;
@@ -403,7 +416,12 @@ bool CDecoder::EnsureContext(AVCodecContext *avctx)
else
m_refs = 2;
}
- return EnsureSurfaces(avctx, m_refs + m_renderbuffers_count + 1);
+
+ int vpp_buf = 0;
+ if(m_vppth && m_vppth->getVPP() && m_vppth->getVPP()->VppSupported())
+ vpp_buf = m_buffer_size / 2 + 4;
+
+ return EnsureSurfaces(avctx, m_refs + vpp_buf + m_renderbuffers_count + 1);
}
bool CDecoder::EnsureSurfaces(AVCodecContext *avctx, unsigned n_surfaces_count)
@@ -459,48 +477,75 @@ int CDecoder::Decode(AVCodecContext* avctx, AVFrame* frame)
return status;
if(frame)
- return VC_BUFFER | VC_PICTURE;
- else
- return VC_BUFFER;
-}
-
-bool CDecoder::GetPicture(AVCodecContext* avctx, AVFrame* frame, DVDVideoPicture* picture)
-{
- ((CDVDVideoCodecFFmpeg*)avctx->opaque)->GetPictureCommon(picture);
- VASurfaceID surface = GetSurfaceID(frame);
-
+ {
+ CVPPPicture picture;
+ VASurfaceID surface = GetSurfaceID(frame);
- m_holder.surface.reset();
+ std::list<CSurfacePtr>::iterator it;
+ for(it = m_surfaces_used.begin(); it != m_surfaces_used.end() && !picture.surface; ++it)
+ if((*it)->m_id == surface)
+ picture.surface = *it;
+ for(it = m_surfaces_free.begin(); it != m_surfaces_free.end() && !picture.surface; ++it)
+ if((*it)->m_id == surface)
+ picture.surface = *it;
+ if(!picture.surface)
+ {
+ CLog::Log(LOGERROR, "VAAPI - Unable to find surface");
+ return VC_ERROR;
+ }
- std::list<CSurfacePtr>::iterator it;
- for(it = m_surfaces_used.begin(); it != m_surfaces_used.end() && !m_holder.surface; ++it)
- {
- if((*it)->m_id == surface)
+ VASurfaceStatus surf_status;
+ if(vaQuerySurfaceStatus(m_display->get(), surface, &surf_status) != VA_STATUS_SUCCESS)
{
- m_holder.surface = *it;
- break;
+ CLog::Log(LOGERROR, "VAAPI - Unable to query surface status");
+ return VC_ERROR;
}
- }
- for(it = m_surfaces_free.begin(); it != m_surfaces_free.end() && !m_holder.surface; ++it)
- {
- if((*it)->m_id == surface)
+ if((((int)surf_status) & 16) == 0)
{
- m_holder.surface = *it;
- break;
+ picture.valid = true;
+ memset(&picture.DVDPic, 0, sizeof(picture.DVDPic));
+ ((CDVDVideoCodecFFmpeg*)avctx->opaque)->GetPictureCommon(&picture.DVDPic);
+
+ m_vppth->InsertNewFrame(picture);
}
}
- if(!m_holder.surface)
+
+ int ret = 0;
+
+ if(m_vppth->GetInputQueueSize() < (m_buffer_size >> 2) && m_vppth->GetOutputQueueSize() < (m_buffer_size >> 1))
+ ret |= VC_BUFFER;
+ if(m_vppth->GetOutputQueueSize() > 0)
+ ret |= VC_PICTURE;
+
+ return ret;
+}
+
+bool CDecoder::GetPicture(AVCodecContext* avctx, AVFrame* frame, DVDVideoPicture* picture)
+{
+ m_holder.surface.reset();
+
+ CVPPPicture outPic = m_vppth->GetOutputPicture();
+ if(!outPic.valid)
{
- CLog::Log(LOGERROR, "VAAPI - Unable to find surface");
+ CLog::Log(LOGERROR, "VAAPI - Got an invalid render picture");
return false;
}
+ m_holder.surface = outPic.surface;
+ *picture = outPic.DVDPic;
+
picture->format = RENDER_FMT_VAAPI;
picture->vaapi = &m_holder;
+
return true;
}
+void CDecoder::Reset()
+{
+ m_vppth->Flush();
+}
+
int CDecoder::Check(AVCodecContext* avctx)
{
if (m_display == NULL)
@@ -537,4 +582,284 @@ unsigned CDecoder::GetAllowedReferences()
return m_renderbuffers_count;
}
+
+CVPPThread::CVPPThread(CDisplayPtr& display, int width, int height)
+ :CThread("VAAPI VPP Thread")
+ ,m_stop(false)
+ ,m_can_skip_deint(false)
+ ,m_num_refs(-1)
+ ,m_last_method(-1)
+{
+ m_vpp = CVPPPtr(new CVPP(display, width, height));
+}
+
+CVPPThread::~CVPPThread()
+{
+ Dispose();
+}
+
+bool CVPPThread::Init(int num_refs)
+{
+ m_num_refs = num_refs;
+ return m_vpp->InitVpp();
+}
+
+void CVPPThread::Start()
+{
+ m_stop = false;
+ m_last_method = -1;
+ Create();
+}
+
+void CVPPThread::Dispose()
+{
+ m_stop = true;
+ m_input_cond.notifyAll();
+ StopThread();
+
+ m_input_queue = std::queue<CVPPPicture>();
+ m_output_queue = std::queue<CVPPPicture>();
+
+ m_vpp->Deinit();
+ m_vpp.reset();
+}
+
+void CVPPThread::OnStartup()
+{
+ CLog::Log(LOGDEBUG, "VAAPI - VPP thread on startup");
+}
+
+void CVPPThread::OnExit()
+{
+ CLog::Log(LOGDEBUG, "VAAPI - VPP thread on exit");
+}
+
+void CVPPThread::InsertNewFrame(CVPPPicture &new_frame)
+{
+ if(!IsRunning())
+ return;
+
+ CSingleLock lock(m_input_queue_lock);
+
+ m_input_queue.push(new_frame);
+ m_input_cond.notify();
+}
+
+CVPPPicture CVPPThread::GetOutputPicture()
+{
+ CVPPPicture res = CVPPPicture();
+
+ if(!IsRunning())
+ return res;
+
+ CSingleLock lock(m_output_queue_lock);
+
+ if(!m_output_queue.empty())
+ {
+ res = m_output_queue.front();
+ m_output_queue.pop();
+ }
+
+ return res;
+}
+
+CVPPPicture CVPPThread::GetCurrentFrame()
+{
+ CVPPPicture res = CVPPPicture();
+
+ if(m_stop)
+ return res;
+
+ CSingleLock lock(m_input_queue_lock);
+
+ if(m_input_queue.empty())
+ m_input_cond.wait(m_input_queue_lock);
+
+ if(!m_input_queue.empty())
+ {
+ res = m_input_queue.front();
+ m_input_queue.pop();
+ }
+
+ return res;
+}
+
+void CVPPThread::InsertOutputFrame(CVPPPicture &new_frame)
+{
+ CSingleLock lock(m_output_queue_lock);
+
+ m_output_queue.push(new_frame);
+}
+
+int CVPPThread::GetInputQueueSize()
+{
+ CSingleLock lock(m_input_queue_lock);
+
+ return m_input_queue.size();
+}
+
+int CVPPThread::GetOutputQueueSize()
+{
+ CSingleLock lock(m_output_queue_lock);
+
+ return m_output_queue.size();
+}
+
+void CVPPThread::Flush()
+{
+ CSingleLock lock(m_work_lock);
+
+ m_input_queue_lock.lock();
+ m_input_queue = std::queue<CVPPPicture>();
+ m_input_queue_lock.unlock();
+
+ m_output_queue_lock.lock();
+ m_output_queue = std::queue<CVPPPicture>();
+ m_output_queue_lock.unlock();
+
+ m_vpp->Flush();
+}
+
+void CVPPThread::CheckMethod(int method)
+{
+ if(method == m_last_method || !m_vpp->VppReady())
+ return;
+
+ EINTERLACEMETHOD emethod = (EINTERLACEMETHOD)method;
+
+ m_vpp->DeinitDeint();
+
+ if(method == VS_INTERLACEMETHOD_VAAPI_AUTO || method == VS_INTERLACEMETHOD_AUTO)
+ {
+ if( !CVPP::DeintSupported(VAAPI::DeinterlacingBob)
+ || !m_vpp->InitDeint(VAAPI::DeinterlacingBob, m_num_refs))
+ {
+ int i;
+ for(i = VAAPI::Deinterlacing_Count - 1; i >= 1; --i)
+ if(CVPP::DeintSupported((DeintMethod)i))
+ if(m_vpp->InitDeint((DeintMethod)i, m_num_refs))
+ break;
+
+ if(i < 1)
+ CLog::Log(LOGDEBUG, "VAAPI - Requested auto deint method, but no method initialized propperly!");
+ }
+ }
+ else if(method == VS_INTERLACEMETHOD_VAAPI_WEAVE)
+ {
+ if(CVPP::DeintSupported(VAAPI::DeinterlacingWeave))
+ m_vpp->InitDeint(VAAPI::DeinterlacingWeave, m_num_refs);
+ else
+ CLog::Log(LOGDEBUG, "VAAPI - Requested unsupported deint method \"Weave\"");
+ }
+ else if(method == VS_INTERLACEMETHOD_VAAPI_BOB)
+ {
+ if(CVPP::DeintSupported(VAAPI::DeinterlacingBob))
+ m_vpp->InitDeint(VAAPI::DeinterlacingBob, m_num_refs);
+ else
+ CLog::Log(LOGDEBUG, "VAAPI - Requested unsupported deint method \"Bob\"");
+ }
+ else if(method == VS_INTERLACEMETHOD_VAAPI_MOTION_ADAPTIVE)
+ {
+ if(CVPP::DeintSupported(VAAPI::DeinterlacingMotionAdaptive))
+ m_vpp->InitDeint(VAAPI::DeinterlacingMotionAdaptive, m_num_refs);
+ else
+ CLog::Log(LOGDEBUG, "VAAPI - Requested unsupported deint method \"Motion Adaptive\"");
+ }
+ else if(method == VS_INTERLACEMETHOD_VAAPI_MOTION_COMPENSATED)
+ {
+ if(CVPP::DeintSupported(VAAPI::DeinterlacingMotionCompensated))
+ m_vpp->InitDeint(VAAPI::DeinterlacingMotionCompensated, m_num_refs);
+ else
+ CLog::Log(LOGDEBUG, "VAAPI - Requested unsupported deint method \"Motion Compensated\"");
+ }
+
+ m_last_method = method;
+}
+
+void CVPPThread::DoDeinterlacing(const CVPPPicture &frame, bool topFieldFirst, bool firstCall)
+{
+ if(!m_vpp->DeintReady())
+ return;
+
+ CVPPPicture res = m_vpp->DoDeint(frame, topFieldFirst, firstCall);
+ if(!res.valid)
+ return;
+
+ res.DVDPic.iFlags &= ~(DVP_FLAG_TOP_FIELD_FIRST | DVP_FLAG_REPEAT_TOP_FIELD | DVP_FLAG_INTERLACED);
+
+ if(!firstCall)
+ {
+ res.DVDPic.pts = DVD_NOPTS_VALUE;
+ res.DVDPic.dts = DVD_NOPTS_VALUE;
+ }
+
+ res.DVDPic.iRepeatPicture = 0.0;
+
+ InsertOutputFrame(res);
+}
+
+void CVPPThread::Process()
+{
+ CVPPPicture currentFrame = CVPPPicture();
+
+ m_work_lock.lock();
+
+ while(!m_stop)
+ {
+ if(currentFrame.valid)
+ {
+ bool isInterlaced = currentFrame.DVDPic.iFlags & DVP_FLAG_INTERLACED;
+
+ bool skipDeint = false;
+ //if(currentFrame.DVDPic.iFlags & DVP_FLAG_DROPDEINT)
+ // skipDeint = true;
+
+ EDEINTERLACEMODE mode = CMediaSettings::Get().GetCurrentVideoSettings().m_DeinterlaceMode;
+ EINTERLACEMETHOD method = CMediaSettings::Get().GetCurrentVideoSettings().m_InterlaceMethod;
+
+ CheckMethod((int)method);
+
+ bool doDeint = m_vpp->DeintReady()
+ && (mode == VS_DEINTERLACEMODE_FORCE || (mode == VS_DEINTERLACEMODE_AUTO && isInterlaced));
+
+ m_can_skip_deint = doDeint;
+
+ if(doDeint && !skipDeint)
+ {
+ bool topFieldFirst = currentFrame.DVDPic.iFlags & DVP_FLAG_TOP_FIELD_FIRST == DVP_FLAG_TOP_FIELD_FIRST;
+
+ DoDeinterlacing(currentFrame, topFieldFirst, true);
+ DoDeinterlacing(currentFrame, topFieldFirst, false);
+ }
+ else
+ {
+ CVPPPicture res;
+ res.valid = true;
+ res.DVDPic = currentFrame.DVDPic;
+ res.surface = currentFrame.surface;
+ InsertOutputFrame(res);
+ }
+ }
+
+ currentFrame = CVPPPicture();
+
+ m_work_lock.unlock();
+ currentFrame = GetCurrentFrame();
+ m_work_lock.lock();
+ }
+
+ m_work_lock.unlock();
+}
+
+bool VAAPI::VppSupported()
+{
+ return CVPP::VppSupported();
+}
+
+bool VAAPI::DeintSupported(DeintMethod method)
+{
+ return CVPP::DeintSupported(method);
+}
+
#endif
+
diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.h
index a520e42..684b8d0 100644
--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.h
+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.h
@@ -23,11 +23,16 @@
#include "DllAvCodec.h"
#include "DVDVideoCodecFFmpeg.h"
+#include "threads/Thread.h"
+#include "threads/Condition.h"
+#include "threads/CriticalSection.h"
+
#include <libavcodec/vaapi.h>
#include <va/va.h>
#include <va/va_x11.h>
#include <va/va_glx.h>
#include <list>
+#include <queue>
#include <boost/shared_ptr.hpp>
@@ -83,13 +88,16 @@ struct CSurfaceGL
, m_display(display)
{}
~CSurfaceGL();
-
+
void* m_id;
CDisplayPtr m_display;
};
typedef boost::shared_ptr<CSurfaceGL> CSurfaceGLPtr;
+class CVPP;
+typedef boost::shared_ptr<CVPP> CVPPPtr;
+
// silly type to avoid includes
struct CHolder
{
@@ -101,6 +109,59 @@ struct CHolder
{}
};
+struct CVPPPicture;
+
+class CVPPThread : private CThread
+{
+public:
+ CVPPThread(CDisplayPtr& display, int width, int height);
+ ~CVPPThread();
+
+ bool Init(int num_refs);
+ void Start();
+ void Dispose();
+
+ void InsertNewFrame(CVPPPicture &new_frame);
+ CVPPPicture GetOutputPicture();
+
+ int GetInputQueueSize();
+ int GetOutputQueueSize();
+
+ void Flush();
+
+ inline CVPPPtr getVPP() { return m_vpp; }
+ inline bool CanSkipDeint() { return m_can_skip_deint; }
+
+protected:
+ void OnStartup();
+ void OnExit();
+ void Process();
+
+ void InsertOutputFrame(CVPPPicture &new_frame);
+ CVPPPicture GetCurrentFrame();
+ void DoDeinterlacing(const CVPPPicture &frame, bool topFieldFirst, bool firstCall);
+ void CheckMethod(int method);
+
+ CVPPPtr m_vpp;
+
+ bool m_stop;
+
+ bool m_can_skip_deint;
+ int m_num_refs;
+ int m_last_method;
+
+ CCriticalSection m_work_lock;
+
+ CCriticalSection m_input_queue_lock;
+ XbmcThreads::ConditionVariable m_input_cond;
+ std::queue<CVPPPicture> m_input_queue;
+
+ CCriticalSection m_output_queue_lock;
+ std::queue<CVPPPicture> m_output_queue;
+};
+
+typedef boost::shared_ptr<CVPPThread> CVPPThreadPtr;
+
class CDecoder
: public CDVDVideoCodecFFmpeg::IHardwareDecoder
{
@@ -113,22 +174,26 @@ class CDecoder
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 const std::string Name() { return "vaapi"; }
virtual CCriticalSection* Section() { if(m_display) return m_display.get(); else return NULL; }
virtual unsigned GetAllowedReferences();
+ virtual bool CanSkipDeint() { if(m_vppth) return m_vppth->CanSkipDeint(); else return false; }
int GetBuffer(AVCodecContext *avctx, AVFrame *pic);
void RelBuffer(AVCodecContext *avctx, AVFrame *pic);
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;
+ int m_buffer_size;
+
int m_refs;
std::list<CSurfacePtr> m_surfaces_used;
std::list<CSurfacePtr> m_surfaces_free;
@@ -139,7 +204,23 @@ class CDecoder
vaapi_context *m_hwaccel;
+ CVPPThreadPtr m_vppth;
+
CHolder m_holder; // silly struct to pass data to renderer
};
+enum DeintMethod
+{
+ DeinterlacingNone = 0,
+ DeinterlacingWeave,
+ DeinterlacingBob,
+ DeinterlacingMotionAdaptive,
+ DeinterlacingMotionCompensated,
+ Deinterlacing_Count
+};
+
+bool VppSupported();
+bool DeintSupported(DeintMethod method);
+
}
+
diff --git a/xbmc/settings/AdvancedSettings.cpp b/xbmc/settings/AdvancedSettings.cpp
index 79ce315..414f6dc 100644
--- a/xbmc/settings/AdvancedSettings.cpp
+++ b/xbmc/settings/AdvancedSettings.cpp
@@ -167,6 +167,7 @@ void CAdvancedSettings::Initialize()
m_videoCaptureUseOcclusionQuery = -1; //-1 is auto detect
m_videoVDPAUtelecine = false;
m_videoVDPAUdeintSkipChromaHD = false;
+ m_useVAAPIAdvancedDeinterlacing = false;
m_DXVACheckCompatibility = false;
m_DXVACheckCompatibilityPresent = false;
m_DXVAForceProcessorRenderer = true;
@@ -605,6 +606,7 @@ void CAdvancedSettings::ParseSettingsFile(const CStdString &file)
XMLUtils::GetInt(pElement, "useocclusionquery", m_videoCaptureUseOcclusionQuery, -1, 1);
XMLUtils::GetBoolean(pElement,"vdpauInvTelecine",m_videoVDPAUtelecine);
XMLUtils::GetBoolean(pElement,"vdpauHDdeintSkipChroma",m_videoVDPAUdeintSkipChromaHD);
+ XMLUtils::GetBoolean(pElement, "vaapiadvanceddeint", m_useVAAPIAdvancedDeinterlacing);
TiXmlElement* pStagefrightElem = pElement->FirstChildElement("stagefright");
if (pStagefrightElem)
diff --git a/xbmc/settings/AdvancedSettings.h b/xbmc/settings/AdvancedSettings.h
index 7d16957..6eae4ee 100644
--- a/xbmc/settings/AdvancedSettings.h
+++ b/xbmc/settings/AdvancedSettings.h
@@ -162,6 +162,7 @@ class CAdvancedSettings : public ISettingCallback, public ISettingsHandler
CStdString m_videoPPFFmpegPostProc;
bool m_videoVDPAUtelecine;
bool m_videoVDPAUdeintSkipChromaHD;
+ bool m_useVAAPIAdvancedDeinterlacing;
bool m_musicUseTimeSeeking;
int m_musicTimeSeekForward;
int m_musicTimeSeekBackward;
diff --git a/xbmc/settings/VideoSettings.h b/xbmc/settings/VideoSettings.h
index 293f363..199290f 100644
--- a/xbmc/settings/VideoSettings.h
+++ b/xbmc/settings/VideoSettings.h
@@ -63,6 +63,12 @@ enum EINTERLACEMETHOD
VS_INTERLACEMETHOD_SW_BLEND = 20,
VS_INTERLACEMETHOD_AUTO_ION = 21,
+ VS_INTERLACEMETHOD_VAAPI_AUTO = 22,
+ VS_INTERLACEMETHOD_VAAPI_WEAVE = 23,
+ VS_INTERLACEMETHOD_VAAPI_BOB = 24,
+ VS_INTERLACEMETHOD_VAAPI_MOTION_ADAPTIVE = 25,
+ VS_INTERLACEMETHOD_VAAPI_MOTION_COMPENSATED = 26,
+
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 5218a83..3fe91d8 100644
--- a/xbmc/video/dialogs/GUIDialogVideoSettings.cpp
+++ b/xbmc/video/dialogs/GUIDialogVideoSettings.cpp
@@ -116,6 +116,11 @@ void CGUIDialogVideoSettings::CreateSettings()
entries.push_back(make_pair(VS_INTERLACEMETHOD_DXVA_BOB , 16320));
entries.push_back(make_pair(VS_INTERLACEMETHOD_DXVA_BEST , 16321));
entries.push_back(make_pair(VS_INTERLACEMETHOD_AUTO_ION , 16325));
+ entries.push_back(make_pair(VS_INTERLACEMETHOD_VAAPI_AUTO , 16327));
+ entries.push_back(make_pair(VS_INTERLACEMETHOD_VAAPI_WEAVE , 16328));
+ entries.push_back(make_pair(VS_INTERLACEMETHOD_VAAPI_BOB , 16329));
+ entries.push_back(make_pair(VS_INTERLACEMETHOD_VAAPI_MOTION_ADAPTIVE , 16330));
+ entries.push_back(make_pair(VS_INTERLACEMETHOD_VAAPI_MOTION_COMPENSATED , 16331));
/* remove unsupported methods */
for(vector<pair<int, int> >::iterator it = entries.begin(); it != entries.end();)
--
1.8.5.1

View File

@ -1,55 +0,0 @@
From dd4346a0cfacbb62bc06644bdf471531ea1f5a8a Mon Sep 17 00:00:00 2001
From: BtbN <btbn@btbn.de>
Date: Mon, 9 Dec 2013 14:47:29 +0100
Subject: [PATCH] VAAPI, squash me: Attempt to fix mysterious non-smoothness
issue
---
xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI_VPP.cpp | 11 ++++++-----
1 file changed, 6 insertions(+), 5 deletions(-)
diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI_VPP.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI_VPP.cpp
index 78e786a..c88e402 100644
--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI_VPP.cpp
+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI_VPP.cpp
@@ -406,6 +406,7 @@ CVPPPicture CVPP::DoDeint(const CVPPPicture& input, bool topFieldFirst, bool fir
VAProcPipelineParameterBuffer *pipelineParam;
VARectangle inputRegion;
VARectangle outputRegion;
+ unsigned int deint_flags = 0;
VASurfaceID *forwRefs = 0;
@@ -416,16 +417,16 @@ CVPPPicture CVPP::DoDeint(const CVPPPicture& input, bool topFieldFirst, bool fir
if(firstCall || m_forwardReferences.size() < m_forwardReferencesCount)
{
if(!topFieldFirst)
- deint->flags = VA_DEINTERLACING_BOTTOM_FIELD_FIRST | VA_DEINTERLACING_BOTTOM_FIELD;
+ deint_flags = deint->flags = VA_DEINTERLACING_BOTTOM_FIELD_FIRST | VA_DEINTERLACING_BOTTOM_FIELD;
else
- deint->flags = 0;
+ deint_flags = deint->flags = 0;
}
else
{
if(topFieldFirst)
- deint->flags = VA_DEINTERLACING_BOTTOM_FIELD;
+ deint_flags = deint->flags = VA_DEINTERLACING_BOTTOM_FIELD;
else
- deint->flags = VA_DEINTERLACING_BOTTOM_FIELD_FIRST;
+ deint_flags = deint->flags = VA_DEINTERLACING_BOTTOM_FIELD_FIRST;
}
CHECK_VA(vaUnmapBuffer(m_display->get(), m_deintFilter), 0);
@@ -449,7 +450,7 @@ CVPPPicture CVPP::DoDeint(const CVPPPicture& input, bool topFieldFirst, bool fir
pipelineParam->surface_region = &inputRegion;
pipelineParam->output_background_color = 0xff000000;
- pipelineParam->filter_flags = 0;
+ pipelineParam->filter_flags = (deint_flags & VA_DEINTERLACING_BOTTOM_FIELD) ? VA_BOTTOM_FIELD : VA_TOP_FIELD;
pipelineParam->filters = &m_deintFilter;
pipelineParam->num_filters = 1;
--
1.8.5.1

View File

@ -1,69 +0,0 @@
From ba08b7255bd022f22de620d66366e85a48fe6a9f Mon Sep 17 00:00:00 2001
From: fritsch <Peter.Fruehberger@gmail.com>
Date: Sun, 22 Dec 2013 10:40:42 +0100
Subject: [PATCH] VPP: Introduce advanced setting to disable mpeg-2 decoding
cause of intel drivers for haswell are horrible broken (default enabled for
the rest of intel family)
---
xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp | 10 ++++++++--
xbmc/settings/AdvancedSettings.cpp | 2 ++
xbmc/settings/AdvancedSettings.h | 1 +
3 files changed, 11 insertions(+), 2 deletions(-)
diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp
index 5692faf..3acb109 100644
--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp
+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp
@@ -104,8 +104,14 @@ enum PixelFormat CDVDVideoCodecFFmpeg::GetFormat( struct AVCodecContext * avctx
#endif
#ifdef HAVE_LIBVA
// mpeg4 vaapi decoding is disabled
- if(*cur == PIX_FMT_VAAPI_VLD && CSettings::Get().GetBool("videoplayer.usevaapi")
- && (avctx->codec_id != AV_CODEC_ID_MPEG4 || g_advancedSettings.m_videoAllowMpeg4VAAPI))
+ // some newer haswells have problems doing mpeg-2 deinterlacing
+ bool allowvaapi = true;
+ if (avctx->codec_id == AV_CODEC_ID_MPEG4 && !g_advancedSettings.m_videoAllowMpeg4VAAPI)
+ allowvaapi = false;
+ else if (avctx->codec_id == AV_CODEC_ID_MPEG2VIDEO && !g_advancedSettings.m_videoAllowMpeg2VAAPI)
+ allowvaapi = false;
+
+ if(*cur == PIX_FMT_VAAPI_VLD && CSettings::Get().GetBool("videoplayer.usevaapi") && allowvaapi)
{
VAAPI::CDecoder* dec = new VAAPI::CDecoder();
if(dec->Open(avctx, *cur, ctx->m_uSurfacesCount))
diff --git a/xbmc/settings/AdvancedSettings.cpp b/xbmc/settings/AdvancedSettings.cpp
index e148f1c..6cb2d91 100644
--- a/xbmc/settings/AdvancedSettings.cpp
+++ b/xbmc/settings/AdvancedSettings.cpp
@@ -163,6 +163,7 @@ void CAdvancedSettings::Initialize()
m_videoAutoScaleMaxFps = 30.0f;
m_videoAllowMpeg4VDPAU = false;
m_videoAllowMpeg4VAAPI = false;
+ m_videoAllowMpeg2VAAPI = true;
m_videoDisableBackgroundDeinterlace = false;
m_videoCaptureUseOcclusionQuery = -1; //-1 is auto detect
m_videoVDPAUtelecine = false;
@@ -602,6 +603,7 @@ void CAdvancedSettings::ParseSettingsFile(const CStdString &file)
XMLUtils::GetBoolean(pElement,"allowmpeg4vdpau",m_videoAllowMpeg4VDPAU);
XMLUtils::GetBoolean(pElement,"disablehi10pmultithreading",m_videoDisableHi10pMultithreading);
XMLUtils::GetBoolean(pElement,"allowmpeg4vaapi",m_videoAllowMpeg4VAAPI);
+ XMLUtils::GetBoolean(pElement,"allowmpeg2vaapi",m_videoAllowMpeg2VAAPI);
XMLUtils::GetBoolean(pElement, "disablebackgrounddeinterlace", m_videoDisableBackgroundDeinterlace);
XMLUtils::GetInt(pElement, "useocclusionquery", m_videoCaptureUseOcclusionQuery, -1, 1);
XMLUtils::GetBoolean(pElement,"vdpauInvTelecine",m_videoVDPAUtelecine);
diff --git a/xbmc/settings/AdvancedSettings.h b/xbmc/settings/AdvancedSettings.h
index 6eae4ee..070f754 100644
--- a/xbmc/settings/AdvancedSettings.h
+++ b/xbmc/settings/AdvancedSettings.h
@@ -184,6 +184,7 @@ class CAdvancedSettings : public ISettingCallback, public ISettingsHandler
float m_videoAutoScaleMaxFps;
bool m_videoAllowMpeg4VDPAU;
bool m_videoAllowMpeg4VAAPI;
+ bool m_videoAllowMpeg2VAAPI;
std::vector<RefreshOverride> m_videoAdjustRefreshOverrides;
std::vector<RefreshVideoLatency> m_videoRefreshLatency;
float m_videoDefaultLatency;
--
1.8.3.2

View File

@ -1,16 +0,0 @@
diff --git a/src/i965_drv_video.c b/src/i965_drv_video.c
index 31dafa2..a58eb7b 100755
--- a/src/i965_drv_video.c
+++ b/src/i965_drv_video.c
@@ -2358,7 +2358,11 @@ i965_QuerySurfaceStatus(VADriverContextP ctx,
*status = VASurfaceReady;
}
} else {
+#ifdef HAVE_VA_SURFACE_STATUS_EMPTY
+ *status = VASurfaceReady | VASurfaceEmpty;
+#else
*status = VASurfaceReady;
+#endif
}
return VA_STATUS_SUCCESS;

View File

@ -1,23 +0,0 @@
diff --git a/va/va.h b/va/va.h
index d9e4c7e..dc0f092 100644
--- a/va/va.h
+++ b/va/va.h
@@ -1905,6 +1905,8 @@ VAStatus vaSyncSurface (
VASurfaceID render_target
);
+#define HAVE_VA_SURFACE_STATUS_EMPTY 1
+
typedef enum
{
VASurfaceRendering = 1, /* Rendering in progress */
@@ -1912,7 +1914,8 @@ typedef enum
/* this status is useful if surface is used as the source */
/* of an overlay */
VASurfaceReady = 4, /* not being rendered or displayed */
- VASurfaceSkipped = 8 /* Indicate a skipped frame during encode */
+ VASurfaceSkipped = 8, /* Indicate a skipped frame during encode */
+ VASurfaceEmpty = 16 /* contains no actual data */
} VASurfaceStatus;
/*