diff --git a/packages/mediacenter/xbmc-theme-Confluence/package.mk b/packages/mediacenter/xbmc-theme-Confluence/package.mk index a2ffecc094..42ed3c1818 100644 --- a/packages/mediacenter/xbmc-theme-Confluence/package.mk +++ b/packages/mediacenter/xbmc-theme-Confluence/package.mk @@ -17,7 +17,7 @@ ################################################################################ PKG_NAME="xbmc-theme-Confluence" -PKG_VERSION="14-0b1a6eb" +PKG_VERSION="14-7f17034" PKG_REV="1" PKG_ARCH="any" PKG_LICENSE="GPL" diff --git a/packages/mediacenter/xbmc/package.mk b/packages/mediacenter/xbmc/package.mk index 2f7bfcd54b..33f453680c 100644 --- a/packages/mediacenter/xbmc/package.mk +++ b/packages/mediacenter/xbmc/package.mk @@ -17,7 +17,7 @@ ################################################################################ PKG_NAME="xbmc" -PKG_VERSION="14-0b1a6eb" +PKG_VERSION="14-7f17034" PKG_REV="1" PKG_ARCH="any" PKG_LICENSE="GPL" diff --git a/packages/mediacenter/xbmc/patches/xbmc-999.91-PR5202.patch b/packages/mediacenter/xbmc/patches/xbmc-999.91-PR5202.patch deleted file mode 100644 index c3612f7abe..0000000000 --- a/packages/mediacenter/xbmc/patches/xbmc-999.91-PR5202.patch +++ /dev/null @@ -1,2303 +0,0 @@ -From 1f7bf1d1451027f0ae9277cdaaea0c1ab6650864 Mon Sep 17 00:00:00 2001 -From: "Chris \"Koying\" Browet" -Date: Thu, 7 Aug 2014 13:46:49 +0200 -Subject: [PATCH 1/2] ADD: Freescale i.MX6 h/w codec - ---- - configure.in | 13 +- - xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp | 244 +++++ - xbmc/cores/VideoRenderers/LinuxRendererGLES.h | 14 +- - xbmc/cores/VideoRenderers/RenderFormats.h | 1 + - xbmc/cores/VideoRenderers/RenderManager.cpp | 4 + - xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.cpp | 16 +- - .../dvdplayer/DVDCodecs/Video/DVDVideoCodec.h | 8 + - .../dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp | 1083 ++++++++++++++++++++ - .../dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h | 151 +++ - xbmc/cores/dvdplayer/DVDCodecs/Video/Makefile.in | 3 + - xbmc/cores/dvdplayer/DVDPlayerVideo.cpp | 1 + - 11 files changed, 1535 insertions(+), 3 deletions(-) - create mode 100644 xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp - create mode 100644 xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h - -diff --git a/configure.in b/configure.in -index 725a271..e364551 100644 ---- a/configure.in -+++ b/configure.in -@@ -542,7 +542,7 @@ AC_ARG_ENABLE([gtest], - - AC_ARG_ENABLE([codec], - [AS_HELP_STRING([--enable-codec], -- [enable additional codecs from a list of comma separated names, (default is none, choices are amcodec, libstagefright)])], -+ [enable additional codecs from a list of comma separated names, (default is none, choices are amcodec, libstagefright and imxvpu)])], - [add_codecs=$enableval], - [add_codecs=no]) - -@@ -1901,6 +1901,17 @@ for codecs in `echo $add_codecs | sed 's/,/ /g'`; do - *libstagefright*) - XB_ADD_CODEC([LIBSTAGEFRIGHT], [libstagefright], [$codecs]) - ;; -+ *imxvpu*) -+ AC_CHECK_HEADER([imx-mm/vpu/vpu_wrapper.h],, AC_MSG_ERROR($missing_headers)) -+ AC_CHECK_LIB([vpu], main, LIBS="$LIBS -lfslvpuwrap -lvpu", AC_MSG_ERROR($missing_library)) -+ XB_ADD_CODEC([IMXVPU], [imxvpu], [$codecs]) -+ CXXFLAGS="$CXXFLAGS -Wno-psabi -DLINUX " -+ CFLAGS="$CFLAGS -DLINUX" -+ if test "$use_x11" = "no"; then -+ CXXFLAGS="$CXXFLAGS -DEGL_API_FB" -+ CFLAGS="$CFLAGS -DEGL_API_FB" -+ fi -+ ;; - *) - esac - done -diff --git a/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp b/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp -index 72eb725..8db4ea1 100644 ---- a/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp -+++ b/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp -@@ -79,6 +79,17 @@ static PFNEGLDESTROYIMAGEKHRPROC eglDestroyImageKHR; - static PFNGLEGLIMAGETARGETTEXTURE2DOESPROC glEGLImageTargetTexture2DOES; - #endif - -+#ifdef HAS_IMXVPU -+#include "windowing/egl/EGLWrapper.h" -+#include "DVDCodecs/Video/DVDVideoCodecIMX.h" -+ -+#define GL_VIV_NV12 0x8FC1 -+typedef void (GL_APIENTRYP PFNGLTEXDIRECTVIVMAPPROC) (GLenum Target, GLsizei Width, GLsizei Height, GLenum Format, GLvoid ** Logical, const GLuint * Physical); -+typedef void (GL_APIENTRYP PFNGLTEXDIRECTINVALIDATEVIVPROC) (GLenum Target); -+static PFNGLTEXDIRECTVIVMAPPROC glTexDirectVIVMap; -+static PFNGLTEXDIRECTINVALIDATEVIVPROC glTexDirectInvalidateVIV; -+#endif -+ - #if defined(TARGET_ANDROID) - #include "DVDCodecs/Video/DVDVideoCodecAndroidMediaCodec.h" - #endif -@@ -103,6 +114,9 @@ CLinuxRendererGLES::YUVBUFFER::YUVBUFFER() - #if defined(TARGET_ANDROID) - mediacodec = NULL; - #endif -+#ifdef HAS_IMXVPU -+ IMXBuffer = NULL; -+#endif - } - - CLinuxRendererGLES::YUVBUFFER::~YUVBUFFER() -@@ -153,6 +167,12 @@ CLinuxRendererGLES::CLinuxRendererGLES() - if (!glEGLImageTargetTexture2DOES) - glEGLImageTargetTexture2DOES = (PFNGLEGLIMAGETARGETTEXTURE2DOESPROC) CEGLWrapper::GetProcAddress("glEGLImageTargetTexture2DOES"); - #endif -+#ifdef HAS_IMXVPU -+ if (!glTexDirectVIVMap) -+ glTexDirectVIVMap = (PFNGLTEXDIRECTVIVMAPPROC) CEGLWrapper::GetProcAddress("glTexDirectVIVMap"); -+ if (!glTexDirectInvalidateVIV) -+ glTexDirectInvalidateVIV = (PFNGLTEXDIRECTINVALIDATEVIVPROC) CEGLWrapper::GetProcAddress("glTexDirectInvalidateVIV"); -+#endif - } - - CLinuxRendererGLES::~CLinuxRendererGLES() -@@ -279,6 +299,10 @@ int CLinuxRendererGLES::GetImage(YV12Image *image, int source, bool readonly) - { - return source; - } -+ if ( m_renderMethod & RENDER_IMXMAP ) -+ { -+ return source; -+ } - - #ifdef HAVE_VIDEOTOOLBOXDECODER - if (m_renderMethod & RENDER_CVREF ) -@@ -604,6 +628,9 @@ unsigned int CLinuxRendererGLES::PreInit() - #if defined(TARGET_ANDROID) - m_formats.push_back(RENDER_FMT_MEDIACODEC); - #endif -+#ifdef HAS_IMXVPU -+ m_formats.push_back(RENDER_FMT_IMXMAP); -+#endif - - // setup the background colour - m_clearColour = (float)(g_advancedSettings.m_videoBlackBarColour & 0xff) / 0xff; -@@ -711,6 +738,12 @@ void CLinuxRendererGLES::LoadShaders(int field) - m_renderMethod = RENDER_MEDIACODEC; - break; - } -+ else if (m_format == RENDER_FMT_IMXMAP) -+ { -+ CLog::Log(LOGNOTICE, "GL: Using IMXMAP render method"); -+ m_renderMethod = RENDER_IMXMAP; -+ break; -+ } - else if (m_format == RENDER_FMT_BYPASS) - { - CLog::Log(LOGNOTICE, "GL: Using BYPASS render method"); -@@ -803,6 +836,12 @@ void CLinuxRendererGLES::LoadShaders(int field) - m_textureCreate = &CLinuxRendererGLES::CreateNV12Texture; - m_textureDelete = &CLinuxRendererGLES::DeleteNV12Texture; - } -+ else if (m_format == RENDER_FMT_IMXMAP) -+ { -+ m_textureUpload = &CLinuxRendererGLES::UploadIMXMAPTexture; -+ m_textureCreate = &CLinuxRendererGLES::CreateIMXMAPTexture; -+ m_textureDelete = &CLinuxRendererGLES::DeleteIMXMAPTexture; -+ } - else - { - // default to YV12 texture handlers -@@ -893,6 +932,16 @@ void CLinuxRendererGLES::ReleaseBuffer(int idx) - } - } - #endif -+#ifdef HAS_IMXVPU -+ if (m_renderMethod & RENDER_IMXMAP) -+ { -+ if (buf.IMXBuffer) -+ { -+ SAFE_RELEASE(buf.IMXBuffer); -+ buf.IMXBuffer = NULL; -+ } -+ } -+#endif - } - - void CLinuxRendererGLES::Render(DWORD flags, int index) -@@ -954,6 +1003,10 @@ void CLinuxRendererGLES::Render(DWORD flags, int index) - { - RenderSurfaceTexture(index, m_currentField); - } -+ else if (m_renderMethod & RENDER_IMXMAP) -+ { -+ RenderIMXMAPTexture(index, m_currentField); -+ } - else - { - RenderSoftware(index, m_currentField); -@@ -1580,6 +1633,85 @@ void CLinuxRendererGLES::RenderCoreVideoRef(int index, int field) - #endif - } - -+void CLinuxRendererGLES::RenderIMXMAPTexture(int index, int field) -+{ -+#if defined(HAS_IMXVPU) -+#ifdef DEBUG_VERBOSE -+ unsigned int time = XbmcThreads::SystemClockMillis(); -+#endif -+ -+ YUVPLANE &plane = m_buffers[index].fields[field][0]; -+ CDVDVideoCodecIMXBuffer *buffer = m_buffers[index].IMXBuffer; -+ -+ if(buffer == NULL) return; -+ -+ CDVDVideoCodecIMX::Enter(); -+ -+ if(!buffer->IsValid()) -+ { -+ CDVDVideoCodecIMX::Leave(); -+ return; -+ } -+ -+ glDisable(GL_DEPTH_TEST); -+ -+ glActiveTexture(GL_TEXTURE0); -+ glBindTexture(m_textureTarget, plane.id); -+ -+ g_Windowing.EnableGUIShader(SM_TEXTURE_RGBA); -+ -+ GLubyte idx[4] = {0, 1, 3, 2}; //determines order of triangle strip -+ GLfloat ver[4][4]; -+ GLfloat tex[4][2]; -+ GLfloat col[3] = {1.0f, 1.0f, 1.0f}; -+ -+ GLint posLoc = g_Windowing.GUIShaderGetPos(); -+ GLint texLoc = g_Windowing.GUIShaderGetCoord0(); -+ GLint colLoc = g_Windowing.GUIShaderGetCol(); -+ -+ glVertexAttribPointer(posLoc, 4, GL_FLOAT, 0, 0, ver); -+ glVertexAttribPointer(texLoc, 2, GL_FLOAT, 0, 0, tex); -+ glVertexAttribPointer(colLoc, 3, GL_FLOAT, 0, 0, col); -+ -+ glEnableVertexAttribArray(posLoc); -+ glEnableVertexAttribArray(texLoc); -+ glEnableVertexAttribArray(colLoc); -+ -+ // Set vertex coordinates -+ for(int i = 0; i < 4; i++) -+ { -+ ver[i][0] = m_rotatedDestCoords[i].x; -+ ver[i][1] = m_rotatedDestCoords[i].y; -+ ver[i][2] = 0.0f;// set z to 0 -+ ver[i][3] = 1.0f; -+ } -+ -+ // Set texture coordinates -+ tex[0][0] = tex[3][0] = plane.rect.x1; -+ tex[0][1] = tex[1][1] = plane.rect.y1; -+ tex[1][0] = tex[2][0] = plane.rect.x2; -+ tex[2][1] = tex[3][1] = plane.rect.y2; -+ -+ glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_BYTE, idx); -+ -+ glDisableVertexAttribArray(posLoc); -+ glDisableVertexAttribArray(texLoc); -+ glDisableVertexAttribArray(colLoc); -+ -+ g_Windowing.DisableGUIShader(); -+ VerifyGLState(); -+ -+ glBindTexture(m_textureTarget, 0); -+ VerifyGLState(); -+ -+ CDVDVideoCodecIMX::Leave(); -+ -+#ifdef DEBUG_VERBOSE -+ CLog::Log(LOGDEBUG, "RenderIMXMAPTexture %d: tm:%d\n", index, XbmcThreads::SystemClockMillis() - time); -+#endif -+#endif -+} -+ - bool CLinuxRendererGLES::RenderCapture(CRenderCapture* capture) - { - if (!m_bValidated) -@@ -2510,6 +2642,96 @@ void CLinuxRendererGLES::SetTextureFilter(GLenum method) - } - } - -+//******************************************************************************************************** -+// IMXMAP creation, deletion, copying + clearing -+//******************************************************************************************************** -+void CLinuxRendererGLES::UploadIMXMAPTexture(int index) -+{ -+#ifdef HAS_IMXVPU -+ YUVBUFFER& buf = m_buffers[index]; -+ CDVDVideoCodecIMXBuffer* IMXBuffer = buf.IMXBuffer; -+ -+ if(IMXBuffer) -+ { -+ CDVDVideoCodecIMX::Enter(); -+ -+ if(!IMXBuffer->IsValid()) -+ { -+ CDVDVideoCodecIMX::Leave(); -+ return; -+ } -+ -+ YUVPLANE &plane = m_buffers[index].fields[0][0]; -+ -+ glActiveTexture(GL_TEXTURE0); -+ glBindTexture(m_textureTarget, plane.id); -+ -+ GLuint physical = ~0U; -+ GLvoid *virt = (GLvoid*)IMXBuffer->m_VirtAddr; -+ glTexDirectVIVMap(m_textureTarget, IMXBuffer->m_iWidth, IMXBuffer->m_iHeight, GL_VIV_NV12, -+ (GLvoid **)&virt, &physical); -+ glTexDirectInvalidateVIV(m_textureTarget); -+ -+ glBindTexture(m_textureTarget, 0); -+ -+ plane.flipindex = m_buffers[index].flipindex; -+ plane.texwidth = IMXBuffer->m_iWidth; -+ plane.texheight = IMXBuffer->m_iHeight; -+ -+ CalculateTextureSourceRects(index, 1); -+ -+ CDVDVideoCodecIMX::Leave(); -+ } -+#endif -+} -+ -+void CLinuxRendererGLES::DeleteIMXMAPTexture(int index) -+{ -+#ifdef HAS_IMXVPU -+ YUVBUFFER &buf = m_buffers[index]; -+ YUVPLANE &plane = buf.fields[0][0]; -+ -+ if(plane.id && glIsTexture(plane.id)) -+ glDeleteTextures(1, &plane.id); -+ plane.id = 0; -+ -+ SAFE_RELEASE(buf.IMXBuffer); -+#endif -+} -+ -+bool CLinuxRendererGLES::CreateIMXMAPTexture(int index) -+{ -+ YV12Image &im = m_buffers[index].image; -+ YUVFIELDS &fields = m_buffers[index].fields; -+ YUVPLANE &plane = fields[0][0]; -+ -+ DeleteEGLIMGTexture(index); -+ -+ memset(&im , 0, sizeof(im)); -+ memset(&fields, 0, sizeof(fields)); -+ -+ im.height = m_sourceHeight; -+ im.width = m_sourceWidth; -+ -+ plane.texwidth = 0; // Must be actual frame width for pseudo-cropping -+ plane.texheight = 0; // Must be actual frame height for pseudo-cropping -+ plane.pixpertex_x = 1; -+ plane.pixpertex_y = 1; -+ -+ glEnable(m_textureTarget); -+ glGenTextures(1, &plane.id); -+ VerifyGLState(); -+ -+ glBindTexture(m_textureTarget, plane.id); -+ -+ glTexParameteri(m_textureTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR); -+ glTexParameteri(m_textureTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR); -+ -+ glDisable(m_textureTarget); -+ return true; -+} -+ -+ - bool CLinuxRendererGLES::Supports(ERENDERFEATURE feature) - { - // Player controls render, let it dictate available render features -@@ -2576,6 +2798,9 @@ bool CLinuxRendererGLES::Supports(EDEINTERLACEMODE mode) - if(m_renderMethod & RENDER_CVREF) - return false; - -+ if(m_renderMethod & RENDER_IMXMAP) -+ return false; -+ - if(mode == VS_DEINTERLACEMODE_AUTO - || mode == VS_DEINTERLACEMODE_FORCE) - return true; -@@ -2604,6 +2829,9 @@ bool CLinuxRendererGLES::Supports(EINTERLACEMETHOD method) - if(m_renderMethod & RENDER_CVREF) - return false; - -+ if(m_renderMethod & RENDER_IMXMAP) -+ return false; -+ - if(method == VS_INTERLACEMETHOD_AUTO) - return true; - -@@ -2655,6 +2883,9 @@ EINTERLACEMETHOD CLinuxRendererGLES::AutoInterlaceMethod() - if(m_renderMethod & RENDER_CVREF) - return VS_INTERLACEMETHOD_NONE; - -+ if(m_renderMethod & RENDER_IMXMAP) -+ return VS_INTERLACEMETHOD_NONE; -+ - #if defined(__i386__) || defined(__x86_64__) - return VS_INTERLACEMETHOD_DEINTERLACE_HALF; - #else -@@ -2739,5 +2970,18 @@ void CLinuxRendererGLES::AddProcessor(CDVDMediaCodecInfo *mediacodec, int index) - } - #endif - -+#ifdef HAS_IMXVPU -+void CLinuxRendererGLES::AddProcessor(CDVDVideoCodecIMXBuffer *buffer, int index) -+{ -+ YUVBUFFER &buf = m_buffers[index]; -+ -+ SAFE_RELEASE(buf.IMXBuffer); -+ buf.IMXBuffer = buffer; -+ -+ if (buffer) -+ buffer->Lock(); -+} -+#endif -+ - #endif - -diff --git a/xbmc/cores/VideoRenderers/LinuxRendererGLES.h b/xbmc/cores/VideoRenderers/LinuxRendererGLES.h -index 642cded..1e89ecf 100644 ---- a/xbmc/cores/VideoRenderers/LinuxRendererGLES.h -+++ b/xbmc/cores/VideoRenderers/LinuxRendererGLES.h -@@ -89,7 +89,8 @@ enum RenderMethod - RENDER_CVREF = 0x080, - RENDER_BYPASS = 0x100, - RENDER_EGLIMG = 0x200, -- RENDER_MEDIACODEC = 0x400 -+ RENDER_MEDIACODEC = 0x400, -+ RENDER_IMXMAP = 0x800 - }; - - enum RenderQuality -@@ -170,6 +171,9 @@ class CLinuxRendererGLES : public CBaseRenderer - // mediaCodec - virtual void AddProcessor(CDVDMediaCodecInfo *mediacodec, int index); - #endif -+#ifdef HAS_IMXVPU -+ virtual void AddProcessor(CDVDVideoCodecIMXBuffer *codecinfo, int index); -+#endif - - protected: - virtual void Render(DWORD flags, int index); -@@ -209,6 +213,10 @@ class CLinuxRendererGLES : public CBaseRenderer - void DeleteSurfaceTexture(int index); - bool CreateSurfaceTexture(int index); - -+ void UploadIMXMAPTexture(int index); -+ void DeleteIMXMAPTexture(int index); -+ bool CreateIMXMAPTexture(int index); -+ - void CalculateTextureSourceRects(int source, int num_planes); - - // renderers -@@ -219,6 +227,7 @@ class CLinuxRendererGLES : public CBaseRenderer - void RenderEglImage(int index, int field); // Android OES texture - void RenderCoreVideoRef(int index, int field); // CoreVideo reference - void RenderSurfaceTexture(int index, int field);// MediaCodec rendering using SurfaceTexture -+ void RenderIMXMAPTexture(int index, int field); // IMXMAP rendering - - CFrameBufferObject m_fbo; - -@@ -285,6 +294,9 @@ class CLinuxRendererGLES : public CBaseRenderer - // mediacodec - CDVDMediaCodecInfo *mediacodec; - #endif -+#ifdef HAS_IMXVPU -+ CDVDVideoCodecIMXBuffer *IMXBuffer; -+#endif - }; - - typedef YUVBUFFER YUVBUFFERS[NUM_BUFFERS]; -diff --git a/xbmc/cores/VideoRenderers/RenderFormats.h b/xbmc/cores/VideoRenderers/RenderFormats.h -index f15e80d..a8b8bd0 100644 ---- a/xbmc/cores/VideoRenderers/RenderFormats.h -+++ b/xbmc/cores/VideoRenderers/RenderFormats.h -@@ -37,6 +37,7 @@ enum ERenderFormat { - RENDER_FMT_BYPASS, - RENDER_FMT_EGLIMG, - RENDER_FMT_MEDIACODEC, -+ RENDER_FMT_IMXMAP, - }; - - #endif -diff --git a/xbmc/cores/VideoRenderers/RenderManager.cpp b/xbmc/cores/VideoRenderers/RenderManager.cpp -index b6fb1a3..101d1c7 100644 ---- a/xbmc/cores/VideoRenderers/RenderManager.cpp -+++ b/xbmc/cores/VideoRenderers/RenderManager.cpp -@@ -932,6 +932,10 @@ int CXBMCRenderManager::AddVideoPicture(DVDVideoPicture& pic) - else if(pic.format == RENDER_FMT_MEDIACODEC) - m_pRenderer->AddProcessor(pic.mediacodec, index); - #endif -+#ifdef HAS_IMXVPU -+ else if(pic.format == RENDER_FMT_IMXMAP) -+ m_pRenderer->AddProcessor(pic.IMXBuffer, index); -+#endif - - m_pRenderer->ReleaseImage(index, false); - -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.cpp b/xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.cpp -index 181d755..f8a5635 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.cpp -+++ b/xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.cpp -@@ -36,6 +36,9 @@ - #include "Video/DVDVideoCodecFFmpeg.h" - #include "Video/DVDVideoCodecOpenMax.h" - #include "Video/DVDVideoCodecLibMpeg2.h" -+#if defined(HAS_IMXVPU) -+#include "Video/DVDVideoCodecIMX.h" -+#endif - #include "Video/DVDVideoCodecStageFright.h" - #if defined(HAS_LIBAMCODEC) - #include "utils/AMLUtils.h" -@@ -181,7 +184,11 @@ CDVDVideoCodec* CDVDFactoryCodec::CreateVideoCodec(CDVDStreamInfo &hint, unsigne - #elif defined(TARGET_POSIX) && !defined(TARGET_DARWIN) - hwSupport += "VAAPI:no "; - #endif -- -+#if defined(HAS_IMXVPU) -+ hwSupport += "iMXVPU:yes "; -+#else -+ hwSupport += "iMXVPU:no "; -+#endif - CLog::Log(LOGDEBUG, "CDVDFactoryCodec: compiled in hardware support: %s", hwSupport.c_str()); - - if (hint.stills && (hint.codec == AV_CODEC_ID_MPEG2VIDEO || hint.codec == AV_CODEC_ID_MPEG1VIDEO)) -@@ -198,6 +205,13 @@ CDVDVideoCodec* CDVDFactoryCodec::CreateVideoCodec(CDVDStreamInfo &hint, unsigne - } - #endif - -+#if defined(HAS_IMXVPU) -+ if (!hint.software) -+ { -+ if ( (pCodec = OpenCodec(new CDVDVideoCodecIMX(), hint, options)) ) return pCodec; -+ } -+#endif -+ - #if defined(TARGET_DARWIN_OSX) - if (!hint.software && CSettings::Get().GetBool("videoplayer.usevda")) - { -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h -index 741017d..e73b917 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h -@@ -26,6 +26,8 @@ - #include - #include "cores/VideoRenderers/RenderFormats.h" - -+ -+ - extern "C" { - #include "libavcodec/avcodec.h" - } -@@ -53,6 +55,7 @@ class COpenMaxVideo; - struct OpenMaxVideoBuffer; - class CDVDVideoCodecStageFright; - class CDVDMediaCodecInfo; -+class CDVDVideoCodecIMXBuffer; - typedef void* EGLImageKHR; - - -@@ -95,6 +98,11 @@ struct DVDVideoPicture - struct { - CDVDMediaCodecInfo *mediacodec; - }; -+ -+ struct { -+ CDVDVideoCodecIMXBuffer *IMXBuffer; -+ }; -+ - }; - - unsigned int iFlags; -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp -new file mode 100644 -index 0000000..adbb27e ---- /dev/null -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp -@@ -0,0 +1,1083 @@ -+/* -+ * Copyright (C) 2010-2013 Team XBMC -+ * http://www.xbmc.org -+ * -+ * This Program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2, or (at your option) -+ * any later version. -+ * -+ * This Program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with XBMC; see the file COPYING. If not, see -+ * . -+ * -+ */ -+ -+#include "DVDVideoCodecIMX.h" -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include "threads/SingleLock.h" -+#include "utils/log.h" -+#include "DVDClock.h" -+#include "threads/Atomics.h" -+ -+#define FRAME_ALIGN 16 -+#define MEDIAINFO 1 -+#define _4CC(c1,c2,c3,c4) (((uint32_t)(c4)<<24)|((uint32_t)(c3)<<16)|((uint32_t)(c2)<<8)|(uint32_t)(c1)) -+#define Align(ptr,align) (((unsigned int)ptr + (align) - 1)/(align)*(align)) -+ -+// Experiments show that we need at least one more (+1) VPU buffer than the min value returned by the VPU -+const int CDVDVideoCodecIMX::m_extraVpuBuffers = 6; -+const int CDVDVideoCodecIMX::m_maxVpuDecodeLoops = 5; -+CCriticalSection CDVDVideoCodecIMX::m_codecBufferLock; -+ -+bool CDVDVideoCodecIMX::VpuAllocBuffers(VpuMemInfo *pMemBlock) -+{ -+ int i, size; -+ void* ptr; -+ VpuMemDesc vpuMem; -+ VpuDecRetCode ret; -+ -+ for(i=0; inSubBlockNum; i++) -+ { -+ size = pMemBlock->MemSubBlock[i].nAlignment + pMemBlock->MemSubBlock[i].nSize; -+ if (pMemBlock->MemSubBlock[i].MemType == VPU_MEM_VIRT) -+ { // Allocate standard virtual memory -+ ptr = malloc(size); -+ if(ptr == NULL) -+ { -+ CLog::Log(LOGERROR, "%s - Unable to malloc %d bytes.\n", __FUNCTION__, size); -+ goto AllocFailure; -+ } -+ pMemBlock->MemSubBlock[i].pVirtAddr = (unsigned char*)Align(ptr, pMemBlock->MemSubBlock[i].nAlignment); -+ -+ m_decMemInfo.nVirtNum++; -+ m_decMemInfo.virtMem = (void**)realloc(m_decMemInfo.virtMem, m_decMemInfo.nVirtNum*sizeof(void*)); -+ m_decMemInfo.virtMem[m_decMemInfo.nVirtNum-1] = ptr; -+ } -+ else -+ { // Allocate contigous mem for DMA -+ vpuMem.nSize = size; -+ ret = VPU_DecGetMem(&vpuMem); -+ if(ret != VPU_DEC_RET_SUCCESS) -+ { -+ CLog::Log(LOGERROR, "%s - Unable alloc %d bytes of physical memory (%d).\n", __FUNCTION__, size, ret); -+ goto AllocFailure; -+ } -+ pMemBlock->MemSubBlock[i].pVirtAddr = (unsigned char*)Align(vpuMem.nVirtAddr, pMemBlock->MemSubBlock[i].nAlignment); -+ pMemBlock->MemSubBlock[i].pPhyAddr = (unsigned char*)Align(vpuMem.nPhyAddr, pMemBlock->MemSubBlock[i].nAlignment); -+ -+ m_decMemInfo.nPhyNum++; -+ m_decMemInfo.phyMem = (VpuMemDesc*)realloc(m_decMemInfo.phyMem, m_decMemInfo.nPhyNum*sizeof(VpuMemDesc)); -+ m_decMemInfo.phyMem[m_decMemInfo.nPhyNum-1].nPhyAddr = vpuMem.nPhyAddr; -+ m_decMemInfo.phyMem[m_decMemInfo.nPhyNum-1].nVirtAddr = vpuMem.nVirtAddr; -+ m_decMemInfo.phyMem[m_decMemInfo.nPhyNum-1].nCpuAddr = vpuMem.nCpuAddr; -+ m_decMemInfo.phyMem[m_decMemInfo.nPhyNum-1].nSize = size; -+ } -+ } -+ -+ return true; -+ -+AllocFailure: -+ VpuFreeBuffers(); -+ return false; -+} -+ -+int CDVDVideoCodecIMX::VpuFindBuffer(void *frameAddr) -+{ -+ for (int i=0; i1) -+ { -+ ySize=Align(ySize,nAlign); -+ uvSize=Align(uvSize,nAlign); -+ } -+ -+ m_outputBuffers = new CDVDVideoCodecIMXBuffer*[m_vpuFrameBufferNum]; -+ -+ for (int i=0 ; i < m_vpuFrameBufferNum; i++) -+ { -+ totalSize=(ySize+uvSize+mvSize+nAlign)*1; -+ -+ vpuMem.nSize=totalSize; -+ ret = VPU_DecGetMem(&vpuMem); -+ if(ret != VPU_DEC_RET_SUCCESS) -+ { -+ CLog::Log(LOGERROR, "%s: vpu malloc frame buf failure: ret=%d \r\n",__FUNCTION__,ret); -+ return false; -+ } -+ -+ //record memory info for release -+ m_decMemInfo.nPhyNum++; -+ m_decMemInfo.phyMem = (VpuMemDesc*)realloc(m_decMemInfo.phyMem, m_decMemInfo.nPhyNum*sizeof(VpuMemDesc)); -+ m_decMemInfo.phyMem[m_decMemInfo.nPhyNum-1].nPhyAddr = vpuMem.nPhyAddr; -+ m_decMemInfo.phyMem[m_decMemInfo.nPhyNum-1].nVirtAddr = vpuMem.nVirtAddr; -+ m_decMemInfo.phyMem[m_decMemInfo.nPhyNum-1].nCpuAddr = vpuMem.nCpuAddr; -+ m_decMemInfo.phyMem[m_decMemInfo.nPhyNum-1].nSize = vpuMem.nSize; -+ -+ //fill frameBuf -+ ptr=(unsigned char*)vpuMem.nPhyAddr; -+ ptrVirt=(unsigned char*)vpuMem.nVirtAddr; -+ -+ //align the base address -+ if(nAlign>1) -+ { -+ ptr=(unsigned char*)Align(ptr,nAlign); -+ ptrVirt=(unsigned char*)Align(ptrVirt,nAlign); -+ } -+ -+ // fill stride info -+ m_vpuFrameBuffers[i].nStrideY=yStride; -+ m_vpuFrameBuffers[i].nStrideC=uvStride; -+ -+ // fill phy addr -+ m_vpuFrameBuffers[i].pbufY=ptr; -+ m_vpuFrameBuffers[i].pbufCb=ptr+ySize; -+ m_vpuFrameBuffers[i].pbufCr=0; -+ m_vpuFrameBuffers[i].pbufMvCol=ptr+ySize+uvSize; -+ -+ // fill virt addr -+ m_vpuFrameBuffers[i].pbufVirtY=ptrVirt; -+ m_vpuFrameBuffers[i].pbufVirtCb=ptrVirt+ySize; -+ m_vpuFrameBuffers[i].pbufVirtCr=0; -+ m_vpuFrameBuffers[i].pbufVirtMvCol=ptrVirt+ySize+uvSize; -+ -+ m_vpuFrameBuffers[i].pbufY_tilebot=0; -+ m_vpuFrameBuffers[i].pbufCb_tilebot=0; -+ m_vpuFrameBuffers[i].pbufVirtY_tilebot=0; -+ m_vpuFrameBuffers[i].pbufVirtCb_tilebot=0; -+ -+#ifdef TRACE_FRAMES -+ m_outputBuffers[i] = new CDVDVideoCodecIMXBuffer(i); -+#else -+ m_outputBuffers[i] = new CDVDVideoCodecIMXBuffer(); -+#endif -+ } -+ -+ return true; -+} -+ -+CDVDVideoCodecIMX::CDVDVideoCodecIMX() -+{ -+ m_pFormatName = "iMX-xxx"; -+ m_vpuHandle = 0; -+ m_vpuFrameBuffers = NULL; -+ m_outputBuffers = NULL; -+ m_lastBuffer = NULL; -+ m_extraMem = NULL; -+ m_vpuFrameBufferNum = 0; -+ m_dropState = false; -+ m_convert_bitstream = false; -+ m_frameCounter = 0; -+ m_usePTS = true; -+ if (getenv("IMX_NOPTS") != NULL) -+ { -+ m_usePTS = false; -+ } -+ m_converter = NULL; -+ m_convert_bitstream = false; -+ m_bytesToBeConsumed = 0; -+ m_previousPts = DVD_NOPTS_VALUE; -+} -+ -+CDVDVideoCodecIMX::~CDVDVideoCodecIMX() -+{ -+ Dispose(); -+} -+ -+bool CDVDVideoCodecIMX::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options) -+{ -+ if (hints.software) -+ { -+ CLog::Log(LOGNOTICE, "iMX VPU : software decoding requested.\n"); -+ return false; -+ } -+ -+ m_hints = hints; -+ CLog::Log(LOGDEBUG, "Let's decode with iMX VPU\n"); -+ -+#ifdef MEDIAINFO -+ CLog::Log(LOGDEBUG, "Decode: MEDIAINFO: fpsrate %d / fpsscale %d\n", m_hints.fpsrate, m_hints.fpsscale); -+ CLog::Log(LOGDEBUG, "Decode: MEDIAINFO: CodecID %d \n", m_hints.codec); -+ CLog::Log(LOGDEBUG, "Decode: MEDIAINFO: StreamType %d \n", m_hints.type); -+ CLog::Log(LOGDEBUG, "Decode: MEDIAINFO: Level %d \n", m_hints.level); -+ CLog::Log(LOGDEBUG, "Decode: MEDIAINFO: Profile %d \n", m_hints.profile); -+ CLog::Log(LOGDEBUG, "Decode: MEDIAINFO: PTS_invalid %d \n", m_hints.ptsinvalid); -+ CLog::Log(LOGDEBUG, "Decode: MEDIAINFO: Tag %d \n", m_hints.codec_tag); -+ CLog::Log(LOGDEBUG, "Decode: MEDIAINFO: %dx%d \n", m_hints.width, m_hints.height); -+ { uint8_t *pb = (uint8_t*)&m_hints.codec_tag; -+ if (isalnum(pb[0]) && isalnum(pb[1]) && isalnum(pb[2]) && isalnum(pb[3])) -+ CLog::Log(LOGDEBUG, "Decode: MEDIAINFO: Tag fourcc %c%c%c%c\n", pb[0], pb[1], pb[2], pb[3]); -+ } -+ if (m_hints.extrasize) -+ { -+ char buf[4096]; -+ -+ for (unsigned int i=0; i < m_hints.extrasize; i++) -+ sprintf(buf+i*2, "%02x", ((uint8_t*)m_hints.extradata)[i]); -+ CLog::Log(LOGDEBUG, "Decode: MEDIAINFO: extradata %d %s\n", m_hints.extrasize, buf); -+ } -+ CLog::Log(LOGDEBUG, "Decode: MEDIAINFO: %d / %d \n", m_hints.width, m_hints.height); -+ CLog::Log(LOGDEBUG, "Decode: aspect %f - forced aspect %d\n", m_hints.aspect, m_hints.forced_aspect); -+#endif -+ -+ m_convert_bitstream = false; -+ switch(m_hints.codec) -+ { -+ case CODEC_ID_MPEG1VIDEO: -+ m_decOpenParam.CodecFormat = VPU_V_MPEG2; -+ m_pFormatName = "iMX-mpeg1"; -+ break; -+ case CODEC_ID_MPEG2VIDEO: -+ case CODEC_ID_MPEG2VIDEO_XVMC: -+ m_decOpenParam.CodecFormat = VPU_V_MPEG2; -+ m_pFormatName = "iMX-mpeg2"; -+ break; -+ case CODEC_ID_H263: -+ m_decOpenParam.CodecFormat = VPU_V_H263; -+ m_pFormatName = "iMX-h263"; -+ break; -+ case CODEC_ID_H264: -+ if (m_hints.profile == 110) -+ { -+ CLog::Log(LOGNOTICE, "i.MX6 VPU is not able to decode AVC high 10 profile\n"); -+ return false; -+ } -+ m_decOpenParam.CodecFormat = VPU_V_AVC; -+ m_pFormatName = "iMX-h264"; -+ if (hints.extradata) -+ { -+ if ( *(char*)hints.extradata == 1 ) -+ { -+ m_converter = new CBitstreamConverter(); -+ m_convert_bitstream = m_converter->Open(hints.codec, (uint8_t *)hints.extradata, hints.extrasize, true); -+ } -+ } -+ break; -+ case CODEC_ID_VC1: -+ m_decOpenParam.CodecFormat = VPU_V_VC1_AP; -+ m_pFormatName = "iMX-vc1"; -+ break; -+ case CODEC_ID_CAVS: -+ case CODEC_ID_AVS: -+ m_decOpenParam.CodecFormat = VPU_V_AVS; -+ m_pFormatName = "iMX-AVS"; -+ break; -+ case CODEC_ID_RV10: -+ case CODEC_ID_RV20: -+ case CODEC_ID_RV30: -+ case CODEC_ID_RV40: -+ m_decOpenParam.CodecFormat = VPU_V_RV; -+ m_pFormatName = "iMX-RV"; -+ break; -+ case CODEC_ID_KMVC: -+ m_decOpenParam.CodecFormat = VPU_V_AVC_MVC; -+ m_pFormatName = "iMX-MVC"; -+ break; -+ case CODEC_ID_VP8: -+ m_decOpenParam.CodecFormat = VPU_V_VP8; -+ m_pFormatName = "iMX-vp8"; -+ break; -+ case CODEC_ID_MPEG4: -+ switch(m_hints.codec_tag) -+ { -+ case _4CC('D','I','V','X'): -+ m_decOpenParam.CodecFormat = VPU_V_XVID; // VPU_V_DIVX4 -+ m_pFormatName = "iMX-divx4"; -+ break; -+ case _4CC('D','X','5','0'): -+ case _4CC('D','I','V','5'): -+ m_decOpenParam.CodecFormat = VPU_V_XVID; // VPU_V_DIVX56 -+ m_pFormatName = "iMX-divx5"; -+ break; -+ case _4CC('X','V','I','D'): -+ case _4CC('M','P','4','V'): -+ case _4CC('P','M','P','4'): -+ case _4CC('F','M','P','4'): -+ m_decOpenParam.CodecFormat = VPU_V_XVID; -+ m_pFormatName = "iMX-xvid"; -+ break; -+ default: -+ CLog::Log(LOGERROR, "iMX VPU : MPEG4 codec tag %d is not (yet) handled.\n", m_hints.codec_tag); -+ return false; -+ } -+ break; -+ default: -+ CLog::Log(LOGERROR, "iMX VPU : codecid %d is not (yet) handled.\n", m_hints.codec); -+ return false; -+ } -+ -+ return true; -+} -+ -+void CDVDVideoCodecIMX::Dispose(void) -+{ -+ VpuDecRetCode ret; -+ bool VPU_loaded = m_vpuHandle; -+ -+ // Prevent rendering thread from using frame buffers -+ Enter(); -+ -+ // Release last buffer -+ if(m_lastBuffer) -+ SAFE_RELEASE(m_lastBuffer); -+ -+ // Invalidate output buffers to prevent the renderer from mapping this memory -+ for (int i=0; iReleaseFramebuffer(&m_vpuHandle); -+ SAFE_RELEASE(m_outputBuffers[i]); -+ } -+ -+ Leave(); -+ -+ if (m_vpuHandle) -+ { -+ ret = VPU_DecFlushAll(m_vpuHandle); -+ if (ret != VPU_DEC_RET_SUCCESS) -+ { -+ CLog::Log(LOGERROR, "%s - VPU flush failed with error code %d.\n", __FUNCTION__, ret); -+ } -+ ret = VPU_DecClose(m_vpuHandle); -+ if (ret != VPU_DEC_RET_SUCCESS) -+ { -+ CLog::Log(LOGERROR, "%s - VPU close failed with error code %d.\n", __FUNCTION__, ret); -+ } -+ m_vpuHandle = 0; -+ } -+ -+ m_frameCounter = 0; -+ -+ // Release memory -+ if (m_outputBuffers != NULL) -+ { -+ delete m_outputBuffers; -+ m_outputBuffers = NULL; -+ } -+ -+ VpuFreeBuffers(); -+ m_vpuFrameBufferNum = 0; -+ -+ if (m_vpuFrameBuffers != NULL) -+ { -+ delete m_vpuFrameBuffers; -+ m_vpuFrameBuffers = NULL; -+ } -+ -+ if (VPU_loaded) -+ { -+ ret = VPU_DecUnLoad(); -+ if (ret != VPU_DEC_RET_SUCCESS) -+ { -+ CLog::Log(LOGERROR, "%s - VPU unload failed with error code %d.\n", __FUNCTION__, ret); -+ } -+ } -+ -+ if (m_converter) -+ { -+ m_converter->Close(); -+ SAFE_DELETE(m_converter); -+ } -+ return; -+} -+ -+int CDVDVideoCodecIMX::Decode(BYTE *pData, int iSize, double dts, double pts) -+{ -+ VpuDecFrameLengthInfo frameLengthInfo; -+ VpuBufferNode inData; -+ VpuDecRetCode ret; -+ int decRet = 0; -+ int retStatus = 0; -+ int demuxer_bytes = iSize; -+ uint8_t *demuxer_content = pData; -+ int retries = 0; -+ int idx; -+ -+#ifdef IMX_PROFILE -+ static unsigned long long previous, current; -+ unsigned long long before_dec; -+#endif -+ -+ if (!m_vpuHandle) -+ { -+ VpuOpen(); -+ if (!m_vpuHandle) -+ return VC_ERROR; -+ } -+ -+ for (int i=0; i < m_vpuFrameBufferNum; i++) -+ { -+ if (m_outputBuffers[i]->Rendered()) -+ { -+ ret = m_outputBuffers[i]->ReleaseFramebuffer(&m_vpuHandle); -+ if(ret != VPU_DEC_RET_SUCCESS) -+ { -+ CLog::Log(LOGERROR, "%s: vpu clear frame display failure: ret=%d \r\n",__FUNCTION__,ret); -+ } -+ } -+ } -+ -+#ifdef IMX_PROFILE -+ current = XbmcThreads::SystemClockMillis(); -+ CLog::Log(LOGDEBUG, "%s - delta time decode : %llu - demux size : %d dts : %f - pts : %f\n", __FUNCTION__, current - previous, iSize, dts, pts); -+ previous = current; -+#endif -+ -+ if ((pData && iSize) || -+ (m_bytesToBeConsumed)) -+ { -+ if ((m_convert_bitstream) && (iSize)) -+ { -+ // convert demuxer packet from bitstream to bytestream (AnnexB) -+ if (m_converter->Convert(demuxer_content, demuxer_bytes)) -+ { -+ demuxer_content = m_converter->GetConvertBuffer(); -+ demuxer_bytes = m_converter->GetConvertSize(); -+ } -+ else -+ CLog::Log(LOGERROR,"%s - bitstream_convert error", __FUNCTION__); -+ } -+ -+ inData.nSize = demuxer_bytes; -+ inData.pPhyAddr = NULL; -+ inData.pVirAddr = demuxer_content; -+ if ((m_decOpenParam.CodecFormat == VPU_V_MPEG2) || -+ (m_decOpenParam.CodecFormat == VPU_V_VC1_AP)|| -+ (m_decOpenParam.CodecFormat == VPU_V_XVID)) -+ { -+ inData.sCodecData.pData = (unsigned char *)m_hints.extradata; -+ inData.sCodecData.nSize = m_hints.extrasize; -+ } -+ else -+ { -+ inData.sCodecData.pData = NULL; -+ inData.sCodecData.nSize = 0; -+ } -+ -+ while (true) // Decode as long as the VPU consumes data -+ { -+#ifdef IMX_PROFILE -+ before_dec = XbmcThreads::SystemClockMillis(); -+#endif -+ if (m_frameReported) -+ m_bytesToBeConsumed += inData.nSize; -+ ret = VPU_DecDecodeBuf(m_vpuHandle, &inData, &decRet); -+#ifdef IMX_PROFILE -+ CLog::Log(LOGDEBUG, "%s - VPU dec 0x%x decode takes : %lld\n\n", __FUNCTION__, decRet, XbmcThreads::SystemClockMillis() - before_dec); -+#endif -+ -+ if (ret != VPU_DEC_RET_SUCCESS) -+ { -+ CLog::Log(LOGERROR, "%s - VPU decode failed with error code %d.\n", __FUNCTION__, ret); -+ goto out_error; -+ } -+ -+ if (decRet & VPU_DEC_INIT_OK) -+ // VPU decoding init OK : We can retrieve stream info -+ { -+ ret = VPU_DecGetInitialInfo(m_vpuHandle, &m_initInfo); -+ if (ret == VPU_DEC_RET_SUCCESS) -+ { -+ CLog::Log(LOGDEBUG, "%s - VPU Init Stream Info : %dx%d (interlaced : %d - Minframe : %d)"\ -+ " - Align : %d bytes - crop : %d %d %d %d - Q16Ratio : %x\n", __FUNCTION__, -+ m_initInfo.nPicWidth, m_initInfo.nPicHeight, m_initInfo.nInterlace, m_initInfo.nMinFrameBufferCount, -+ m_initInfo.nAddressAlignment, m_initInfo.PicCropRect.nLeft, m_initInfo.PicCropRect.nTop, -+ m_initInfo.PicCropRect.nRight, m_initInfo.PicCropRect.nBottom, m_initInfo.nQ16ShiftWidthDivHeightRatio); -+ if (VpuAllocFrameBuffers()) -+ { -+ ret = VPU_DecRegisterFrameBuffer(m_vpuHandle, m_vpuFrameBuffers, m_vpuFrameBufferNum); -+ if (ret != VPU_DEC_RET_SUCCESS) -+ { -+ CLog::Log(LOGERROR, "%s - VPU error while registering frame buffers (%d).\n", __FUNCTION__, ret); -+ goto out_error; -+ } -+ } -+ else -+ { -+ goto out_error; -+ } -+ } -+ else -+ { -+ CLog::Log(LOGERROR, "%s - VPU get initial info failed (%d).\n", __FUNCTION__, ret); -+ goto out_error; -+ } -+ } //VPU_DEC_INIT_OK -+ -+ if (decRet & VPU_DEC_ONE_FRM_CONSUMED) -+ { -+ ret = VPU_DecGetConsumedFrameInfo(m_vpuHandle, &frameLengthInfo); -+ if (ret != VPU_DEC_RET_SUCCESS) -+ { -+ CLog::Log(LOGERROR, "%s - VPU error retireving info about consummed frame (%d).\n", __FUNCTION__, ret); -+ } -+ m_bytesToBeConsumed -= (frameLengthInfo.nFrameLength + frameLengthInfo.nStuffLength); -+ if (frameLengthInfo.pFrame) -+ { -+ idx = VpuFindBuffer(frameLengthInfo.pFrame->pbufY); -+ if (m_bytesToBeConsumed < 50) -+ m_bytesToBeConsumed = 0; -+ if (idx != -1) -+ { -+ if (m_previousPts != DVD_NOPTS_VALUE) -+ { -+ m_outputBuffers[idx]->SetPts(m_previousPts); -+ m_previousPts = DVD_NOPTS_VALUE; -+ } -+ else -+ m_outputBuffers[idx]->SetPts(pts); -+ } -+ else -+ CLog::Log(LOGERROR, "%s - could not find frame buffer\n", __FUNCTION__); -+ } -+ } //VPU_DEC_ONE_FRM_CONSUMED -+ -+ if (decRet & VPU_DEC_OUTPUT_DIS) -+ // Frame ready to be displayed -+ { -+ if (retStatus & VC_PICTURE) -+ CLog::Log(LOGERROR, "%s - Second picture in the same decode call !\n", __FUNCTION__); -+ -+ ret = VPU_DecGetOutputFrame(m_vpuHandle, &m_frameInfo); -+ if(ret != VPU_DEC_RET_SUCCESS) -+ { -+ CLog::Log(LOGERROR, "%s - VPU Cannot get output frame(%d).\n", __FUNCTION__, ret); -+ goto out_error; -+ } -+ -+ // Some codecs (VC1?) lie about their frame size (mod 16). Adjust... -+ m_frameInfo.pExtInfo->nFrmWidth = (((m_frameInfo.pExtInfo->nFrmWidth) + 15) & ~15); -+ m_frameInfo.pExtInfo->nFrmHeight = (((m_frameInfo.pExtInfo->nFrmHeight) + 15) & ~15); -+ -+ retStatus |= VC_PICTURE; -+ } //VPU_DEC_OUTPUT_DIS -+ -+ // According to libfslvpuwrap: If this flag is set then the frame should -+ // be dropped. It is just returned to gather decoder information but not -+ // for display. -+ if (decRet & VPU_DEC_OUTPUT_MOSAIC_DIS) -+ { -+ ret = VPU_DecGetOutputFrame(m_vpuHandle, &m_frameInfo); -+ if(ret != VPU_DEC_RET_SUCCESS) -+ { -+ CLog::Log(LOGERROR, "%s - VPU Cannot get output frame(%d).\n", __FUNCTION__, ret); -+ goto out_error; -+ } -+ -+ // Display frame -+ ret = VPU_DecOutFrameDisplayed(m_vpuHandle, m_frameInfo.pDisplayFrameBuf); -+ if(ret != VPU_DEC_RET_SUCCESS) -+ { -+ CLog::Log(LOGERROR, "%s: VPU Clear frame display failure(%d)\n",__FUNCTION__,ret); -+ goto out_error; -+ } -+ } //VPU_DEC_OUTPUT_MOSAIC_DIS -+ -+ if (decRet & VPU_DEC_OUTPUT_REPEAT) -+ { -+ CLog::Log(LOGDEBUG, "%s - Frame repeat.\n", __FUNCTION__); -+ } -+ if (decRet & VPU_DEC_OUTPUT_DROPPED) -+ { -+ CLog::Log(LOGDEBUG, "%s - Frame dropped.\n", __FUNCTION__); -+ } -+ if (decRet & VPU_DEC_NO_ENOUGH_BUF) -+ { -+ CLog::Log(LOGERROR, "%s - No frame buffer available.\n", __FUNCTION__); -+ } -+ if (decRet & VPU_DEC_SKIP) -+ { -+ CLog::Log(LOGDEBUG, "%s - Frame skipped.\n", __FUNCTION__); -+ } -+ if (decRet & VPU_DEC_FLUSH) -+ { -+ CLog::Log(LOGNOTICE, "%s - VPU requires a flush.\n", __FUNCTION__); -+ Reset(); -+ retStatus = VC_FLUSHED; -+ } -+ if (decRet & VPU_DEC_OUTPUT_EOS) -+ { -+ CLog::Log(LOGNOTICE, "%s - EOS encountered.\n", __FUNCTION__); -+ } -+ if ((decRet & VPU_DEC_NO_ENOUGH_INBUF) || -+ (decRet & VPU_DEC_OUTPUT_DIS)) -+ { -+ // We are done with VPU decoder that time -+ break; -+ } -+ -+ retries++; -+ if (retries >= m_maxVpuDecodeLoops) -+ { -+ CLog::Log(LOGERROR, "%s - Leaving VPU decoding loop after %d iterations\n", __FUNCTION__, m_maxVpuDecodeLoops); -+ break; -+ } -+ -+ if (!(decRet & VPU_DEC_INPUT_USED)) -+ { -+ CLog::Log(LOGERROR, "%s - input not used : addr %p size :%d!\n", __FUNCTION__, inData.pVirAddr, inData.nSize); -+ } -+ -+ // Let's process again as VPU_DEC_NO_ENOUGH_INBUF was not set -+ // and we don't have an image ready if we reach that point -+ inData.pVirAddr = NULL; -+ inData.nSize = 0; -+ } // Decode loop -+ } //(pData && iSize) -+ -+ if (retStatus == 0) -+ { -+ retStatus |= VC_BUFFER; -+ } -+ -+ if (m_bytesToBeConsumed > 0) -+ { -+ // Remember the current pts because the data which has just -+ // been sent to the VPU has not yet been consumed. -+ // This pts is related to the frame that will be consumed -+ // at next call... -+ m_previousPts = pts; -+ } -+ // Store current dts (will be used only if VC_PICTURE is set) -+ m_dts = dts; -+ -+#ifdef IMX_PROFILE -+ CLog::Log(LOGDEBUG, "%s - returns %x - duration %lld\n", __FUNCTION__, retStatus, XbmcThreads::SystemClockMillis() - previous); -+#endif -+ return retStatus; -+ -+out_error: -+ return VC_ERROR; -+} -+ -+void CDVDVideoCodecIMX::Reset() -+{ -+ int ret; -+ -+ CLog::Log(LOGDEBUG, "%s - called\n", __FUNCTION__); -+ -+ // Release last buffer -+ if(m_lastBuffer) -+ SAFE_RELEASE(m_lastBuffer); -+ -+ // Invalidate all buffers -+ for(int i=0; i < m_vpuFrameBufferNum; i++) -+ m_outputBuffers[i]->ReleaseFramebuffer(&m_vpuHandle); -+ -+ m_frameCounter = 0; -+ m_bytesToBeConsumed = 0; -+ m_previousPts = DVD_NOPTS_VALUE; -+ -+ // Flush VPU -+ ret = VPU_DecFlushAll(m_vpuHandle); -+ if (ret != VPU_DEC_RET_SUCCESS) -+ { -+ CLog::Log(LOGERROR, "%s - VPU flush failed with error code %d.\n", __FUNCTION__, ret); -+ } -+ -+} -+ -+unsigned CDVDVideoCodecIMX::GetAllowedReferences() -+{ -+ return 3; -+} -+ -+bool CDVDVideoCodecIMX::ClearPicture(DVDVideoPicture* pDvdVideoPicture) -+{ -+ if (pDvdVideoPicture) -+ { -+ SAFE_RELEASE(pDvdVideoPicture->IMXBuffer); -+ } -+ -+ return true; -+} -+ -+bool CDVDVideoCodecIMX::GetPicture(DVDVideoPicture* pDvdVideoPicture) -+{ -+#ifdef IMX_PROFILE -+ static unsigned int previous = 0; -+ unsigned int current; -+ -+ current = XbmcThreads::SystemClockMillis(); -+ CLog::Log(LOGDEBUG, "%s tm:%03d\n", __FUNCTION__, current - previous); -+ previous = current; -+#endif -+ -+ m_frameCounter++; -+ -+ pDvdVideoPicture->iFlags = DVP_FLAG_ALLOCATED; -+ if (m_dropState) -+ pDvdVideoPicture->iFlags |= DVP_FLAG_DROPPED; -+ else -+ pDvdVideoPicture->iFlags &= ~DVP_FLAG_DROPPED; -+ -+ pDvdVideoPicture->format = RENDER_FMT_IMXMAP; -+ pDvdVideoPicture->dts = DVD_NOPTS_VALUE; -+ pDvdVideoPicture->iWidth = m_frameInfo.pExtInfo->FrmCropRect.nRight - m_frameInfo.pExtInfo->FrmCropRect.nLeft; -+ pDvdVideoPicture->iHeight = m_frameInfo.pExtInfo->FrmCropRect.nBottom - m_frameInfo.pExtInfo->FrmCropRect.nTop; -+ -+ pDvdVideoPicture->iDisplayWidth = ((pDvdVideoPicture->iWidth * m_frameInfo.pExtInfo->nQ16ShiftWidthDivHeightRatio) + 32767) >> 16; -+ pDvdVideoPicture->iDisplayHeight = pDvdVideoPicture->iHeight; -+ -+ int idx = VpuFindBuffer(m_frameInfo.pDisplayFrameBuf->pbufY); -+ if (idx != -1) -+ { -+ CDVDVideoCodecIMXBuffer *buffer = m_outputBuffers[idx]; -+ -+ pDvdVideoPicture->pts = buffer->GetPts(); -+ pDvdVideoPicture->dts = m_dts; -+ if (!m_usePTS) -+ { -+ pDvdVideoPicture->pts = DVD_NOPTS_VALUE; -+ pDvdVideoPicture->dts = DVD_NOPTS_VALUE; -+ } -+ -+ buffer->Queue(&m_frameInfo, m_lastBuffer); -+ -+#ifdef TRACE_FRAMES -+ CLog::Log(LOGDEBUG, "+ %02d dts %f pts %f (VPU)\n", idx, pDvdVideoPicture->dts, pDvdVideoPicture->pts); -+#endif -+ -+ pDvdVideoPicture->IMXBuffer = buffer; -+ pDvdVideoPicture->IMXBuffer->Lock(); -+ -+ // Save last buffer -+ if (m_lastBuffer) -+ SAFE_RELEASE(m_lastBuffer); -+ m_lastBuffer = buffer; -+ m_lastBuffer->Lock(); -+ } -+ else -+ { -+ CLog::Log(LOGERROR, "%s - could not find frame buffer\n", __FUNCTION__); -+ } -+ -+ return true; -+} -+ -+void CDVDVideoCodecIMX::SetDropState(bool bDrop) -+{ -+ -+ // We are fast enough to continue to really decode every frames -+ // and avoid artefacts... -+ // (Of course these frames won't be rendered but only decoded) -+ -+ if (m_dropState != bDrop) -+ { -+ m_dropState = bDrop; -+#ifdef TRACE_FRAMES -+ CLog::Log(LOGDEBUG, "%s : %d\n", __FUNCTION__, bDrop); -+#endif -+ } -+} -+ -+void CDVDVideoCodecIMX::Enter() -+{ -+ m_codecBufferLock.lock(); -+} -+ -+void CDVDVideoCodecIMX::Leave() -+{ -+ m_codecBufferLock.unlock(); -+} -+ -+/*******************************************/ -+ -+#ifdef TRACE_FRAMES -+CDVDVideoCodecIMXBuffer::CDVDVideoCodecIMXBuffer(int idx) -+ : m_refs(1) -+ , m_idx(idx) -+#else -+CDVDVideoCodecIMXBuffer::CDVDVideoCodecIMXBuffer() -+ : m_refs(1) -+#endif -+ , m_frameBuffer(NULL) -+ , m_rendered(false) -+ , m_pts(DVD_NOPTS_VALUE) -+ , m_previousBuffer(NULL) -+{ -+} -+ -+void CDVDVideoCodecIMXBuffer::Lock() -+{ -+#ifdef TRACE_FRAMES -+ long count = AtomicIncrement(&m_refs); -+ CLog::Log(LOGDEBUG, "R+ %02d - ref : %d (VPU)\n", m_idx, count); -+#else -+ AtomicIncrement(&m_refs); -+#endif -+} -+ -+long CDVDVideoCodecIMXBuffer::Release() -+{ -+ long count = AtomicDecrement(&m_refs); -+#ifdef TRACE_FRAMES -+ CLog::Log(LOGDEBUG, "R- %02d - ref : %d (VPU)\n", m_idx, count); -+#endif -+ if (count == 2) -+ { -+ // Only referenced by the coded and its next frame, release the previous -+ SAFE_RELEASE(m_previousBuffer); -+ } -+ if (count == 1) -+ { -+ // If count drops to 1 then the only reference is being held by the codec -+ // that it can be released in the next Decode call. -+ if(m_frameBuffer != NULL) -+ { -+ m_rendered = true; -+ SAFE_RELEASE(m_previousBuffer); -+#ifdef TRACE_FRAMES -+ CLog::Log(LOGDEBUG, "R %02d (VPU)\n", m_idx); -+#endif -+ } -+ } -+ else if (count == 0) -+ { -+ delete this; -+ } -+ -+ return count; -+} -+ -+bool CDVDVideoCodecIMXBuffer::IsValid() -+{ -+ return m_frameBuffer != NULL; -+} -+ -+bool CDVDVideoCodecIMXBuffer::Rendered() const -+{ -+ return m_rendered; -+} -+ -+void CDVDVideoCodecIMXBuffer::Queue(VpuDecOutFrameInfo *frameInfo, -+ CDVDVideoCodecIMXBuffer *previous) -+{ -+ // No lock necessary because at this time there is definitely no -+ // thread still holding a reference -+ m_frameBuffer = frameInfo->pDisplayFrameBuf; -+ m_rendered = false; -+ m_previousBuffer = previous; -+ if (m_previousBuffer) -+ m_previousBuffer->Lock(); -+ -+ m_iWidth = frameInfo->pExtInfo->nFrmWidth; -+ m_iHeight = frameInfo->pExtInfo->nFrmHeight; -+ m_VirtAddr = m_frameBuffer->pbufVirtY; -+ m_phyAddr = m_frameBuffer->pbufY; -+} -+ -+VpuDecRetCode CDVDVideoCodecIMXBuffer::ReleaseFramebuffer(VpuDecHandle *handle) -+{ -+ // Again no lock required because this is only issued after the last -+ // external reference was released -+ VpuDecRetCode ret = VPU_DEC_RET_FAILURE; -+ -+ if((m_frameBuffer != NULL) && *handle) -+ { -+ ret = VPU_DecOutFrameDisplayed(*handle, m_frameBuffer); -+ if(ret != VPU_DEC_RET_SUCCESS) -+ CLog::Log(LOGERROR, "%s: vpu clear frame display failure: ret=%d \r\n",__FUNCTION__,ret); -+ } -+#ifdef TRACE_FRAMES -+ CLog::Log(LOGDEBUG, "- %02d (VPU)\n", m_idx); -+#endif -+ m_rendered = false; -+ m_frameBuffer = NULL; -+ m_pts = DVD_NOPTS_VALUE; -+ SAFE_RELEASE(m_previousBuffer); -+ -+ return ret; -+} -+ -+void CDVDVideoCodecIMXBuffer::SetPts(double pts) -+{ -+ m_pts = pts; -+} -+ -+double CDVDVideoCodecIMXBuffer::GetPts(void) const -+{ -+ return m_pts; -+} -+ -+CDVDVideoCodecIMXBuffer *CDVDVideoCodecIMXBuffer::GetPreviousBuffer() const -+{ -+ return m_previousBuffer; -+} -+ -+CDVDVideoCodecIMXBuffer::~CDVDVideoCodecIMXBuffer() -+{ -+ assert(m_refs == 0); -+#ifdef TRACE_FRAMES -+ CLog::Log(LOGDEBUG, "~ %02d (VPU)\n", m_idx); -+#endif -+} -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h -new file mode 100644 -index 0000000..6533683 ---- /dev/null -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h -@@ -0,0 +1,151 @@ -+#pragma once -+/* -+ * Copyright (C) 2010-2013 Team XBMC -+ * http://www.xbmc.org -+ * -+ * This Program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2, or (at your option) -+ * any later version. -+ * -+ * This Program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with XBMC; see the file COPYING. If not, see -+ * . -+ * -+ */ -+#include -+#include -+#include "DVDVideoCodec.h" -+#include "DVDStreamInfo.h" -+#include "threads/CriticalSection.h" -+#include "utils/BitstreamConverter.h" -+ -+ -+//#define IMX_PROFILE -+//#define TRACE_FRAMES -+ -+class CDecMemInfo -+{ -+public: -+ CDecMemInfo() -+ : nVirtNum(0) -+ , virtMem(NULL) -+ , nPhyNum(0) -+ , phyMem(NULL) -+ {} -+ -+ //virtual mem info -+ int nVirtNum; -+ void** virtMem; -+ -+ //phy mem info -+ int nPhyNum; -+ VpuMemDesc* phyMem; -+}; -+ -+class CDVDVideoCodecIMXBuffer -+{ -+public: -+#ifdef TRACE_FRAMES -+ CDVDVideoCodecIMXBuffer(int idx); -+#else -+ CDVDVideoCodecIMXBuffer(); -+#endif -+ -+ // reference counting -+ virtual void Lock(); -+ virtual long Release(); -+ virtual bool IsValid(); -+ -+ bool Rendered() const; -+ void Queue(VpuDecOutFrameInfo *frameInfo, -+ CDVDVideoCodecIMXBuffer *previous); -+ VpuDecRetCode ReleaseFramebuffer(VpuDecHandle *handle); -+ void SetPts(double pts); -+ double GetPts(void) const; -+ CDVDVideoCodecIMXBuffer *GetPreviousBuffer() const; -+ -+ uint32_t m_iWidth; -+ uint32_t m_iHeight; -+ uint8_t *m_phyAddr; -+ uint8_t *m_VirtAddr; -+ -+private: -+ // private because we are reference counted -+ virtual ~CDVDVideoCodecIMXBuffer(); -+ -+private: -+#ifdef TRACE_FRAMES -+ int m_idx; -+#endif -+ long m_refs; -+ VpuFrameBuffer *m_frameBuffer; -+ bool m_rendered; -+ double m_pts; -+ CDVDVideoCodecIMXBuffer *m_previousBuffer; // Holds a the reference counted -+ // previous buffer -+}; -+ -+class CDVDVideoCodecIMX : public CDVDVideoCodec -+{ -+ friend class CDVDVideoCodecIMXBuffer; -+ friend class CDVDVideoCodecIPUBuffer; -+ -+public: -+ CDVDVideoCodecIMX(); -+ virtual ~CDVDVideoCodecIMX(); -+ -+ // Methods from CDVDVideoCodec which require overrides -+ virtual bool Open(CDVDStreamInfo &hints, CDVDCodecOptions &options); -+ virtual void Dispose(void); -+ virtual int Decode(BYTE *pData, int iSize, double dts, double pts); -+ virtual void Reset(void); -+ virtual bool ClearPicture(DVDVideoPicture *pDvdVideoPicture); -+ virtual bool GetPicture(DVDVideoPicture *pDvdVideoPicture); -+ virtual void SetDropState(bool bDrop); -+ virtual const char* GetName(void) { return (const char*)m_pFormatName; } -+ virtual unsigned GetAllowedReferences(); -+ -+ static void Enter(); -+ static void Leave(); -+ -+protected: -+ -+ bool VpuOpen(); -+ bool VpuAllocBuffers(VpuMemInfo *); -+ bool VpuFreeBuffers(); -+ bool VpuAllocFrameBuffers(); -+ int VpuFindBuffer(void *frameAddr); -+ -+ static const int m_extraVpuBuffers; // Number of additional buffers for VPU -+ static const int m_maxVpuDecodeLoops; // Maximum iterations in VPU decoding loop -+ static CCriticalSection m_codecBufferLock; // Lock to protect buffers handled -+ // by both decoding and rendering threads -+ -+ CDVDStreamInfo m_hints; // Hints from demuxer at stream opening -+ const char *m_pFormatName; // Current decoder format name -+ VpuDecOpenParam m_decOpenParam; // Parameters required to call VPU_DecOpen -+ CDecMemInfo m_decMemInfo; // VPU dedicated memory description -+ VpuDecHandle m_vpuHandle; // Handle for VPU library calls -+ VpuDecInitInfo m_initInfo; // Initial info returned from VPU at decoding start -+ bool m_dropState; // Current drop state -+ int m_vpuFrameBufferNum; // Total number of allocated frame buffers -+ VpuFrameBuffer *m_vpuFrameBuffers; // Table of VPU frame buffers description -+ CDVDVideoCodecIMXBuffer **m_outputBuffers; // Table of VPU output buffers -+ CDVDVideoCodecIMXBuffer *m_lastBuffer; // Keep track of previous VPU output buffer (needed by deinterlacing motion engin) -+ VpuMemDesc *m_extraMem; // Table of allocated extra Memory -+ int m_frameCounter; // Decoded frames counter -+ bool m_usePTS; // State whether pts out of decoding process should be used -+ VpuDecOutFrameInfo m_frameInfo; // Store last VPU output frame info -+ CBitstreamConverter *m_converter; // H264 annex B converter -+ bool m_convert_bitstream; // State whether bitstream conversion is required -+ int m_bytesToBeConsumed; // Remaining bytes in VPU -+ double m_previousPts; // Enable to keep pts when needed -+ bool m_frameReported; // State whether the frame consumed event will be reported by libfslvpu -+ double m_dts; // Current dts -+}; -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/Makefile.in b/xbmc/cores/dvdplayer/DVDCodecs/Video/Makefile.in -index 9c13da8..50dc8b7 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/Makefile.in -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/Makefile.in -@@ -20,6 +20,9 @@ SRCS += OpenMax.cpp - SRCS += OpenMaxVideo.cpp - SRCS += DVDVideoCodecOpenMax.cpp - endif -+ifeq (@USE_IMXVPU@,1) -+SRCS += DVDVideoCodecIMX.cpp -+endif - ifeq (@USE_LIBAMCODEC@,1) - SRCS += AMLCodec.cpp - SRCS += DVDVideoCodecAmlogic.cpp -diff --git a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp -index ac78f18..619e25e 100644 ---- a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp -+++ b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp -@@ -994,6 +994,7 @@ static std::string GetRenderFormatName(ERenderFormat format) - case RENDER_FMT_EGLIMG: return "EGLIMG"; - case RENDER_FMT_BYPASS: return "BYPASS"; - case RENDER_FMT_MEDIACODEC:return "MEDIACODEC"; -+ case RENDER_FMT_IMXMAP: return "IMXMAP"; - case RENDER_FMT_NONE: return "NONE"; - } - return "UNKNOWN"; --- -2.0.4 - - -From fba4372a70547e34afe098034caac432b247b002 Mon Sep 17 00:00:00 2001 -From: "Chris \"Koying\" Browet" -Date: Thu, 7 Aug 2014 13:51:15 +0200 -Subject: [PATCH 2/2] ADD: [imx] native framebuffer support - ---- - xbmc/windowing/egl/EGLNativeTypeIMX.cpp | 336 ++++++++++++++++++++++++++++++++ - xbmc/windowing/egl/EGLNativeTypeIMX.h | 59 ++++++ - xbmc/windowing/egl/EGLWrapper.cpp | 7 +- - xbmc/windowing/egl/Makefile.in | 1 + - 4 files changed, 400 insertions(+), 3 deletions(-) - create mode 100644 xbmc/windowing/egl/EGLNativeTypeIMX.cpp - create mode 100644 xbmc/windowing/egl/EGLNativeTypeIMX.h - -diff --git a/xbmc/windowing/egl/EGLNativeTypeIMX.cpp b/xbmc/windowing/egl/EGLNativeTypeIMX.cpp -new file mode 100644 -index 0000000..04cadc8 ---- /dev/null -+++ b/xbmc/windowing/egl/EGLNativeTypeIMX.cpp -@@ -0,0 +1,336 @@ -+/* -+ * Copyright (C) 2011-2013 Team XBMC -+ * http://www.xbmc.org -+ * -+ * This Program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2, or (at your option) -+ * any later version. -+ * -+ * This Program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with XBMC; see the file COPYING. If not, see -+ * . -+ * -+ */ -+ -+#include "system.h" -+#include -+ -+#include "EGLNativeTypeIMX.h" -+#include -+#include -+#include -+#include "utils/log.h" -+#include "utils/RegExp.h" -+#include "utils/StringUtils.h" -+#include "utils/Environment.h" -+#include "guilib/gui3d.h" -+#include "windowing/WindowingFactory.h" -+#include "cores/AudioEngine/AEFactory.h" -+#include -+ -+CEGLNativeTypeIMX::CEGLNativeTypeIMX() -+ : m_display(NULL) -+ , m_window(NULL) -+{ -+} -+ -+CEGLNativeTypeIMX::~CEGLNativeTypeIMX() -+{ -+} -+ -+bool CEGLNativeTypeIMX::CheckCompatibility() -+{ -+ std::ifstream file("/sys/class/graphics/fb0/fsl_disp_dev_property"); -+ return file; -+} -+ -+void CEGLNativeTypeIMX::Initialize() -+{ -+ int fd; -+ -+ fd = open("/dev/fb0",O_RDWR); -+ if (fd < 0) -+ { -+ CLog::Log(LOGERROR, "%s - Error while opening /dev/fb0.\n", __FUNCTION__); -+ return; -+ } -+ -+ // Unblank the fb -+ if (ioctl(fd, FBIOBLANK, 0) < 0) -+ { -+ CLog::Log(LOGERROR, "%s - Error while unblanking fb0.\n", __FUNCTION__); -+ } -+ -+ close(fd); -+ -+ // Check if we can change the framebuffer resolution -+ fd = open("/sys/class/graphics/fb0/mode", O_RDWR); -+ if (fd >= 0) -+ { -+ CLog::Log(LOGNOTICE, "%s - graphics sysfs is writable", __FUNCTION__); -+ m_readonly = false; -+ } -+ else -+ { -+ CLog::Log(LOGNOTICE, "%s - graphics sysfs is read-only", __FUNCTION__); -+ m_readonly = true; -+ } -+ close(fd); -+ -+ return; -+} -+ -+void CEGLNativeTypeIMX::Destroy() -+{ -+ struct fb_fix_screeninfo fixed_info; -+ void *fb_buffer; -+ int fd; -+ -+ fd = open("/dev/fb0",O_RDWR); -+ if (fd < 0) -+ { -+ CLog::Log(LOGERROR, "%s - Error while opening /dev/fb0.\n", __FUNCTION__); -+ return; -+ } -+ -+ ioctl( fd, FBIOGET_FSCREENINFO, &fixed_info); -+ // Black fb0 -+ fb_buffer = mmap(NULL, fixed_info.smem_len, PROT_WRITE, MAP_SHARED, fd, 0); -+ if (fb_buffer == MAP_FAILED) -+ { -+ CLog::Log(LOGERROR, "%s - fb mmap failed %s.\n", __FUNCTION__, strerror(errno)); -+ } -+ else -+ { -+ memset(fb_buffer, 0x0, fixed_info.smem_len); -+ munmap(fb_buffer, fixed_info.smem_len); -+ } -+ -+ close(fd); -+ -+ return; -+} -+ -+bool CEGLNativeTypeIMX::CreateNativeDisplay() -+{ -+ // Force double-buffering -+ CEnvironment::setenv("FB_MULTI_BUFFER", "2", 0); -+ -+#ifdef HAS_IMXVPU -+ // EGL will be rendered on fb0 -+ m_display = fbGetDisplayByIndex(0); -+ m_nativeDisplay = &m_display; -+ return true; -+#else -+ return false; -+#endif -+} -+ -+bool CEGLNativeTypeIMX::CreateNativeWindow() -+{ -+#ifdef HAS_IMXVPU -+ m_window = fbCreateWindow(m_display, 0, 0, 0, 0); -+ m_nativeWindow = &m_window; -+ return true; -+#else -+ return false; -+#endif -+} -+ -+bool CEGLNativeTypeIMX::GetNativeDisplay(XBNativeDisplayType **nativeDisplay) const -+{ -+ if (!nativeDisplay) -+ return false; -+ if (!m_nativeDisplay) -+ return false; -+ *nativeDisplay = (XBNativeDisplayType*)m_nativeDisplay; -+ return true; -+} -+ -+bool CEGLNativeTypeIMX::GetNativeWindow(XBNativeWindowType **nativeWindow) const -+{ -+ if (!nativeWindow) -+ return false; -+ if (!m_nativeWindow || !m_window) -+ return false; -+ *nativeWindow = (XBNativeWindowType*)m_nativeWindow; -+ return true; -+} -+ -+bool CEGLNativeTypeIMX::DestroyNativeDisplay() -+{ -+#ifdef HAS_IMXVPU -+ if (m_display) -+ fbDestroyDisplay(m_display); -+ m_display = NULL; -+ return true; -+#else -+ return false; -+#endif -+} -+ -+bool CEGLNativeTypeIMX::DestroyNativeWindow() -+{ -+#ifdef HAS_IMXVPU -+ if (m_window) -+ fbDestroyWindow(m_window); -+ m_window = NULL; -+ return true; -+#else -+ return false; -+#endif -+} -+ -+bool CEGLNativeTypeIMX::GetNativeResolution(RESOLUTION_INFO *res) const -+{ -+ std::string mode; -+ get_sysfs_str("/sys/class/graphics/fb0/mode", mode); -+ return ModeToResolution(mode, res); -+} -+ -+bool CEGLNativeTypeIMX::SetNativeResolution(const RESOLUTION_INFO &res) -+{ -+ if (m_readonly) -+ return false; -+ -+ std::string mode; -+ get_sysfs_str("/sys/class/graphics/fb0/mode", mode); -+ if (res.strId == mode) -+ return false; -+ -+ DestroyNativeWindow(); -+ DestroyNativeDisplay(); -+ -+ set_sysfs_str("/sys/class/graphics/fb0/mode", res.strId); -+ -+ CreateNativeDisplay(); -+ -+ CLog::Log(LOGDEBUG, "%s: %s",__FUNCTION__, res.strId.c_str()); -+ -+ // Reset AE -+ CAEFactory::DeviceChange(); -+ -+ return true; -+} -+ -+bool CEGLNativeTypeIMX::ProbeResolutions(std::vector &resolutions) -+{ -+ if (m_readonly) -+ return false; -+ -+ std::string valstr; -+ get_sysfs_str("/sys/class/graphics/fb0/modes", valstr); -+ std::vector probe_str; -+ probe_str = StringUtils::Split(valstr, "\n"); -+ -+ resolutions.clear(); -+ RESOLUTION_INFO res; -+ for (size_t i = 0; i < probe_str.size(); i++) -+ { -+ if(!StringUtils::StartsWith(probe_str[i], "S:")) -+ continue; -+ if(ModeToResolution(probe_str[i], &res)) -+ resolutions.push_back(res); -+ } -+ return resolutions.size() > 0; -+} -+ -+bool CEGLNativeTypeIMX::GetPreferredResolution(RESOLUTION_INFO *res) const -+{ -+ return GetNativeResolution(res); -+} -+ -+bool CEGLNativeTypeIMX::ShowWindow(bool show) -+{ -+ // Force vsync by default -+ eglSwapInterval(g_Windowing.GetEGLDisplay(), 1); -+ EGLint result = eglGetError(); -+ if(result != EGL_SUCCESS) -+ CLog::Log(LOGERROR, "EGL error in %s: %x",__FUNCTION__, result); -+ -+ return false; -+} -+ -+int CEGLNativeTypeIMX::get_sysfs_str(std::string path, std::string& valstr) const -+{ -+ int len; -+ char buf[256] = {0}; -+ -+ int fd = open(path.c_str(), O_RDONLY); -+ if (fd >= 0) -+ { -+ while ((len = read(fd, buf, 255)) > 0) -+ valstr.append(buf, len); -+ close(fd); -+ } -+ else -+ { -+ CLog::Log(LOGERROR, "%s: error reading %s",__FUNCTION__, path.c_str()); -+ valstr = "fail"; -+ return -1; -+ } -+ return 0; -+} -+ -+int CEGLNativeTypeIMX::set_sysfs_str(std::string path, std::string val) const -+{ -+ int fd = open(path.c_str(), O_WRONLY); -+ if (fd >= 0) -+ { -+ val += '\n'; -+ write(fd, val.c_str(), val.size()); -+ close(fd); -+ return 0; -+ } -+ CLog::Log(LOGERROR, "%s: error writing %s",__FUNCTION__, path.c_str()); -+ return -1; -+} -+ -+bool CEGLNativeTypeIMX::ModeToResolution(std::string mode, RESOLUTION_INFO *res) const -+{ -+ if (!res) -+ return false; -+ -+ res->iWidth = 0; -+ res->iHeight= 0; -+ -+ if(mode.empty()) -+ return false; -+ -+ std::string fromMode = StringUtils::Mid(mode, 2); -+ StringUtils::Trim(fromMode); -+ -+ CRegExp split(true); -+ split.RegComp("([0-9]+)x([0-9]+)([pi])-([0-9]+)"); -+ if (split.RegFind(fromMode) < 0) -+ return false; -+ -+ int w = atoi(split.GetMatch(1).c_str()); -+ int h = atoi(split.GetMatch(2).c_str()); -+ std::string p = split.GetMatch(3); -+ int r = atoi(split.GetMatch(4).c_str()); -+ -+ res->iWidth = w; -+ res->iHeight= h; -+ res->iScreenWidth = w; -+ res->iScreenHeight= h; -+ res->fRefreshRate = r; -+ res->dwFlags = p[0] == 'p' ? D3DPRESENTFLAG_PROGRESSIVE : D3DPRESENTFLAG_INTERLACED; -+ -+ res->iScreen = 0; -+ res->bFullScreen = true; -+ res->iSubtitles = (int)(0.965 * res->iHeight); -+ res->fPixelRatio = 1.0f; -+ res->strMode = StringUtils::Format("%dx%d @ %.2f%s - Full Screen", res->iScreenWidth, res->iScreenHeight, res->fRefreshRate, -+ res->dwFlags & D3DPRESENTFLAG_INTERLACED ? "i" : ""); -+ res->strId = mode; -+ -+ return res->iWidth > 0 && res->iHeight> 0; -+} -+ -diff --git a/xbmc/windowing/egl/EGLNativeTypeIMX.h b/xbmc/windowing/egl/EGLNativeTypeIMX.h -new file mode 100644 -index 0000000..c95dcfb ---- /dev/null -+++ b/xbmc/windowing/egl/EGLNativeTypeIMX.h -@@ -0,0 +1,59 @@ -+#pragma once -+ -+/* -+ * Copyright (C) 2011-2013 Team XBMC -+ * http://www.xbmc.org -+ * -+ * This Program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2, or (at your option) -+ * any later version. -+ * -+ * This Program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with XBMC; see the file COPYING. If not, see -+ * . -+ * -+ */ -+#include -+#include "EGLNativeType.h" -+ -+class CEGLNativeTypeIMX : public CEGLNativeType -+{ -+public: -+ CEGLNativeTypeIMX(); -+ virtual ~CEGLNativeTypeIMX(); -+ virtual std::string GetNativeName() const { return "iMX"; } -+ virtual bool CheckCompatibility(); -+ virtual void Initialize(); -+ virtual void Destroy(); -+ virtual int GetQuirks() { return EGL_QUIRK_NONE; } -+ -+ virtual bool CreateNativeDisplay(); -+ virtual bool CreateNativeWindow(); -+ virtual bool GetNativeDisplay(XBNativeDisplayType **nativeDisplay) const; -+ virtual bool GetNativeWindow(XBNativeWindowType **nativeWindow) const; -+ -+ virtual bool DestroyNativeWindow(); -+ virtual bool DestroyNativeDisplay(); -+ -+ virtual bool GetNativeResolution(RESOLUTION_INFO *res) const; -+ virtual bool SetNativeResolution(const RESOLUTION_INFO &res); -+ virtual bool ProbeResolutions(std::vector &resolutions); -+ virtual bool GetPreferredResolution(RESOLUTION_INFO *res) const; -+ -+ virtual bool ShowWindow(bool show); -+ -+protected: -+ bool m_readonly; -+ int get_sysfs_str(std::string path, std::string& valstr) const; -+ int set_sysfs_str(std::string path, std::string val) const; -+ bool ModeToResolution(std::string mode, RESOLUTION_INFO *res) const; -+ -+ EGLNativeDisplayType m_display; -+ EGLNativeWindowType m_window; -+}; -diff --git a/xbmc/windowing/egl/EGLWrapper.cpp b/xbmc/windowing/egl/EGLWrapper.cpp -index 045cdfc..e19ce63 100644 ---- a/xbmc/windowing/egl/EGLWrapper.cpp -+++ b/xbmc/windowing/egl/EGLWrapper.cpp -@@ -17,16 +17,15 @@ - * . - * - */ -- - #include "system.h" - - #ifdef HAS_EGL -- - #include "utils/log.h" - #include "EGLNativeTypeAndroid.h" - #include "EGLNativeTypeAmlogic.h" - #include "EGLNativeTypeRaspberryPI.h" - #include "EGLNativeTypeWayland.h" -+#include "EGLNativeTypeIMX.h" - #include "EGLWrapper.h" - - #define CheckError() m_result = eglGetError(); if(m_result != EGL_SUCCESS) CLog::Log(LOGERROR, "EGL error in %s: %x",__FUNCTION__, m_result); -@@ -83,7 +82,9 @@ bool CEGLWrapper::Initialize(const std::string &implementation) - if ((nativeGuess = CreateEGLNativeType(implementation)) || - (nativeGuess = CreateEGLNativeType(implementation)) || - (nativeGuess = CreateEGLNativeType(implementation)) || -- (nativeGuess = CreateEGLNativeType(implementation))) -+ (nativeGuess = CreateEGLNativeType(implementation)) || -+ (nativeGuess = CreateEGLNativeType(implementation)) -+ ) - { - m_nativeTypes = nativeGuess; - -diff --git a/xbmc/windowing/egl/Makefile.in b/xbmc/windowing/egl/Makefile.in -index f800b7f..f59f9cb 100644 ---- a/xbmc/windowing/egl/Makefile.in -+++ b/xbmc/windowing/egl/Makefile.in -@@ -5,6 +5,7 @@ SRCS+= EGLNativeTypeAmlogic.cpp - SRCS+= EGLNativeTypeAndroid.cpp - SRCS+= EGLNativeTypeRaspberryPI.cpp - SRCS+= EGLNativeTypeWayland.cpp -+SRCS+= EGLNativeTypeIMX.cpp - SRCS+= EGLWrapper.cpp - - # Wayland specific detail --- -2.0.4 - diff --git a/packages/mediacenter/xbmc/patches/xbmc-999.93-fix_dpms_wakeup.patch b/packages/mediacenter/xbmc/patches/xbmc-999.93-fix_dpms_wakeup.patch deleted file mode 100644 index 1ca7fdd166..0000000000 --- a/packages/mediacenter/xbmc/patches/xbmc-999.93-fix_dpms_wakeup.patch +++ /dev/null @@ -1,89 +0,0 @@ -From cd6e87d934c52dc47e77054a3a640b20c585c62f Mon Sep 17 00:00:00 2001 -From: Rainer Hochecker -Date: Mon, 1 Sep 2014 19:24:32 +0200 -Subject: [PATCH] X11: recreate window after wakeup from dpms - ---- - xbmc/powermanagement/DPMSSupport.cpp | 10 ++-------- - xbmc/windowing/X11/WinSystemX11.cpp | 13 ++++++++++--- - xbmc/windowing/X11/WinSystemX11.h | 1 + - 3 files changed, 13 insertions(+), 11 deletions(-) - -diff --git a/xbmc/powermanagement/DPMSSupport.cpp b/xbmc/powermanagement/DPMSSupport.cpp -index 7c00281..3aefedd 100644 ---- a/xbmc/powermanagement/DPMSSupport.cpp -+++ b/xbmc/powermanagement/DPMSSupport.cpp -@@ -174,14 +174,8 @@ bool DPMSSupport::PlatformSpecificDisablePowerSaving() - DPMSForceLevel(dpy, DPMSModeOn); - DPMSDisable(dpy); - XFlush(dpy); -- // On my ATI, the full-screen window stays blank after waking up from -- // DPMS, presumably due to being OpenGL. There is something magical about -- // window expose events (involving the window manager) that solves this -- // without fail. -- XUnmapWindow(dpy, g_Windowing.GetWindow()); -- XFlush(dpy); -- XMapWindow(dpy, g_Windowing.GetWindow()); -- XFlush(dpy); -+ -+ g_Windowing.RecreateWindow(); - - return true; - } -diff --git a/xbmc/windowing/X11/WinSystemX11.cpp b/xbmc/windowing/X11/WinSystemX11.cpp -index bb30b52..9cae5ce 100644 ---- a/xbmc/windowing/X11/WinSystemX11.cpp -+++ b/xbmc/windowing/X11/WinSystemX11.cpp -@@ -693,7 +693,6 @@ bool CWinSystemX11::Show(bool raise) - void CWinSystemX11::NotifyXRREvent() - { - CLog::Log(LOGDEBUG, "%s - notify display reset event", __FUNCTION__); -- m_windowDirty = true; - - CSingleLock lock(g_graphicsContext); - -@@ -709,6 +708,15 @@ void CWinSystemX11::NotifyXRREvent() - UpdateResolutions(); - } - -+ RecreateWindow(); -+} -+ -+void CWinSystemX11::RecreateWindow() -+{ -+ m_windowDirty = true; -+ -+ CSingleLock lock(g_graphicsContext); -+ - XOutput *out = g_xrandr.GetOutput(m_userOutput); - XMode mode = g_xrandr.GetCurrentMode(m_userOutput); - -@@ -733,7 +741,7 @@ void CWinSystemX11::NotifyXRREvent() - - if (!found) - { -- CLog::Log(LOGERROR, "CWinSystemX11::RefreshWindow - could not find resolution"); -+ CLog::Log(LOGERROR, "CWinSystemX11::RecreateWindow - could not find resolution"); - i = RES_DESKTOP; - } - -@@ -741,7 +749,6 @@ void CWinSystemX11::NotifyXRREvent() - g_graphicsContext.SetVideoResolution((RESOLUTION)i, true); - else - g_graphicsContext.SetVideoResolution(RES_WINDOW, true); -- - } - - void CWinSystemX11::OnLostDevice() -diff --git a/xbmc/windowing/X11/WinSystemX11.h b/xbmc/windowing/X11/WinSystemX11.h -index 6d0a740..ec333e8 100644 ---- a/xbmc/windowing/X11/WinSystemX11.h -+++ b/xbmc/windowing/X11/WinSystemX11.h -@@ -72,6 +72,7 @@ class CWinSystemX11 : public CWinSystemBase, public ISettingCallback - void NotifyXRREvent(); - void GetConnectedOutputs(std::vector *outputs); - bool IsCurrentOutput(CStdString output); -+ void RecreateWindow(); - - protected: - bool RefreshGlxContext(bool force); diff --git a/packages/mediacenter/xbmc/patches/xbmc-999.93-revert-5814e7f.patch b/packages/mediacenter/xbmc/patches/xbmc-999.93-revert-5814e7f.patch deleted file mode 100644 index 9d5fca93a4..0000000000 --- a/packages/mediacenter/xbmc/patches/xbmc-999.93-revert-5814e7f.patch +++ /dev/null @@ -1,12 +0,0 @@ -diff -Naur xbmc-14-0b1a6eb/xbmc/windowing/X11/XRandR.cpp xbmc-14-0b1a6eb.patch/xbmc/windowing/X11/XRandR.cpp ---- xbmc-14-0b1a6eb/xbmc/windowing/X11/XRandR.cpp 2014-09-01 09:53:24.000000000 +0200 -+++ xbmc-14-0b1a6eb.patch/xbmc/windowing/X11/XRandR.cpp 2014-09-01 17:39:11.816218099 +0200 -@@ -74,7 +74,7 @@ - CStdString cmd; - cmd = getenv("XBMC_BIN_HOME"); - cmd += "/xbmc-xrandr"; -- cmd = StringUtils::Format("%s -q --screen %d --current", cmd.c_str(), screennum); -+ cmd = StringUtils::Format("%s -q --screen %d", cmd.c_str(), screennum); - - FILE* file = popen(cmd.c_str(),"r"); - if (!file)