mirror of
https://github.com/LibreELEC/LibreELEC.tv.git
synced 2025-07-24 11:16:51 +00:00
commit
46dc2db4df
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
@ -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;
|
||||
|
||||
/*
|
Loading…
x
Reference in New Issue
Block a user