diff --git a/packages/mediacenter/xbmc/patches/xbmc-998.0001-ADD-Freeescale-IMX-h-w-codec.patch b/packages/mediacenter/xbmc/patches/xbmc-998.0001-ADD-Freeescale-IMX-h-w-codec.patch new file mode 100644 index 00000000000..d7dbb648f5c --- /dev/null +++ b/packages/mediacenter/xbmc/patches/xbmc-998.0001-ADD-Freeescale-IMX-h-w-codec.patch @@ -0,0 +1,2366 @@ +From cb8668cbfc946e558134be722cf0356d0f224af5 Mon Sep 17 00:00:00 2001 +From: "Chris \"Koying\" Browet" +Date: Thu, 7 Aug 2014 13:46:49 +0200 +Subject: [PATCH 1/4] ADD: Freeescale IMX h/w codec + +--- + configure.in | 13 +- + xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp | 256 ++++ + xbmc/cores/VideoRenderers/LinuxRendererGLES.h | 11 +- + xbmc/cores/VideoRenderers/RenderFormats.h | 1 + + xbmc/cores/VideoRenderers/RenderManager.cpp | 4 + + xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.cpp | 18 +- + .../dvdplayer/DVDCodecs/Video/DVDVideoCodec.h | 6 + + .../dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp | 1501 ++++++++++++++++++++ + .../dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h | 215 +++ + .../dvdplayer/DVDCodecs/Video/DVDVideoCodecInfo.h | 38 + + xbmc/cores/dvdplayer/DVDCodecs/Video/Makefile.in | 3 + + xbmc/cores/dvdplayer/DVDPlayerVideo.cpp | 1 + + 12 files changed, 2064 insertions(+), 3 deletions(-) + create mode 100644 xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp + create mode 100644 xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h + create mode 100644 xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecInfo.h + +diff --git a/configure.in b/configure.in +index fb02f14..c8a9ce2 100644 +--- a/configure.in ++++ b/configure.in +@@ -515,7 +515,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]) + +@@ -1943,6 +1943,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..9e32a69 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,7 @@ CLinuxRendererGLES::YUVBUFFER::YUVBUFFER() + #if defined(TARGET_ANDROID) + mediacodec = NULL; + #endif ++ codecinfo = NULL; + } + + CLinuxRendererGLES::YUVBUFFER::~YUVBUFFER() +@@ -153,6 +165,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 +297,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 +626,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 +736,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 +834,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 +@@ -954,6 +991,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 +1621,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]; ++ CDVDVideoCodecBuffer* codecinfo = m_buffers[index].codecinfo; ++ ++ if(codecinfo == NULL) return; ++ ++ CDVDVideoCodecIMX::Enter(); ++ ++ if(!codecinfo->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 +2630,114 @@ void CLinuxRendererGLES::SetTextureFilter(GLenum method) + } + } + ++//******************************************************************************************************** ++// IMXMAP creation, deletion, copying + clearing ++//******************************************************************************************************** ++void CLinuxRendererGLES::UploadIMXMAPTexture(int index) ++{ ++#ifdef HAS_IMXVPU ++ YUVBUFFER& buf = m_buffers[index]; ++ CDVDVideoCodecBuffer* codecinfo = buf.codecinfo; ++ ++ if(codecinfo) ++ { ++ CDVDVideoCodecIMX::Enter(); ++ ++ if(!codecinfo->IsValid()) ++ { ++ CDVDVideoCodecIMX::Leave(); ++ return; ++ } ++ ++ YUVPLANE &plane = m_buffers[index].fields[0][0]; ++ CDVDVideoCodecIPUBuffers *deinterlacer = (CDVDVideoCodecIPUBuffers*)codecinfo->data[2]; ++ ++ if (deinterlacer) ++ { ++ EDEINTERLACEMODE deinterlacemode = CMediaSettings::Get().GetCurrentVideoSettings().m_DeinterlaceMode; ++ ++ if (deinterlacemode != VS_DEINTERLACEMODE_OFF) ++ { ++ CDVDVideoCodecBuffer *deint; ++ EINTERLACEMETHOD interlacemethod = CMediaSettings::Get().GetCurrentVideoSettings().m_InterlaceMethod; ++ deint = deinterlacer->Process(codecinfo, (VpuFieldType)(int)codecinfo->data[3], ++ interlacemethod == VS_INTERLACEMETHOD_DEINTERLACE); ++ if (deint) ++ { ++ SAFE_RELEASE(buf.codecinfo); ++ buf.codecinfo = deint; ++ buf.codecinfo->Lock(); ++ codecinfo = buf.codecinfo; ++ } ++ } ++ } ++ ++ glActiveTexture(GL_TEXTURE0); ++ glBindTexture(m_textureTarget, plane.id); ++ ++ GLuint physical = ~0U; ++ GLvoid *virt = (GLvoid*)codecinfo->data[0]; ++ glTexDirectVIVMap(m_textureTarget, codecinfo->iWidth, codecinfo->iHeight, GL_VIV_NV12, ++ (GLvoid **)&virt, &physical); ++ glTexDirectInvalidateVIV(m_textureTarget); ++ ++ glBindTexture(m_textureTarget, 0); ++ ++ plane.flipindex = m_buffers[index].flipindex; ++ plane.texwidth = codecinfo->iWidth; ++ plane.texheight = codecinfo->iHeight; ++ ++ CalculateTextureSourceRects(index, 1); ++ ++ CDVDVideoCodecIMX::Leave(); ++ } ++ ++#endif ++} ++void CLinuxRendererGLES::DeleteIMXMAPTexture(int index) ++{ ++ 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.codecinfo); ++} ++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,9 +2804,14 @@ bool CLinuxRendererGLES::Supports(EDEINTERLACEMODE mode) + if(m_renderMethod & RENDER_CVREF) + return false; + ++#ifdef HAS_IMXVPU ++ if(mode == VS_DEINTERLACEMODE_AUTO) ++ return true; ++#else + if(mode == VS_DEINTERLACEMODE_AUTO + || mode == VS_DEINTERLACEMODE_FORCE) + return true; ++#endif + + return false; + } +@@ -2607,6 +2840,15 @@ bool CLinuxRendererGLES::Supports(EINTERLACEMETHOD method) + if(method == VS_INTERLACEMETHOD_AUTO) + return true; + ++ if(m_renderMethod & RENDER_IMXMAP) ++ { ++ if(method == VS_INTERLACEMETHOD_DEINTERLACE ++ || method == VS_INTERLACEMETHOD_DEINTERLACE_HALF) ++ return true; ++ else ++ return false; ++ } ++ + #if defined(__i386__) || defined(__x86_64__) + if(method == VS_INTERLACEMETHOD_DEINTERLACE + || method == VS_INTERLACEMETHOD_DEINTERLACE_HALF +@@ -2655,6 +2897,9 @@ EINTERLACEMETHOD CLinuxRendererGLES::AutoInterlaceMethod() + if(m_renderMethod & RENDER_CVREF) + return VS_INTERLACEMETHOD_NONE; + ++ if(m_renderMethod & RENDER_IMXMAP) ++ return VS_INTERLACEMETHOD_DEINTERLACE_HALF; ++ + #if defined(__i386__) || defined(__x86_64__) + return VS_INTERLACEMETHOD_DEINTERLACE_HALF; + #else +@@ -2739,5 +2984,16 @@ void CLinuxRendererGLES::AddProcessor(CDVDMediaCodecInfo *mediacodec, int index) + } + #endif + ++void CLinuxRendererGLES::AddProcessor(CDVDVideoCodecBuffer *codecinfo, int index) ++{ ++ YUVBUFFER &buf = m_buffers[index]; ++ ++ SAFE_RELEASE(buf.codecinfo); ++ buf.codecinfo = codecinfo; ++ ++ if (codecinfo) ++ codecinfo->Lock(); ++} ++ + #endif + +diff --git a/xbmc/cores/VideoRenderers/LinuxRendererGLES.h b/xbmc/cores/VideoRenderers/LinuxRendererGLES.h +index 642cded..54f0c18 100644 +--- a/xbmc/cores/VideoRenderers/LinuxRendererGLES.h ++++ b/xbmc/cores/VideoRenderers/LinuxRendererGLES.h +@@ -33,6 +33,7 @@ + #include "guilib/GraphicContext.h" + #include "BaseRenderer.h" + #include "xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h" ++#include "xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecInfo.h" + + class CRenderCapture; + +@@ -89,7 +90,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 +172,7 @@ public: + // mediaCodec + virtual void AddProcessor(CDVDMediaCodecInfo *mediacodec, int index); + #endif ++ virtual void AddProcessor(CDVDVideoCodecBuffer *codecinfo, int index); + + protected: + virtual void Render(DWORD flags, int index); +@@ -209,6 +212,10 @@ protected: + 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 +226,7 @@ protected: + 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 +293,7 @@ protected: + // mediacodec + CDVDMediaCodecInfo *mediacodec; + #endif ++ CDVDVideoCodecBuffer *codecinfo; + }; + + 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..6598e00 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.codecinfo, index); ++#endif + + m_pRenderer->ReleaseImage(index, false); + +diff --git a/xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.cpp b/xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.cpp +index 32d58d4..048bd92 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(HAVE_LIBCRYSTALHD) + #include "Video/DVDVideoCodecCrystalHD.h" +@@ -189,7 +192,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)) +@@ -206,6 +213,15 @@ CDVDVideoCodec* CDVDFactoryCodec::CreateVideoCodec(CDVDStreamInfo &hint, unsigne + } + #endif + ++/*#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..c25eb38 100644 +--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h ++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h +@@ -25,6 +25,7 @@ + #include + #include + #include "cores/VideoRenderers/RenderFormats.h" ++#include "DVDVideoCodecInfo.h" + + extern "C" { + #include "libavcodec/avcodec.h" +@@ -95,6 +96,11 @@ struct DVDVideoPicture + struct { + CDVDMediaCodecInfo *mediacodec; + }; ++ ++ struct { ++ CDVDVideoCodecBuffer *codecinfo; ++ }; ++ + }; + + 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..782510f +--- /dev/null ++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp +@@ -0,0 +1,1501 @@ ++/* ++ * 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 ++#include ++#include "threads/SingleLock.h" ++#include "utils/log.h" ++#include "DVDClock.h" ++#include "threads/Atomics.h" ++ ++ ++// FIXME get rid of these defines properly ++#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)) ++ ++// Extrace physical and virtual addresses from CDVDVideoCodecBuffer pointers ++#define GET_PHYS_ADDR(buf) (buf)->data[1] ++#define GET_VIRT_ADDR(buf) (buf)->data[0] ++#define GET_DEINTERLACER(buf) (buf)->data[2] ++#define GET_FIELDTYPE(buf) (buf)->data[3] ++ ++// Experiments show that we need at least one more (+1) V4L 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; ++ //ptr+=ySize+uSize+vSize+mvSize; ++ // 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; ++ //ptrVirt+=ySize+uSize+vSize+mvSize; ++ ++ 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 ++ } ++ ++ if (m_initInfo.nInterlace) ++ { ++ CLog::Log(LOGNOTICE, "IMX: Enable hardware deinterlacing\n"); ++ if (!m_deinterlacer.Init(m_initInfo.nPicWidth, m_initInfo.nPicHeight, GetAllowedReferences()+1, nAlign)) ++ { ++ CLog::Log(LOGWARNING, "IMX: Failed to initialize IPU buffers: deinterlacing disabled\n"); ++ } ++ else ++ { ++ for (int i=0; iOpen(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; ++/* FIXME TODO ++ * => for this type we have to set height, width, nChromaInterleave and nMapType ++ case CODEC_ID_MJPEG: ++ m_decOpenParam.CodecFormat = VPU_V_MJPG; ++ m_pFormatName = "iMX-mjpg"; ++ 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; ++ ++ // Block render thread from using that framebuffers ++ 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; ++ m_deinterlacer.Close(); ++ ++ // Clear 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; ++ // FIXME TODO VP8 & DivX3 require specific sCodecData values ++ 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_deinterlacer.Reset(); ++ 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->codecinfo); ++ } ++ ++ 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 ++ ++ /* ++ // This does not work reliably since some streams do not report ++ // correctly if a frame is interlaced. ++ if (m_frameInfo.eFieldType != VPU_FIELD_NONE) ++ GET_DEINTERLACER(buffer) = (uint8_t*)&m_deinterlacer; ++ else ++ GET_DEINTERLACER(buffer) = NULL; ++ */ ++ ++ pDvdVideoPicture->codecinfo = buffer; ++ pDvdVideoPicture->codecinfo->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) ++{ ++ GET_DEINTERLACER(this) = 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(); ++ ++ iWidth = frameInfo->pExtInfo->nFrmWidth; ++ iHeight = frameInfo->pExtInfo->nFrmHeight; ++ GET_VIRT_ADDR(this) = m_frameBuffer->pbufVirtY; ++ GET_PHYS_ADDR(this) = m_frameBuffer->pbufY; ++ GET_FIELDTYPE(this) = (uint8_t*)frameInfo->eFieldType; ++} ++ ++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 ++} ++ ++#ifdef TRACE_FRAMES ++CDVDVideoCodecIPUBuffer::CDVDVideoCodecIPUBuffer(int idx) ++ : m_refs(1) ++ , m_idx(idx) ++#else ++CDVDVideoCodecIPUBuffer::CDVDVideoCodecIPUBuffer() ++ : m_refs(1) ++#endif ++ , m_source(NULL) ++ , m_pPhyAddr(NULL) ++ , m_pVirtAddr(NULL) ++ , m_nSize(0) ++{ ++} ++ ++CDVDVideoCodecIPUBuffer::~CDVDVideoCodecIPUBuffer() ++{ ++ assert(m_refs == 0); ++#ifdef TRACE_FRAMES ++ CLog::Log(LOGDEBUG, "~ %02d (IPU)\n", m_idx); ++#endif ++} ++ ++void CDVDVideoCodecIPUBuffer::Lock() ++{ ++#ifdef TRACE_FRAMES ++ long count = AtomicIncrement(&m_refs); ++ CLog::Log(LOGDEBUG, "R+ %02d - ref : %d (IPU)\n", m_idx, count); ++#else ++ AtomicIncrement(&m_refs); ++#endif ++ ++} ++ ++long CDVDVideoCodecIPUBuffer::Release() ++{ ++ long count = AtomicDecrement(&m_refs); ++#ifdef TRACE_FRAMES ++ CLog::Log(LOGDEBUG, "R- %02d - ref : %d (IPU)\n", m_idx, count); ++#endif ++ if (count == 1) ++ { ++ ReleaseFrameBuffer(); ++ } ++ else if (count == 0) ++ { ++ delete this; ++ } ++ ++ return count; ++} ++ ++bool CDVDVideoCodecIPUBuffer::IsValid() ++{ ++ return m_source && m_source->IsValid() && m_pPhyAddr; ++} ++ ++bool CDVDVideoCodecIPUBuffer::Process(int fd, CDVDVideoCodecIMXBuffer *buffer, ++ VpuFieldType fieldType, int fieldFmt, ++ bool lowMotion) ++{ ++ CDVDVideoCodecIMXBuffer *previousBuffer; ++ struct ipu_task task; ++ memset(&task, 0, sizeof(task)); ++ task.priority = IPU_TASK_PRIORITY_HIGH; ++ ++ if (lowMotion) ++ previousBuffer = buffer->GetPreviousBuffer(); ++ else ++ previousBuffer = NULL; ++ ++ SAFE_RELEASE(m_source); ++ ++ iWidth = buffer->iWidth; ++ iHeight = buffer->iHeight; ++ ++ // Input is the VPU decoded frame ++ task.input.width = iWidth; ++ task.input.height = iHeight; ++ task.input.format = IPU_PIX_FMT_NV12; ++ ++ // Output is our IPU buffer ++ task.output.width = iWidth; ++ task.output.height = iHeight; ++ task.output.format = IPU_PIX_FMT_NV12; ++ task.output.paddr = (int)GET_PHYS_ADDR(this); ++ ++ // Fill current and next buffer address ++ if (lowMotion && previousBuffer && previousBuffer->IsValid()) ++ { ++ task.input.paddr = (int)GET_PHYS_ADDR(previousBuffer); ++ task.input.paddr_n = (int)GET_PHYS_ADDR(buffer); ++ task.input.deinterlace.motion = LOW_MOTION; ++ } ++ else ++ { ++ task.input.paddr = (int)GET_PHYS_ADDR(buffer); ++ task.input.deinterlace.motion = HIGH_MOTION; ++ } ++ ++ task.input.deinterlace.enable = 1; ++ task.input.deinterlace.field_fmt = fieldFmt; ++ ++ switch (fieldType) ++ { ++ case VPU_FIELD_TOP: ++ case VPU_FIELD_TB: ++ task.input.deinterlace.field_fmt |= IPU_DEINTERLACE_FIELD_TOP; ++ break; ++ case VPU_FIELD_BOTTOM: ++ case VPU_FIELD_BT: ++ task.input.deinterlace.field_fmt |= IPU_DEINTERLACE_FIELD_BOTTOM; ++ break; ++ default: ++ break; ++ } ++ ++#ifdef IMX_PROFILE ++ unsigned int time = XbmcThreads::SystemClockMillis(); ++#endif ++ int ret = ioctl(fd, IPU_QUEUE_TASK, &task); ++#ifdef IMX_PROFILE ++ CLog::Log(LOGDEBUG, "DEINT: tm:%d\n", XbmcThreads::SystemClockMillis() - time); ++#endif ++ if (ret < 0) ++ { ++ CLog::Log(LOGERROR, "IPU task failed: %s\n", strerror(errno)); ++ return false; ++ } ++ ++ buffer->Lock(); ++ ++ // Remember the source buffer. This is actually not necessary since the output ++ // buffer is the one that is used by the renderer. But keep it bound for now ++ // since this state is used in IsValid which then needs to become a flag in ++ // this class. ++ m_source = buffer; ++ m_source->Lock(); ++ ++ buffer->Release(); ++ ++ return true; ++} ++ ++void CDVDVideoCodecIPUBuffer::ReleaseFrameBuffer() ++{ ++#ifdef TRACE_FRAMES ++ CLog::Log(LOGDEBUG, "- %02d (IPU)\n", m_idx); ++#endif ++ CSingleLock lock(CDVDVideoCodecIMX::m_codecBufferLock); ++ SAFE_RELEASE(m_source); ++} ++ ++bool CDVDVideoCodecIPUBuffer::Allocate(int fd, int width, int height, int nAlign) ++{ ++ m_iWidth = Align(width,FRAME_ALIGN); ++ m_iHeight = Align(height,(2*FRAME_ALIGN)); ++ // NV12 == 12 bpp ++ m_nSize = m_iWidth*m_iHeight*12/8; ++ m_pPhyAddr = m_nSize; ++ ++ GET_PHYS_ADDR(this) = GET_VIRT_ADDR(this) = NULL; ++ ++ int r = ioctl(fd, IPU_ALLOC, &m_pPhyAddr); ++ if (r < 0) ++ { ++ m_pPhyAddr = 0; ++ CLog::Log(LOGERROR, "ioctl IPU_ALLOC fail: disable deinterlacing: %s\n", strerror(errno)); ++ return false; ++ } ++ ++ CLog::Log(LOGNOTICE, "IPU: alloc %d bytes for frame of %dx%d at 0x%x\n", ++ m_nSize, m_iWidth, m_iHeight, m_pPhyAddr); ++ ++ m_pVirtAddr = (uint8_t*)mmap(0, m_nSize, PROT_READ | PROT_WRITE, MAP_SHARED, ++ fd, m_pPhyAddr); ++ if (!m_pVirtAddr) ++ { ++ CLog::Log(LOGERROR, "IPU mmap failed: disable deinterlacing: %s\n", strerror(errno)); ++ return false; ++ } ++ ++ if (nAlign>1) ++ { ++ GET_PHYS_ADDR(this) = (uint8_t*)Align(m_pPhyAddr, nAlign); ++ GET_VIRT_ADDR(this) = (uint8_t*)Align(m_pVirtAddr, nAlign); ++ } ++ else ++ { ++ GET_PHYS_ADDR(this) = (uint8_t*)m_pPhyAddr; ++ GET_VIRT_ADDR(this) = (uint8_t*)m_pVirtAddr; ++ } ++ ++ GET_DEINTERLACER(this) = NULL; ++ ++ return true; ++} ++ ++bool CDVDVideoCodecIPUBuffer::Free(int fd) ++{ ++ CSingleLock lock(CDVDVideoCodecIMX::m_codecBufferLock); ++ bool ret = true; ++ ++ // Unmap virtual memory ++ if (m_pVirtAddr != NULL) ++ { ++ if(munmap(m_pVirtAddr, m_nSize)) ++ { ++ CLog::Log(LOGERROR, "IPU unmap failed: %s\n", strerror(errno)); ++ ret = false; ++ } ++ ++ m_pVirtAddr = NULL; ++ } ++ ++ // Free IPU memory ++ if (m_pPhyAddr) ++ { ++ if (ioctl(fd, IPU_FREE, &m_pPhyAddr)) ++ { ++ CLog::Log(LOGERROR, "IPU free buffer 0x%x failed: %s\n", ++ m_pPhyAddr, strerror(errno)); ++ ret = false; ++ } ++ ++ m_pPhyAddr = 0; ++ } ++ ++ GET_PHYS_ADDR(this) = GET_VIRT_ADDR(this) = NULL; ++ SAFE_RELEASE(m_source); ++ ++ return ret; ++} ++ ++CDVDVideoCodecIPUBuffers::CDVDVideoCodecIPUBuffers() ++ : m_ipuHandle(0) ++ , m_bufferNum(0) ++ , m_buffers(NULL) ++ , m_currentFieldFmt(0) ++{ ++} ++ ++CDVDVideoCodecIPUBuffers::~CDVDVideoCodecIPUBuffers() ++{ ++ Close(); ++} ++ ++bool CDVDVideoCodecIPUBuffers::Init(int width, int height, int numBuffers, int nAlign) ++{ ++ if (numBuffers<=0) ++ { ++ CLog::Log(LOGERROR, "IPU Init: invalid number of buffers: %d\n", numBuffers); ++ return false; ++ } ++ ++ m_ipuHandle = open("/dev/mxc_ipu", O_RDWR, 0); ++ if (m_ipuHandle<=0) ++ { ++ CLog::Log(LOGWARNING, "Failed to initialize IPU: deinterlacing disabled: %s\n", ++ strerror(errno)); ++ m_ipuHandle = 0; ++ return false; ++ } ++ ++ m_bufferNum = numBuffers; ++ m_buffers = new CDVDVideoCodecIPUBuffer*[m_bufferNum]; ++ m_currentFieldFmt = 0; ++ ++ for (int i=0; i < m_bufferNum; i++) ++ { ++#ifdef TRACE_FRAMES ++ m_buffers[i] = new CDVDVideoCodecIPUBuffer(i); ++#else ++ m_buffers[i] = new CDVDVideoCodecIPUBuffer; ++#endif ++ if (!m_buffers[i]->Allocate(m_ipuHandle, width, height, nAlign)) ++ { ++ Close(); ++ return false; ++ } ++ } ++ ++ return true; ++} ++ ++bool CDVDVideoCodecIPUBuffers::Reset() ++{ ++ for (int i=0; i < m_bufferNum; i++) ++ m_buffers[i]->ReleaseFrameBuffer(); ++ m_currentFieldFmt = 0; ++} ++ ++bool CDVDVideoCodecIPUBuffers::Close() ++{ ++ bool ret = true; ++ ++ if (m_ipuHandle) ++ { ++ for (int i=0; i < m_bufferNum; i++) ++ { ++ if (m_buffers[i] == NULL ) continue; ++ if (!m_buffers[i]->Free(m_ipuHandle)) ++ ret = false; ++ } ++ ++ // Close IPU device ++ if (close(m_ipuHandle)) ++ { ++ CLog::Log(LOGERROR, "IPU failed to close interface: %s\n", strerror(errno)); ++ ret = false; ++ } ++ ++ m_ipuHandle = 0; ++ } ++ ++ if (m_buffers) ++ { ++ for (int i=0; i < m_bufferNum; i++) ++ SAFE_RELEASE(m_buffers[i]); ++ ++ delete m_buffers; ++ m_buffers = NULL; ++ } ++ ++ m_bufferNum = 0; ++ return true; ++} ++ ++CDVDVideoCodecIPUBuffer * ++CDVDVideoCodecIPUBuffers::Process(CDVDVideoCodecBuffer *sourceBuffer, ++ VpuFieldType fieldType, bool lowMotion) ++{ ++ CDVDVideoCodecIPUBuffer *target = NULL; ++ bool ret = true; ++ ++ // TODO: Needs further checks on real streams ++ if (!m_bufferNum /*|| (fieldType == VPU_FIELD_NONE)*/) ++ return NULL; ++ ++ for (int i=0; i < m_bufferNum; i++ ) ++ { ++ if (!m_buffers[i]->Rendered()) continue; ++ ++ // IPU process: ++ // SRC: Current VPU physical buffer address + last VPU buffer address ++ // DST: IPU buffer[i] ++ ret = m_buffers[i]->Process(m_ipuHandle, (CDVDVideoCodecIMXBuffer*)sourceBuffer, ++ fieldType, m_currentFieldFmt/* | IPU_DEINTERLACE_RATE_EN*/, ++ lowMotion); ++ if (ret) ++ { ++#ifdef TRACE_FRAMES ++ CLog::Log(LOGDEBUG, "+ %02d (IPU)\n", i); ++#endif ++ target = m_buffers[i]; ++ } ++ break; ++ } ++ ++ // Buffers are there but there is no free one, this is an error! ++ // Rendering will continue with unprocessed frames ... ++ if (ret && target==NULL) ++ { ++ CLog::Log(LOGERROR, "Deinterlacing: did not find free buffer, forward unprocessed frame\n"); ++ } ++ ++ // Toggle frame index bit ++ //m_currentFieldFmt ^= IPU_DEINTERLACE_RATE_FRAME1; ++ ++ return target; ++} +diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h +new file mode 100644 +index 0000000..05722ce +--- /dev/null ++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h +@@ -0,0 +1,215 @@ ++#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 "DVDVideoCodecInfo.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 CDVDVideoCodecIPUBuffer; ++ ++class CDVDVideoCodecIMXBuffer : public CDVDVideoCodecBuffer ++{ ++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; ++ ++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 ++}; ++ ++// Shared buffer that holds an IPU allocated memory block and serves as target ++// for IPU operations such as deinterlacing, rotation or color conversion. ++class CDVDVideoCodecIPUBuffer : public CDVDVideoCodecBuffer ++{ ++public: ++#ifdef TRACE_FRAMES ++ CDVDVideoCodecIPUBuffer(int idx); ++#else ++ CDVDVideoCodecIPUBuffer(); ++#endif ++ ++ // reference counting ++ virtual void Lock(); ++ virtual long Release(); ++ virtual bool IsValid(); ++ ++ // Returns whether the buffer is ready to be used ++ bool Rendered() const { return m_source == NULL; } ++ bool Process(int fd, CDVDVideoCodecIMXBuffer *buffer, ++ VpuFieldType fieldType, int fieldFmt, ++ bool lowMotion); ++ void ReleaseFrameBuffer(); ++ ++ bool Allocate(int fd, int width, int height, int nAlign); ++ bool Free(int fd); ++ ++private: ++ virtual ~CDVDVideoCodecIPUBuffer(); ++ ++private: ++#ifdef TRACE_FRAMES ++ int m_idx; ++#endif ++ long m_refs; ++ CDVDVideoCodecBuffer *m_source; ++ int m_pPhyAddr; ++ uint8_t *m_pVirtAddr; ++ int m_iWidth; ++ int m_iHeight; ++ int m_nSize; ++}; ++ ++// Collection class that manages a pool of IPU buffers that are used for ++// deinterlacing. In future they can also serve rotation or color conversion ++// buffers. ++class CDVDVideoCodecIPUBuffers ++{ ++ public: ++ CDVDVideoCodecIPUBuffers(); ++ ~CDVDVideoCodecIPUBuffers(); ++ ++ bool Init(int width, int height, int numBuffers, int nAlign); ++ bool Reset(); ++ bool Close(); ++ ++ CDVDVideoCodecIPUBuffer *Process(CDVDVideoCodecBuffer *sourceBuffer, ++ VpuFieldType fieldType, bool lowMotion); ++ ++ private: ++ int m_ipuHandle; ++ int m_bufferNum; ++ CDVDVideoCodecIPUBuffer **m_buffers; ++ int m_currentFieldFmt; ++}; ++ ++ ++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; ++ ++ 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 ++ CDVDVideoCodecIPUBuffers m_deinterlacer; ++ CDVDVideoCodecIMXBuffer **m_outputBuffers; ++ CDVDVideoCodecIMXBuffer *m_lastBuffer; ++ 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; ++ CBitstreamConverter *m_converter; ++ bool m_convert_bitstream; ++ 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/DVDVideoCodecInfo.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecInfo.h +new file mode 100644 +index 0000000..6096bf4 +--- /dev/null ++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecInfo.h +@@ -0,0 +1,38 @@ ++/* ++ * Copyright (C) 2010-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 ++ * . ++ * ++ */ ++ ++#ifndef DVDVIDEOCODECINFO_H ++#define DVDVIDEOCODECINFO_H ++ ++class CDVDVideoCodecBuffer ++{ ++public: ++ // reference counting ++ virtual void Lock() = 0; ++ virtual long Release() = 0; ++ virtual bool IsValid() = 0; ++ ++ uint32_t iWidth; ++ uint32_t iHeight; ++ uint8_t* data[4]; // [4] = alpha channel, currently not used ++ int iLineSize[4]; // [4] = alpha channel, currently not used ++}; ++ ++#endif // DVDVIDEOCODECINFO_H +diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/Makefile.in b/xbmc/cores/dvdplayer/DVDCodecs/Video/Makefile.in +index 8a97889..d019a91 100644 +--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/Makefile.in ++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/Makefile.in +@@ -24,6 +24,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 be532ec..7812523 100644 +--- a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp ++++ b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp +@@ -996,6 +996,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"; +-- +1.9.3 + diff --git a/packages/mediacenter/xbmc/patches/xbmc-998.0002-ADD-imx-native-framebuffer-support.patch b/packages/mediacenter/xbmc/patches/xbmc-998.0002-ADD-imx-native-framebuffer-support.patch new file mode 100644 index 00000000000..65ffccf3bca --- /dev/null +++ b/packages/mediacenter/xbmc/patches/xbmc-998.0002-ADD-imx-native-framebuffer-support.patch @@ -0,0 +1,483 @@ +From 5f58f7153633ba7bc803fe40580d361dbae96592 Mon Sep 17 00:00:00 2001 +From: "Chris \"Koying\" Browet" +Date: Thu, 7 Aug 2014 13:51:15 +0200 +Subject: [PATCH 2/4] ADD: [imx] native framebuffer support + +--- + configure.in | 9 + + xbmc/windowing/egl/EGLNativeTypeIMX.cpp | 321 ++++++++++++++++++++++++++++++++ + xbmc/windowing/egl/EGLNativeTypeIMX.h | 60 ++++++ + xbmc/windowing/egl/EGLWrapper.cpp | 11 +- + xbmc/windowing/egl/Makefile.in | 4 + + 5 files changed, 402 insertions(+), 3 deletions(-) + create mode 100644 xbmc/windowing/egl/EGLNativeTypeIMX.cpp + create mode 100644 xbmc/windowing/egl/EGLNativeTypeIMX.h + +diff --git a/configure.in b/configure.in +index c8a9ce2..a505582 100644 +--- a/configure.in ++++ b/configure.in +@@ -985,6 +985,15 @@ else + AC_MSG_RESULT($wayland_disabled) + fi + ++# i.MX6 ++AC_MSG_CHECKING([for i.MX framebuffer support]) ++AC_CHECK_HEADER([linux/mxcfb.h], have_imxfb=yes,have_imxfb=no) ++AC_MSG_RESULT($have_imxfb) ++if test "x$have_imxfb" = "xyes"; then ++ AC_DEFINE([HAS_IMXFB], [1], [Whether i.MX framebuffer support is enabled.]) ++ AC_SUBST([USE_IMXFB], 1) ++fi ++ + # Checks for platforms libraries. + if test "$use_gles" = "yes"; then + use_gl="no" +diff --git a/xbmc/windowing/egl/EGLNativeTypeIMX.cpp b/xbmc/windowing/egl/EGLNativeTypeIMX.cpp +new file mode 100644 +index 0000000..3dc64a3 +--- /dev/null ++++ b/xbmc/windowing/egl/EGLNativeTypeIMX.cpp +@@ -0,0 +1,321 @@ ++/* ++ * 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 "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); ++ ++ // EGL will be rendered on fb0 ++ m_display = fbGetDisplayByIndex(0); ++ m_nativeDisplay = &m_display; ++ return true; ++} ++ ++bool CEGLNativeTypeIMX::CreateNativeWindow() ++{ ++ m_window = fbCreateWindow(m_display, 0, 0, 0, 0); ++ m_nativeWindow = &m_window; ++ return true; ++} ++ ++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() ++{ ++ if (m_display) ++ fbDestroyDisplay(m_display); ++ m_display = NULL; ++ return true; ++} ++ ++bool CEGLNativeTypeIMX::DestroyNativeWindow() ++{ ++ if (m_window) ++ fbDestroyWindow(m_window); ++ m_window = NULL; ++ return true; ++} ++ ++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; ++ StringUtils::SplitString(valstr, "\n", probe_str); ++ ++ 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..df7b3b7 +--- /dev/null ++++ b/xbmc/windowing/egl/EGLNativeTypeIMX.h +@@ -0,0 +1,60 @@ ++#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" ++#include "EGL/eglvivante.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..4d74be5 100644 +--- a/xbmc/windowing/egl/EGLWrapper.cpp ++++ b/xbmc/windowing/egl/EGLWrapper.cpp +@@ -17,16 +17,17 @@ + * . + * + */ +- + #include "system.h" + + #ifdef HAS_EGL +- + #include "utils/log.h" + #include "EGLNativeTypeAndroid.h" + #include "EGLNativeTypeAmlogic.h" + #include "EGLNativeTypeRaspberryPI.h" + #include "EGLNativeTypeWayland.h" ++#ifdef HAS_IMXVPU ++#include "EGLNativeTypeIMX.h" ++#endif + #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 +84,11 @@ bool CEGLWrapper::Initialize(const std::string &implementation) + if ((nativeGuess = CreateEGLNativeType(implementation)) || + (nativeGuess = CreateEGLNativeType(implementation)) || + (nativeGuess = CreateEGLNativeType(implementation)) || +- (nativeGuess = CreateEGLNativeType(implementation))) ++ (nativeGuess = CreateEGLNativeType(implementation)) ++#ifdef HAS_IMXFB ++ || (nativeGuess = CreateEGLNativeType(implementation)) ++#endif ++ ) + { + m_nativeTypes = nativeGuess; + +diff --git a/xbmc/windowing/egl/Makefile.in b/xbmc/windowing/egl/Makefile.in +index f800b7f..ec84c1d 100644 +--- a/xbmc/windowing/egl/Makefile.in ++++ b/xbmc/windowing/egl/Makefile.in +@@ -24,6 +24,10 @@ SRCS+= wayland/Callback.cpp \ + wayland/XBMCSurface.cpp + endif + ++ifeq (@USE_IMXFB@,1) ++SRCS+= EGLNativeTypeIMX.cpp ++endif ++ + LIB = windowing_egl.a + + include ../../../Makefile.include +-- +1.9.3 + diff --git a/packages/mediacenter/xbmc/patches/xbmc-998.0003-imx-squashme-fix-build-after-https-github.com-xbmc-i.patch b/packages/mediacenter/xbmc/patches/xbmc-998.0003-imx-squashme-fix-build-after-https-github.com-xbmc-i.patch new file mode 100644 index 00000000000..9dbfecb9ee6 --- /dev/null +++ b/packages/mediacenter/xbmc/patches/xbmc-998.0003-imx-squashme-fix-build-after-https-github.com-xbmc-i.patch @@ -0,0 +1,27 @@ +From 01c1e0d01e418f2b07828c1eaaaa1a6ab5e82a4e Mon Sep 17 00:00:00 2001 +From: Stephan Raue +Date: Sun, 10 Aug 2014 01:48:04 +0200 +Subject: [PATCH 3/4] [imx] squashme: fix build after + https://github.com/xbmc-imx6/xbmc/commit/74f3f02 + +--- + xbmc/windowing/egl/EGLNativeTypeIMX.cpp | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/xbmc/windowing/egl/EGLNativeTypeIMX.cpp b/xbmc/windowing/egl/EGLNativeTypeIMX.cpp +index 3dc64a3..b1f2783 100644 +--- a/xbmc/windowing/egl/EGLNativeTypeIMX.cpp ++++ b/xbmc/windowing/egl/EGLNativeTypeIMX.cpp +@@ -211,8 +211,7 @@ bool CEGLNativeTypeIMX::ProbeResolutions(std::vector &resolutio + + std::string valstr; + get_sysfs_str("/sys/class/graphics/fb0/modes", valstr); +- std::vector probe_str; +- StringUtils::SplitString(valstr, "\n", probe_str); ++ std::vector probe_str = StringUtils::Split(valstr, "\n"); + + resolutions.clear(); + RESOLUTION_INFO res; +-- +1.9.3 + diff --git a/packages/mediacenter/xbmc/patches/xbmc-998.0004-ADD-imx-add-Freescale-imx-audio-support.patch b/packages/mediacenter/xbmc/patches/xbmc-998.0004-ADD-imx-add-Freescale-imx-audio-support.patch new file mode 100644 index 00000000000..acdd932819c --- /dev/null +++ b/packages/mediacenter/xbmc/patches/xbmc-998.0004-ADD-imx-add-Freescale-imx-audio-support.patch @@ -0,0 +1,69 @@ +From e062d1adba00d0503a46937eb0957ba6405af36b Mon Sep 17 00:00:00 2001 +From: wolfgar +Date: Fri, 31 Jan 2014 14:43:24 +0100 +Subject: [PATCH 4/4] ADD: [imx] add Freescale imx audio support + +--- + xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp | 25 +++++++++++++++++++++++++ + 1 file changed, 25 insertions(+) + +diff --git a/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp b/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp +index 8dee4bc..871ecc0 100644 +--- a/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp ++++ b/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp +@@ -1079,12 +1079,17 @@ void CAESinkALSA::EnumerateDevicesEx(AEDeviceInfoList &list, bool force) + snd_config_t *config; + snd_config_copy(&config, snd_config); + ++#ifndef HAS_IMXFB + /* Always enumerate the default device. + * Note: If "default" is a stereo device, EnumerateDevice() + * will automatically add "@" instead to enable surroundXX mangling. + * We don't want to do that if "default" can handle multichannel + * itself (e.g. in case of a pulseaudio server). */ ++ ++ /* For IMX6, we do not enurate default device as it will be grabbed ++ * as one of the sysdefault devices... */ + EnumerateDevice(list, "default", "", config); ++#endif + + void **hints; + +@@ -1136,7 +1141,10 @@ void CAESinkALSA::EnumerateDevicesEx(AEDeviceInfoList &list, bool force) + * "plughw", "dsnoop"). */ + + else if (baseName != "default" ++#ifndef HAS_IMXFB ++ /* For wandboard all devices are prefixed by sysdefault so do not ignore them */ + && baseName != "sysdefault" ++#endif + && baseName != "surround40" + && baseName != "surround41" + && baseName != "surround50" +@@ -1245,6 +1253,23 @@ void CAESinkALSA::EnumerateDevicesEx(AEDeviceInfoList &list, bool force) + + AEDeviceType CAESinkALSA::AEDeviceTypeFromName(const std::string &name) + { ++#ifdef HAS_IMXFB ++ std::size_t found; ++ ++ /* Hack : Check for specific wandboard sound device names */ ++ found = name.find("imxspdif"); ++ if (found!=std::string::npos) ++ return AE_DEVTYPE_IEC958; ++ ++ found = name.find("imxhdmisoc"); ++ if (found!=std::string::npos) ++ return AE_DEVTYPE_HDMI; ++ ++ found = name.find("sgtl5000audio"); ++ if (found!=std::string::npos) ++ return AE_DEVTYPE_PCM; ++#endif ++ + if (name.substr(0, 4) == "hdmi") + return AE_DEVTYPE_HDMI; + else if (name.substr(0, 6) == "iec958" || name.substr(0, 5) == "spdif") +-- +1.9.3 + diff --git a/projects/Cuboxi/patches/xbmc/xbmc-001-imx6_support-master-pr.patch b/projects/Cuboxi/patches/xbmc/xbmc-001-imx6_support-master-pr.patch deleted file mode 100644 index b5071220245..00000000000 --- a/projects/Cuboxi/patches/xbmc/xbmc-001-imx6_support-master-pr.patch +++ /dev/null @@ -1,13200 +0,0 @@ -From 8960497bcda032b018953ebc675ecfdb96827a56 Mon Sep 17 00:00:00 2001 -From: wolfgar -Date: Fri, 31 Jan 2014 14:43:24 +0100 -Subject: [PATCH 01/50] ADD: Freeescale imx h/w codec - ---- - configure.in | 13 +- - xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp | 23 +- - xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp | 103 +- - xbmc/cores/VideoRenderers/LinuxRendererGLES.h | 7 + - xbmc/cores/VideoRenderers/RenderFormats.h | 1 + - xbmc/cores/VideoRenderers/RenderManager.cpp | 4 + - xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.cpp | 18 +- - .../dvdplayer/DVDCodecs/Video/DVDVideoCodec.h | 7 +- - .../dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp | 1737 ++++++++++++++++++++ - .../dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h | 191 +++ - xbmc/cores/dvdplayer/DVDCodecs/Video/Makefile.in | 3 + - xbmc/cores/dvdplayer/DVDCodecs/Video/mfw_gst_ts.c | 752 +++++++++ - xbmc/cores/dvdplayer/DVDCodecs/Video/mfw_gst_ts.h | 170 ++ - xbmc/cores/dvdplayer/DVDPlayerVideo.cpp | 1 + - xbmc/input/linux/LinuxInputDevices.cpp | 3 +- - xbmc/powermanagement/PowerManager.cpp | 8 +- - xbmc/windowing/egl/EGLNativeTypeIMX.cpp | 272 +++ - xbmc/windowing/egl/EGLNativeTypeIMX.h | 62 + - xbmc/windowing/egl/EGLWrapper.cpp | 6 +- - xbmc/windowing/egl/Makefile.in | 1 + - 20 files changed, 3362 insertions(+), 20 deletions(-) - create mode 100644 xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp - create mode 100644 xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h - create mode 100644 xbmc/cores/dvdplayer/DVDCodecs/Video/mfw_gst_ts.c - create mode 100644 xbmc/cores/dvdplayer/DVDCodecs/Video/mfw_gst_ts.h - create mode 100644 xbmc/windowing/egl/EGLNativeTypeIMX.cpp - create mode 100644 xbmc/windowing/egl/EGLNativeTypeIMX.h - -diff --git a/configure.in b/configure.in -index 5f3bf00..5d46d24 100644 ---- a/configure.in -+++ b/configure.in -@@ -524,7 +524,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]) - -@@ -1968,6 +1968,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/AudioEngine/Sinks/AESinkALSA.cpp b/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp -index 8dee4bc..4592e39 100644 ---- a/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp -+++ b/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp -@@ -1084,7 +1084,10 @@ void CAESinkALSA::EnumerateDevicesEx(AEDeviceInfoList &list, bool force) - * will automatically add "@" instead to enable surroundXX mangling. - * We don't want to do that if "default" can handle multichannel - * itself (e.g. in case of a pulseaudio server). */ -- EnumerateDevice(list, "default", "", config); -+ -+ /* For Wandboard, we do not enurate default device as it will be grabbed -+ * as one of the sysdefault devices... */ -+ - - void **hints; - -@@ -1135,8 +1138,8 @@ void CAESinkALSA::EnumerateDevicesEx(AEDeviceInfoList &list, bool force) - * found by the enumeration process. Skip them as well ("hw", "dmix", - * "plughw", "dsnoop"). */ - -+ /* For wandboard all devices are prefixed by sysdefault so do not ignore them */ - else if (baseName != "default" -- && baseName != "sysdefault" - && baseName != "surround40" - && baseName != "surround41" - && baseName != "surround50" -@@ -1245,6 +1248,22 @@ void CAESinkALSA::EnumerateDevicesEx(AEDeviceInfoList &list, bool force) - - AEDeviceType CAESinkALSA::AEDeviceTypeFromName(const std::string &name) - { -+ std::size_t found; -+ -+ /* Hack : Check for specific wandboard sound device names */ -+ found = name.find("imxspdif"); -+ if (found!=std::string::npos) -+ return AE_DEVTYPE_IEC958; -+ -+ found = name.find("imxhdmisoc"); -+ if (found!=std::string::npos) -+ return AE_DEVTYPE_HDMI; -+ -+ found = name.find("sgtl5000audio"); -+ if (found!=std::string::npos) -+ return AE_DEVTYPE_PCM; -+ -+ - if (name.substr(0, 4) == "hdmi") - return AE_DEVTYPE_HDMI; - else if (name.substr(0, 6) == "iec958" || name.substr(0, 5) == "spdif") -diff --git a/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp b/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp -index 72eb725..913fb0f 100644 ---- a/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp -+++ b/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp -@@ -20,6 +20,10 @@ - - //#define DEBUG_VERBOSE 1 - -+#ifdef HAS_IMXVPU -+#include -+#endif -+ - #include "system.h" - #if (defined HAVE_CONFIG_H) && (!defined TARGET_WINDOWS) - #include "config.h" -@@ -66,6 +70,11 @@ extern "C" { - #ifdef TARGET_DARWIN_IOS - #include "osx/DarwinUtils.h" - #endif -+ -+#ifdef HAS_IMXVPU -+#include "DVDCodecs/Video/DVDVideoCodecIMX.h" -+#endif -+ - #if defined(HAS_LIBSTAGEFRIGHT) - #include - #include -@@ -103,6 +112,10 @@ CLinuxRendererGLES::YUVBUFFER::YUVBUFFER() - #if defined(TARGET_ANDROID) - mediacodec = NULL; - #endif -+#ifdef HAS_IMXVPU -+ imxOutputFrame = NULL; -+#endif -+ - } - - CLinuxRendererGLES::YUVBUFFER::~YUVBUFFER() -@@ -113,6 +126,23 @@ CLinuxRendererGLES::CLinuxRendererGLES() - { - m_textureTarget = GL_TEXTURE_2D; - -+ /* FIXME a verifier */ -+#if 0 -+ -+ for (int i = 0; i < NUM_BUFFERS; i++) -+ { -+#if defined(HAVE_LIBOPENMAX) -+ m_buffers[i].openMaxBuffer = 0; -+#endif -+#ifdef HAVE_VIDEOTOOLBOXDECODER -+ m_buffers[i].cvBufferRef = NULL; -+#endif -+#ifdef HAS_IMXVPU -+ m_buffers[i].imx = NULL; -+#endif -+ } -+#endif -+ - m_renderMethod = RENDER_GLSL; - m_oldRenderMethod = m_renderMethod; - m_renderQuality = RQ_SINGLEPASS; -@@ -498,18 +528,53 @@ void CLinuxRendererGLES::RenderUpdate(bool clear, DWORD flags, DWORD alpha) - (*m_RenderUpdateCallBackFn)(m_RenderUpdateCallBackCtx, m_sourceRect, m_destRect); - - CRect old = g_graphicsContext.GetScissors(); -+ RESOLUTION res = GetResolution(); -+ int iWidth = CDisplaySettings::Get().GetResolutionInfo(res).iWidth; -+ int iHeight = CDisplaySettings::Get().GetResolutionInfo(res).iHeight; - - g_graphicsContext.BeginPaint(); -+ if (clear) -+ { -+ glScissor(0, -+ 0, -+ iWidth, -+ iHeight); -+ glClearColor(GLfloat(0.0), GLfloat(0.0), GLfloat(0.0), 0); -+ glClear(GL_COLOR_BUFFER_BIT); -+ } -+ - g_graphicsContext.SetScissors(m_destRect); -+ /* CLog::Log(LOGDEBUG, "%s - m_destRect : %f %f %f %f\n", -+ __FUNCTION__, m_destRect.x1, m_destRect.x2, m_destRect.y1,m_destRect.y2);*/ - -- glEnable(GL_BLEND); -- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); -- glClearColor(0, 0, 0, 0); -+ -+/* glEnable(GL_BLEND); -+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);*/ -+ glClearColor(GLfloat(2.0/31.0), GLfloat(2.0/63.0), GLfloat(2.0/31.0), 0); - glClear(GL_COLOR_BUFFER_BIT); - - g_graphicsContext.SetScissors(old); - g_graphicsContext.EndPaint(); -+ -+#ifdef HAS_IMXVPU -+ // FIXME : move in its own render mode instead of mixup with BYPASS -+ if (m_format == RENDER_FMT_IMX) -+ { -+ int index = m_iYV12RenderBuffer; -+ struct v4l2_crop crop; -+ crop.c.top = (int)m_destRect.y1; -+ crop.c.left = (int)m_destRect.x1; -+ crop.c.width = (int)(m_destRect.x2 - m_destRect.x1); -+ crop.c.height = (int)(m_destRect.y2 - m_destRect.y1); -+ CIMXOutputFrame *imxPicture = m_buffers[index].imxOutputFrame; -+ if (imxPicture != NULL) -+ { -+ imxPicture->Render(crop); -+ m_buffers[index].imxOutputFrame = NULL; -+ } -+ } - return; -+#endif - } - - // this needs to be checked after texture validation -@@ -598,6 +663,9 @@ unsigned int CLinuxRendererGLES::PreInit() - #ifdef HAVE_VIDEOTOOLBOXDECODER - m_formats.push_back(RENDER_FMT_CVBREF); - #endif -+#ifdef HAS_IMXVPU -+ m_formats.push_back(RENDER_FMT_IMX); -+#endif - #ifdef HAS_LIBSTAGEFRIGHT - m_formats.push_back(RENDER_FMT_EGLIMG); - #endif -@@ -723,6 +791,13 @@ void CLinuxRendererGLES::LoadShaders(int field) - m_renderMethod = RENDER_CVREF; - break; - } -+ else if (m_format == RENDER_FMT_IMX) -+ { -+ CLog::Log(LOGNOTICE, "GL: IMX format Uses BYPASS render method"); -+ m_renderMethod = RENDER_BYPASS; -+ break; -+ } -+ - #if defined(TARGET_DARWIN_IOS) - else if (ios_version < 5.0 && m_format == RENDER_FMT_YUV420P) - { -@@ -893,6 +968,18 @@ void CLinuxRendererGLES::ReleaseBuffer(int idx) - } - } - #endif -+#ifdef HAS_IMXVPU -+ if (buf.imxOutputFrame != NULL) -+ { -+ // If we take that branch the buffer was not queued to V4L2 -+ // So release the picture now so that VPU will be given -+ // the buffer back as soon as next ::Decode() call -+ buf.imxOutputFrame->Release(); -+ buf.imxOutputFrame = NULL; -+ } -+ return; -+#endif -+ - } - - void CLinuxRendererGLES::Render(DWORD flags, int index) -@@ -2691,6 +2778,15 @@ void CLinuxRendererGLES::AddProcessor(struct __CVBuffer *cvBufferRef, int index) - CVBufferRetain(buf.cvBufferRef); - } - #endif -+ -+#ifdef HAS_IMXVPU -+void CLinuxRendererGLES::AddProcessor(CIMXOutputFrame *imx, int index) -+{ -+ YUVBUFFER &buf = m_buffers[index]; -+ buf.imxOutputFrame = imx; -+} -+#endif -+ - #ifdef HAS_LIBSTAGEFRIGHT - void CLinuxRendererGLES::AddProcessor(CDVDVideoCodecStageFright* stf, EGLImageKHR eglimg, int index) - { -@@ -2712,6 +2808,7 @@ void CLinuxRendererGLES::AddProcessor(CDVDVideoCodecStageFright* stf, EGLImageKH - } - #endif - -+ - #if defined(TARGET_ANDROID) - void CLinuxRendererGLES::AddProcessor(CDVDMediaCodecInfo *mediacodec, int index) - { -diff --git a/xbmc/cores/VideoRenderers/LinuxRendererGLES.h b/xbmc/cores/VideoRenderers/LinuxRendererGLES.h -index 642cded..e58330a 100644 ---- a/xbmc/cores/VideoRenderers/LinuxRendererGLES.h -+++ b/xbmc/cores/VideoRenderers/LinuxRendererGLES.h -@@ -42,6 +42,7 @@ namespace Shaders { class BaseVideoFilterShader; } - class COpenMaxVideo; - class CDVDVideoCodecStageFright; - class CDVDMediaCodecInfo; -+class CIMXOutputFrame; - typedef std::vector Features; - - -@@ -166,6 +167,9 @@ class CLinuxRendererGLES : public CBaseRenderer - #ifdef HAS_LIBSTAGEFRIGHT - virtual void AddProcessor(CDVDVideoCodecStageFright* stf, EGLImageKHR eglimg, int index); - #endif -+#ifdef HAS_IMXVPU -+ virtual void AddProcessor(CIMXOutputFrame *imx, int index); -+#endif - #if defined(TARGET_ANDROID) - // mediaCodec - virtual void AddProcessor(CDVDMediaCodecInfo *mediacodec, int index); -@@ -277,6 +281,9 @@ class CLinuxRendererGLES : public CBaseRenderer - #ifdef HAVE_VIDEOTOOLBOXDECODER - struct __CVBuffer *cvBufferRef; - #endif -+#ifdef HAS_IMXVPU -+ CIMXOutputFrame *imxOutputFrame; -+#endif - #ifdef HAS_LIBSTAGEFRIGHT - CDVDVideoCodecStageFright* stf; - EGLImageKHR eglimg; -diff --git a/xbmc/cores/VideoRenderers/RenderFormats.h b/xbmc/cores/VideoRenderers/RenderFormats.h -index f15e80d..d40e4f5 100644 ---- a/xbmc/cores/VideoRenderers/RenderFormats.h -+++ b/xbmc/cores/VideoRenderers/RenderFormats.h -@@ -35,6 +35,7 @@ enum ERenderFormat { - RENDER_FMT_OMXEGL, - RENDER_FMT_CVBREF, - RENDER_FMT_BYPASS, -+ RENDER_FMT_IMX, - RENDER_FMT_EGLIMG, - RENDER_FMT_MEDIACODEC, - }; -diff --git a/xbmc/cores/VideoRenderers/RenderManager.cpp b/xbmc/cores/VideoRenderers/RenderManager.cpp -index b6fb1a3..79c4223 100644 ---- a/xbmc/cores/VideoRenderers/RenderManager.cpp -+++ b/xbmc/cores/VideoRenderers/RenderManager.cpp -@@ -924,6 +924,10 @@ int CXBMCRenderManager::AddVideoPicture(DVDVideoPicture& pic) - else if(pic.format == RENDER_FMT_VAAPI) - m_pRenderer->AddProcessor(*pic.vaapi, index); - #endif -+#ifdef HAS_IMXVPU -+ else if(pic.format == RENDER_FMT_IMX) -+ m_pRenderer->AddProcessor(pic.imxOutputFrame, index); -+#endif - #ifdef HAS_LIBSTAGEFRIGHT - else if(pic.format == RENDER_FMT_EGLIMG) - m_pRenderer->AddProcessor(pic.stf, pic.eglimg, index); -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.cpp b/xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.cpp -index 32d58d4..048bd92 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(HAVE_LIBCRYSTALHD) - #include "Video/DVDVideoCodecCrystalHD.h" -@@ -189,7 +192,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)) -@@ -206,6 +213,15 @@ CDVDVideoCodec* CDVDFactoryCodec::CreateVideoCodec(CDVDStreamInfo &hint, unsigne - } - #endif - -+/*#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..f6e576e 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h -@@ -51,6 +51,7 @@ namespace VDPAU { class CVdpauRenderPicture; } - class COpenMax; - class COpenMaxVideo; - struct OpenMaxVideoBuffer; -+class CIMXOutputFrame; - class CDVDVideoCodecStageFright; - class CDVDMediaCodecInfo; - typedef void* EGLImageKHR; -@@ -77,17 +78,19 @@ struct DVDVideoPicture - struct { - VAAPI::CHolder* vaapi; - }; -- - struct { - COpenMax *openMax; - OpenMaxVideoBuffer *openMaxBuffer; - }; -- - struct { - struct __CVBuffer *cvBufferRef; - }; - - struct { -+ CIMXOutputFrame *imxOutputFrame; -+ }; -+ -+ struct { - CDVDVideoCodecStageFright* stf; - EGLImageKHR eglimg; - }; -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp -new file mode 100644 -index 0000000..c0af493 ---- /dev/null -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp -@@ -0,0 +1,1737 @@ -+/* -+ * Copyright (C) 2013 Stephan Rafin -+ * -+ * 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 "DVDVideoCodecIMX.h" -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include "threads/SingleLock.h" -+#include "utils/log.h" -+#include "DVDClock.h" -+#include "mfw_gst_ts.h" -+#include "threads/Atomics.h" -+ -+//#define NO_V4L_RENDERING -+ -+#ifdef IMX_PROFILE -+static unsigned long long render_ts[30]; -+static unsigned long long get_time() -+{ -+ struct timespec ts; -+ unsigned long long now; -+ -+ clock_gettime(CLOCK_MONOTONIC, &ts); -+ now = (((unsigned long long)ts.tv_sec) * 1000000000ULL) + -+ ((unsigned long long)ts.tv_nsec); -+ -+ return now; -+} -+#endif -+ -+void CIMXOutputFrame::Render(struct v4l2_crop &crop) -+{ -+ CIMXRenderingFrames& renderingFrames = CIMXRenderingFrames::GetInstance(); -+ renderingFrames.Queue(this, crop); -+} -+ -+/* video device on which the video will be rendered (/dev/video17 => /dev/fb1) */ -+const char *CIMXRenderingFrames::m_v4lDeviceName = "/dev/video17"; -+static long sg_singleton_lock_variable = 0; -+CIMXRenderingFrames* CIMXRenderingFrames::m_instance = 0; -+ -+CIMXRenderingFrames& -+CIMXRenderingFrames::GetInstance() -+{ -+ CAtomicSpinLock lock(sg_singleton_lock_variable); -+ if( ! m_instance ) -+ { -+ m_instance = new CIMXRenderingFrames(); -+ } -+ return *m_instance; -+} -+ -+CIMXRenderingFrames::CIMXRenderingFrames() -+{ -+ m_ready = false; -+ m_v4lfd = -1; -+ m_virtAddr = NULL; -+ m_v4lBuffers = NULL; -+ memset(&m_crop, 0, sizeof(m_crop)); -+ m_crop.type = V4L2_BUF_TYPE_VIDEO_OUTPUT; -+ m_motionCtrl = -1; -+} -+ -+bool CIMXRenderingFrames::AllocateBuffers(const struct v4l2_format *format, int nbBuffers) -+{ -+ int ret, i; -+ struct v4l2_requestbuffers bufReq; -+ struct v4l2_format fmt; -+ struct v4l2_buffer v4lBuf; -+ struct v4l2_control ctrl; -+ -+ CSingleLock lock(m_renderingFramesLock); -+ if (m_ready) -+ { -+ CLog::Log(LOGERROR, "%s - Try to re-allocate buffers while previous buffers were not freed.\n", __FUNCTION__); -+ return false; -+ } -+ -+ m_v4lfd = open(m_v4lDeviceName, O_RDWR|O_NONBLOCK, 0); -+ if (m_v4lfd < 0) -+ { -+ CLog::Log(LOGERROR, "%s - Error while trying to open %s.\n", __FUNCTION__, m_v4lDeviceName); -+ __ReleaseBuffers(); -+ return false; -+ } -+ -+ ret = ioctl(m_v4lfd, VIDIOC_S_FMT, format); -+ if (ret < 0) -+ { -+ CLog::Log(LOGERROR, "%s - Error while setting V4L format (ret %d : %s).\n", __FUNCTION__, ret, strerror(errno)); -+ __ReleaseBuffers(); -+ return false; -+ } -+ -+ if (format->fmt.pix.field != V4L2_FIELD_NONE) -+ { -+ char * motion_entry; -+ motion_entry = getenv("IMX_DEINT_MOTION"); -+ if (motion_entry != NULL) -+ { -+ errno = 0; -+ m_motionCtrl = strtol(motion_entry, NULL, 10); -+ if (errno != 0) -+ m_motionCtrl = -1; -+ } -+ if (m_motionCtrl == -1) -+ m_motionCtrl = 2; /* Default value : 2 stands for high motion */ -+ -+ if ((m_motionCtrl >= 0) && (m_motionCtrl <=2)) -+ { -+ ctrl.id = V4L2_CID_MXC_MOTION; -+ ctrl.value = m_motionCtrl; -+ ret = ioctl (m_v4lfd, VIDIOC_S_CTRL, &ctrl); -+ if (ret < 0) -+ { -+ CLog::Log(LOGERROR, "%s - Error while setting V4L motion (ret %d : %s).\n", __FUNCTION__, ret, strerror(errno)); -+ } -+ } -+ else -+ { -+ CLog::Log(LOGNOTICE, "%s - IMX_DEINT_MOTION set to %d. Disabling deinterlacing.\n", __FUNCTION__, m_motionCtrl); -+ m_motionCtrl = -2; -+ } -+ } -+ -+ fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT; -+ ret = ioctl(m_v4lfd, VIDIOC_G_FMT, &fmt); -+ if (ret < 0) -+ { -+ CLog::Log(LOGERROR, "%s - Error while getting V4L format (ret %d : %s).\n", __FUNCTION__, ret, strerror(errno)); -+ __ReleaseBuffers(); -+ return false; -+ } -+ -+ m_bufferNum = nbBuffers; -+ /* Alloc V4L2 buffers */ -+ memset(&bufReq, 0, sizeof(bufReq)); -+ bufReq.count = m_bufferNum; -+ bufReq.type = V4L2_BUF_TYPE_VIDEO_OUTPUT; -+ bufReq.memory = V4L2_MEMORY_MMAP; -+ ret = ioctl(m_v4lfd, VIDIOC_REQBUFS, &bufReq); -+ if (ret < 0) -+ { -+ CLog::Log(LOGERROR, "%s - %d Hw buffer allocation error (%d)\n", __FUNCTION__, bufReq.count, ret); -+ __ReleaseBuffers(); -+ return false; -+ } -+ CLog::Log(LOGDEBUG, "%s - %d Hw buffer of %d bytes allocated\n", __FUNCTION__, bufReq.count, fmt.fmt.pix.sizeimage); -+ -+ m_virtAddr = new void*[m_bufferNum]; -+ if (m_virtAddr == NULL) -+ { -+ CLog::Log(LOGERROR, "%s - Allocation failure (m_virtAddr table of %d elements)\n", __FUNCTION__, m_bufferNum); -+ __ReleaseBuffers(); -+ return false; -+ } -+ m_v4lBuffers = new v4l2_buffer[m_bufferNum]; -+ if (m_v4lBuffers == NULL) -+ { -+ CLog::Log(LOGERROR, "%s - Allocation failure (m_v4lBuffers table of %d elements)\n", __FUNCTION__, m_bufferNum); -+ __ReleaseBuffers(); -+ return false; -+ } -+ -+ for (i = 0 ; i < m_bufferNum; i++) -+ { -+ memset(&v4lBuf, 0, sizeof(v4lBuf)); -+ v4lBuf.index = i; -+ v4lBuf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT; -+ v4lBuf.memory = V4L2_MEMORY_MMAP; -+ ret = ioctl (m_v4lfd, VIDIOC_QUERYBUF, &v4lBuf); -+ if (ret < 0) -+ { -+ CLog::Log(LOGERROR, "%s - Error during 1st query of V4L buffer (ret %d : %s)\n", __FUNCTION__, ret, strerror(errno)); -+ return false; -+ } -+ m_v4lBuffers[i] = v4lBuf; -+ m_virtAddr[i] = NULL; -+ } -+ memset(&m_crop, 0, sizeof(m_crop)); -+ m_crop.type = V4L2_BUF_TYPE_VIDEO_OUTPUT; -+ m_pushedFrames = 0; -+ m_streamOn = false; -+ m_ready = true; -+ return true; -+} -+ -+void *CIMXRenderingFrames::GetVirtAddr(int idx) -+{ -+ struct v4l2_buffer v4lBuf; -+ int ret; -+ -+ CSingleLock lock(m_renderingFramesLock); -+ if (!m_ready) -+ return NULL; -+ if ((idx < 0) || (idx >= m_bufferNum)) -+ return NULL; -+ -+ if (m_virtAddr[idx] == NULL) -+ { -+ v4lBuf = m_v4lBuffers[idx]; -+ m_virtAddr[idx] = mmap(NULL, v4lBuf.length, PROT_READ | PROT_WRITE, MAP_SHARED, m_v4lfd, v4lBuf.m.offset); -+ -+ /* 2nd query to retrieve real Physical address after mmap (iMX6 bug) */ -+ ret = ioctl (m_v4lfd, VIDIOC_QUERYBUF, &v4lBuf); -+ if (ret < 0) -+ { -+ CLog::Log(LOGERROR, "%s - Error during 2nd query of V4L buffer (ret %d : %s)\n", __FUNCTION__, ret, strerror(errno)); -+ } -+ m_v4lBuffers[idx] = v4lBuf; -+ } -+ return m_virtAddr[idx]; -+} -+ -+void *CIMXRenderingFrames::GetPhyAddr(int idx) -+{ -+ -+ CSingleLock lock(m_renderingFramesLock); -+ if (!m_ready) -+ return NULL; -+ if ((idx < 0) || (idx >= m_bufferNum)) -+ return NULL; -+ -+ return (void *)m_v4lBuffers[idx].m.offset; -+} -+ -+int CIMXRenderingFrames::FindBuffer(void *phyAddr) -+{ -+ int i; -+ -+ CSingleLock lock(m_renderingFramesLock); -+ if (!m_ready) -+ return -1; -+ -+ for (i = 0; i < m_bufferNum; i++) -+ { -+ if (m_v4lBuffers[i].m.offset == (unsigned int)phyAddr) -+ { -+ // CLog::Log(LOGNOTICE, "%s - found buffer OK %d!\n", __FUNCTION__, i); -+ return i; -+ } -+ } -+ return -1; -+} -+ -+int CIMXRenderingFrames::DeQueue(bool wait) -+{ -+ int ret; -+ int status; -+ struct v4l2_buffer buf; -+ -+ CSingleLock lock(m_renderingFramesLock); -+ if (!m_ready) -+ { -+ CLog::Log(LOGNOTICE, "%s - Cannot dequeue frame as buffers were released !\n", -+ __FUNCTION__); -+ return -1; -+ } -+ if (!m_streamOn) -+ { -+ return -1; -+ } -+ -+ if (wait) -+ { -+ status = fcntl(m_v4lfd, F_GETFL); -+ fcntl(m_v4lfd, F_SETFL, status & (~O_NONBLOCK)); -+ } -+ buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT; -+ buf.memory = V4L2_MEMORY_MMAP; -+ ret = ioctl(m_v4lfd, VIDIOC_DQBUF, &buf); -+ if (wait) -+ { -+ fcntl(m_v4lfd, F_SETFL, status | O_NONBLOCK); -+ } -+ if (ret != 0) -+ { -+ if (errno != EAGAIN) -+ CLog::Log(LOGERROR, "%s - Dequeue buffer error (ret %d : %s)\n", -+ __FUNCTION__, ret, strerror(errno)); -+ return -1; -+ } -+ -+#ifdef IMX_PROFILE -+ CLog::Log(LOGDEBUG, "%s - Time render to dequeue (%d) %llu\n", -+ __FUNCTION__, buf.index, get_time() - render_ts[buf.index]); -+#endif -+// CLog::Log(LOGERROR, "%s dequeued retuns (%d)\n", __FUNCTION__, buf.index); -+ -+ return buf.index; -+} -+ -+void CIMXRenderingFrames::Queue(CIMXOutputFrame *picture, struct v4l2_crop &destRect) -+{ -+ /* Warning : called from renderer thread -+ * Especially do not call any VPU functions as they are not thread safe -+ */ -+ -+ int ret, type; -+ struct timeval queue_ts; -+ int stream_trigger; -+ bool crop_update = false; -+ -+ CSingleLock lock(m_renderingFramesLock); -+ if (!m_ready) -+ { -+ CLog::Log(LOGNOTICE, "%s - Cannot queue frame as buffers were released !\n", -+ __FUNCTION__); -+ return; -+ } -+ -+ /*CLog::Log(LOGDEBUG, "%s - queuing frame %d - picture adress : %p\n", -+ __FUNCTION__, picture->v4l2BufferIdx, picture);*/ -+ -+ if ((picture->v4l2BufferIdx < 0) || (picture->v4l2BufferIdx >= m_bufferNum)) -+ { -+ CLog::Log(LOGERROR, "%s - Invalid buffer index : %d - picture address : %p\n", -+ __FUNCTION__, picture->v4l2BufferIdx, picture); -+ return; -+ } -+ -+ /* Set field type for each buffer otherwise the mxc_vout driver reverts to progressive */ -+ switch (picture->field) -+ { -+ case VPU_FIELD_TB: -+ m_v4lBuffers[picture->v4l2BufferIdx].field = V4L2_FIELD_INTERLACED_TB; -+ break; -+ case VPU_FIELD_BT: -+ m_v4lBuffers[picture->v4l2BufferIdx].field= V4L2_FIELD_INTERLACED_BT; -+ break; -+ case VPU_FIELD_NONE: -+ default: -+ m_v4lBuffers[picture->v4l2BufferIdx].field = V4L2_FIELD_NONE; -+ break; -+ } -+ /* In case deinterlacing is forced to disabled */ -+ if (m_motionCtrl == -2) -+ m_v4lBuffers[picture->v4l2BufferIdx].field = V4L2_FIELD_NONE; -+ -+ /* mxc_vout driver does not display immediatly -+ * if timestamp is set to 0 -+ * (instead this driver expects a 30fps rate) -+ * So we explicitly set current time for immediate display -+ */ -+ gettimeofday (&queue_ts, NULL); -+ m_v4lBuffers[picture->v4l2BufferIdx].timestamp = queue_ts; -+ -+#ifndef NO_V4L_RENDERING -+ ret = ioctl(m_v4lfd, VIDIOC_QBUF, &m_v4lBuffers[picture->v4l2BufferIdx]); -+ if (ret < 0) -+ { -+ CLog::Log(LOGERROR, "%s - V4L Queue buffer failed (ret %d : %s)\n", -+ __FUNCTION__, ret, strerror(errno)); -+ /* If it fails odds are very high picture is invalid so just exit now */ -+ return; -+ } -+ else -+ { -+ m_pushedFrames++; -+ } -+ -+ /* Force cropping dimensions to be aligned */ -+ destRect.c.top &= 0xFFFFFFF8; -+ destRect.c.left &= 0xFFFFFFF8; -+ destRect.c.width &= 0xFFFFFFF8; -+ destRect.c.height &= 0xFFFFFFF8; -+ if ((m_crop.c.top != destRect.c.top) || -+ (m_crop.c.left != destRect.c.left) || -+ (m_crop.c.width != destRect.c.width) || -+ (m_crop.c.height != destRect.c.height)) -+ { -+ CLog::Log(LOGNOTICE, "%s - Newcrop : %d % d %d %d\n", -+ __FUNCTION__, destRect.c.top, destRect.c.left, destRect.c.width, destRect.c.height); -+ m_crop.c = destRect.c; -+ crop_update = true; -+ } -+ -+ if (!m_streamOn) -+ { -+ if (picture->field == VPU_FIELD_NONE) -+ stream_trigger = 1; -+ else { -+ if (m_motionCtrl < 2) -+ stream_trigger = 3; -+ else -+ stream_trigger = 2; -+ } -+ -+ if (m_pushedFrames >= stream_trigger) { -+ CLog::Log(LOGDEBUG, "%s - Motion control is : %d - Number of required frames before streaming : %d\n", -+ __FUNCTION__, m_motionCtrl, stream_trigger); -+ -+ type = V4L2_BUF_TYPE_VIDEO_OUTPUT; -+ ret = ioctl(m_v4lfd, VIDIOC_STREAMON, &type); -+ if (ret < 0) -+ { -+ CLog::Log(LOGERROR, "%s - V4L Stream ON failed (ret %d : %s)\n", -+ __FUNCTION__, ret, strerror(errno)); -+ } -+ else -+ { -+ CLog::Log(LOGDEBUG, "%s - V4L Stream ON OK\n", -+ __FUNCTION__); -+ m_streamOn = true; -+ } -+ /* We have to repeat crop command after streamon for some vids -+ * FIXME : Check why in drivers... -+ */ -+ ret = ioctl(m_v4lfd, VIDIOC_S_CROP, &m_crop); -+ if (ret < 0) -+ { -+ CLog::Log(LOGERROR, "%s - S_CROP failed (ret %d : %s)\n", -+ __FUNCTION__, ret, strerror(errno)); -+ } -+ } -+ } -+ else -+ { -+ if (crop_update) -+ { -+ ret = ioctl(m_v4lfd, VIDIOC_S_CROP, &m_crop); -+ if (ret < 0) -+ { -+ CLog::Log(LOGERROR, "%s - S_CROP failed (ret %d : %s)\n", -+ __FUNCTION__, ret, strerror(errno)); -+ } -+ } -+ } -+#endif -+ -+#ifdef IMX_PROFILE -+ render_ts[picture->v4l2BufferIdx] = get_time(); -+ CLog::Log(LOGDEBUG, "%s - Time push to render (%d) %llu\n", -+ __FUNCTION__, picture->v4l2BufferIdx, render_ts[picture->v4l2BufferIdx] - picture->pushTS); -+#endif -+} -+ -+void CIMXRenderingFrames::ReleaseBuffers() -+{ -+ CSingleLock lock(m_renderingFramesLock); -+ if (!m_ready) -+ { -+ CLog::Log(LOGERROR, "%s - AllocateBuffers was not previously called\n", __FUNCTION__); -+ return; -+ } -+ __ReleaseBuffers(); -+} -+ -+/* Note : Has to be called with m_renderingFramesLock held */ -+void CIMXRenderingFrames::__ReleaseBuffers() -+{ -+ int type, i; -+ -+ if (m_v4lfd >= 0) -+ { -+ /* stream off */ -+ type = V4L2_BUF_TYPE_VIDEO_OUTPUT; -+ ioctl (m_v4lfd, VIDIOC_STREAMOFF, &type); -+ m_streamOn = false; -+ } -+ -+ if (m_virtAddr != NULL) -+ { -+ for (i = 0; i < m_bufferNum; i++) -+ { -+ if (m_virtAddr[i] != NULL) -+ munmap (m_virtAddr[i], m_v4lBuffers[i].length); -+ } -+ delete m_virtAddr; -+ m_virtAddr = NULL; -+ } -+ -+ if (m_v4lfd >= 0) -+ { -+ /* Close V4L2 device */ -+ close(m_v4lfd); -+ m_v4lfd = -1; -+ } -+ -+ if (m_v4lBuffers != NULL) -+ { -+ delete m_v4lBuffers; -+ m_v4lBuffers = NULL; -+ } -+ m_bufferNum = 0; -+ m_pushedFrames = 0; -+ m_ready = false; -+ m_motionCtrl = -1; -+} -+ -+/* FIXME get rid of these defines properly */ -+#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)) -+#define min(a, b) (aGetClock() / DVD_TIME_BASE; -+ -+ return clock_pts; -+} -+ -+void CDVDVideoCodecIMX::FlushDecodedFrames(void) -+{ -+ DVDVideoPicture DVDFrame; -+ while (m_decodedFrames.size() > 0) -+ { -+ DVDFrame = m_decodedFrames.front(); -+ VpuReleaseBufferV4L(DVDFrame.imxOutputFrame->v4l2BufferIdx); -+ m_decodedFrames.pop(); -+ } -+} -+ -+bool CDVDVideoCodecIMX::VpuAllocBuffers(VpuMemInfo *pMemBlock) -+{ -+ int i, size; -+ unsigned char * 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 = (unsigned char *)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.virtMem[m_decMemInfo.nVirtNum] = (unsigned int)ptr; -+ m_decMemInfo.nVirtNum++; -+ } -+ 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.phyMem_phyAddr[m_decMemInfo.nPhyNum] = (unsigned int)vpuMem.nPhyAddr; -+ m_decMemInfo.phyMem_virtAddr[m_decMemInfo.nPhyNum] = (unsigned int)vpuMem.nVirtAddr; -+ m_decMemInfo.phyMem_cpuAddr[m_decMemInfo.nPhyNum] = (unsigned int)vpuMem.nCpuAddr; -+ m_decMemInfo.phyMem_size[m_decMemInfo.nPhyNum] = size; -+ m_decMemInfo.nPhyNum++; -+ } -+ } -+ -+ return true; -+ -+AllocFailure: -+ VpuFreeBuffers(); -+ return false; -+} -+ -+bool CDVDVideoCodecIMX::VpuFreeBuffers(void) -+{ -+ int i; -+ VpuMemDesc vpuMem; -+ VpuDecRetCode vpuRet; -+ bool ret = true; -+ -+ //free virtual mem -+ for(i=0; ipDisplayFrameBuf; -+ CIMXOutputFrame *outputFrame; -+ int i; -+ double pts; -+ DVDVideoPicture DVDFrame; -+ -+ // FIXME pts = (double)TSManagerSend2(m_tsm, frameBuffer) / (double)1000.0; -+ pts = (double)TSManagerSend(m_tsm) / (double)1000.0; -+ /* Find Frame given physical address */ -+ i = m_renderingFrames.FindBuffer(frameBuffer->pbufY); -+ if (i == -1) -+ { -+ CLog::Log(LOGERROR, "%s - V4L buffer not found\n", __FUNCTION__); -+ return false; -+ } -+ if (m_outputBuffers[i].used()) -+ { -+ CLog::Log(LOGERROR, "%s - Try to reuse buffer which was not dequeued !\n", __FUNCTION__); -+ return false; -+ } -+ -+ /* Store the pointer to be able to invoke VPU_DecOutFrameDisplayed when the buffer will be dequeued */ -+ m_outputBuffers[i].store(frameBuffer, m_frameCounter++); -+ -+ outputFrame = &m_outputBuffers[i].outputFrame; -+ outputFrame->v4l2BufferIdx = i; -+ outputFrame->field = frameInfo->eFieldType; -+ outputFrame->picCrop = frameInfo->pExtInfo->FrmCropRect; -+ outputFrame->nQ16ShiftWidthDivHeightRatio = frameInfo->pExtInfo->nQ16ShiftWidthDivHeightRatio; -+ DVDFrame.imxOutputFrame = outputFrame; -+ -+ DVDFrame.pts = pts; -+ DVDFrame.dts = DVD_NOPTS_VALUE; -+ /* -+ m_outputFrame.iWidth = frameInfo->pExtInfo->nFrmWidth; -+ m_outputFrame.iHeight = frameInfo->pExtInfo->nFrmHeight; -+ */ -+ DVDFrame.iWidth = frameInfo->pExtInfo->FrmCropRect.nRight - frameInfo->pExtInfo->FrmCropRect.nLeft; -+ DVDFrame.iHeight = frameInfo->pExtInfo->FrmCropRect.nBottom - frameInfo->pExtInfo->FrmCropRect.nTop; -+ DVDFrame.format = RENDER_FMT_IMX; -+ -+ m_decodedFrames.push(DVDFrame); -+ if (m_decodedFrames.size() > IMX_MAX_QUEUE_SIZE) -+ { -+ CLog::Log(LOGERROR, "%s - Too many enqueued decoded frames : %d (Max %d)\n", __FUNCTION__, m_decodedFrames.size(), IMX_MAX_QUEUE_SIZE); -+ } -+ -+#ifdef IMX_PROFILE -+ DVDFrame.imxOutputFrame->pushTS = get_time(); -+ CLog::Log(LOGDEBUG, "%s - push (%i) Time between push %llu\n", -+ __FUNCTION__, i, DVDFrame.imxOutputFrame->pushTS - previous_ts); -+ previous_ts =DVDFrame.imxOutputFrame->pushTS; -+#endif -+ -+ return true; -+} -+ -+int CDVDVideoCodecIMX::GetAvailableBufferNb(void) -+{ -+ int i, nb; -+ -+ nb = 0; -+ for (i = 0; i < m_vpuFrameBufferNum; i++) -+ { -+ if (!m_outputBuffers[i].used()) -+ nb++; -+ } -+ return nb; -+} -+ -+bool CDVDVideoCodecIMX::VpuReleaseBufferV4L(int idx) -+{ -+ if (idx < 0 || idx >= m_vpuFrameBufferNum) -+ { -+ CLog::Log(LOGERROR, "%s - Invalid index - idx : %d\n", __FUNCTION__, idx); -+ return false; -+ } -+ -+ /*CLog::Log(LOGDEBUG, "%s - idx : %d - frame : %d\n", __FUNCTION__, -+ idx, m_outputBuffers[idx].frameNo);*/ -+ -+ VPU_DecOutFrameDisplayed(m_vpuHandle, m_outputBuffers[idx].buffer); -+ m_outputBuffers[idx].clear(); -+ return true; -+} -+ -+/* Dequeue queued frames and free the corresponding VPU buffers */ -+bool CDVDVideoCodecIMX::VpuDeQueueFrame(bool wait) -+{ -+ int idx, i, frameNo; -+ -+ idx = m_renderingFrames.DeQueue(wait); -+ if (idx != -1) -+ { -+ if (!m_outputBuffers[idx].used()) -+ { -+ CLog::Log(LOGERROR, "%s - WTF : associated buffer does not exist anymore\n", -+ __FUNCTION__); -+ return true; -+ } -+ else -+ { -+ frameNo = m_outputBuffers[idx].frameNo(); -+ VpuReleaseBufferV4L(idx); -+ if (frameNo > 0) -+ { -+ /* Release buffers which are not used anymore and were -+ * queued before the idx buffer that has just been dequeued*/ -+ for (i = 0; i < m_vpuFrameBufferNum; ++i) -+ { -+ if (m_outputBuffers[i].expired(frameNo)) -+ { -+ CLog::Log(LOGNOTICE, "%s - Release expired buffer - idx : %d\n", __FUNCTION__, i); -+ VpuReleaseBufferV4L(i); -+ } -+ } -+ } -+ return true; -+ } -+ } -+ else -+ { -+#ifdef NO_V4L_RENDERING -+ int i; -+ for (i = 0; i < m_vpuFrameBufferNum; i++) -+ { -+ if (m_outputBuffers[i].used()) -+ { -+ VpuReleaseBufferV4L(idx); -+ } -+ } -+#endif -+ return false; -+ } -+} -+ -+CDVDVideoCodecIMX::CDVDVideoCodecIMX() : m_renderingFrames(CIMXRenderingFrames::GetInstance()) -+{ -+ m_pFormatName = "iMX-xxx"; -+ memset(&m_decMemInfo, 0, sizeof(DecMemInfo)); -+ m_vpuHandle = 0; -+ m_vpuFrameBuffers = NULL; -+ m_outputBuffers = NULL; -+ m_extraMem = NULL; -+ m_vpuFrameBufferNum = 0; -+ m_tsSyncRequired = true; -+ m_dropState = false; -+ m_tsm = NULL; -+ m_convert_bitstream = false; -+ m_frameCounter = 0; -+ m_usePTS = true; -+ if (getenv("IMX_NOPTS") != NULL) -+ { -+ m_usePTS = false; -+ } -+} -+ -+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) -+ { -+ unsigned int i; -+ char buf[4096]; -+ -+ for (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_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: -+ m_decOpenParam.CodecFormat = VPU_V_AVC; -+ m_pFormatName = "iMX-h264"; -+ if (hints.extradata) -+ { -+ if ( *(char*)hints.extradata == 1 ) -+ m_convert_bitstream = bitstream_convert_init(hints.extradata,hints.extrasize); -+ } -+ break; -+ case CODEC_ID_VC1: -+ m_decOpenParam.CodecFormat = VPU_V_VC1_AP; -+ m_pFormatName = "iMX-vc1"; -+ break; -+/* FIXME TODO -+ * => for this type we have to set height, width, nChromaInterleave and nMapType -+ case CODEC_ID_MJPEG: -+ m_decOpenParam.CodecFormat = VPU_V_MJPG; -+ m_pFormatName = "iMX-mjpg"; -+ 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_MSMPEG4V3: -+ m_decOpenParam.CodecFormat = VPU_V_XVID; /* VPU_V_DIVX3 */ -+ m_pFormatName = "iMX-divx3"; -+ 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; -+ int i; -+ bool VPU_loaded = m_vpuHandle; -+ -+ FlushDecodedFrames(); -+ 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; -+ } -+ -+ VpuFreeBuffers(); -+ -+ if (m_outputBuffers != NULL) -+ { -+ while (VpuDeQueueFrame(false)); -+ m_renderingFrames.ReleaseBuffers(); -+ RestoreFB(); -+ delete m_outputBuffers; -+ m_outputBuffers = NULL; -+ } -+ -+ /* Free extramem */ -+ if (m_extraMem != NULL) -+ { -+ for (i = 0; i < m_vpuFrameBufferNum; i++) -+ { -+ if (m_extraMem[i].nSize > 0) -+ { -+ ret = VPU_DecFreeMem(&m_extraMem[i]); -+ if (ret != VPU_DEC_RET_SUCCESS) -+ { -+ CLog::Log(LOGERROR, "%s - Release extra mem failed with error code %d.\n", __FUNCTION__, ret); -+ } -+ m_extraMem[i].nSize = 0; -+ } -+ } -+ delete m_extraMem; -+ m_extraMem = NULL; -+ } -+ 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_tsm != NULL) -+ { -+ destroyTSManager(m_tsm); -+ m_tsm = NULL; -+ } -+ -+ if (m_convert_bitstream) -+ { -+ if (m_sps_pps_context.sps_pps_data) -+ { -+ free(m_sps_pps_context.sps_pps_data); -+ m_sps_pps_context.sps_pps_data = NULL; -+ } -+ } -+ return; -+} -+ -+int CDVDVideoCodecIMX::Decode(BYTE *pData, int iSize, double dts, double pts) -+{ -+ VpuDecFrameLengthInfo frameLengthInfo; -+ VpuBufferNode inData; -+ VpuDecRetCode ret; -+ VpuDecOutFrameInfo frameInfo; -+ int decRet = 0; -+ int retStatus = 0; -+ int demuxer_bytes = iSize; -+ uint8_t *demuxer_content = pData; -+ bool bitstream_convered = false; -+ bool retry = false; -+ -+#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; -+ } -+ -+#ifdef IMX_PROFILE -+ current = get_time(); -+ 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 -+ -+/* FIXME tests -+ CLog::Log(LOGDEBUG, "%s - demux size : %d dts : %f - pts : %f - %x %x %x %x\n", __FUNCTION__, iSize, dts, pts, ((unsigned int *)pData)[0], ((unsigned int *)pData)[1], ((unsigned int *)pData)[2], ((unsigned int *)pData)[3]); -+ ((unsigned int *)pData)[0] = htonl(iSize-4); -+*/ -+ -+ while (VpuDeQueueFrame(false)); -+ -+ if (pData && iSize) -+ { -+ if (m_convert_bitstream) -+ { -+ // convert demuxer packet from bitstream to bytestream (AnnexB) -+ int bytestream_size = 0; -+ uint8_t *bytestream_buff = NULL; -+ -+ if (!bitstream_convert(demuxer_content, demuxer_bytes, &bytestream_buff, &bytestream_size)) -+ { -+ CLog::Log(LOGERROR, "%s - bitstream convert error...\n", __FUNCTION__); -+ return VC_ERROR; -+ } -+ -+ if (bytestream_buff && (bytestream_size > 0)) -+ { -+ bitstream_convered = true; -+ demuxer_bytes = bytestream_size; -+ demuxer_content = bytestream_buff; -+ } -+ } -+ -+ if (pts != DVD_NOPTS_VALUE) -+ { -+ if (m_tsSyncRequired) -+ { -+ m_tsSyncRequired = false; -+ resyncTSManager(m_tsm, llrint(pts) * 1000, MODE_AI); -+ } -+ //TSManagerReceive2(m_tsm, llrint(pts) * 1000, iSize); -+ TSManagerReceive(m_tsm, llrint(pts) * 1000); -+ } -+ else -+ { -+ //If no pts but dts available (AVI container for instance) then use this one -+ if (dts != DVD_NOPTS_VALUE) -+ { -+ if (m_tsSyncRequired) -+ { -+ m_tsSyncRequired = false; -+ resyncTSManager(m_tsm, llrint(dts) * 1000, MODE_AI); -+ } -+ //TSManagerReceive2(m_tsm, llrint(dts) * 1000, iSize); -+ TSManagerReceive(m_tsm, llrint(dts) * 1000); -+ } -+ } -+ -+ inData.nSize = demuxer_bytes; -+ inData.pPhyAddr = NULL; -+ inData.pVirAddr = demuxer_content; -+ /* FIXME TODO VP8 & DivX3 require specific sCodecData values */ -+ 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; -+ } -+ -+ do // Decode as long as the VPU consumes data -+ { -+ retry = false; -+#ifdef IMX_PROFILE -+ before_dec = get_time(); -+#endif -+ 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, get_time() - 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); -+ } -+ // FIXME TSManagerValid2(m_tsm, frameLengthInfo.nFrameLength + frameLengthInfo.nStuffLength, frameLengthInfo.pFrame); -+ //CLog::Log(LOGDEBUG, "%s - size : %d - key consummed : %x\n", __FUNCTION__, frameLengthInfo.nFrameLength + frameLengthInfo.nStuffLength, frameLengthInfo.pFrame); -+ }//VPU_DEC_ONE_FRM_CONSUMED -+ -+ if ((decRet & VPU_DEC_OUTPUT_DIS) || -+ (decRet & VPU_DEC_OUTPUT_MOSAIC_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, &frameInfo); -+ if(ret != VPU_DEC_RET_SUCCESS) -+ { -+ CLog::Log(LOGERROR, "%s - VPU Cannot get output frame(%d).\n", __FUNCTION__, ret); -+ goto out_error; -+ } -+ if (VpuPushFrame(&frameInfo)) -+ { -+ retStatus |= VC_PICTURE; -+ } -+ } //VPU_DEC_OUTPUT_DIS -+ -+ if (decRet & VPU_DEC_OUTPUT_REPEAT) -+ { -+ TSManagerSend(m_tsm); -+ CLog::Log(LOGDEBUG, "%s - Frame repeat.\n", __FUNCTION__); -+ } -+ if (decRet & VPU_DEC_OUTPUT_DROPPED) -+ { -+ TSManagerSend(m_tsm); -+ 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) -+ { -+ TSManagerSend(m_tsm); -+ CLog::Log(LOGDEBUG, "%s - Frame skipped.\n", __FUNCTION__); -+ } -+ if (decRet & VPU_DEC_FLUSH) -+ { -+ CLog::Log(LOGNOTICE, "%s - VPU requires a flush.\n", __FUNCTION__); -+ ret = VPU_DecFlushAll(m_vpuHandle); -+ if (ret != VPU_DEC_RET_SUCCESS) -+ { -+ CLog::Log(LOGERROR, "%s - VPU flush failed(%d).\n", __FUNCTION__, ret); -+ } -+ retStatus = VC_FLUSHED; -+ } -+ if (decRet & VPU_DEC_OUTPUT_EOS) -+ { -+ CLog::Log(LOGNOTICE, "%s - EOS encountered.\n", __FUNCTION__); -+ } -+ if (decRet & VPU_DEC_NO_ENOUGH_INBUF) -+ { -+ // We are done with VPU decoder that time -+ break; -+ } -+ if (!(decRet & VPU_DEC_INPUT_USED)) -+ { -+ CLog::Log(LOGERROR, "%s - input not used : addr %p size :%d!\n", __FUNCTION__, inData.pVirAddr, inData.nSize); -+ TSManagerSend(m_tsm); -+ } -+ -+ -+ if (!(decRet & VPU_DEC_OUTPUT_DIS) && -+ (inData.nSize != 0)) -+ { -+ /* 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; -+ retry = true; -+ } -+ -+ } while (retry == true); -+ } //(pData && iSize) -+ -+ if (GetAvailableBufferNb() > (m_vpuFrameBufferNum - m_extraVpuBuffers)) -+ { -+ retStatus |= VC_BUFFER; -+ } -+ else -+ { -+ if (retStatus == 0) { -+ /* No Picture ready and Not enough VPU buffers. It should NOT happen so log dedicated error */ -+ CLog::Log(LOGERROR, "%s - Not hw buffer available. Waiting for 2ms\n", __FUNCTION__); -+ /* Lets wait for the IPU to free a buffer. Anyway we have several decoded frames ready */ -+ usleep(2000); -+ } -+ } -+ -+ if (bitstream_convered) -+ free(demuxer_content); -+ -+ retStatus &= (~VC_PICTURE); -+ if (m_decodedFrames.size() >= IMX_MAX_QUEUE_SIZE) -+ retStatus |= VC_PICTURE; -+ -+#ifdef IMX_PROFILE -+ CLog::Log(LOGDEBUG, "%s - returns %x - duration %lld\n", __FUNCTION__, retStatus, get_time() - previous); -+#endif -+ return retStatus; -+ -+out_error: -+ if (bitstream_convered) -+ free(demuxer_content); -+ return VC_ERROR; -+} -+ -+void CDVDVideoCodecIMX::Reset() -+{ -+ int ret; -+ -+ CLog::Log(LOGDEBUG, "%s - called\n", __FUNCTION__); -+ -+ /* We have to resync timestamp manager */ -+ m_tsSyncRequired = true; -+ -+ /* Flush decoded frames */ -+ FlushDecodedFrames(); -+ -+ /* 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() -+{ -+ // Note : It is useless if CLinuxRendererGLES::GetProcessorSize returns 0 for RENDER_FMT_IMX -+ return min(3, m_extraVpuBuffers / 2); -+} -+ -+ -+bool CDVDVideoCodecIMX::GetPicture(DVDVideoPicture* pDvdVideoPicture) -+{ -+ double currentPlayerPts; -+ double ts = DVD_NOPTS_VALUE; -+ DVDVideoPicture DVDFrame; -+ -+ if (m_decodedFrames.size() == 0) -+ { -+ CLog::Log(LOGERROR, "%s called while no picture ready\n", __FUNCTION__); -+ return false; -+ } -+ -+ /* Retrieve oldest decoded frame */ -+ DVDFrame = m_decodedFrames.front(); -+ m_decodedFrames.pop(); -+ //CLog::Log(LOGNOTICE, "%s - buffer(%d)\n", __FUNCTION__, DVDFrame.imxOutputFrame->v4l2BufferIdx); -+ -+ pDvdVideoPicture->iFlags &= DVP_FLAG_DROPPED; -+ if ((pDvdVideoPicture->iFlags != 0) || (m_dropState)) -+ { -+ CLog::Log(LOGNOTICE, "%s - Flushing video picture\n", __FUNCTION__); -+ pDvdVideoPicture->iFlags = DVP_FLAG_DROPPED; -+ VpuReleaseBufferV4L(DVDFrame.imxOutputFrame->v4l2BufferIdx); -+ DVDFrame.imxOutputFrame = NULL; -+ } -+ else -+ { -+ ts = DVDFrame.pts; -+ currentPlayerPts = GetPlayerPtsSeconds() * (double)DVD_TIME_BASE; -+ if (currentPlayerPts > ts) -+ { -+ CLog::Log(LOGERROR, "%s - player is ahead of time (%f)\n", __FUNCTION__, currentPlayerPts - ts); -+ } -+ //CLog::Log(LOGINFO, "%s - idx : %d - delta call %f - delta ts %f \n", __FUNCTION__, outputFrame.v4l2_buffer->index,ts - previous, ts - currentPlayerPts); -+ } -+ -+#ifdef NO_V4L_RENDERING -+ if (!m_dropState) -+ { -+ VpuReleaseBufferV4L(DVDFrame.imxOutputFrame->v4l2BufferIdx); -+ } -+#endif -+ -+ pDvdVideoPicture->pts = DVDFrame.pts; -+ if (!m_usePTS) -+ { -+ pDvdVideoPicture->pts = DVD_NOPTS_VALUE; -+ } -+ pDvdVideoPicture->dts = DVDFrame.dts; -+ pDvdVideoPicture->iWidth = DVDFrame.iWidth; -+ pDvdVideoPicture->iHeight = DVDFrame.iHeight; -+ if (m_dropState) -+ { -+ pDvdVideoPicture->iDisplayWidth = DVDFrame.iWidth; -+ pDvdVideoPicture->iDisplayHeight = DVDFrame.iHeight; -+ } -+ else -+ { -+ pDvdVideoPicture->iDisplayWidth = ((pDvdVideoPicture->iWidth * DVDFrame.imxOutputFrame->nQ16ShiftWidthDivHeightRatio) + 32767) >> 16; -+ pDvdVideoPicture->iDisplayHeight = pDvdVideoPicture->iHeight; -+ } -+ pDvdVideoPicture->format = DVDFrame.format; -+ pDvdVideoPicture->imxOutputFrame = DVDFrame.imxOutputFrame; -+ -+#ifdef V4L_OUTPUT_PROFILE -+ CLog::Log(LOGDEBUG, "%s - QF : %d - HWfre : %d/%d/%d\n", -+ (int)m_decodedFrames.size(), GetAvailableBufferNb(), -+ m_extraVpuBuffers, m_vpuFrameBufferNum); -+#endif -+ 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; -+ CLog::Log(LOGNOTICE, "%s : %d\n", __FUNCTION__, bDrop); -+ } -+} -+ -+/* bitstream convert : Shameless copy from openmax */ -+/* TODO : Have a look at it as the malloc/copy/free strategy is obviously not the most efficient one */ -+ -+bool CDVDVideoCodecIMX::bitstream_convert_init(void *in_extradata, int in_extrasize) -+{ -+ // based on h264_mp4toannexb_bsf.c (ffmpeg) -+ // which is Copyright (c) 2007 Benoit Fouet -+ // and Licensed GPL 2.1 or greater -+ -+ m_sps_pps_size = 0; -+ m_sps_pps_context.sps_pps_data = NULL; -+ -+ // nothing to filter -+ if (!in_extradata || in_extrasize < 6) -+ return false; -+ -+ uint16_t unit_size; -+ uint32_t total_size = 0; -+ uint8_t *out = NULL, unit_nb, sps_done = 0; -+ const uint8_t *extradata = (uint8_t*)in_extradata + 4; -+ static const uint8_t nalu_header[4] = {0, 0, 0, 1}; -+ -+ // retrieve length coded size -+ m_sps_pps_context.length_size = (*extradata++ & 0x3) + 1; -+ if (m_sps_pps_context.length_size == 3) -+ return false; -+ -+ // retrieve sps and pps unit(s) -+ unit_nb = *extradata++ & 0x1f; // number of sps unit(s) -+ if (!unit_nb) -+ { -+ unit_nb = *extradata++; // number of pps unit(s) -+ sps_done++; -+ } -+ while (unit_nb--) -+ { -+ unit_size = extradata[0] << 8 | extradata[1]; -+ total_size += unit_size + 4; -+ if ( (extradata + 2 + unit_size) > ((uint8_t*)in_extradata + in_extrasize) ) -+ { -+ free(out); -+ return false; -+ } -+ uint8_t* new_out = (uint8_t*)realloc(out, total_size); -+ if (new_out) -+ { -+ out = new_out; -+ } -+ else -+ { -+ CLog::Log(LOGERROR, "bitstream_convert_init failed - %s : could not realloc the buffer out", __FUNCTION__); -+ free(out); -+ return false; -+ } -+ -+ memcpy(out + total_size - unit_size - 4, nalu_header, 4); -+ memcpy(out + total_size - unit_size, extradata + 2, unit_size); -+ extradata += 2 + unit_size; -+ -+ if (!unit_nb && !sps_done++) -+ unit_nb = *extradata++; // number of pps unit(s) -+ } -+ -+ m_sps_pps_context.sps_pps_data = out; -+ m_sps_pps_context.size = total_size; -+ m_sps_pps_context.first_idr = 1; -+ -+ return true; -+} -+ -+bool CDVDVideoCodecIMX::bitstream_convert(BYTE* pData, int iSize, uint8_t **poutbuf, int *poutbuf_size) -+{ -+ // based on h264_mp4toannexb_bsf.c (ffmpeg) -+ // which is Copyright (c) 2007 Benoit Fouet -+ // and Licensed GPL 2.1 or greater -+ -+ uint8_t *buf = pData; -+ uint32_t buf_size = iSize; -+ uint8_t unit_type; -+ int32_t nal_size; -+ uint32_t cumul_size = 0; -+ const uint8_t *buf_end = buf + buf_size; -+ -+ do -+ { -+ if (buf + m_sps_pps_context.length_size > buf_end) -+ goto fail; -+ -+ if (m_sps_pps_context.length_size == 1) -+ nal_size = buf[0]; -+ else if (m_sps_pps_context.length_size == 2) -+ nal_size = buf[0] << 8 | buf[1]; -+ else -+ nal_size = buf[0] << 24 | buf[1] << 16 | buf[2] << 8 | buf[3]; -+ -+ // FIXME CLog::Log(LOGERROR, "%s - nal_size : %d \n", __FUNCTION__, nal_size); -+ buf += m_sps_pps_context.length_size; -+ unit_type = *buf & 0x1f; -+ -+ if (buf + nal_size > buf_end || nal_size < 0) -+ goto fail; -+ -+ // prepend only to the first type 5 NAL unit of an IDR picture -+ if (m_sps_pps_context.first_idr && unit_type == 5) -+ { -+ bitstream_alloc_and_copy(poutbuf, poutbuf_size, -+ m_sps_pps_context.sps_pps_data, m_sps_pps_context.size, buf, nal_size); -+ m_sps_pps_context.first_idr = 0; -+ } -+ else -+ { -+ bitstream_alloc_and_copy(poutbuf, poutbuf_size, NULL, 0, buf, nal_size); -+ if (!m_sps_pps_context.first_idr && unit_type == 1) -+ m_sps_pps_context.first_idr = 1; -+ } -+ -+ buf += nal_size; -+ cumul_size += nal_size + m_sps_pps_context.length_size; -+ } while (cumul_size < buf_size); -+ -+ return true; -+ -+fail: -+ free(*poutbuf); -+ *poutbuf = NULL; -+ *poutbuf_size = 0; -+ return false; -+} -+ -+void CDVDVideoCodecIMX::bitstream_alloc_and_copy( -+ uint8_t **poutbuf, int *poutbuf_size, -+ const uint8_t *sps_pps, uint32_t sps_pps_size, -+ const uint8_t *in, uint32_t in_size) -+{ -+ // based on h264_mp4toannexb_bsf.c (ffmpeg) -+ // which is Copyright (c) 2007 Benoit Fouet -+ // and Licensed GPL 2.1 or greater -+ -+ #define CHD_WB32(p, d) { \ -+ ((uint8_t*)(p))[3] = (d); \ -+ ((uint8_t*)(p))[2] = (d) >> 8; \ -+ ((uint8_t*)(p))[1] = (d) >> 16; \ -+ ((uint8_t*)(p))[0] = (d) >> 24; } -+ -+ uint32_t offset = *poutbuf_size; -+ uint8_t nal_header_size = offset ? 3 : 4; -+ -+ *poutbuf_size += sps_pps_size + in_size + nal_header_size; -+ *poutbuf = (uint8_t*)realloc(*poutbuf, *poutbuf_size); -+ if (sps_pps) -+ memcpy(*poutbuf + offset, sps_pps, sps_pps_size); -+ -+ memcpy(*poutbuf + sps_pps_size + nal_header_size + offset, in, in_size); -+ if (!offset) -+ { -+ CHD_WB32(*poutbuf + sps_pps_size, 1); -+ } -+ else -+ { -+ (*poutbuf + offset + sps_pps_size)[0] = 0; -+ (*poutbuf + offset + sps_pps_size)[1] = 0; -+ (*poutbuf + offset + sps_pps_size)[2] = 1; -+ } -+} -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h -new file mode 100644 -index 0000000..d72b899 ---- /dev/null -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h -@@ -0,0 +1,191 @@ -+#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 -+#include "DVDVideoCodec.h" -+#include "DVDStreamInfo.h" -+#include "threads/CriticalSection.h" -+ -+ -+//#define IMX_PROFILE -+ -+/* FIXME TODO Develop real proper CVPUBuffer class */ -+#define VPU_DEC_MAX_NUM_MEM_NUM 20 -+typedef struct -+{ -+ //virtual mem info -+ int nVirtNum; -+ unsigned int virtMem[VPU_DEC_MAX_NUM_MEM_NUM]; -+ -+ //phy mem info -+ int nPhyNum; -+ unsigned int phyMem_virtAddr[VPU_DEC_MAX_NUM_MEM_NUM]; -+ unsigned int phyMem_phyAddr[VPU_DEC_MAX_NUM_MEM_NUM]; -+ unsigned int phyMem_cpuAddr[VPU_DEC_MAX_NUM_MEM_NUM]; -+ unsigned int phyMem_size[VPU_DEC_MAX_NUM_MEM_NUM]; -+} DecMemInfo; -+ -+/* Output frame properties */ -+struct CIMXOutputFrame { -+ // Render a picture. Calls RenderingFrames.Queue -+ void Render(struct v4l2_crop &); -+ // Clear a picture by settings the frameNo to "expired" -+ void Release() { frameNo = 0; } -+ -+ int v4l2BufferIdx; -+ VpuFieldType field; -+ VpuRect picCrop; -+ unsigned int nQ16ShiftWidthDivHeightRatio; -+ int frameNo; -+#ifdef IMX_PROFILE -+ unsigned long long pushTS; -+#endif -+}; -+ -+class CIMXRenderingFrames -+{ -+public: -+ static CIMXRenderingFrames& GetInstance(); -+ bool AllocateBuffers(const struct v4l2_format *, int); -+ void *GetVirtAddr(int idx); -+ void *GetPhyAddr(int idx); -+ void ReleaseBuffers(); -+ int FindBuffer(void *); -+ int DeQueue(bool wait); -+ void Queue(CIMXOutputFrame *, struct v4l2_crop &); -+ -+private: -+ CIMXRenderingFrames(); -+ void __ReleaseBuffers(); -+ -+ static const char *m_v4lDeviceName; // V4L2 device Name -+ static CIMXRenderingFrames* m_instance; // Unique instance of the class -+ -+ CCriticalSection m_renderingFramesLock; // Lock to ensure multithreading safety for class fields -+ bool m_ready; // Buffers are allocated and frames can be Queued/Dequeue -+ int m_v4lfd; // fd on V4L2 device -+ struct v4l2_buffer *m_v4lBuffers; // Table of V4L buffer info (as returned by VIDIOC_QUERYBUF) -+ int m_bufferNum; // Number of allocated V4L2 buffers -+ struct v4l2_crop m_crop; // Current cropping properties -+ bool m_streamOn; // Flag that indicates whether streaming in on (from V4L point of view) -+ int m_pushedFrames; // Number of frames queued in V4L2 -+ void **m_virtAddr; // Table holding virtual adresses of mmaped V4L2 buffers -+ int m_motionCtrl; // Current motion control algo -+}; -+ -+class CDVDVideoCodecIMX : public CDVDVideoCodec -+{ -+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 GetPicture(DVDVideoPicture *pDvdVideoPicture); -+ virtual void SetDropState(bool bDrop); -+ virtual const char* GetName(void) { return (const char*)m_pFormatName; } -+ virtual unsigned GetAllowedReferences(); -+ -+protected: -+ -+ bool VpuOpen(void); -+ bool VpuAllocBuffers(VpuMemInfo *); -+ bool VpuFreeBuffers(void); -+ bool VpuAllocFrameBuffers(void); -+ bool VpuPushFrame(VpuDecOutFrameInfo*); -+ bool VpuDeQueueFrame(bool); -+ int GetAvailableBufferNb(void); -+ void InitFB(void); -+ void RestoreFB(void); -+ void FlushDecodedFrames(void); -+ bool VpuReleaseBufferV4L(int); -+ -+ /* Helper structure which holds a queued output frame -+ * and its associated decoder frame buffer.*/ -+ struct VpuV4LFrameBuffer -+ { -+ // Returns whether the buffer is currently used (associated) -+ bool used() const { return buffer != NULL; } -+ int frameNo() const { return outputFrame.frameNo; } -+ bool expired(int frameNo) const -+ { return (buffer != NULL) && (outputFrame.frameNo < frameNo); } -+ // Associate a VPU frame buffer -+ void store(VpuFrameBuffer *b, int frameNo) { -+ buffer = b; -+ outputFrame.frameNo = frameNo; -+ } -+ // Reset the state -+ void clear() { store(NULL, 0); } -+ -+ VpuFrameBuffer *buffer; -+ CIMXOutputFrame outputFrame; -+ }; -+ -+ static const int m_extraVpuBuffers; // Number of additional buffers for VPU -+ -+ CIMXRenderingFrames&m_renderingFrames; // The global RenderingFrames instance -+ 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 -+ DecMemInfo 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 -+ void *m_tsm; // fsl Timestamp manager (from gstreamer implementation) -+ bool m_tsSyncRequired; // state whether timestamp manager has to be sync'ed -+ bool m_dropState; // Current drop state -+ int m_vpuFrameBufferNum; // Total number of allocated frame buffers -+ VpuFrameBuffer *m_vpuFrameBuffers; // Table of VPU frame buffers description -+ VpuMemDesc *m_extraMem; // Table of allocated extra Memory -+ VpuV4LFrameBuffer *m_outputBuffers; // Table of V4L buffers out of VPU (index is V4L buf index) (used to call properly VPU_DecOutFrameDisplayed) -+ std::queue m_decodedFrames; // Decoded Frames ready to be retrieved by GetPicture -+ int m_frameCounter; // Decoded frames counter -+ bool m_usePTS; // State whether pts out of decoding process should be used -+ -+ /* FIXME : Rework is still required for fields below this line */ -+ -+ /* create a real class and share with openmax ? */ -+ // bitstream to bytestream (Annex B) conversion support. -+ bool bitstream_convert_init(void *in_extradata, int in_extrasize); -+ bool bitstream_convert(BYTE* pData, int iSize, uint8_t **poutbuf, int *poutbuf_size); -+ static void bitstream_alloc_and_copy( uint8_t **poutbuf, int *poutbuf_size, -+ const uint8_t *sps_pps, uint32_t sps_pps_size, const uint8_t *in, uint32_t in_size); -+ typedef struct omx_bitstream_ctx { -+ uint8_t length_size; -+ uint8_t first_idr; -+ uint8_t *sps_pps_data; -+ uint32_t size; -+ omx_bitstream_ctx() -+ { -+ length_size = 0; -+ first_idr = 0; -+ sps_pps_data = NULL; -+ size = 0; -+ } -+ } omx_bitstream_ctx; -+ uint32_t m_sps_pps_size; -+ omx_bitstream_ctx m_sps_pps_context; -+ bool m_convert_bitstream; -+ -+}; -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/Makefile.in b/xbmc/cores/dvdplayer/DVDCodecs/Video/Makefile.in -index 8a97889..1df37c6 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/Makefile.in -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/Makefile.in -@@ -24,6 +24,9 @@ SRCS += OpenMax.cpp - SRCS += OpenMaxVideo.cpp - SRCS += DVDVideoCodecOpenMax.cpp - endif -+ifeq (@USE_IMXVPU@,1) -+SRCS += DVDVideoCodecIMX.cpp mfw_gst_ts.c -+endif - ifeq (@USE_LIBAMCODEC@,1) - SRCS += AMLCodec.cpp - SRCS += DVDVideoCodecAmlogic.cpp -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/mfw_gst_ts.c b/xbmc/cores/dvdplayer/DVDCodecs/Video/mfw_gst_ts.c -new file mode 100644 -index 0000000..86a8fea ---- /dev/null -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/mfw_gst_ts.c -@@ -0,0 +1,752 @@ -+/* -+ * Copyright (c) 2010-2012, Freescale Semiconductor, Inc. All rights reserved. -+ * -+ */ -+ -+/* -+ * This library is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU Library General Public -+ * License as published by the Free Software Foundation; either -+ * version 2 of the License, or (at your option) any later version. -+ * -+ * This library is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * Library General Public License for more details. -+ * -+ * You should have received a copy of the GNU Library General Public -+ * License along with this library; if not, write to the -+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330, -+ * Boston, MA 02111-1307, USA. -+ */ -+ -+/* -+ * Module Name: TimeStamp.c -+ * -+ * Description: include TimeStamp stratege for VPU / SW video decoder plugin -+ * -+ * Portability: This code is written for Linux OS and Gstreamer -+ */ -+ -+/* -+ * Changelog: -+ 11/2/2010 draft version Lyon Wang -+ * -+ */ -+#include -+#include -+#include -+ -+#include "mfw_gst_ts.h" -+ -+ -+const char *debug_env = "ME_DEBUG"; -+char *debug = NULL; -+int debug_level = 0; -+ -+ -+enum -+{ -+ DEBUG_LEVEL_ERROR = 1, -+ DEBUG_LEVEL_WARNING, -+ DEBUG_LEVEL_LOG, -+ DEBUG_LEVEL_VERBOSE, -+}; -+ -+ -+#define TSM_MESSAGE(level, fmt, ...)\ -+ do{\ -+ if (debug_level>=(level)){\ -+ printf("TSM:"fmt, ##__VA_ARGS__);\ -+ }\ -+ }while(0) -+ -+#define TSM_ERROR(...) TSM_MESSAGE(DEBUG_LEVEL_ERROR, ##__VA_ARGS__) -+#define TSM_WARNING(...) TSM_MESSAGE(DEBUG_LEVEL_WARNING, ##__VA_ARGS__) -+#define TSM_LOG(...) TSM_MESSAGE(DEBUG_LEVEL_LOG, ##__VA_ARGS__) -+#define TSM_VERBOSE(...) TSM_MESSAGE(DEBUG_LEVEL_VERBOSE, ##__VA_ARGS__) -+ -+#define TSM_HISTORY_POWER 5 -+#define TSM_HISTORY_SIZE (1<dur_history_total>>TSM_HISTORY_POWER) -+ -+#define TSM_SECOND ((TSM_TIMESTAMP)1000000000) -+#define TSM_DEFAULT_INTERVAL (TSM_SECOND/30) -+#define TSM_DEFAULT_TS_BUFFER_SIZE (128) -+ -+#define TSM_TS_IS_VALID(ts) \ -+ ((ts) != TSM_TIMESTAMP_NONE) -+ -+#define TSM_KEY_IS_VALID(key) \ -+ ((key) != TSM_KEY_NONE) -+ -+#define TSM_DISTANCE(tsm)\ -+ (((tsm->rx)>=(tsm->tx))?((tsm->rx)-(tsm->tx)):(tsm->ts_buf_size-(tsm->tx)+(tsm->rx))) -+ -+#define TSM_PLUS_AGE(tsm)\ -+ (TSM_DISTANCE(tsm)+tsm->invalid_ts_count+2) -+ -+#define TSM_ABS(ts0, ts1)\ -+ (((ts0)>(ts1))?((ts0)-(ts1)):((ts1)-(ts0))) -+ -+#define TSM_TIME_FORMAT "u:%02u:%02u.%09u" -+ -+#define TSM_TIME_ARGS(t) \ -+ TSM_TS_IS_VALID (t) ? \ -+ (unsigned int) (((TSM_TIMESTAMP)(t)) / (TSM_SECOND * 60 * 60)) : 99, \ -+ TSM_TS_IS_VALID (t) ? \ -+ (unsigned int) ((((TSM_TIMESTAMP)(t)) / (TSM_SECOND * 60)) % 60) : 99, \ -+ TSM_TS_IS_VALID (t) ? \ -+ (unsigned int) ((((TSM_TIMESTAMP)(t)) / TSM_SECOND) % 60) : 99, \ -+ TSM_TS_IS_VALID (t) ? \ -+ (unsigned int) (((TSM_TIMESTAMP)(t)) % TSM_SECOND) : 999999999 -+ -+#define TSM_BUFFER_SET(buf, value, size) \ -+ do {\ -+ int i;\ -+ for (i=0;i<(size);i++){\ -+ (buf)[i] = (value);\ -+ }\ -+ }while(0) -+ -+#define TSM_RECEIVED_NUNBER 512 -+ -+ -+typedef struct -+{ -+ TSM_TIMESTAMP ts; -+ unsigned long long age; -+ void *key; -+} TSMControl; -+ -+typedef struct _TSMReceivedEntry -+{ -+ TSM_TIMESTAMP ts; -+ struct _TSMReceivedEntry *next; -+ unsigned int used:1; -+ unsigned int subentry:1; -+ int size; -+} TSMReceivedEntry; -+ -+typedef struct _TSMReceivedEntryMemory -+{ -+ struct _TSMReceivedEntryMemory *next; -+ TSMReceivedEntry entrys[TSM_RECEIVED_NUNBER]; -+} TSMReceivedEntryMemory; -+ -+typedef struct -+{ -+ TSMReceivedEntry *head; -+ TSMReceivedEntry *tail; -+ TSMReceivedEntry *free; -+ TSMReceivedEntryMemory *memory; -+ int cnt; -+} TSMRecivedCtl; -+ -+typedef struct _TSManager -+{ -+ int first_tx; -+ int first_rx; -+ int rx; //timestamps received -+ int tx; //timestamps transfered -+ TSM_TIMESTAMP last_ts_sent; //last time stamp sent -+ TSM_TIMESTAMP last_ts_received; -+ TSM_TIMESTAMP suspicious_ts; -+ -+ TSM_TIMESTAMP discont_threshold; -+ -+ unsigned int invalid_ts_count; -+ TSMGR_MODE mode; -+ int ts_buf_size; -+ int dur_history_tx; -+ TSM_TIMESTAMP dur_history_total; -+ TSM_TIMESTAMP dur_history_buf[TSM_HISTORY_SIZE]; -+ TSMControl *ts_buf; -+ unsigned long long age; -+ int tx_cnt; -+ int rx_cnt; -+ int cnt; -+ int valid_ts_received:1; -+ int big_cnt; -+ -+ TSMRecivedCtl rctl; -+} TSManager; -+ -+ -+static void -+tsm_free_received_entry (TSMRecivedCtl * rctl, TSMReceivedEntry * entry) -+{ -+ entry->next = rctl->free; -+ rctl->free = entry; -+} -+ -+ -+static TSMReceivedEntry * -+tsm_new_received_entry (TSMRecivedCtl * rctl) -+{ -+ TSMReceivedEntry *ret = NULL; -+ if (rctl->free) { -+ ret = rctl->free; -+ rctl->free = ret->next; -+ } else { -+ TSMReceivedEntryMemory *p = malloc (sizeof (TSMReceivedEntryMemory)); -+ if (p) { -+ int i; -+ for (i = 1; i < TSM_RECEIVED_NUNBER; i++) { -+ TSMReceivedEntry *e = &p->entrys[i]; -+ tsm_free_received_entry (rctl, e); -+ }; -+ -+ p->next = rctl->memory; -+ rctl->memory = p; -+ -+ ret = p->entrys; -+ } -+ } -+ return ret; -+} -+ -+ -+void -+TSManagerReceive2 (void *handle, TSM_TIMESTAMP timestamp, int size) -+{ -+#define CLEAR_TSM_RENTRY(entry)\ -+ do { \ -+ (entry)->used = 0; \ -+ (entry)->subentry = 0; \ -+ (entry)->next = NULL; \ -+ } while (0) -+ TSManager *tsm = (TSManager *) handle; -+ -+ TSM_VERBOSE ("receive2 %" TSM_TIME_FORMAT " size %d\n", -+ TSM_TIME_ARGS (timestamp), size); -+ -+ if (tsm) { -+ if (size > 0) { -+ TSMRecivedCtl *rctl = &tsm->rctl; -+ TSMReceivedEntry *e = tsm_new_received_entry (rctl); -+ if (e) { -+ CLEAR_TSM_RENTRY (e); -+ if ((rctl->tail) && (rctl->tail->ts == timestamp)) { -+ e->subentry = 1; -+ } -+ e->ts = timestamp; -+ e->size = size; -+ if (rctl->tail) { -+ rctl->tail->next = e; -+ rctl->tail = e; -+ } else { -+ rctl->head = rctl->tail = e; -+ } -+ } -+ rctl->cnt++; -+ } else { -+ TSManagerReceive (handle, timestamp); -+ } -+ } -+} -+ -+ -+static TSM_TIMESTAMP -+TSManagerGetLastTimeStamp (TSMRecivedCtl * rctl, int size, int use) -+{ -+ TSM_TIMESTAMP ts = TSM_TIMESTAMP_NONE; -+ TSMReceivedEntry *e; -+ while ((size > 0) && (e = rctl->head)) { -+ ts = ((e->used) ? (TSM_TIMESTAMP_NONE) : (e->ts)); -+ if (use) -+ e->used = 1; -+ if (size >= e->size) { -+ rctl->head = e->next; -+ if (rctl->head == NULL) { -+ rctl->tail = NULL; -+ } else { -+ if (rctl->head->subentry) { -+ rctl->head->used = e->used; -+ } -+ } -+ size -= e->size; -+ rctl->cnt--; -+ tsm_free_received_entry (rctl, e); -+ } else { -+ e->size -= size; -+ size = 0; -+ } -+ } -+ return ts; -+} -+ -+ -+void -+TSManagerFlush2 (void *handle, int size) -+{ -+ TSManager *tsm = (TSManager *) handle; -+ if (tsm) { -+ TSManagerGetLastTimeStamp (&tsm->rctl, size, 0); -+ } -+ -+} -+ -+ -+/*====================================================================================== -+FUNCTION: mfw_gst_receive_ts -+ -+DESCRIPTION: Check timestamp and do frame dropping if enabled -+ -+ARGUMENTS PASSED: pTimeStamp_Object - TimeStamp Manager to handle related timestamp -+ timestamp - time stamp of the input buffer which has video data. -+ -+RETURN VALUE: None -+PRE-CONDITIONS: None -+POST-CONDITIONS: None -+IMPORTANT NOTES: None -+=======================================================================================*/ -+static void -+_TSManagerReceive (void *handle, TSM_TIMESTAMP timestamp, void *key) -+{ -+ TSManager *tsm = (TSManager *) handle; -+ -+ if (tsm) { -+ if (TSM_TS_IS_VALID (timestamp) && (tsm->rx_cnt)) -+ tsm->valid_ts_received = 1; -+ tsm->rx_cnt++; -+ if (tsm->cnt < tsm->ts_buf_size - 1) { -+ tsm->cnt++; -+ if (tsm->mode == MODE_AI) { -+ -+ if (TSM_TS_IS_VALID (timestamp)) { -+ if (tsm->first_rx) { -+ tsm->last_ts_received = timestamp; -+ tsm->first_rx = 0; -+ } else { -+ if (tsm->suspicious_ts) { -+ if (timestamp >= tsm->suspicious_ts) { -+ tsm->last_ts_received = timestamp; -+ } -+ tsm->suspicious_ts = 0; -+ } -+ if ((timestamp > tsm->last_ts_received) -+ && (timestamp - tsm->last_ts_received > tsm->discont_threshold)) { -+ tsm->suspicious_ts = timestamp; -+ timestamp = TSM_TIMESTAMP_NONE; -+ } -+ } -+ } -+ -+ if (TSM_TS_IS_VALID (timestamp)) // && (TSM_ABS(timestamp, tsm->last_ts_sent)ts_buf[tsm->rx].ts = timestamp; -+ tsm->ts_buf[tsm->rx].age = tsm->age + TSM_PLUS_AGE (tsm); -+ tsm->ts_buf[tsm->rx].key = key; -+ tsm->last_ts_received = timestamp; -+#ifdef DEBUG -+ //printf("age should %lld %lld\n", tsm->age, tsm->ts_buf[tsm->rx].age); -+ //printf("++++++ distance = %d tx=%d, rx=%d, invalid count=%d\n", TSM_DISTANCE(tsm), tsm->tx, tsm->rx,tsm->invalid_ts_count); -+#endif -+ tsm->rx = ((tsm->rx + 1) % tsm->ts_buf_size); -+ } else { -+ tsm->invalid_ts_count++; -+ } -+ } else if (tsm->mode == MODE_FIFO) { -+ tsm->ts_buf[tsm->rx].ts = timestamp; -+ tsm->rx = ((tsm->rx + 1) % tsm->ts_buf_size); -+ } -+ TSM_LOG ("++Receive %d:%" TSM_TIME_FORMAT -+ ", invalid:%d, size:%d key %p\n", tsm->rx_cnt, -+ TSM_TIME_ARGS (timestamp), tsm->invalid_ts_count, tsm->cnt, key); -+ } else { -+ TSM_ERROR ("Too many timestamps recieved!! (cnt=%d)\n", tsm->cnt); -+ } -+ } -+} -+ -+ -+void -+TSManagerValid2 (void *handle, int size, void *key) -+{ -+ TSManager *tsm = (TSManager *) handle; -+ -+ TSM_VERBOSE ("valid2 size %d\n", size); -+ -+ if (tsm) { -+ TSM_TIMESTAMP ts; -+ ts = TSManagerGetLastTimeStamp (&tsm->rctl, size, 1); -+ _TSManagerReceive (tsm, ts, key); -+ } -+} -+ -+ -+void -+TSManagerReceive (void *handle, TSM_TIMESTAMP timestamp) -+{ -+ _TSManagerReceive (handle, timestamp, TSM_KEY_NONE); -+} -+ -+ -+/*====================================================================================== -+FUNCTION: TSManagerSend -+ -+DESCRIPTION: Check timestamp and do frame dropping if enabled -+ -+ARGUMENTS PASSED: pTimeStamp_Object - TimeStamp Manager to handle related timestamp -+ ptimestamp - returned timestamp to use at render -+ -+RETURN VALUE: None -+PRE-CONDITIONS: None -+POST-CONDITIONS: None -+IMPORTANT NOTES: None -+=======================================================================================*/ -+static TSM_TIMESTAMP -+_TSManagerSend2 (void *handle, void *key, int send) -+{ -+ TSManager *tsm = (TSManager *) handle; -+ int i = tsm->tx; -+ int index = -1; -+ TSM_TIMESTAMP ts0 = 0, tstmp = TSM_TIMESTAMP_NONE; -+ unsigned long long age = 0; -+ TSM_TIMESTAMP half_interval = TSM_ADAPTIVE_INTERVAL (tsm) >> 1; -+ -+ if (tsm) { -+ if (send) { -+ tsm->tx_cnt++; -+ } else { -+ tsm->cnt++; -+ tsm->invalid_ts_count++; -+ } -+ if (tsm->cnt > 0) { -+ if (send) { -+ tsm->cnt--; -+ } -+ if (tsm->mode == MODE_AI) { -+ -+ if (tsm->first_tx == 0) { -+ tstmp = tsm->last_ts_sent + TSM_ADAPTIVE_INTERVAL (tsm); -+ } else { -+ tstmp = tsm->last_ts_sent; -+ } -+ -+ while (i != tsm->rx) { -+ if (index >= 0) { -+ if (tsm->ts_buf[i].ts < ts0) { -+ ts0 = tsm->ts_buf[i].ts; -+ age = tsm->ts_buf[i].age; -+ index = i; -+ } -+ } else { -+ ts0 = tsm->ts_buf[i].ts; -+ age = tsm->ts_buf[i].age; -+ index = i; -+ } -+ if ((TSM_KEY_IS_VALID (key)) && (key == tsm->ts_buf[i].key)) -+ break; -+ i = ((i + 1) % tsm->ts_buf_size); -+ } -+ if (index >= 0) { -+ if ((tsm->invalid_ts_count) && (ts0 >= ((tstmp) + half_interval)) -+ && (age > tsm->age)) { -+ /* use calculated ts0 */ -+ if (send) { -+ tsm->invalid_ts_count--; -+ } -+ } else { -+ -+ if (send) { -+ if (index != tsm->tx) { -+ tsm->ts_buf[index] = tsm->ts_buf[tsm->tx]; -+ } -+ tsm->tx = ((tsm->tx + 1) % tsm->ts_buf_size); -+ -+ } -+#if 0 -+ if (ts0 >= ((tstmp) + half_interval)) -+ tstmp = tstmp; -+ else -+ tstmp = ts0; -+#else -+ tstmp = ts0; -+#endif -+ } -+ -+ } else { -+ if (send) { -+ tsm->invalid_ts_count--; -+ } -+ } -+ -+ if (tsm->first_tx == 0) { -+ -+ if (tstmp > tsm->last_ts_sent) { -+ ts0 = (tstmp - tsm->last_ts_sent); -+ } else { -+ ts0 = 0; -+ tstmp = tsm->last_ts_sent; -+ } -+ -+ if (ts0 > TSM_ADAPTIVE_INTERVAL (tsm) * 3 / 2) { -+ TSM_WARNING ("Jitter1:%" TSM_TIME_FORMAT " %" TSM_TIME_FORMAT "\n", -+ TSM_TIME_ARGS (ts0), -+ TSM_TIME_ARGS (TSM_ADAPTIVE_INTERVAL (tsm) * 3 / 2)); -+ } else if (ts0 == 0) { -+ TSM_WARNING ("Jitter:%" TSM_TIME_FORMAT "\n", TSM_TIME_ARGS (ts0)); -+ } -+ -+ if (send) { -+ if ((ts0 < TSM_ADAPTIVE_INTERVAL (tsm) * 2) || (tsm->big_cnt > 3)) { -+ tsm->big_cnt = 0; -+ tsm->dur_history_total -= -+ tsm->dur_history_buf[tsm->dur_history_tx]; -+ tsm->dur_history_buf[tsm->dur_history_tx] = ts0; -+ tsm->dur_history_tx = -+ ((tsm->dur_history_tx + 1) % TSM_HISTORY_SIZE); -+ tsm->dur_history_total += ts0; -+ } else { -+ tsm->big_cnt++; -+ } -+ } -+ } -+ -+ if (send) { -+ tsm->last_ts_sent = tstmp; -+ tsm->age++; -+ tsm->first_tx = 0; -+ } -+ -+ } else if (tsm->mode == MODE_FIFO) { -+ tstmp = tsm->ts_buf[tsm->tx].ts; -+ if (send) { -+ tsm->tx = ((tsm->tx + 1) % tsm->ts_buf_size); -+ } -+ ts0 = tstmp - tsm->last_ts_sent; -+ if (send) { -+ tsm->last_ts_sent = tstmp; -+ } -+ } -+ -+ if (send) { -+ TSM_LOG ("--Send %d:%" TSM_TIME_FORMAT ", int:%" TSM_TIME_FORMAT -+ ", avg:%" TSM_TIME_FORMAT " inkey %p\n", tsm->tx_cnt, -+ TSM_TIME_ARGS (tstmp), TSM_TIME_ARGS (ts0), -+ TSM_TIME_ARGS (TSM_ADAPTIVE_INTERVAL (tsm)), key); -+ } -+ -+ } else { -+ if (tsm->valid_ts_received == 0) { -+ if (tsm->first_tx) { -+ tstmp = tsm->last_ts_sent; -+ } else { -+ tstmp = tsm->last_ts_sent + TSM_ADAPTIVE_INTERVAL (tsm); -+ } -+ if (send) { -+ tsm->first_tx = 0; -+ tsm->last_ts_sent = tstmp; -+ } -+ } -+ TSM_ERROR ("Too many timestamps send!!\n"); -+ } -+ -+ if (send == 0) { -+ tsm->cnt--; -+ tsm->invalid_ts_count--; -+ } -+ -+ } -+ -+ return tstmp; -+} -+ -+ -+TSM_TIMESTAMP -+TSManagerSend2 (void *handle, void *key) -+{ -+ return _TSManagerSend2 (handle, key, 1); -+} -+ -+ -+TSM_TIMESTAMP -+TSManagerQuery2 (void *handle, void *key) -+{ -+ return _TSManagerSend2 (handle, key, 0); -+} -+ -+ -+TSM_TIMESTAMP -+TSManagerSend (void *handle) -+{ -+ return TSManagerSend2 (handle, TSM_KEY_NONE); -+} -+ -+ -+TSM_TIMESTAMP -+TSManagerQuery (void *handle) -+{ -+ return TSManagerQuery2 (handle, TSM_KEY_NONE); -+} -+ -+ -+void -+resyncTSManager (void *handle, TSM_TIMESTAMP synctime, TSMGR_MODE mode) -+{ -+ TSManager *tsm = (TSManager *) handle; -+ if (tsm) { -+ TSMRecivedCtl *rctl = &tsm->rctl; -+ TSMReceivedEntry *e = rctl->head; -+ -+ while ((e = rctl->head)) { -+ rctl->head = e->next; -+ tsm_free_received_entry (rctl, e); -+ }; -+ rctl->cnt = 0; -+ -+ rctl->tail = NULL; -+ -+ tsm->first_tx = 1; -+ tsm->first_rx = 1; -+ tsm->suspicious_ts = 0; -+ -+ if (TSM_TS_IS_VALID (synctime)) -+ tsm->last_ts_sent = synctime; -+ -+ tsm->tx = tsm->rx = 0; -+ tsm->invalid_ts_count = 0; -+ tsm->mode = mode; -+ tsm->age = 0; -+ tsm->rx_cnt = tsm->tx_cnt = tsm->cnt = 0; -+ tsm->valid_ts_received = 0; -+ -+ tsm->big_cnt = 0; -+ } -+} -+ -+ -+/*====================================================================================== -+FUNCTION: mfw_gst_init_ts -+ -+DESCRIPTION: malloc and initialize timestamp strcture -+ -+ARGUMENTS PASSED: ppTimeStamp_Object - pointer of TimeStamp Manager to handle related timestamp -+ -+RETURN VALUE: TimeStamp structure pointer -+PRE-CONDITIONS: None -+POST-CONDITIONS: None -+IMPORTANT NOTES: None -+=======================================================================================*/ -+void * -+createTSManager (int ts_buf_size) -+{ -+ TSManager *tsm = (TSManager *) malloc (sizeof (TSManager)); -+ debug = getenv (debug_env); -+ if (debug) { -+ debug_level = atoi (debug); -+ } -+ // printf("debug = %s \n ++++++++++++++++++++++++++++",debug); -+ if (tsm) { -+ memset (tsm, 0, sizeof (TSManager)); -+ if (ts_buf_size <= 0) { -+ ts_buf_size = TSM_DEFAULT_TS_BUFFER_SIZE; -+ } -+ tsm->ts_buf_size = ts_buf_size; -+ tsm->ts_buf = malloc (sizeof (TSMControl) * ts_buf_size); -+ -+ if (tsm->ts_buf == NULL) { -+ goto fail; -+ } -+ -+ resyncTSManager (tsm, (TSM_TIMESTAMP) 0, MODE_AI); -+ -+ tsm->dur_history_tx = 0; -+ TSM_BUFFER_SET (tsm->dur_history_buf, TSM_DEFAULT_INTERVAL, -+ TSM_HISTORY_SIZE); -+ tsm->dur_history_total = TSM_DEFAULT_INTERVAL << TSM_HISTORY_POWER; -+ -+ tsm->discont_threshold = 10000000000LL; // 10s -+ } -+ return tsm; -+fail: -+ if (tsm) { -+ if (tsm->ts_buf) { -+ free (tsm->ts_buf); -+ } -+ free (tsm); -+ tsm = NULL; -+ } -+ return tsm; -+} -+ -+ -+void -+destroyTSManager (void *handle) -+{ -+ TSManager *tsm = (TSManager *) handle; -+ if (tsm) { -+ TSMRecivedCtl *rctl = &tsm->rctl; -+ TSMReceivedEntryMemory *rmem; -+ if (tsm->ts_buf) { -+ free (tsm->ts_buf); -+ } -+ -+ while ((rmem = rctl->memory)) { -+ rctl->memory = rmem->next; -+ free (rmem); -+ } -+ free (tsm); -+ tsm = NULL; -+ } -+} -+ -+ -+void -+setTSManagerFrameRate (void *handle, int fps_n, int fps_d) -+//void setTSManagerFrameRate(void * handle, float framerate) -+{ -+ TSManager *tsm = (TSManager *) handle; -+ TSM_TIMESTAMP ts; -+ if ((fps_n > 0) && (fps_d > 0) && (fps_n / fps_d <= 80)) -+ ts = TSM_SECOND * fps_d / fps_n; -+ else -+ ts = TSM_DEFAULT_INTERVAL; -+ // TSM_TIMESTAMP ts = TSM_SECOND / framerate; -+ -+ if (tsm) { -+ TSM_BUFFER_SET (tsm->dur_history_buf, ts, TSM_HISTORY_SIZE); -+ tsm->dur_history_total = (ts << TSM_HISTORY_POWER); -+ if (debug) -+ TSM_LOG ("Set frame intrval:%" TSM_TIME_FORMAT "\n", TSM_TIME_ARGS (ts)); -+ } -+} -+ -+ -+TSM_TIMESTAMP -+getTSManagerFrameInterval (void *handle) -+{ -+ TSManager *tsm = (TSManager *) handle; -+ TSM_TIMESTAMP ts = 0; -+ if (tsm) { -+ ts = TSM_ADAPTIVE_INTERVAL (tsm); -+ } -+ return ts; -+} -+ -+ -+TSM_TIMESTAMP -+getTSManagerPosition (void *handle) -+{ -+ TSManager *tsm = (TSManager *) handle; -+ TSM_TIMESTAMP ts = 0; -+ if (tsm) { -+ ts = tsm->last_ts_sent; -+ } -+ return ts; -+} -+ -+ -+int -+getTSManagerPreBufferCnt (void *handle) -+{ -+ int i = 0; -+ TSManager *tsm = (TSManager *) handle; -+ if (tsm) { -+ i = tsm->rctl.cnt; -+ } -+ return i; -+} -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/mfw_gst_ts.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/mfw_gst_ts.h -new file mode 100644 -index 0000000..f5d66c4 ---- /dev/null -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/mfw_gst_ts.h -@@ -0,0 +1,170 @@ -+/* -+ * Copyright (c) 2010-2012, Freescale Semiconductor, Inc. All rights reserved. -+ * -+ */ -+ -+/* -+ * This library is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU Library General Public -+ * License as published by the Free Software Foundation; either -+ * version 2 of the License, or (at your option) any later version. -+ * -+ * This library is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * Library General Public License for more details. -+ * -+ * You should have received a copy of the GNU Library General Public -+ * License along with this library; if not, write to the -+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330, -+ * Boston, MA 02111-1307, USA. -+ */ -+ -+/* -+ * Module Name: TimeStamp.h -+ * -+ * Description: include TimeStamp stratege for VPU / SW video decoder plugin -+ * -+ * Portability: This code is written for Linux OS and Gstreamer -+ */ -+ -+/* -+ * Changelog: -+ 11/2/2010 draft version Lyon Wang -+ * -+ */ -+ -+#ifndef _TIMESTAMP_H_ -+#define _TIMESTAMP_H_ -+ -+ -+/** -+ * GST_CLOCK_TIME_NONE: -+ * -+ * Constant to define an undefined clock time. -+ */ -+ -+typedef long long TSM_TIMESTAMP; -+ -+typedef enum -+{ -+ MODE_AI, -+ MODE_FIFO, -+} TSMGR_MODE; -+ -+#define TSM_TIMESTAMP_NONE ((long long)(-1)) -+#define TSM_KEY_NONE ((void *)0) -+ -+/** -+ * GST_CLOCK_TIME_IS_VALID: -+ * @time: clock time to validate -+ * -+ * Tests if a given #GstClockTime represents a valid defined time. -+ */ -+ -+#ifdef __cplusplus -+#define EXTERN -+#else -+#define EXTERN extern -+#endif -+ -+#ifdef __cplusplus -+extern "C" -+{ -+#endif -+ -+/*! -+ * This function receive timestamp into timestamp manager. -+ * -+ * @param handle handle of timestamp manager. -+ * -+ * @param timestamp timestamp received -+ * -+ * @return -+ */ -+ EXTERN void TSManagerReceive (void *handle, TSM_TIMESTAMP timestamp); -+ -+ EXTERN void TSManagerReceive2 (void *handle, TSM_TIMESTAMP timestamp, -+ int size); -+ -+ EXTERN void TSManagerFlush2 (void *handle, int size); -+ -+ EXTERN void TSManagerValid2 (void *handle, int size, void *key); -+ -+/*! -+ * This function send the timestamp for next output frame. -+ * -+ * @param handle handle of timestamp manager. -+ * -+ * @return timestamp for next output frame. -+ */ -+ EXTERN TSM_TIMESTAMP TSManagerSend (void *handle); -+ -+ EXTERN TSM_TIMESTAMP TSManagerSend2 (void *handle, void *key); -+ -+ EXTERN TSM_TIMESTAMP TSManagerQuery2 (void *handle, void *key); -+ -+ EXTERN TSM_TIMESTAMP TSManagerQuery (void *handle); -+/*! -+ * This function resync timestamp handler when reset and seek -+ * -+ * @param handle handle of timestamp manager. -+ * -+ * @param synctime the postion time needed to set, if value invalid, position keeps original -+ * -+ * @param mode playing mode (AI or FIFO) -+ * -+ * @return -+ */ -+ EXTERN void resyncTSManager (void *handle, TSM_TIMESTAMP synctime, -+ TSMGR_MODE mode); -+/*! -+ * This function create and reset timestamp handler -+ * -+ * @param ts_buf_size time stamp queue buffer size -+ * -+ * @return -+ */ -+ EXTERN void *createTSManager (int ts_buf_size); -+/*! -+ * This function destory timestamp handler -+ * -+ * @param handle handle of timestamp manager. -+ * -+ * @return -+ */ -+ EXTERN void destroyTSManager (void *handle); -+/*! -+ * This function set history buffer frame interval by fps_n and fps_d -+ * -+ * @param handle handle of timestamp manager. -+ * -+ * @param framerate the framerate to be set -+ * -+ * @return -+ */ -+ EXTERN void setTSManagerFrameRate (void *handle, int fps_n, int fps_d); -+//EXTERN void setTSManagerFrameRate(void * handle, float framerate); -+/*! -+ * This function set the current calculated Frame Interval -+ * -+ * @param handle handle of timestamp manager. -+ * -+ * @return -+ */ -+ EXTERN TSM_TIMESTAMP getTSManagerFrameInterval (void *handle); -+/*! -+ * This function get the current time stamp postion -+ * -+ * @param handle handle of timestamp manager. -+ * -+ * @return -+ */ -+ EXTERN TSM_TIMESTAMP getTSManagerPosition (void *handle); -+ EXTERN int getTSManagerPreBufferCnt (void *handle); -+ -+#ifdef __cplusplus -+} -+#endif -+ -+#endif /*_TIMESTAMP_H_ */ -diff --git a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp -index be532ec..9a0acf1 100644 ---- a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp -+++ b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp -@@ -995,6 +995,7 @@ static std::string GetRenderFormatName(ERenderFormat format) - case RENDER_FMT_CVBREF: return "BGRA"; - case RENDER_FMT_EGLIMG: return "EGLIMG"; - case RENDER_FMT_BYPASS: return "BYPASS"; -+ case RENDER_FMT_IMX: return "IMX"; - case RENDER_FMT_MEDIACODEC:return "MEDIACODEC"; - case RENDER_FMT_NONE: return "NONE"; - } -diff --git a/xbmc/input/linux/LinuxInputDevices.cpp b/xbmc/input/linux/LinuxInputDevices.cpp -index ee21474..1446a56 100644 ---- a/xbmc/input/linux/LinuxInputDevices.cpp -+++ b/xbmc/input/linux/LinuxInputDevices.cpp -@@ -1227,7 +1227,8 @@ XBMC_Event CLinuxInputDevices::ReadEvent() - - if ((now - m_lastHotplugCheck) >= 10) - { -- CheckHotplugged(); -+ // Comment for now as it has visible issue on video decoding when USB devices are available -+ //CheckHotplugged(); - m_lastHotplugCheck = now; - } - } -diff --git a/xbmc/windowing/egl/EGLNativeTypeIMX.cpp b/xbmc/windowing/egl/EGLNativeTypeIMX.cpp -new file mode 100644 -index 0000000..4ac19c4 ---- /dev/null -+++ b/xbmc/windowing/egl/EGLNativeTypeIMX.cpp -@@ -0,0 +1,272 @@ -+/* -+ * 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 "system.h" -+#include -+ -+#include "EGLNativeTypeIMX.h" -+#include -+#include -+#include -+#include "utils/log.h" -+#include "utils/StringUtils.h" -+#include "guilib/gui3d.h" -+ -+CEGLNativeTypeIMX::CEGLNativeTypeIMX() -+{ -+} -+ -+CEGLNativeTypeIMX::~CEGLNativeTypeIMX() -+{ -+} -+ -+bool CEGLNativeTypeIMX::CheckCompatibility() -+{ -+ char name[256] = {0}; -+ get_sysfs_str("/sys/class/graphics/fb0/device/modalias", name, 255); -+ CStdString strName = name; -+ StringUtils::Trim(strName); -+ if (strName == "platform:mxc_sdc_fb") -+ return true; -+ return false; -+} -+ -+void CEGLNativeTypeIMX::Initialize() -+{ -+ struct mxcfb_gbl_alpha alpha; -+ int fd, fd2; -+ -+ -+ fd = open("/dev/fb0",O_RDWR); -+ if (fd < 0) -+ { -+ CLog::Log(LOGERROR, "%s - Error while opening /dev/fb0.\n", __FUNCTION__); -+ return; -+ } -+ fd2 = open("/dev/fb1",O_RDWR); -+ if (fd2 < 0) -+ { -+ CLog::Log(LOGERROR, "%s - Error while opening /dev/fb1.\n", __FUNCTION__); -+ return; -+ } -+ -+ /* Store screen info */ -+ if (ioctl(fd, FBIOGET_VSCREENINFO, &m_screeninfo) != 0) -+ { -+ CLog::Log(LOGERROR, "%s - Error while querying frame buffer.\n", __FUNCTION__); -+ return; -+ } -+ /* Configure overlay in the same way as BG plane */ -+ if (ioctl(fd2, FBIOPUT_VSCREENINFO, &m_screeninfo) != 0) -+ { -+ CLog::Log(LOGERROR, "%s - Error while setting overlay frame buffer.\n", __FUNCTION__); -+ return; -+ } -+ -+ /* set fb0 as the only visible layer - ioctl on /dev/fb0 so that fb0 is BG and fb1 is FG */ -+ alpha.alpha = 255; -+ alpha.enable = 1; -+ if (ioctl(fd, MXCFB_SET_GBL_ALPHA, &alpha) != 0) -+ { -+ CLog::Log(LOGERROR, "%s - Error while initializing frame buffer.\n", __FUNCTION__); -+ } -+ -+ /* Unblank the fbs */ -+ if (ioctl(fd, FBIOBLANK, 0) < 0) -+ { -+ CLog::Log(LOGERROR, "%s - Error while unblanking fb0.\n", __FUNCTION__); -+ } -+ if (ioctl(fd2, FBIOBLANK, 0) < 0) -+ { -+ CLog::Log(LOGERROR, "%s - Error while unblanking fb0.\n", __FUNCTION__); -+ } -+ -+ close(fd); -+ close(fd2); -+ -+ return; -+} -+ -+void CEGLNativeTypeIMX::Destroy() -+{ -+ struct fb_fix_screeninfo fixed_info; -+ void *fb_buffer; -+ struct mxcfb_gbl_alpha alpha; -+ int fd; -+ -+ fd = open("/dev/fb0",O_RDWR); -+ if (fd < 0) -+ { -+ CLog::Log(LOGERROR, "%s - Error while opening /dev/fb0.\n", __FUNCTION__); -+ return; -+ } -+ /* only fb0 visible */ -+ alpha.alpha = 255; -+ alpha.enable = 1; -+ if (ioctl(fd, MXCFB_SET_GBL_ALPHA, &alpha) != 0) -+ { -+ CLog::Log(LOGERROR, "%s - Error while initializing frame buffer.\n", __FUNCTION__); -+ } -+ -+ 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); -+ -+ /* Blank overlay */ -+ fd = open("/dev/fb1",O_RDWR); -+ if (fd < 0) -+ { -+ CLog::Log(LOGERROR, "%s - Error while opening /dev/fb1.\n", __FUNCTION__); -+ return; -+ } -+ if (ioctl(fd, FBIOBLANK, 1) < 0) -+ { -+ CLog::Log(LOGERROR, "%s - Error while blanking fb1.\n", __FUNCTION__); -+ } -+ close(fd); -+ -+ return; -+} -+ -+bool CEGLNativeTypeIMX::CreateNativeDisplay() -+{ -+ /* EGL will be rendered on fb0 */ -+ m_display = fbGetDisplayByIndex(0); -+ m_nativeDisplay = &m_display; -+ return true; -+} -+ -+bool CEGLNativeTypeIMX::CreateNativeWindow() -+{ -+ m_window = fbCreateWindow(m_display, 0, 0, m_screeninfo.xres, m_screeninfo.yres); -+ m_nativeWindow = &m_window; -+ return true; -+} -+ -+bool CEGLNativeTypeIMX::GetNativeDisplay(XBNativeDisplayType **nativeDisplay) const -+{ -+ if (!nativeDisplay) -+ return false; -+ *nativeDisplay = (XBNativeDisplayType*)m_nativeDisplay; -+ return true; -+} -+ -+bool CEGLNativeTypeIMX::GetNativeWindow(XBNativeWindowType **nativeWindow) const -+{ -+ if (!nativeWindow) -+ return false; -+ *nativeWindow = (XBNativeWindowType*)m_nativeWindow; -+ return true; -+} -+ -+bool CEGLNativeTypeIMX::DestroyNativeDisplay() -+{ -+ return true; -+} -+ -+bool CEGLNativeTypeIMX::DestroyNativeWindow() -+{ -+ return true; -+} -+ -+bool CEGLNativeTypeIMX::GetNativeResolution(RESOLUTION_INFO *res) const -+{ -+ double drate = 0, hrate = 0, vrate = 0; -+ if (!res) -+ return false; -+ -+ drate = 1e12 / m_screeninfo.pixclock; -+ hrate = drate / (m_screeninfo.left_margin + m_screeninfo.xres + m_screeninfo.right_margin + m_screeninfo.hsync_len); -+ vrate = hrate / (m_screeninfo.upper_margin + m_screeninfo.yres + m_screeninfo.lower_margin + m_screeninfo.vsync_len); -+ -+ res->iWidth = m_screeninfo.xres; -+ res->iHeight = m_screeninfo.yres; -+ res->iScreenWidth = res->iWidth; -+ res->iScreenHeight = res->iHeight; -+ res->fRefreshRate = lrint(vrate); -+ res->dwFlags= D3DPRESENTFLAG_PROGRESSIVE; -+ 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" : ""); -+ -+ return res->iWidth > 0 && res->iHeight> 0; -+} -+ -+bool CEGLNativeTypeIMX::SetNativeResolution(const RESOLUTION_INFO &res) -+{ -+ return false; -+} -+ -+bool CEGLNativeTypeIMX::ProbeResolutions(std::vector &resolutions) -+{ -+ RESOLUTION_INFO res; -+ bool ret = false; -+ ret = GetNativeResolution(&res); -+ if (ret && res.iWidth > 1 && res.iHeight > 1) -+ { -+ resolutions.push_back(res); -+ return true; -+ } -+ return false; -+} -+ -+bool CEGLNativeTypeIMX::GetPreferredResolution(RESOLUTION_INFO *res) const -+{ -+ return false; -+} -+ -+bool CEGLNativeTypeIMX::ShowWindow(bool show) -+{ -+ // CLog::Log(LOGERROR, "%s - call CEGLNativeTypeIMX::ShowWindow with %d.\n", __FUNCTION__, show); -+ return false; -+} -+ -+int CEGLNativeTypeIMX::get_sysfs_str(const char *path, char *valstr, const int size) const -+{ -+ int fd = open(path, O_RDONLY); -+ if (fd >= 0) -+ { -+ int len = read(fd, valstr, size - 1); -+ if (len != -1 ) -+ valstr[len] = '\0'; -+ close(fd); -+ } -+ else -+ { -+ sprintf(valstr, "%s", "fail"); -+ return -1; -+ } -+ return 0; -+} -diff --git a/xbmc/windowing/egl/EGLNativeTypeIMX.h b/xbmc/windowing/egl/EGLNativeTypeIMX.h -new file mode 100644 -index 0000000..61d5833 ---- /dev/null -+++ b/xbmc/windowing/egl/EGLNativeTypeIMX.h -@@ -0,0 +1,62 @@ -+#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" -+#include "EGL/eglvivante.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: -+ int get_sysfs_str(const char *path, char *valstr, const int size) const; -+ bool ModeToResolution(const char *mode, RESOLUTION_INFO *res) const; -+ -+ EGLNativeDisplayType m_display; -+ EGLNativeWindowType m_window; -+ -+protected: -+ struct fb_var_screeninfo m_screeninfo; -+ -+}; -diff --git a/xbmc/windowing/egl/EGLWrapper.cpp b/xbmc/windowing/egl/EGLWrapper.cpp -index 045cdfc..0726cc2 100644 ---- a/xbmc/windowing/egl/EGLWrapper.cpp -+++ b/xbmc/windowing/egl/EGLWrapper.cpp -@@ -17,11 +17,10 @@ - * . - * - */ -- -+#include "EGLNativeTypeIMX.h" - #include "system.h" - - #ifdef HAS_EGL -- - #include "utils/log.h" - #include "EGLNativeTypeAndroid.h" - #include "EGLNativeTypeAmlogic.h" -@@ -83,7 +82,8 @@ 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 --- -1.9.3 - - -From 8621accc7a9a0ebf81369ee4ad85b3d4cd7f126a Mon Sep 17 00:00:00 2001 -From: "Chris \"Koying\" Browet" -Date: Thu, 6 Feb 2014 16:26:29 +0100 -Subject: [PATCH 02/50] CHG: [imx] remove V4L and baseline software rendering - ---- - xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp | 103 +- - xbmc/cores/VideoRenderers/LinuxRendererGLES.h | 7 - - xbmc/cores/VideoRenderers/RenderFormats.h | 1 - - xbmc/cores/VideoRenderers/RenderManager.cpp | 4 - - .../dvdplayer/DVDCodecs/Video/DVDVideoCodec.h | 7 +- - .../dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp | 1168 +++----------------- - .../dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h | 110 +- - xbmc/cores/dvdplayer/DVDPlayerVideo.cpp | 1 - - xbmc/windowing/egl/EGLWrapper.cpp | 11 +- - xbmc/windowing/egl/Makefile.in | 5 +- - 10 files changed, 155 insertions(+), 1262 deletions(-) - -diff --git a/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp b/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp -index 913fb0f..72eb725 100644 ---- a/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp -+++ b/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp -@@ -20,10 +20,6 @@ - - //#define DEBUG_VERBOSE 1 - --#ifdef HAS_IMXVPU --#include --#endif -- - #include "system.h" - #if (defined HAVE_CONFIG_H) && (!defined TARGET_WINDOWS) - #include "config.h" -@@ -70,11 +66,6 @@ extern "C" { - #ifdef TARGET_DARWIN_IOS - #include "osx/DarwinUtils.h" - #endif -- --#ifdef HAS_IMXVPU --#include "DVDCodecs/Video/DVDVideoCodecIMX.h" --#endif -- - #if defined(HAS_LIBSTAGEFRIGHT) - #include - #include -@@ -112,10 +103,6 @@ CLinuxRendererGLES::YUVBUFFER::YUVBUFFER() - #if defined(TARGET_ANDROID) - mediacodec = NULL; - #endif --#ifdef HAS_IMXVPU -- imxOutputFrame = NULL; --#endif -- - } - - CLinuxRendererGLES::YUVBUFFER::~YUVBUFFER() -@@ -126,23 +113,6 @@ CLinuxRendererGLES::CLinuxRendererGLES() - { - m_textureTarget = GL_TEXTURE_2D; - -- /* FIXME a verifier */ --#if 0 -- -- for (int i = 0; i < NUM_BUFFERS; i++) -- { --#if defined(HAVE_LIBOPENMAX) -- m_buffers[i].openMaxBuffer = 0; --#endif --#ifdef HAVE_VIDEOTOOLBOXDECODER -- m_buffers[i].cvBufferRef = NULL; --#endif --#ifdef HAS_IMXVPU -- m_buffers[i].imx = NULL; --#endif -- } --#endif -- - m_renderMethod = RENDER_GLSL; - m_oldRenderMethod = m_renderMethod; - m_renderQuality = RQ_SINGLEPASS; -@@ -528,53 +498,18 @@ void CLinuxRendererGLES::RenderUpdate(bool clear, DWORD flags, DWORD alpha) - (*m_RenderUpdateCallBackFn)(m_RenderUpdateCallBackCtx, m_sourceRect, m_destRect); - - CRect old = g_graphicsContext.GetScissors(); -- RESOLUTION res = GetResolution(); -- int iWidth = CDisplaySettings::Get().GetResolutionInfo(res).iWidth; -- int iHeight = CDisplaySettings::Get().GetResolutionInfo(res).iHeight; - - g_graphicsContext.BeginPaint(); -- if (clear) -- { -- glScissor(0, -- 0, -- iWidth, -- iHeight); -- glClearColor(GLfloat(0.0), GLfloat(0.0), GLfloat(0.0), 0); -- glClear(GL_COLOR_BUFFER_BIT); -- } -- - g_graphicsContext.SetScissors(m_destRect); -- /* CLog::Log(LOGDEBUG, "%s - m_destRect : %f %f %f %f\n", -- __FUNCTION__, m_destRect.x1, m_destRect.x2, m_destRect.y1,m_destRect.y2);*/ -- - --/* glEnable(GL_BLEND); -- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);*/ -- glClearColor(GLfloat(2.0/31.0), GLfloat(2.0/63.0), GLfloat(2.0/31.0), 0); -+ glEnable(GL_BLEND); -+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); -+ glClearColor(0, 0, 0, 0); - glClear(GL_COLOR_BUFFER_BIT); - - g_graphicsContext.SetScissors(old); - g_graphicsContext.EndPaint(); -- --#ifdef HAS_IMXVPU -- // FIXME : move in its own render mode instead of mixup with BYPASS -- if (m_format == RENDER_FMT_IMX) -- { -- int index = m_iYV12RenderBuffer; -- struct v4l2_crop crop; -- crop.c.top = (int)m_destRect.y1; -- crop.c.left = (int)m_destRect.x1; -- crop.c.width = (int)(m_destRect.x2 - m_destRect.x1); -- crop.c.height = (int)(m_destRect.y2 - m_destRect.y1); -- CIMXOutputFrame *imxPicture = m_buffers[index].imxOutputFrame; -- if (imxPicture != NULL) -- { -- imxPicture->Render(crop); -- m_buffers[index].imxOutputFrame = NULL; -- } -- } - return; --#endif - } - - // this needs to be checked after texture validation -@@ -663,9 +598,6 @@ unsigned int CLinuxRendererGLES::PreInit() - #ifdef HAVE_VIDEOTOOLBOXDECODER - m_formats.push_back(RENDER_FMT_CVBREF); - #endif --#ifdef HAS_IMXVPU -- m_formats.push_back(RENDER_FMT_IMX); --#endif - #ifdef HAS_LIBSTAGEFRIGHT - m_formats.push_back(RENDER_FMT_EGLIMG); - #endif -@@ -791,13 +723,6 @@ void CLinuxRendererGLES::LoadShaders(int field) - m_renderMethod = RENDER_CVREF; - break; - } -- else if (m_format == RENDER_FMT_IMX) -- { -- CLog::Log(LOGNOTICE, "GL: IMX format Uses BYPASS render method"); -- m_renderMethod = RENDER_BYPASS; -- break; -- } -- - #if defined(TARGET_DARWIN_IOS) - else if (ios_version < 5.0 && m_format == RENDER_FMT_YUV420P) - { -@@ -968,18 +893,6 @@ void CLinuxRendererGLES::ReleaseBuffer(int idx) - } - } - #endif --#ifdef HAS_IMXVPU -- if (buf.imxOutputFrame != NULL) -- { -- // If we take that branch the buffer was not queued to V4L2 -- // So release the picture now so that VPU will be given -- // the buffer back as soon as next ::Decode() call -- buf.imxOutputFrame->Release(); -- buf.imxOutputFrame = NULL; -- } -- return; --#endif -- - } - - void CLinuxRendererGLES::Render(DWORD flags, int index) -@@ -2778,15 +2691,6 @@ void CLinuxRendererGLES::AddProcessor(struct __CVBuffer *cvBufferRef, int index) - CVBufferRetain(buf.cvBufferRef); - } - #endif -- --#ifdef HAS_IMXVPU --void CLinuxRendererGLES::AddProcessor(CIMXOutputFrame *imx, int index) --{ -- YUVBUFFER &buf = m_buffers[index]; -- buf.imxOutputFrame = imx; --} --#endif -- - #ifdef HAS_LIBSTAGEFRIGHT - void CLinuxRendererGLES::AddProcessor(CDVDVideoCodecStageFright* stf, EGLImageKHR eglimg, int index) - { -@@ -2808,7 +2712,6 @@ void CLinuxRendererGLES::AddProcessor(CDVDVideoCodecStageFright* stf, EGLImageKH - } - #endif - -- - #if defined(TARGET_ANDROID) - void CLinuxRendererGLES::AddProcessor(CDVDMediaCodecInfo *mediacodec, int index) - { -diff --git a/xbmc/cores/VideoRenderers/LinuxRendererGLES.h b/xbmc/cores/VideoRenderers/LinuxRendererGLES.h -index e58330a..642cded 100644 ---- a/xbmc/cores/VideoRenderers/LinuxRendererGLES.h -+++ b/xbmc/cores/VideoRenderers/LinuxRendererGLES.h -@@ -42,7 +42,6 @@ namespace Shaders { class BaseVideoFilterShader; } - class COpenMaxVideo; - class CDVDVideoCodecStageFright; - class CDVDMediaCodecInfo; --class CIMXOutputFrame; - typedef std::vector Features; - - -@@ -167,9 +166,6 @@ class CLinuxRendererGLES : public CBaseRenderer - #ifdef HAS_LIBSTAGEFRIGHT - virtual void AddProcessor(CDVDVideoCodecStageFright* stf, EGLImageKHR eglimg, int index); - #endif --#ifdef HAS_IMXVPU -- virtual void AddProcessor(CIMXOutputFrame *imx, int index); --#endif - #if defined(TARGET_ANDROID) - // mediaCodec - virtual void AddProcessor(CDVDMediaCodecInfo *mediacodec, int index); -@@ -281,9 +277,6 @@ class CLinuxRendererGLES : public CBaseRenderer - #ifdef HAVE_VIDEOTOOLBOXDECODER - struct __CVBuffer *cvBufferRef; - #endif --#ifdef HAS_IMXVPU -- CIMXOutputFrame *imxOutputFrame; --#endif - #ifdef HAS_LIBSTAGEFRIGHT - CDVDVideoCodecStageFright* stf; - EGLImageKHR eglimg; -diff --git a/xbmc/cores/VideoRenderers/RenderFormats.h b/xbmc/cores/VideoRenderers/RenderFormats.h -index d40e4f5..f15e80d 100644 ---- a/xbmc/cores/VideoRenderers/RenderFormats.h -+++ b/xbmc/cores/VideoRenderers/RenderFormats.h -@@ -35,7 +35,6 @@ enum ERenderFormat { - RENDER_FMT_OMXEGL, - RENDER_FMT_CVBREF, - RENDER_FMT_BYPASS, -- RENDER_FMT_IMX, - RENDER_FMT_EGLIMG, - RENDER_FMT_MEDIACODEC, - }; -diff --git a/xbmc/cores/VideoRenderers/RenderManager.cpp b/xbmc/cores/VideoRenderers/RenderManager.cpp -index 79c4223..b6fb1a3 100644 ---- a/xbmc/cores/VideoRenderers/RenderManager.cpp -+++ b/xbmc/cores/VideoRenderers/RenderManager.cpp -@@ -924,10 +924,6 @@ int CXBMCRenderManager::AddVideoPicture(DVDVideoPicture& pic) - else if(pic.format == RENDER_FMT_VAAPI) - m_pRenderer->AddProcessor(*pic.vaapi, index); - #endif --#ifdef HAS_IMXVPU -- else if(pic.format == RENDER_FMT_IMX) -- m_pRenderer->AddProcessor(pic.imxOutputFrame, index); --#endif - #ifdef HAS_LIBSTAGEFRIGHT - else if(pic.format == RENDER_FMT_EGLIMG) - m_pRenderer->AddProcessor(pic.stf, pic.eglimg, index); -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h -index f6e576e..741017d 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h -@@ -51,7 +51,6 @@ namespace VDPAU { class CVdpauRenderPicture; } - class COpenMax; - class COpenMaxVideo; - struct OpenMaxVideoBuffer; --class CIMXOutputFrame; - class CDVDVideoCodecStageFright; - class CDVDMediaCodecInfo; - typedef void* EGLImageKHR; -@@ -78,16 +77,14 @@ struct DVDVideoPicture - struct { - VAAPI::CHolder* vaapi; - }; -+ - struct { - COpenMax *openMax; - OpenMaxVideoBuffer *openMaxBuffer; - }; -- struct { -- struct __CVBuffer *cvBufferRef; -- }; - - struct { -- CIMXOutputFrame *imxOutputFrame; -+ struct __CVBuffer *cvBufferRef; - }; - - struct { -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp -index c0af493..9adffd3 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp -@@ -32,484 +32,8 @@ - #include "mfw_gst_ts.h" - #include "threads/Atomics.h" - --//#define NO_V4L_RENDERING - --#ifdef IMX_PROFILE --static unsigned long long render_ts[30]; --static unsigned long long get_time() --{ -- struct timespec ts; -- unsigned long long now; -- -- clock_gettime(CLOCK_MONOTONIC, &ts); -- now = (((unsigned long long)ts.tv_sec) * 1000000000ULL) + -- ((unsigned long long)ts.tv_nsec); -- -- return now; --} --#endif -- --void CIMXOutputFrame::Render(struct v4l2_crop &crop) --{ -- CIMXRenderingFrames& renderingFrames = CIMXRenderingFrames::GetInstance(); -- renderingFrames.Queue(this, crop); --} -- --/* video device on which the video will be rendered (/dev/video17 => /dev/fb1) */ --const char *CIMXRenderingFrames::m_v4lDeviceName = "/dev/video17"; --static long sg_singleton_lock_variable = 0; --CIMXRenderingFrames* CIMXRenderingFrames::m_instance = 0; -- --CIMXRenderingFrames& --CIMXRenderingFrames::GetInstance() --{ -- CAtomicSpinLock lock(sg_singleton_lock_variable); -- if( ! m_instance ) -- { -- m_instance = new CIMXRenderingFrames(); -- } -- return *m_instance; --} -- --CIMXRenderingFrames::CIMXRenderingFrames() --{ -- m_ready = false; -- m_v4lfd = -1; -- m_virtAddr = NULL; -- m_v4lBuffers = NULL; -- memset(&m_crop, 0, sizeof(m_crop)); -- m_crop.type = V4L2_BUF_TYPE_VIDEO_OUTPUT; -- m_motionCtrl = -1; --} -- --bool CIMXRenderingFrames::AllocateBuffers(const struct v4l2_format *format, int nbBuffers) --{ -- int ret, i; -- struct v4l2_requestbuffers bufReq; -- struct v4l2_format fmt; -- struct v4l2_buffer v4lBuf; -- struct v4l2_control ctrl; -- -- CSingleLock lock(m_renderingFramesLock); -- if (m_ready) -- { -- CLog::Log(LOGERROR, "%s - Try to re-allocate buffers while previous buffers were not freed.\n", __FUNCTION__); -- return false; -- } -- -- m_v4lfd = open(m_v4lDeviceName, O_RDWR|O_NONBLOCK, 0); -- if (m_v4lfd < 0) -- { -- CLog::Log(LOGERROR, "%s - Error while trying to open %s.\n", __FUNCTION__, m_v4lDeviceName); -- __ReleaseBuffers(); -- return false; -- } -- -- ret = ioctl(m_v4lfd, VIDIOC_S_FMT, format); -- if (ret < 0) -- { -- CLog::Log(LOGERROR, "%s - Error while setting V4L format (ret %d : %s).\n", __FUNCTION__, ret, strerror(errno)); -- __ReleaseBuffers(); -- return false; -- } -- -- if (format->fmt.pix.field != V4L2_FIELD_NONE) -- { -- char * motion_entry; -- motion_entry = getenv("IMX_DEINT_MOTION"); -- if (motion_entry != NULL) -- { -- errno = 0; -- m_motionCtrl = strtol(motion_entry, NULL, 10); -- if (errno != 0) -- m_motionCtrl = -1; -- } -- if (m_motionCtrl == -1) -- m_motionCtrl = 2; /* Default value : 2 stands for high motion */ -- -- if ((m_motionCtrl >= 0) && (m_motionCtrl <=2)) -- { -- ctrl.id = V4L2_CID_MXC_MOTION; -- ctrl.value = m_motionCtrl; -- ret = ioctl (m_v4lfd, VIDIOC_S_CTRL, &ctrl); -- if (ret < 0) -- { -- CLog::Log(LOGERROR, "%s - Error while setting V4L motion (ret %d : %s).\n", __FUNCTION__, ret, strerror(errno)); -- } -- } -- else -- { -- CLog::Log(LOGNOTICE, "%s - IMX_DEINT_MOTION set to %d. Disabling deinterlacing.\n", __FUNCTION__, m_motionCtrl); -- m_motionCtrl = -2; -- } -- } -- -- fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT; -- ret = ioctl(m_v4lfd, VIDIOC_G_FMT, &fmt); -- if (ret < 0) -- { -- CLog::Log(LOGERROR, "%s - Error while getting V4L format (ret %d : %s).\n", __FUNCTION__, ret, strerror(errno)); -- __ReleaseBuffers(); -- return false; -- } -- -- m_bufferNum = nbBuffers; -- /* Alloc V4L2 buffers */ -- memset(&bufReq, 0, sizeof(bufReq)); -- bufReq.count = m_bufferNum; -- bufReq.type = V4L2_BUF_TYPE_VIDEO_OUTPUT; -- bufReq.memory = V4L2_MEMORY_MMAP; -- ret = ioctl(m_v4lfd, VIDIOC_REQBUFS, &bufReq); -- if (ret < 0) -- { -- CLog::Log(LOGERROR, "%s - %d Hw buffer allocation error (%d)\n", __FUNCTION__, bufReq.count, ret); -- __ReleaseBuffers(); -- return false; -- } -- CLog::Log(LOGDEBUG, "%s - %d Hw buffer of %d bytes allocated\n", __FUNCTION__, bufReq.count, fmt.fmt.pix.sizeimage); -- -- m_virtAddr = new void*[m_bufferNum]; -- if (m_virtAddr == NULL) -- { -- CLog::Log(LOGERROR, "%s - Allocation failure (m_virtAddr table of %d elements)\n", __FUNCTION__, m_bufferNum); -- __ReleaseBuffers(); -- return false; -- } -- m_v4lBuffers = new v4l2_buffer[m_bufferNum]; -- if (m_v4lBuffers == NULL) -- { -- CLog::Log(LOGERROR, "%s - Allocation failure (m_v4lBuffers table of %d elements)\n", __FUNCTION__, m_bufferNum); -- __ReleaseBuffers(); -- return false; -- } -- -- for (i = 0 ; i < m_bufferNum; i++) -- { -- memset(&v4lBuf, 0, sizeof(v4lBuf)); -- v4lBuf.index = i; -- v4lBuf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT; -- v4lBuf.memory = V4L2_MEMORY_MMAP; -- ret = ioctl (m_v4lfd, VIDIOC_QUERYBUF, &v4lBuf); -- if (ret < 0) -- { -- CLog::Log(LOGERROR, "%s - Error during 1st query of V4L buffer (ret %d : %s)\n", __FUNCTION__, ret, strerror(errno)); -- return false; -- } -- m_v4lBuffers[i] = v4lBuf; -- m_virtAddr[i] = NULL; -- } -- memset(&m_crop, 0, sizeof(m_crop)); -- m_crop.type = V4L2_BUF_TYPE_VIDEO_OUTPUT; -- m_pushedFrames = 0; -- m_streamOn = false; -- m_ready = true; -- return true; --} -- --void *CIMXRenderingFrames::GetVirtAddr(int idx) --{ -- struct v4l2_buffer v4lBuf; -- int ret; -- -- CSingleLock lock(m_renderingFramesLock); -- if (!m_ready) -- return NULL; -- if ((idx < 0) || (idx >= m_bufferNum)) -- return NULL; -- -- if (m_virtAddr[idx] == NULL) -- { -- v4lBuf = m_v4lBuffers[idx]; -- m_virtAddr[idx] = mmap(NULL, v4lBuf.length, PROT_READ | PROT_WRITE, MAP_SHARED, m_v4lfd, v4lBuf.m.offset); -- -- /* 2nd query to retrieve real Physical address after mmap (iMX6 bug) */ -- ret = ioctl (m_v4lfd, VIDIOC_QUERYBUF, &v4lBuf); -- if (ret < 0) -- { -- CLog::Log(LOGERROR, "%s - Error during 2nd query of V4L buffer (ret %d : %s)\n", __FUNCTION__, ret, strerror(errno)); -- } -- m_v4lBuffers[idx] = v4lBuf; -- } -- return m_virtAddr[idx]; --} -- --void *CIMXRenderingFrames::GetPhyAddr(int idx) --{ -- -- CSingleLock lock(m_renderingFramesLock); -- if (!m_ready) -- return NULL; -- if ((idx < 0) || (idx >= m_bufferNum)) -- return NULL; -- -- return (void *)m_v4lBuffers[idx].m.offset; --} -- --int CIMXRenderingFrames::FindBuffer(void *phyAddr) --{ -- int i; -- -- CSingleLock lock(m_renderingFramesLock); -- if (!m_ready) -- return -1; -- -- for (i = 0; i < m_bufferNum; i++) -- { -- if (m_v4lBuffers[i].m.offset == (unsigned int)phyAddr) -- { -- // CLog::Log(LOGNOTICE, "%s - found buffer OK %d!\n", __FUNCTION__, i); -- return i; -- } -- } -- return -1; --} -- --int CIMXRenderingFrames::DeQueue(bool wait) --{ -- int ret; -- int status; -- struct v4l2_buffer buf; -- -- CSingleLock lock(m_renderingFramesLock); -- if (!m_ready) -- { -- CLog::Log(LOGNOTICE, "%s - Cannot dequeue frame as buffers were released !\n", -- __FUNCTION__); -- return -1; -- } -- if (!m_streamOn) -- { -- return -1; -- } -- -- if (wait) -- { -- status = fcntl(m_v4lfd, F_GETFL); -- fcntl(m_v4lfd, F_SETFL, status & (~O_NONBLOCK)); -- } -- buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT; -- buf.memory = V4L2_MEMORY_MMAP; -- ret = ioctl(m_v4lfd, VIDIOC_DQBUF, &buf); -- if (wait) -- { -- fcntl(m_v4lfd, F_SETFL, status | O_NONBLOCK); -- } -- if (ret != 0) -- { -- if (errno != EAGAIN) -- CLog::Log(LOGERROR, "%s - Dequeue buffer error (ret %d : %s)\n", -- __FUNCTION__, ret, strerror(errno)); -- return -1; -- } -- --#ifdef IMX_PROFILE -- CLog::Log(LOGDEBUG, "%s - Time render to dequeue (%d) %llu\n", -- __FUNCTION__, buf.index, get_time() - render_ts[buf.index]); --#endif --// CLog::Log(LOGERROR, "%s dequeued retuns (%d)\n", __FUNCTION__, buf.index); -- -- return buf.index; --} -- --void CIMXRenderingFrames::Queue(CIMXOutputFrame *picture, struct v4l2_crop &destRect) --{ -- /* Warning : called from renderer thread -- * Especially do not call any VPU functions as they are not thread safe -- */ -- -- int ret, type; -- struct timeval queue_ts; -- int stream_trigger; -- bool crop_update = false; -- -- CSingleLock lock(m_renderingFramesLock); -- if (!m_ready) -- { -- CLog::Log(LOGNOTICE, "%s - Cannot queue frame as buffers were released !\n", -- __FUNCTION__); -- return; -- } -- -- /*CLog::Log(LOGDEBUG, "%s - queuing frame %d - picture adress : %p\n", -- __FUNCTION__, picture->v4l2BufferIdx, picture);*/ -- -- if ((picture->v4l2BufferIdx < 0) || (picture->v4l2BufferIdx >= m_bufferNum)) -- { -- CLog::Log(LOGERROR, "%s - Invalid buffer index : %d - picture address : %p\n", -- __FUNCTION__, picture->v4l2BufferIdx, picture); -- return; -- } -- -- /* Set field type for each buffer otherwise the mxc_vout driver reverts to progressive */ -- switch (picture->field) -- { -- case VPU_FIELD_TB: -- m_v4lBuffers[picture->v4l2BufferIdx].field = V4L2_FIELD_INTERLACED_TB; -- break; -- case VPU_FIELD_BT: -- m_v4lBuffers[picture->v4l2BufferIdx].field= V4L2_FIELD_INTERLACED_BT; -- break; -- case VPU_FIELD_NONE: -- default: -- m_v4lBuffers[picture->v4l2BufferIdx].field = V4L2_FIELD_NONE; -- break; -- } -- /* In case deinterlacing is forced to disabled */ -- if (m_motionCtrl == -2) -- m_v4lBuffers[picture->v4l2BufferIdx].field = V4L2_FIELD_NONE; -- -- /* mxc_vout driver does not display immediatly -- * if timestamp is set to 0 -- * (instead this driver expects a 30fps rate) -- * So we explicitly set current time for immediate display -- */ -- gettimeofday (&queue_ts, NULL); -- m_v4lBuffers[picture->v4l2BufferIdx].timestamp = queue_ts; -- --#ifndef NO_V4L_RENDERING -- ret = ioctl(m_v4lfd, VIDIOC_QBUF, &m_v4lBuffers[picture->v4l2BufferIdx]); -- if (ret < 0) -- { -- CLog::Log(LOGERROR, "%s - V4L Queue buffer failed (ret %d : %s)\n", -- __FUNCTION__, ret, strerror(errno)); -- /* If it fails odds are very high picture is invalid so just exit now */ -- return; -- } -- else -- { -- m_pushedFrames++; -- } -- -- /* Force cropping dimensions to be aligned */ -- destRect.c.top &= 0xFFFFFFF8; -- destRect.c.left &= 0xFFFFFFF8; -- destRect.c.width &= 0xFFFFFFF8; -- destRect.c.height &= 0xFFFFFFF8; -- if ((m_crop.c.top != destRect.c.top) || -- (m_crop.c.left != destRect.c.left) || -- (m_crop.c.width != destRect.c.width) || -- (m_crop.c.height != destRect.c.height)) -- { -- CLog::Log(LOGNOTICE, "%s - Newcrop : %d % d %d %d\n", -- __FUNCTION__, destRect.c.top, destRect.c.left, destRect.c.width, destRect.c.height); -- m_crop.c = destRect.c; -- crop_update = true; -- } -- -- if (!m_streamOn) -- { -- if (picture->field == VPU_FIELD_NONE) -- stream_trigger = 1; -- else { -- if (m_motionCtrl < 2) -- stream_trigger = 3; -- else -- stream_trigger = 2; -- } -- -- if (m_pushedFrames >= stream_trigger) { -- CLog::Log(LOGDEBUG, "%s - Motion control is : %d - Number of required frames before streaming : %d\n", -- __FUNCTION__, m_motionCtrl, stream_trigger); -- -- type = V4L2_BUF_TYPE_VIDEO_OUTPUT; -- ret = ioctl(m_v4lfd, VIDIOC_STREAMON, &type); -- if (ret < 0) -- { -- CLog::Log(LOGERROR, "%s - V4L Stream ON failed (ret %d : %s)\n", -- __FUNCTION__, ret, strerror(errno)); -- } -- else -- { -- CLog::Log(LOGDEBUG, "%s - V4L Stream ON OK\n", -- __FUNCTION__); -- m_streamOn = true; -- } -- /* We have to repeat crop command after streamon for some vids -- * FIXME : Check why in drivers... -- */ -- ret = ioctl(m_v4lfd, VIDIOC_S_CROP, &m_crop); -- if (ret < 0) -- { -- CLog::Log(LOGERROR, "%s - S_CROP failed (ret %d : %s)\n", -- __FUNCTION__, ret, strerror(errno)); -- } -- } -- } -- else -- { -- if (crop_update) -- { -- ret = ioctl(m_v4lfd, VIDIOC_S_CROP, &m_crop); -- if (ret < 0) -- { -- CLog::Log(LOGERROR, "%s - S_CROP failed (ret %d : %s)\n", -- __FUNCTION__, ret, strerror(errno)); -- } -- } -- } --#endif -- --#ifdef IMX_PROFILE -- render_ts[picture->v4l2BufferIdx] = get_time(); -- CLog::Log(LOGDEBUG, "%s - Time push to render (%d) %llu\n", -- __FUNCTION__, picture->v4l2BufferIdx, render_ts[picture->v4l2BufferIdx] - picture->pushTS); --#endif --} -- --void CIMXRenderingFrames::ReleaseBuffers() --{ -- CSingleLock lock(m_renderingFramesLock); -- if (!m_ready) -- { -- CLog::Log(LOGERROR, "%s - AllocateBuffers was not previously called\n", __FUNCTION__); -- return; -- } -- __ReleaseBuffers(); --} -- --/* Note : Has to be called with m_renderingFramesLock held */ --void CIMXRenderingFrames::__ReleaseBuffers() --{ -- int type, i; -- -- if (m_v4lfd >= 0) -- { -- /* stream off */ -- type = V4L2_BUF_TYPE_VIDEO_OUTPUT; -- ioctl (m_v4lfd, VIDIOC_STREAMOFF, &type); -- m_streamOn = false; -- } -- -- if (m_virtAddr != NULL) -- { -- for (i = 0; i < m_bufferNum; i++) -- { -- if (m_virtAddr[i] != NULL) -- munmap (m_virtAddr[i], m_v4lBuffers[i].length); -- } -- delete m_virtAddr; -- m_virtAddr = NULL; -- } -- -- if (m_v4lfd >= 0) -- { -- /* Close V4L2 device */ -- close(m_v4lfd); -- m_v4lfd = -1; -- } -- -- if (m_v4lBuffers != NULL) -- { -- delete m_v4lBuffers; -- m_v4lBuffers = NULL; -- } -- m_bufferNum = 0; -- m_pushedFrames = 0; -- m_ready = false; -- m_motionCtrl = -1; --} -- --/* FIXME get rid of these defines properly */ -+// FIXME get rid of these defines properly - #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)) -@@ -517,30 +41,9 @@ void CIMXRenderingFrames::__ReleaseBuffers() - #define min(a, b) (aGetClock() / DVD_TIME_BASE; -- -- return clock_pts; --} -- --void CDVDVideoCodecIMX::FlushDecodedFrames(void) --{ -- DVDVideoPicture DVDFrame; -- while (m_decodedFrames.size() > 0) -- { -- DVDFrame = m_decodedFrames.front(); -- VpuReleaseBufferV4L(DVDFrame.imxOutputFrame->v4l2BufferIdx); -- m_decodedFrames.pop(); -- } --} -- - bool CDVDVideoCodecIMX::VpuAllocBuffers(VpuMemInfo *pMemBlock) - { - int i, size; -@@ -694,269 +197,113 @@ bool CDVDVideoCodecIMX::VpuOpen(void) - return false; - } - --void CDVDVideoCodecIMX::InitFB(void) --{ -- struct mxcfb_gbl_alpha alpha; -- struct mxcfb_color_key colorKey; -- int fd; -- -- fd = open("/dev/fb0",O_RDWR); -- /* set FG/BG semi opaque */ -- alpha.alpha = 235; -- alpha.enable = 1; -- ioctl(fd, MXCFB_SET_GBL_ALPHA, &alpha); -- /* Enable color keying */ -- colorKey.enable = 1; -- colorKey.color_key = (16 << 16) | (8 << 8) | 16; -- if (ioctl(fd, MXCFB_SET_CLR_KEY, &colorKey) < 0) -- CLog::Log(LOGERROR, "%s - Error while trying to enable color keying %s.\n", __FUNCTION__, strerror(errno)); -- close(fd); --} -- --void CDVDVideoCodecIMX::RestoreFB(void) --{ -- struct mxcfb_gbl_alpha alpha; -- struct mxcfb_color_key colorKey; -- int fd; -- -- fd = open("/dev/fb0",O_RDWR); -- /* set FG as opaque */ -- alpha.alpha = 255; -- alpha.enable = 1; -- ioctl(fd, MXCFB_SET_GBL_ALPHA, &alpha); -- /* Disable color keying */ -- colorKey.enable = 0; -- colorKey.color_key = 0; -- if (ioctl(fd, MXCFB_SET_CLR_KEY, &colorKey) < 0) -- CLog::Log(LOGERROR, "%s - Error while trying to disable color keying %s.\n", __FUNCTION__, strerror(errno)); -- close(fd); --} -- - bool CDVDVideoCodecIMX::VpuAllocFrameBuffers(void) - { -- /* Alloc frame buffers from V4L2 for efficient rendering through V4L streaming */ -- struct v4l2_format fmt; -- struct v4l2_rect rect; -- int i, j; -- int ySize, cSize; -- VpuDecRetCode vpuRet; -- -- InitFB(); -- -- /* Set V4L2 Format */ -- memset(&fmt, 0, sizeof(fmt)); -- fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT; -- fmt.fmt.pix.width = Align( m_initInfo.nPicWidth, FRAME_ALIGN); -- fmt.fmt.pix.height = Align(m_initInfo.nPicHeight, FRAME_ALIGN); -- fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUV420; -- /* Take into account cropping from decoded video (for input picture) */ -- rect.left = m_initInfo.PicCropRect.nLeft; -- rect.top = m_initInfo.PicCropRect.nTop; -- rect.width = m_initInfo.PicCropRect.nRight - m_initInfo.PicCropRect.nLeft; -- rect.height = m_initInfo.PicCropRect.nBottom - m_initInfo.PicCropRect.nTop; -- fmt.fmt.pix.priv = (unsigned int)▭ -+ VpuDecRetCode ret; -+ VpuMemDesc vpuMem; -+ int i; -+ int totalSize=0; -+ int mvSize=0; -+ int ySize=0; -+ int uSize=0; -+ int vSize=0; -+ int yStride=0; -+ int uStride=0; -+ int vStride=0; -+ unsigned char* ptr; -+ unsigned char* ptrVirt; -+ int nAlign; - - m_vpuFrameBufferNum = m_initInfo.nMinFrameBufferCount + m_extraVpuBuffers; -- if (m_initInfo.nInterlace) -- fmt.fmt.pix.field = V4L2_FIELD_INTERLACED_TB; -+ m_vpuFrameBuffers = new VpuFrameBuffer[m_vpuFrameBufferNum]; -+ -+ yStride=Align(m_initInfo.nPicWidth,FRAME_ALIGN); -+ if(m_initInfo.nInterlace) -+ { -+ ySize=Align(m_initInfo.nPicWidth,FRAME_ALIGN)*Align(m_initInfo.nPicHeight,(2*FRAME_ALIGN)); -+ } - else -- fmt.fmt.pix.field = V4L2_FIELD_NONE; -- if (!m_renderingFrames.AllocateBuffers(&fmt, m_vpuFrameBufferNum)) - { -- return false; -+ ySize=Align(m_initInfo.nPicWidth,FRAME_ALIGN)*Align(m_initInfo.nPicHeight,FRAME_ALIGN); - } - -- m_outputBuffers = new VpuV4LFrameBuffer[m_vpuFrameBufferNum]; -- m_vpuFrameBuffers = new VpuFrameBuffer[m_vpuFrameBufferNum]; -- m_extraMem = new VpuMemDesc[m_vpuFrameBufferNum]; -- ySize = fmt.fmt.pix.width * fmt.fmt.pix.height; -- cSize = ySize / 4; -- for (i = 0 ; i < m_vpuFrameBufferNum; i++) -+ //4:2:0 for all video -+ uStride=yStride/2; -+ vStride=uStride; -+ uSize=ySize/4; -+ vSize=uSize; -+ mvSize=uSize; -+ -+ nAlign=m_initInfo.nAddressAlignment; -+ if(nAlign>1) - { -- m_vpuFrameBuffers[i].pbufVirtY = (unsigned char *)m_renderingFrames.GetVirtAddr(i); -- m_vpuFrameBuffers[i].nStrideY = fmt.fmt.pix.width; -- m_vpuFrameBuffers[i].nStrideC = m_vpuFrameBuffers[i].nStrideY / 2; -- m_vpuFrameBuffers[i].pbufY = (unsigned char *)m_renderingFrames.GetPhyAddr(i); -- m_vpuFrameBuffers[i].pbufCb = m_vpuFrameBuffers[i].pbufY + ySize; -- m_vpuFrameBuffers[i].pbufCr = m_vpuFrameBuffers[i].pbufCb + cSize; -- m_vpuFrameBuffers[i].pbufVirtCb = m_vpuFrameBuffers[i].pbufVirtY + ySize; -- m_vpuFrameBuffers[i].pbufVirtCr = m_vpuFrameBuffers[i].pbufVirtCb + cSize; -- /* Dont care about tile */ -- m_vpuFrameBuffers[i].pbufY_tilebot = 0; -- m_vpuFrameBuffers[i].pbufCb_tilebot = 0; -- m_vpuFrameBuffers[i].pbufVirtY_tilebot = 0; -- m_vpuFrameBuffers[i].pbufVirtCb_tilebot = 0; -- m_outputBuffers[i].clear(); -+ ySize=Align(ySize,nAlign); -+ uSize=Align(uSize,nAlign); -+ vSize=Align(vSize,nAlign); - } - -- /* Allocate physical extra memory */ - for (i = 0 ; i < m_vpuFrameBufferNum; i++) - { -- m_extraMem[i].nSize = cSize; -- vpuRet = VPU_DecGetMem(&m_extraMem[i]); -- if (vpuRet != VPU_DEC_RET_SUCCESS) -+ totalSize=(ySize+uSize+vSize+mvSize+nAlign)*1; -+ -+ vpuMem.nSize=totalSize; -+ ret = VPU_DecGetMem(&vpuMem); -+ if(ret != VPU_DEC_RET_SUCCESS) - { -- CLog::Log(LOGERROR, "%s - Extra memory (%d bytes) allocation failure (%d).\n", -- __FUNCTION__, m_extraMem[i].nSize , vpuRet); -- for (j=i ; jpDisplayFrameBuf; -- CIMXOutputFrame *outputFrame; -- int i; -- double pts; -- DVDVideoPicture DVDFrame; -- -- // FIXME pts = (double)TSManagerSend2(m_tsm, frameBuffer) / (double)1000.0; -- pts = (double)TSManagerSend(m_tsm) / (double)1000.0; -- /* Find Frame given physical address */ -- i = m_renderingFrames.FindBuffer(frameBuffer->pbufY); -- if (i == -1) -- { -- CLog::Log(LOGERROR, "%s - V4L buffer not found\n", __FUNCTION__); -- return false; -- } -- if (m_outputBuffers[i].used()) -- { -- CLog::Log(LOGERROR, "%s - Try to reuse buffer which was not dequeued !\n", __FUNCTION__); -- return false; -- } -+ //record memory info for release -+ m_decMemInfo.phyMem_phyAddr[m_decMemInfo.nPhyNum]=vpuMem.nPhyAddr; -+ m_decMemInfo.phyMem_virtAddr[m_decMemInfo.nPhyNum]=vpuMem.nVirtAddr; -+ m_decMemInfo.phyMem_cpuAddr[m_decMemInfo.nPhyNum]=vpuMem.nCpuAddr; -+ m_decMemInfo.phyMem_size[m_decMemInfo.nPhyNum]=vpuMem.nSize; -+ m_decMemInfo.nPhyNum++; - -- /* Store the pointer to be able to invoke VPU_DecOutFrameDisplayed when the buffer will be dequeued */ -- m_outputBuffers[i].store(frameBuffer, m_frameCounter++); -- -- outputFrame = &m_outputBuffers[i].outputFrame; -- outputFrame->v4l2BufferIdx = i; -- outputFrame->field = frameInfo->eFieldType; -- outputFrame->picCrop = frameInfo->pExtInfo->FrmCropRect; -- outputFrame->nQ16ShiftWidthDivHeightRatio = frameInfo->pExtInfo->nQ16ShiftWidthDivHeightRatio; -- DVDFrame.imxOutputFrame = outputFrame; -- -- DVDFrame.pts = pts; -- DVDFrame.dts = DVD_NOPTS_VALUE; -- /* -- m_outputFrame.iWidth = frameInfo->pExtInfo->nFrmWidth; -- m_outputFrame.iHeight = frameInfo->pExtInfo->nFrmHeight; -- */ -- DVDFrame.iWidth = frameInfo->pExtInfo->FrmCropRect.nRight - frameInfo->pExtInfo->FrmCropRect.nLeft; -- DVDFrame.iHeight = frameInfo->pExtInfo->FrmCropRect.nBottom - frameInfo->pExtInfo->FrmCropRect.nTop; -- DVDFrame.format = RENDER_FMT_IMX; -- -- m_decodedFrames.push(DVDFrame); -- if (m_decodedFrames.size() > IMX_MAX_QUEUE_SIZE) -- { -- CLog::Log(LOGERROR, "%s - Too many enqueued decoded frames : %d (Max %d)\n", __FUNCTION__, m_decodedFrames.size(), IMX_MAX_QUEUE_SIZE); -- } -+ //fill frameBuf -+ ptr=(unsigned char*)vpuMem.nPhyAddr; -+ ptrVirt=(unsigned char*)vpuMem.nVirtAddr; - --#ifdef IMX_PROFILE -- DVDFrame.imxOutputFrame->pushTS = get_time(); -- CLog::Log(LOGDEBUG, "%s - push (%i) Time between push %llu\n", -- __FUNCTION__, i, DVDFrame.imxOutputFrame->pushTS - previous_ts); -- previous_ts =DVDFrame.imxOutputFrame->pushTS; --#endif -+ /*align the base address*/ -+ if(nAlign>1) -+ { -+ ptr=(unsigned char*)Align(ptr,nAlign); -+ ptrVirt=(unsigned char*)Align(ptrVirt,nAlign); -+ } - -- return true; --} -+ /* fill stride info */ -+ m_vpuFrameBuffers[i].nStrideY=yStride; -+ m_vpuFrameBuffers[i].nStrideC=uStride; - --int CDVDVideoCodecIMX::GetAvailableBufferNb(void) --{ -- int i, nb; -+ /* fill phy addr*/ -+ m_vpuFrameBuffers[i].pbufY=ptr; -+ m_vpuFrameBuffers[i].pbufCb=ptr+ySize; -+ m_vpuFrameBuffers[i].pbufCr=ptr+ySize+uSize; -+ m_vpuFrameBuffers[i].pbufMvCol=ptr+ySize+uSize+vSize; -+ //ptr+=ySize+uSize+vSize+mvSize; -+ /* fill virt addr */ -+ m_vpuFrameBuffers[i].pbufVirtY=ptrVirt; -+ m_vpuFrameBuffers[i].pbufVirtCb=ptrVirt+ySize; -+ m_vpuFrameBuffers[i].pbufVirtCr=ptrVirt+ySize+uSize; -+ m_vpuFrameBuffers[i].pbufVirtMvCol=ptrVirt+ySize+uSize+vSize; -+ //ptrVirt+=ySize+uSize+vSize+mvSize; - -- nb = 0; -- for (i = 0; i < m_vpuFrameBufferNum; i++) -- { -- if (!m_outputBuffers[i].used()) -- nb++; -+ m_vpuFrameBuffers[i].pbufY_tilebot=0; -+ m_vpuFrameBuffers[i].pbufCb_tilebot=0; -+ m_vpuFrameBuffers[i].pbufVirtY_tilebot=0; -+ m_vpuFrameBuffers[i].pbufVirtCb_tilebot=0; - } -- return nb; --} - --bool CDVDVideoCodecIMX::VpuReleaseBufferV4L(int idx) --{ -- if (idx < 0 || idx >= m_vpuFrameBufferNum) -- { -- CLog::Log(LOGERROR, "%s - Invalid index - idx : %d\n", __FUNCTION__, idx); -- return false; -- } -- -- /*CLog::Log(LOGDEBUG, "%s - idx : %d - frame : %d\n", __FUNCTION__, -- idx, m_outputBuffers[idx].frameNo);*/ -- -- VPU_DecOutFrameDisplayed(m_vpuHandle, m_outputBuffers[idx].buffer); -- m_outputBuffers[idx].clear(); - return true; - } - --/* Dequeue queued frames and free the corresponding VPU buffers */ --bool CDVDVideoCodecIMX::VpuDeQueueFrame(bool wait) --{ -- int idx, i, frameNo; -- -- idx = m_renderingFrames.DeQueue(wait); -- if (idx != -1) -- { -- if (!m_outputBuffers[idx].used()) -- { -- CLog::Log(LOGERROR, "%s - WTF : associated buffer does not exist anymore\n", -- __FUNCTION__); -- return true; -- } -- else -- { -- frameNo = m_outputBuffers[idx].frameNo(); -- VpuReleaseBufferV4L(idx); -- if (frameNo > 0) -- { -- /* Release buffers which are not used anymore and were -- * queued before the idx buffer that has just been dequeued*/ -- for (i = 0; i < m_vpuFrameBufferNum; ++i) -- { -- if (m_outputBuffers[i].expired(frameNo)) -- { -- CLog::Log(LOGNOTICE, "%s - Release expired buffer - idx : %d\n", __FUNCTION__, i); -- VpuReleaseBufferV4L(i); -- } -- } -- } -- return true; -- } -- } -- else -- { --#ifdef NO_V4L_RENDERING -- int i; -- for (i = 0; i < m_vpuFrameBufferNum; i++) -- { -- if (m_outputBuffers[i].used()) -- { -- VpuReleaseBufferV4L(idx); -- } -- } --#endif -- return false; -- } --} -- --CDVDVideoCodecIMX::CDVDVideoCodecIMX() : m_renderingFrames(CIMXRenderingFrames::GetInstance()) -+CDVDVideoCodecIMX::CDVDVideoCodecIMX() - { - m_pFormatName = "iMX-xxx"; - memset(&m_decMemInfo, 0, sizeof(DecMemInfo)); - m_vpuHandle = 0; - m_vpuFrameBuffers = NULL; -- m_outputBuffers = NULL; - m_extraMem = NULL; - m_vpuFrameBufferNum = 0; - m_tsSyncRequired = true; -@@ -1028,11 +375,14 @@ bool CDVDVideoCodecIMX::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options) - case CODEC_ID_H264: - m_decOpenParam.CodecFormat = VPU_V_AVC; - m_pFormatName = "iMX-h264"; -- if (hints.extradata) -+ if (hints.extrasize < 7 || hints.extradata == NULL) - { -- if ( *(char*)hints.extradata == 1 ) -- m_convert_bitstream = bitstream_convert_init(hints.extradata,hints.extrasize); -+ CLog::Log(LOGNOTICE, -+ "%s - avcC data too small or missing", __FUNCTION__); -+ return false; - } -+ 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; -@@ -1103,10 +453,8 @@ bool CDVDVideoCodecIMX::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options) - void CDVDVideoCodecIMX::Dispose(void) - { - VpuDecRetCode ret; -- int i; - bool VPU_loaded = m_vpuHandle; - -- FlushDecodedFrames(); - if (m_vpuHandle) - { - ret = VPU_DecFlushAll(m_vpuHandle); -@@ -1123,34 +471,6 @@ void CDVDVideoCodecIMX::Dispose(void) - } - - VpuFreeBuffers(); -- -- if (m_outputBuffers != NULL) -- { -- while (VpuDeQueueFrame(false)); -- m_renderingFrames.ReleaseBuffers(); -- RestoreFB(); -- delete m_outputBuffers; -- m_outputBuffers = NULL; -- } -- -- /* Free extramem */ -- if (m_extraMem != NULL) -- { -- for (i = 0; i < m_vpuFrameBufferNum; i++) -- { -- if (m_extraMem[i].nSize > 0) -- { -- ret = VPU_DecFreeMem(&m_extraMem[i]); -- if (ret != VPU_DEC_RET_SUCCESS) -- { -- CLog::Log(LOGERROR, "%s - Release extra mem failed with error code %d.\n", __FUNCTION__, ret); -- } -- m_extraMem[i].nSize = 0; -- } -- } -- delete m_extraMem; -- m_extraMem = NULL; -- } - m_vpuFrameBufferNum = 0; - - if (m_vpuFrameBuffers != NULL) -@@ -1174,13 +494,10 @@ void CDVDVideoCodecIMX::Dispose(void) - m_tsm = NULL; - } - -- if (m_convert_bitstream) -+ if (m_converter) - { -- if (m_sps_pps_context.sps_pps_data) -- { -- free(m_sps_pps_context.sps_pps_data); -- m_sps_pps_context.sps_pps_data = NULL; -- } -+ m_converter->Close(); -+ SAFE_DELETE(m_converter); - } - return; - } -@@ -1190,12 +507,10 @@ int CDVDVideoCodecIMX::Decode(BYTE *pData, int iSize, double dts, double pts) - VpuDecFrameLengthInfo frameLengthInfo; - VpuBufferNode inData; - VpuDecRetCode ret; -- VpuDecOutFrameInfo frameInfo; - int decRet = 0; - int retStatus = 0; - int demuxer_bytes = iSize; - uint8_t *demuxer_content = pData; -- bool bitstream_convered = false; - bool retry = false; - - #ifdef IMX_PROFILE -@@ -1211,8 +526,7 @@ int CDVDVideoCodecIMX::Decode(BYTE *pData, int iSize, double dts, double pts) - } - - #ifdef IMX_PROFILE -- current = get_time(); -- CLog::Log(LOGDEBUG, "%s - delta time decode : %llu - demux size : %d dts : %f - pts : %f\n", __FUNCTION__, current - previous, iSize, dts, pts); -+ CLog::Log(LOGDEBUG, "%s - delta time decode : %llu - demux size : %d dts : %f - pts : %f\n", __FUNCTION__, -1, iSize, dts, pts); - previous = current; - #endif - -@@ -1221,28 +535,18 @@ int CDVDVideoCodecIMX::Decode(BYTE *pData, int iSize, double dts, double pts) - ((unsigned int *)pData)[0] = htonl(iSize-4); - */ - -- while (VpuDeQueueFrame(false)); -- - if (pData && iSize) - { - if (m_convert_bitstream) - { - // convert demuxer packet from bitstream to bytestream (AnnexB) -- int bytestream_size = 0; -- uint8_t *bytestream_buff = NULL; -- -- if (!bitstream_convert(demuxer_content, demuxer_bytes, &bytestream_buff, &bytestream_size)) -- { -- CLog::Log(LOGERROR, "%s - bitstream convert error...\n", __FUNCTION__); -- return VC_ERROR; -- } -- -- if (bytestream_buff && (bytestream_size > 0)) -+ if (m_converter->Convert(demuxer_content, demuxer_bytes)) - { -- bitstream_convered = true; -- demuxer_bytes = bytestream_size; -- demuxer_content = bytestream_buff; -+ demuxer_content = m_converter->GetConvertBuffer(); -+ demuxer_bytes = m_converter->GetConvertSize(); - } -+ else -+ CLog::Log(LOGERROR,"%s - bitstream_convert error", __FUNCTION__); - } - - if (pts != DVD_NOPTS_VALUE) -@@ -1291,11 +595,11 @@ int CDVDVideoCodecIMX::Decode(BYTE *pData, int iSize, double dts, double pts) - { - retry = false; - #ifdef IMX_PROFILE -- before_dec = get_time(); -+ //before_dec = get_time(); - #endif - 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, get_time() - before_dec); -+ CLog::Log(LOGDEBUG, "%s - VPU dec 0x%x decode takes : %lld\n\n", __FUNCTION__, decRet, -1); - #endif - - if (ret != VPU_DEC_RET_SUCCESS) -@@ -1354,16 +658,13 @@ int CDVDVideoCodecIMX::Decode(BYTE *pData, int iSize, double dts, double pts) - if (retStatus & VC_PICTURE) - CLog::Log(LOGERROR, "%s - Second picture in the same decode call !\n", __FUNCTION__); - -- ret = VPU_DecGetOutputFrame(m_vpuHandle, &frameInfo); -+ 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; - } -- if (VpuPushFrame(&frameInfo)) -- { -- retStatus |= VC_PICTURE; -- } -+ retStatus |= VC_PICTURE; - } //VPU_DEC_OUTPUT_DIS - - if (decRet & VPU_DEC_OUTPUT_REPEAT) -@@ -1425,35 +726,17 @@ int CDVDVideoCodecIMX::Decode(BYTE *pData, int iSize, double dts, double pts) - } while (retry == true); - } //(pData && iSize) - -- if (GetAvailableBufferNb() > (m_vpuFrameBufferNum - m_extraVpuBuffers)) -+ if (retStatus == 0) - { - retStatus |= VC_BUFFER; - } -- else -- { -- if (retStatus == 0) { -- /* No Picture ready and Not enough VPU buffers. It should NOT happen so log dedicated error */ -- CLog::Log(LOGERROR, "%s - Not hw buffer available. Waiting for 2ms\n", __FUNCTION__); -- /* Lets wait for the IPU to free a buffer. Anyway we have several decoded frames ready */ -- usleep(2000); -- } -- } -- -- if (bitstream_convered) -- free(demuxer_content); -- -- retStatus &= (~VC_PICTURE); -- if (m_decodedFrames.size() >= IMX_MAX_QUEUE_SIZE) -- retStatus |= VC_PICTURE; - - #ifdef IMX_PROFILE -- CLog::Log(LOGDEBUG, "%s - returns %x - duration %lld\n", __FUNCTION__, retStatus, get_time() - previous); -+ CLog::Log(LOGDEBUG, "%s - returns %x - duration %lld\n", __FUNCTION__, retStatus, -1); - #endif - return retStatus; - - out_error: -- if (bitstream_convered) -- free(demuxer_content); - return VC_ERROR; - } - -@@ -1466,9 +749,6 @@ void CDVDVideoCodecIMX::Reset() - /* We have to resync timestamp manager */ - m_tsSyncRequired = true; - -- /* Flush decoded frames */ -- FlushDecodedFrames(); -- - /* Flush VPU */ - ret = VPU_DecFlushAll(m_vpuHandle); - if (ret != VPU_DEC_RET_SUCCESS) -@@ -1480,80 +760,61 @@ void CDVDVideoCodecIMX::Reset() - - unsigned CDVDVideoCodecIMX::GetAllowedReferences() - { -- // Note : It is useless if CLinuxRendererGLES::GetProcessorSize returns 0 for RENDER_FMT_IMX -- return min(3, m_extraVpuBuffers / 2); -+ return 3; - } - -- --bool CDVDVideoCodecIMX::GetPicture(DVDVideoPicture* pDvdVideoPicture) -+bool CDVDVideoCodecIMX::ClearPicture(DVDVideoPicture* pDvdVideoPicture) - { -- double currentPlayerPts; -- double ts = DVD_NOPTS_VALUE; -- DVDVideoPicture DVDFrame; -- -- if (m_decodedFrames.size() == 0) -- { -- CLog::Log(LOGERROR, "%s called while no picture ready\n", __FUNCTION__); -- return false; -- } -- -- /* Retrieve oldest decoded frame */ -- DVDFrame = m_decodedFrames.front(); -- m_decodedFrames.pop(); -- //CLog::Log(LOGNOTICE, "%s - buffer(%d)\n", __FUNCTION__, DVDFrame.imxOutputFrame->v4l2BufferIdx); -- -- pDvdVideoPicture->iFlags &= DVP_FLAG_DROPPED; -- if ((pDvdVideoPicture->iFlags != 0) || (m_dropState)) -+ if (pDvdVideoPicture) - { -- CLog::Log(LOGNOTICE, "%s - Flushing video picture\n", __FUNCTION__); -- pDvdVideoPicture->iFlags = DVP_FLAG_DROPPED; -- VpuReleaseBufferV4L(DVDFrame.imxOutputFrame->v4l2BufferIdx); -- DVDFrame.imxOutputFrame = NULL; -- } -- else -- { -- ts = DVDFrame.pts; -- currentPlayerPts = GetPlayerPtsSeconds() * (double)DVD_TIME_BASE; -- if (currentPlayerPts > ts) -+ //clear frame display flag -+ VpuDecRetCode ret = VPU_DecOutFrameDisplayed(m_vpuHandle, m_frameInfo.pDisplayFrameBuf); -+ if(ret != VPU_DEC_RET_SUCCESS) - { -- CLog::Log(LOGERROR, "%s - player is ahead of time (%f)\n", __FUNCTION__, currentPlayerPts - ts); -+ CLog::Log(LOGERROR, "%s: vpu clear frame display failure: ret=%d \r\n",__FUNCTION__,ret); -+ return false; - } -- //CLog::Log(LOGINFO, "%s - idx : %d - delta call %f - delta ts %f \n", __FUNCTION__, outputFrame.v4l2_buffer->index,ts - previous, ts - currentPlayerPts); - } - --#ifdef NO_V4L_RENDERING -- if (!m_dropState) -- { -- VpuReleaseBufferV4L(DVDFrame.imxOutputFrame->v4l2BufferIdx); -- } --#endif -+ return true; -+} -+ -+bool CDVDVideoCodecIMX::GetPicture(DVDVideoPicture* pDvdVideoPicture) -+{ -+ pDvdVideoPicture->iFlags = DVP_FLAG_ALLOCATED; -+ if (m_dropState) -+ pDvdVideoPicture->iFlags |= DVP_FLAG_DROPPED; -+ else -+ pDvdVideoPicture->iFlags &= ~DVP_FLAG_DROPPED; - -- pDvdVideoPicture->pts = DVDFrame.pts; -+ pDvdVideoPicture->pts = (double)TSManagerSend(m_tsm) / (double)1000.0; - if (!m_usePTS) - { - pDvdVideoPicture->pts = DVD_NOPTS_VALUE; - } -- pDvdVideoPicture->dts = DVDFrame.dts; -- pDvdVideoPicture->iWidth = DVDFrame.iWidth; -- pDvdVideoPicture->iHeight = DVDFrame.iHeight; -+ 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; - if (m_dropState) - { -- pDvdVideoPicture->iDisplayWidth = DVDFrame.iWidth; -- pDvdVideoPicture->iDisplayHeight = DVDFrame.iHeight; -+ pDvdVideoPicture->iDisplayWidth = pDvdVideoPicture->iWidth; -+ pDvdVideoPicture->iDisplayHeight = pDvdVideoPicture->iHeight; - } - else - { -- pDvdVideoPicture->iDisplayWidth = ((pDvdVideoPicture->iWidth * DVDFrame.imxOutputFrame->nQ16ShiftWidthDivHeightRatio) + 32767) >> 16; -+ pDvdVideoPicture->iDisplayWidth = ((pDvdVideoPicture->iWidth * m_frameInfo.pExtInfo->nQ16ShiftWidthDivHeightRatio) + 32767) >> 16; - pDvdVideoPicture->iDisplayHeight = pDvdVideoPicture->iHeight; - } -- pDvdVideoPicture->format = DVDFrame.format; -- pDvdVideoPicture->imxOutputFrame = DVDFrame.imxOutputFrame; -+ pDvdVideoPicture->format = RENDER_FMT_YUV420P; -+ pDvdVideoPicture->iLineSize[0] = m_frameInfo.pDisplayFrameBuf->nStrideY; -+ pDvdVideoPicture->iLineSize[1] = m_frameInfo.pDisplayFrameBuf->nStrideC; -+ pDvdVideoPicture->iLineSize[2] = m_frameInfo.pDisplayFrameBuf->nStrideC; -+ pDvdVideoPicture->iLineSize[3] = 0; -+ pDvdVideoPicture->data[0] = m_frameInfo.pDisplayFrameBuf->pbufVirtY; -+ pDvdVideoPicture->data[1] = m_frameInfo.pDisplayFrameBuf->pbufVirtCb; -+ pDvdVideoPicture->data[2] = m_frameInfo.pDisplayFrameBuf->pbufVirtCr; -+ pDvdVideoPicture->data[3] = 0; - --#ifdef V4L_OUTPUT_PROFILE -- CLog::Log(LOGDEBUG, "%s - QF : %d - HWfre : %d/%d/%d\n", -- (int)m_decodedFrames.size(), GetAvailableBufferNb(), -- m_extraVpuBuffers, m_vpuFrameBufferNum); --#endif - return true; - } - -@@ -1570,168 +831,3 @@ void CDVDVideoCodecIMX::SetDropState(bool bDrop) - CLog::Log(LOGNOTICE, "%s : %d\n", __FUNCTION__, bDrop); - } - } -- --/* bitstream convert : Shameless copy from openmax */ --/* TODO : Have a look at it as the malloc/copy/free strategy is obviously not the most efficient one */ -- --bool CDVDVideoCodecIMX::bitstream_convert_init(void *in_extradata, int in_extrasize) --{ -- // based on h264_mp4toannexb_bsf.c (ffmpeg) -- // which is Copyright (c) 2007 Benoit Fouet -- // and Licensed GPL 2.1 or greater -- -- m_sps_pps_size = 0; -- m_sps_pps_context.sps_pps_data = NULL; -- -- // nothing to filter -- if (!in_extradata || in_extrasize < 6) -- return false; -- -- uint16_t unit_size; -- uint32_t total_size = 0; -- uint8_t *out = NULL, unit_nb, sps_done = 0; -- const uint8_t *extradata = (uint8_t*)in_extradata + 4; -- static const uint8_t nalu_header[4] = {0, 0, 0, 1}; -- -- // retrieve length coded size -- m_sps_pps_context.length_size = (*extradata++ & 0x3) + 1; -- if (m_sps_pps_context.length_size == 3) -- return false; -- -- // retrieve sps and pps unit(s) -- unit_nb = *extradata++ & 0x1f; // number of sps unit(s) -- if (!unit_nb) -- { -- unit_nb = *extradata++; // number of pps unit(s) -- sps_done++; -- } -- while (unit_nb--) -- { -- unit_size = extradata[0] << 8 | extradata[1]; -- total_size += unit_size + 4; -- if ( (extradata + 2 + unit_size) > ((uint8_t*)in_extradata + in_extrasize) ) -- { -- free(out); -- return false; -- } -- uint8_t* new_out = (uint8_t*)realloc(out, total_size); -- if (new_out) -- { -- out = new_out; -- } -- else -- { -- CLog::Log(LOGERROR, "bitstream_convert_init failed - %s : could not realloc the buffer out", __FUNCTION__); -- free(out); -- return false; -- } -- -- memcpy(out + total_size - unit_size - 4, nalu_header, 4); -- memcpy(out + total_size - unit_size, extradata + 2, unit_size); -- extradata += 2 + unit_size; -- -- if (!unit_nb && !sps_done++) -- unit_nb = *extradata++; // number of pps unit(s) -- } -- -- m_sps_pps_context.sps_pps_data = out; -- m_sps_pps_context.size = total_size; -- m_sps_pps_context.first_idr = 1; -- -- return true; --} -- --bool CDVDVideoCodecIMX::bitstream_convert(BYTE* pData, int iSize, uint8_t **poutbuf, int *poutbuf_size) --{ -- // based on h264_mp4toannexb_bsf.c (ffmpeg) -- // which is Copyright (c) 2007 Benoit Fouet -- // and Licensed GPL 2.1 or greater -- -- uint8_t *buf = pData; -- uint32_t buf_size = iSize; -- uint8_t unit_type; -- int32_t nal_size; -- uint32_t cumul_size = 0; -- const uint8_t *buf_end = buf + buf_size; -- -- do -- { -- if (buf + m_sps_pps_context.length_size > buf_end) -- goto fail; -- -- if (m_sps_pps_context.length_size == 1) -- nal_size = buf[0]; -- else if (m_sps_pps_context.length_size == 2) -- nal_size = buf[0] << 8 | buf[1]; -- else -- nal_size = buf[0] << 24 | buf[1] << 16 | buf[2] << 8 | buf[3]; -- -- // FIXME CLog::Log(LOGERROR, "%s - nal_size : %d \n", __FUNCTION__, nal_size); -- buf += m_sps_pps_context.length_size; -- unit_type = *buf & 0x1f; -- -- if (buf + nal_size > buf_end || nal_size < 0) -- goto fail; -- -- // prepend only to the first type 5 NAL unit of an IDR picture -- if (m_sps_pps_context.first_idr && unit_type == 5) -- { -- bitstream_alloc_and_copy(poutbuf, poutbuf_size, -- m_sps_pps_context.sps_pps_data, m_sps_pps_context.size, buf, nal_size); -- m_sps_pps_context.first_idr = 0; -- } -- else -- { -- bitstream_alloc_and_copy(poutbuf, poutbuf_size, NULL, 0, buf, nal_size); -- if (!m_sps_pps_context.first_idr && unit_type == 1) -- m_sps_pps_context.first_idr = 1; -- } -- -- buf += nal_size; -- cumul_size += nal_size + m_sps_pps_context.length_size; -- } while (cumul_size < buf_size); -- -- return true; -- --fail: -- free(*poutbuf); -- *poutbuf = NULL; -- *poutbuf_size = 0; -- return false; --} -- --void CDVDVideoCodecIMX::bitstream_alloc_and_copy( -- uint8_t **poutbuf, int *poutbuf_size, -- const uint8_t *sps_pps, uint32_t sps_pps_size, -- const uint8_t *in, uint32_t in_size) --{ -- // based on h264_mp4toannexb_bsf.c (ffmpeg) -- // which is Copyright (c) 2007 Benoit Fouet -- // and Licensed GPL 2.1 or greater -- -- #define CHD_WB32(p, d) { \ -- ((uint8_t*)(p))[3] = (d); \ -- ((uint8_t*)(p))[2] = (d) >> 8; \ -- ((uint8_t*)(p))[1] = (d) >> 16; \ -- ((uint8_t*)(p))[0] = (d) >> 24; } -- -- uint32_t offset = *poutbuf_size; -- uint8_t nal_header_size = offset ? 3 : 4; -- -- *poutbuf_size += sps_pps_size + in_size + nal_header_size; -- *poutbuf = (uint8_t*)realloc(*poutbuf, *poutbuf_size); -- if (sps_pps) -- memcpy(*poutbuf + offset, sps_pps, sps_pps_size); -- -- memcpy(*poutbuf + sps_pps_size + nal_header_size + offset, in, in_size); -- if (!offset) -- { -- CHD_WB32(*poutbuf + sps_pps_size, 1); -- } -- else -- { -- (*poutbuf + offset + sps_pps_size)[0] = 0; -- (*poutbuf + offset + sps_pps_size)[1] = 0; -- (*poutbuf + offset + sps_pps_size)[2] = 1; -- } --} -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h -index d72b899..cc0f26c 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h -@@ -24,6 +24,7 @@ - #include "DVDVideoCodec.h" - #include "DVDStreamInfo.h" - #include "threads/CriticalSection.h" -+#include "utils/BitstreamConverter.h" - - - //#define IMX_PROFILE -@@ -44,54 +45,6 @@ typedef struct - unsigned int phyMem_size[VPU_DEC_MAX_NUM_MEM_NUM]; - } DecMemInfo; - --/* Output frame properties */ --struct CIMXOutputFrame { -- // Render a picture. Calls RenderingFrames.Queue -- void Render(struct v4l2_crop &); -- // Clear a picture by settings the frameNo to "expired" -- void Release() { frameNo = 0; } -- -- int v4l2BufferIdx; -- VpuFieldType field; -- VpuRect picCrop; -- unsigned int nQ16ShiftWidthDivHeightRatio; -- int frameNo; --#ifdef IMX_PROFILE -- unsigned long long pushTS; --#endif --}; -- --class CIMXRenderingFrames --{ --public: -- static CIMXRenderingFrames& GetInstance(); -- bool AllocateBuffers(const struct v4l2_format *, int); -- void *GetVirtAddr(int idx); -- void *GetPhyAddr(int idx); -- void ReleaseBuffers(); -- int FindBuffer(void *); -- int DeQueue(bool wait); -- void Queue(CIMXOutputFrame *, struct v4l2_crop &); -- --private: -- CIMXRenderingFrames(); -- void __ReleaseBuffers(); -- -- static const char *m_v4lDeviceName; // V4L2 device Name -- static CIMXRenderingFrames* m_instance; // Unique instance of the class -- -- CCriticalSection m_renderingFramesLock; // Lock to ensure multithreading safety for class fields -- bool m_ready; // Buffers are allocated and frames can be Queued/Dequeue -- int m_v4lfd; // fd on V4L2 device -- struct v4l2_buffer *m_v4lBuffers; // Table of V4L buffer info (as returned by VIDIOC_QUERYBUF) -- int m_bufferNum; // Number of allocated V4L2 buffers -- struct v4l2_crop m_crop; // Current cropping properties -- bool m_streamOn; // Flag that indicates whether streaming in on (from V4L point of view) -- int m_pushedFrames; // Number of frames queued in V4L2 -- void **m_virtAddr; // Table holding virtual adresses of mmaped V4L2 buffers -- int m_motionCtrl; // Current motion control algo --}; -- - class CDVDVideoCodecIMX : public CDVDVideoCodec - { - public: -@@ -103,6 +56,7 @@ class CDVDVideoCodecIMX : public CDVDVideoCodec - 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; } -@@ -114,38 +68,9 @@ class CDVDVideoCodecIMX : public CDVDVideoCodec - bool VpuAllocBuffers(VpuMemInfo *); - bool VpuFreeBuffers(void); - bool VpuAllocFrameBuffers(void); -- bool VpuPushFrame(VpuDecOutFrameInfo*); -- bool VpuDeQueueFrame(bool); -- int GetAvailableBufferNb(void); -- void InitFB(void); -- void RestoreFB(void); -- void FlushDecodedFrames(void); -- bool VpuReleaseBufferV4L(int); -- -- /* Helper structure which holds a queued output frame -- * and its associated decoder frame buffer.*/ -- struct VpuV4LFrameBuffer -- { -- // Returns whether the buffer is currently used (associated) -- bool used() const { return buffer != NULL; } -- int frameNo() const { return outputFrame.frameNo; } -- bool expired(int frameNo) const -- { return (buffer != NULL) && (outputFrame.frameNo < frameNo); } -- // Associate a VPU frame buffer -- void store(VpuFrameBuffer *b, int frameNo) { -- buffer = b; -- outputFrame.frameNo = frameNo; -- } -- // Reset the state -- void clear() { store(NULL, 0); } -- -- VpuFrameBuffer *buffer; -- CIMXOutputFrame outputFrame; -- }; - - static const int m_extraVpuBuffers; // Number of additional buffers for VPU - -- CIMXRenderingFrames&m_renderingFrames; // The global RenderingFrames instance - 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 -@@ -158,34 +83,11 @@ class CDVDVideoCodecIMX : public CDVDVideoCodec - int m_vpuFrameBufferNum; // Total number of allocated frame buffers - VpuFrameBuffer *m_vpuFrameBuffers; // Table of VPU frame buffers description - VpuMemDesc *m_extraMem; // Table of allocated extra Memory -- VpuV4LFrameBuffer *m_outputBuffers; // Table of V4L buffers out of VPU (index is V4L buf index) (used to call properly VPU_DecOutFrameDisplayed) -- std::queue m_decodedFrames; // Decoded Frames ready to be retrieved by GetPicture -+// VpuMemDesc *m_outputBuffers; // Table of buffers out of VPU (used to call properly VPU_DecOutFrameDisplayed) - int m_frameCounter; // Decoded frames counter - bool m_usePTS; // State whether pts out of decoding process should be used -- -- /* FIXME : Rework is still required for fields below this line */ -- -- /* create a real class and share with openmax ? */ -- // bitstream to bytestream (Annex B) conversion support. -- bool bitstream_convert_init(void *in_extradata, int in_extrasize); -- bool bitstream_convert(BYTE* pData, int iSize, uint8_t **poutbuf, int *poutbuf_size); -- static void bitstream_alloc_and_copy( uint8_t **poutbuf, int *poutbuf_size, -- const uint8_t *sps_pps, uint32_t sps_pps_size, const uint8_t *in, uint32_t in_size); -- typedef struct omx_bitstream_ctx { -- uint8_t length_size; -- uint8_t first_idr; -- uint8_t *sps_pps_data; -- uint32_t size; -- omx_bitstream_ctx() -- { -- length_size = 0; -- first_idr = 0; -- sps_pps_data = NULL; -- size = 0; -- } -- } omx_bitstream_ctx; -- uint32_t m_sps_pps_size; -- omx_bitstream_ctx m_sps_pps_context; -- bool m_convert_bitstream; -+ VpuDecOutFrameInfo m_frameInfo; -+ CBitstreamConverter *m_converter; -+ bool m_convert_bitstream; - - }; -diff --git a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp -index 9a0acf1..be532ec 100644 ---- a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp -+++ b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp -@@ -995,7 +995,6 @@ static std::string GetRenderFormatName(ERenderFormat format) - case RENDER_FMT_CVBREF: return "BGRA"; - case RENDER_FMT_EGLIMG: return "EGLIMG"; - case RENDER_FMT_BYPASS: return "BYPASS"; -- case RENDER_FMT_IMX: return "IMX"; - case RENDER_FMT_MEDIACODEC:return "MEDIACODEC"; - case RENDER_FMT_NONE: return "NONE"; - } -diff --git a/xbmc/windowing/egl/EGLWrapper.cpp b/xbmc/windowing/egl/EGLWrapper.cpp -index 0726cc2..717b369 100644 ---- a/xbmc/windowing/egl/EGLWrapper.cpp -+++ b/xbmc/windowing/egl/EGLWrapper.cpp -@@ -17,7 +17,6 @@ - * . - * - */ --#include "EGLNativeTypeIMX.h" - #include "system.h" - - #ifdef HAS_EGL -@@ -26,6 +25,9 @@ - #include "EGLNativeTypeAmlogic.h" - #include "EGLNativeTypeRaspberryPI.h" - #include "EGLNativeTypeWayland.h" -+#ifdef HAS_IMXVPU -+#include "EGLNativeTypeIMX.h" -+#endif - #include "EGLWrapper.h" - - #define CheckError() m_result = eglGetError(); if(m_result != EGL_SUCCESS) CLog::Log(LOGERROR, "EGL error in %s: %x",__FUNCTION__, m_result); -@@ -82,8 +84,11 @@ 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)) -+#ifdef HAS_IMXVPU -+ || (nativeGuess = CreateEGLNativeType(implementation)) -+#endif -+ ) - { - m_nativeTypes = nativeGuess; - -diff --git a/xbmc/windowing/egl/Makefile.in b/xbmc/windowing/egl/Makefile.in -index f59f9cb..85abb44 100644 ---- a/xbmc/windowing/egl/Makefile.in -+++ b/xbmc/windowing/egl/Makefile.in -@@ -5,7 +5,6 @@ SRCS+= EGLNativeTypeAmlogic.cpp - SRCS+= EGLNativeTypeAndroid.cpp - SRCS+= EGLNativeTypeRaspberryPI.cpp - SRCS+= EGLNativeTypeWayland.cpp --SRCS+= EGLNativeTypeIMX.cpp - SRCS+= EGLWrapper.cpp - - # Wayland specific detail -@@ -25,6 +24,10 @@ SRCS+= wayland/Callback.cpp \ - wayland/XBMCSurface.cpp - endif - -+ifeq (@USE_IMXVPU@,1) -+SRCS+= EGLNativeTypeIMX.cpp -+endif -+ - LIB = windowing_egl.a - - include ../../../Makefile.include --- -1.9.3 - - -From 1a49ec3b85157e39d0045965d055db089cf95cd0 Mon Sep 17 00:00:00 2001 -From: "Chris \"Koying\" Browet" -Date: Tue, 11 Feb 2014 13:42:53 +0100 -Subject: [PATCH 03/50] CHG: [IMX] baseline direct buffer rendering - ---- - xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp | 107 ++++++++++++++++++++- - xbmc/cores/VideoRenderers/LinuxRendererGLES.h | 5 + - xbmc/cores/VideoRenderers/RenderFormats.h | 1 + - xbmc/cores/VideoRenderers/RenderManager.cpp | 2 + - .../VideoRenderers/VideoShaders/YUV2RGBShader.cpp | 14 +-- - .../dvdplayer/DVDCodecs/Video/DVDVideoCodec.h | 6 ++ - .../dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp | 66 ++++++++++--- - .../dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h | 19 ++++ - .../dvdplayer/DVDCodecs/Video/DVDVideoCodecInfo.h | 37 +++++++ - xbmc/cores/dvdplayer/DVDPlayerVideo.cpp | 1 + - 10 files changed, 232 insertions(+), 26 deletions(-) - create mode 100644 xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecInfo.h - -diff --git a/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp b/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp -index 72eb725..bc3a39f 100644 ---- a/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp -+++ b/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp -@@ -103,6 +103,7 @@ CLinuxRendererGLES::YUVBUFFER::YUVBUFFER() - #if defined(TARGET_ANDROID) - mediacodec = NULL; - #endif -+ codecinfo = NULL; - } - - CLinuxRendererGLES::YUVBUFFER::~YUVBUFFER() -@@ -604,6 +605,7 @@ unsigned int CLinuxRendererGLES::PreInit() - #if defined(TARGET_ANDROID) - m_formats.push_back(RENDER_FMT_MEDIACODEC); - #endif -+ m_formats.push_back(RENDER_FMT_YV12_BUFFER); - - // setup the background colour - m_clearColour = (float)(g_advancedSettings.m_videoBlackBarColour & 0xff) / 0xff; -@@ -711,6 +713,10 @@ void CLinuxRendererGLES::LoadShaders(int field) - m_renderMethod = RENDER_MEDIACODEC; - break; - } -+ else if (m_format == RENDER_FMT_YV12_BUFFER) -+ { -+ CLog::Log(LOGNOTICE, "GL: Using YV12 Buffer render method"); -+ } - else if (m_format == RENDER_FMT_BYPASS) - { - CLog::Log(LOGNOTICE, "GL: Using BYPASS render method"); -@@ -803,6 +809,12 @@ void CLinuxRendererGLES::LoadShaders(int field) - m_textureCreate = &CLinuxRendererGLES::CreateNV12Texture; - m_textureDelete = &CLinuxRendererGLES::DeleteNV12Texture; - } -+ else if (m_format == RENDER_FMT_YV12_BUFFER) -+ { -+ m_textureUpload = &CLinuxRendererGLES::UploadYV12BufferTexture; -+ m_textureCreate = &CLinuxRendererGLES::CreateYV12Texture; -+ m_textureDelete = &CLinuxRendererGLES::DeleteYV12Texture; -+ } - else - { - // default to YV12 texture handlers -@@ -1158,7 +1170,7 @@ void CLinuxRendererGLES::RenderMultiPass(int index, int field) - // imgwidth *= planes[0].pixpertex_x; - // imgheight *= planes[0].pixpertex_y; - // } --// -+// - // glBegin(GL_QUADS); - // - // glMultiTexCoord2fARB(GL_TEXTURE0, planes[0].rect.x1, planes[0].rect.y1); -@@ -2301,7 +2313,7 @@ bool CLinuxRendererGLES::CreateCVRefTexture(int index) - - glTexParameteri(m_textureTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(m_textureTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR); -- // This is necessary for non-power-of-two textures -+ // This is necessary for non-power-of-two textures - glTexParameteri(m_textureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(m_textureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glPixelStorei(GL_UNPACK_ALIGNMENT, 4); -@@ -2407,7 +2419,7 @@ bool CLinuxRendererGLES::CreateEGLIMGTexture(int index) - - glTexParameteri(m_textureTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(m_textureTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR); -- // This is necessary for non-power-of-two textures -+ // This is necessary for non-power-of-two textures - glTexParameteri(m_textureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(m_textureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - -@@ -2481,6 +2493,84 @@ bool CLinuxRendererGLES::CreateSurfaceTexture(int index) - return true; - } - -+//******************************************************************************************************** -+// Buffer creation, deletion, copying + clearing -+//******************************************************************************************************** -+void CLinuxRendererGLES::UploadYV12BufferTexture(int index) -+{ -+ YUVBUFFER& buf = m_buffers[index]; -+ YV12Image* im = &buf.image; -+ YUVFIELDS& fields = buf.fields; -+ -+ if (!buf.codecinfo || !(im->flags & IMAGE_FLAG_READY)) -+ return; -+ -+ bool deinterlacing; -+ if (m_currentField == FIELD_FULL) -+ deinterlacing = false; -+ else -+ deinterlacing = true; -+ -+ glEnable(m_textureTarget); -+ VerifyGLState(); -+ -+ glPixelStorei(GL_UNPACK_ALIGNMENT,1); -+ -+ if (deinterlacing) -+ { -+ // Load Even Y Field -+ LoadPlane( fields[FIELD_TOP][0] , GL_LUMINANCE, buf.flipindex -+ , im->width, im->height >> 1 -+ , buf.codecinfo->iLineSize[0]*2, im->bpp, buf.codecinfo->data[0] ); -+ -+ // Load Odd Y fields -+ LoadPlane( fields[FIELD_BOT][0], GL_LUMINANCE, buf.flipindex -+ , im->width, im->height >> 1 -+ , buf.codecinfo->iLineSize[0]*2, im->bpp, buf.codecinfo->data[0] + buf.codecinfo->iLineSize[0]) ; -+ -+ // Load Even U & V Fields -+ LoadPlane( fields[FIELD_TOP][1], GL_LUMINANCE, buf.flipindex -+ , im->width >> im->cshift_x, im->height >> (im->cshift_y + 1) -+ , buf.codecinfo->iLineSize[1]*2, im->bpp, buf.codecinfo->data[1] ); -+ -+ LoadPlane( fields[FIELD_TOP][2], GL_ALPHA, buf.flipindex -+ , im->width >> im->cshift_x, im->height >> (im->cshift_y + 1) -+ , buf.codecinfo->iLineSize[2]*2, im->bpp, buf.codecinfo->data[2] ); -+ -+ // Load Odd U & V Fields -+ LoadPlane( fields[FIELD_BOT][1], GL_LUMINANCE, buf.flipindex -+ , im->width >> im->cshift_x, im->height >> (im->cshift_y + 1) -+ , buf.codecinfo->iLineSize[1]*2, im->bpp, buf.codecinfo->data[1] + buf.codecinfo->iLineSize[1] ); -+ -+ LoadPlane( fields[FIELD_BOT][2], GL_ALPHA, buf.flipindex -+ , im->width >> im->cshift_x, im->height >> (im->cshift_y + 1) -+ , buf.codecinfo->iLineSize[2]*2, im->bpp, buf.codecinfo->data[2] + buf.codecinfo->iLineSize[2] ); -+ } -+ else -+ { -+ // Load Y plane -+ LoadPlane( fields[FIELD_FULL][0], GL_LUMINANCE, buf.flipindex -+ , im->width, im->height -+ , buf.codecinfo->iLineSize[0], im->bpp, buf.codecinfo->data[0] ); -+ -+ //load U plane -+ LoadPlane( fields[FIELD_FULL][1], GL_LUMINANCE, buf.flipindex -+ , im->width >> im->cshift_x, im->height >> im->cshift_y -+ , buf.codecinfo->iLineSize[1], im->bpp, buf.codecinfo->data[1] ); -+ -+ //load V plane -+ LoadPlane( fields[FIELD_FULL][2], GL_ALPHA, buf.flipindex -+ , im->width >> im->cshift_x, im->height >> im->cshift_y -+ , buf.codecinfo->iLineSize[2], im->bpp, buf.codecinfo->data[2] ); -+ } -+ -+ VerifyGLState(); -+ -+ CalculateTextureSourceRects(index, 3); -+ -+ glDisable(m_textureTarget); -+} -+ - void CLinuxRendererGLES::SetTextureFilter(GLenum method) - { - for (int i = 0 ; iLock(); -+} -+ - #endif - -diff --git a/xbmc/cores/VideoRenderers/LinuxRendererGLES.h b/xbmc/cores/VideoRenderers/LinuxRendererGLES.h -index 642cded..e39a93f 100644 ---- a/xbmc/cores/VideoRenderers/LinuxRendererGLES.h -+++ b/xbmc/cores/VideoRenderers/LinuxRendererGLES.h -@@ -33,6 +33,7 @@ - #include "guilib/GraphicContext.h" - #include "BaseRenderer.h" - #include "xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h" -+#include "xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecInfo.h" - - class CRenderCapture; - -@@ -170,6 +171,7 @@ class CLinuxRendererGLES : public CBaseRenderer - // mediaCodec - virtual void AddProcessor(CDVDMediaCodecInfo *mediacodec, int index); - #endif -+ virtual void AddProcessor(CDVDVideoCodecBuffer *codecinfo, int index); - - protected: - virtual void Render(DWORD flags, int index); -@@ -209,6 +211,8 @@ class CLinuxRendererGLES : public CBaseRenderer - void DeleteSurfaceTexture(int index); - bool CreateSurfaceTexture(int index); - -+ void UploadYV12BufferTexture(int index); -+ - void CalculateTextureSourceRects(int source, int num_planes); - - // renderers -@@ -285,6 +289,7 @@ class CLinuxRendererGLES : public CBaseRenderer - // mediacodec - CDVDMediaCodecInfo *mediacodec; - #endif -+ CDVDVideoCodecBuffer *codecinfo; - }; - - typedef YUVBUFFER YUVBUFFERS[NUM_BUFFERS]; -diff --git a/xbmc/cores/VideoRenderers/RenderFormats.h b/xbmc/cores/VideoRenderers/RenderFormats.h -index f15e80d..384bcd6 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_YV12_BUFFER, - }; - - #endif -diff --git a/xbmc/cores/VideoRenderers/RenderManager.cpp b/xbmc/cores/VideoRenderers/RenderManager.cpp -index b6fb1a3..0aebd2d 100644 ---- a/xbmc/cores/VideoRenderers/RenderManager.cpp -+++ b/xbmc/cores/VideoRenderers/RenderManager.cpp -@@ -932,6 +932,8 @@ int CXBMCRenderManager::AddVideoPicture(DVDVideoPicture& pic) - else if(pic.format == RENDER_FMT_MEDIACODEC) - m_pRenderer->AddProcessor(pic.mediacodec, index); - #endif -+ else if(pic.format == RENDER_FMT_YV12_BUFFER) -+ m_pRenderer->AddProcessor(pic.codecinfo, index); - - m_pRenderer->ReleaseImage(index, false); - -diff --git a/xbmc/cores/VideoRenderers/VideoShaders/YUV2RGBShader.cpp b/xbmc/cores/VideoRenderers/VideoShaders/YUV2RGBShader.cpp -index 21a4ee2..7e82149 100644 ---- a/xbmc/cores/VideoRenderers/VideoShaders/YUV2RGBShader.cpp -+++ b/xbmc/cores/VideoRenderers/VideoShaders/YUV2RGBShader.cpp -@@ -39,12 +39,12 @@ - // - // Transformation matrixes for different colorspaces. - // --static float yuv_coef_bt601[4][4] = -+static float yuv_coef_bt601[4][4] = - { - { 1.0f, 1.0f, 1.0f, 0.0f }, - { 0.0f, -0.344f, 1.773f, 0.0f }, - { 1.403f, -0.714f, 0.0f, 0.0f }, -- { 0.0f, 0.0f, 0.0f, 0.0f } -+ { 0.0f, 0.0f, 0.0f, 0.0f } - }; - - static float yuv_coef_bt709[4][4] = -@@ -55,7 +55,7 @@ static float yuv_coef_bt709[4][4] = - { 0.0f, 0.0f, 0.0f, 0.0f } - }; - --static float yuv_coef_ebu[4][4] = -+static float yuv_coef_ebu[4][4] = - { - { 1.0f, 1.0f, 1.0f, 0.0f }, - { 0.0f, -0.3960f, 2.029f, 0.0f }, -@@ -74,19 +74,19 @@ static float yuv_coef_smtp240m[4][4] = - static float** PickYUVConversionMatrix(unsigned flags) - { - // Pick the matrix. -- -+ - switch(CONF_FLAGS_YUVCOEF_MASK(flags)) - { - case CONF_FLAGS_YUVCOEF_240M: - return (float**)yuv_coef_smtp240m; break; - case CONF_FLAGS_YUVCOEF_BT709: - return (float**)yuv_coef_bt709; break; -- case CONF_FLAGS_YUVCOEF_BT601: -+ case CONF_FLAGS_YUVCOEF_BT601: - return (float**)yuv_coef_bt601; break; - case CONF_FLAGS_YUVCOEF_EBU: - return (float**)yuv_coef_ebu; break; - } -- -+ - return (float**)yuv_coef_bt601; - } - -@@ -228,7 +228,7 @@ BaseYUV2RGBGLSLShader::BaseYUV2RGBGLSLShader(bool rect, unsigned flags, ERenderF - m_hProj = -1; - m_hModel = -1; - m_hAlpha = -1; -- if (m_format == RENDER_FMT_YUV420P) -+ if (m_format == RENDER_FMT_YUV420P || m_format == RENDER_FMT_YV12_BUFFER) - m_defines += "#define XBMC_YV12\n"; - else if (m_format == RENDER_FMT_NV12) - m_defines += "#define XBMC_NV12\n"; -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h -index 741017d..c25eb38 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h -@@ -25,6 +25,7 @@ - #include - #include - #include "cores/VideoRenderers/RenderFormats.h" -+#include "DVDVideoCodecInfo.h" - - extern "C" { - #include "libavcodec/avcodec.h" -@@ -95,6 +96,11 @@ struct DVDVideoPicture - struct { - CDVDMediaCodecInfo *mediacodec; - }; -+ -+ struct { -+ CDVDVideoCodecBuffer *codecinfo; -+ }; -+ - }; - - unsigned int iFlags; -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp -index 9adffd3..6f29357 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp -@@ -316,6 +316,8 @@ CDVDVideoCodecIMX::CDVDVideoCodecIMX() - { - m_usePTS = false; - } -+ m_converter = NULL; -+ m_convert_bitstream = false; - } - - CDVDVideoCodecIMX::~CDVDVideoCodecIMX() -@@ -767,13 +769,7 @@ bool CDVDVideoCodecIMX::ClearPicture(DVDVideoPicture* pDvdVideoPicture) - { - if (pDvdVideoPicture) - { -- //clear frame display flag -- VpuDecRetCode ret = VPU_DecOutFrameDisplayed(m_vpuHandle, m_frameInfo.pDisplayFrameBuf); -- if(ret != VPU_DEC_RET_SUCCESS) -- { -- CLog::Log(LOGERROR, "%s: vpu clear frame display failure: ret=%d \r\n",__FUNCTION__,ret); -- return false; -- } -+ SAFE_RELEASE(pDvdVideoPicture->codecinfo); - } - - return true; -@@ -805,15 +801,18 @@ bool CDVDVideoCodecIMX::GetPicture(DVDVideoPicture* pDvdVideoPicture) - pDvdVideoPicture->iDisplayWidth = ((pDvdVideoPicture->iWidth * m_frameInfo.pExtInfo->nQ16ShiftWidthDivHeightRatio) + 32767) >> 16; - pDvdVideoPicture->iDisplayHeight = pDvdVideoPicture->iHeight; - } -- pDvdVideoPicture->format = RENDER_FMT_YUV420P; -- pDvdVideoPicture->iLineSize[0] = m_frameInfo.pDisplayFrameBuf->nStrideY; -- pDvdVideoPicture->iLineSize[1] = m_frameInfo.pDisplayFrameBuf->nStrideC; -- pDvdVideoPicture->iLineSize[2] = m_frameInfo.pDisplayFrameBuf->nStrideC; -- pDvdVideoPicture->iLineSize[3] = 0; -- pDvdVideoPicture->data[0] = m_frameInfo.pDisplayFrameBuf->pbufVirtY; -- pDvdVideoPicture->data[1] = m_frameInfo.pDisplayFrameBuf->pbufVirtCb; -- pDvdVideoPicture->data[2] = m_frameInfo.pDisplayFrameBuf->pbufVirtCr; -- pDvdVideoPicture->data[3] = 0; -+ -+ pDvdVideoPicture->format = RENDER_FMT_YV12_BUFFER; -+ -+ pDvdVideoPicture->codecinfo = new CDVDVideoCodecIMXBuffer(m_vpuHandle, m_frameInfo); -+ pDvdVideoPicture->codecinfo->iLineSize[0] = m_frameInfo.pDisplayFrameBuf->nStrideY; -+ pDvdVideoPicture->codecinfo->iLineSize[1] = m_frameInfo.pDisplayFrameBuf->nStrideC; -+ pDvdVideoPicture->codecinfo->iLineSize[2] = m_frameInfo.pDisplayFrameBuf->nStrideC; -+ pDvdVideoPicture->codecinfo->iLineSize[3] = 0; -+ pDvdVideoPicture->codecinfo->data[0] = m_frameInfo.pDisplayFrameBuf->pbufVirtY; -+ pDvdVideoPicture->codecinfo->data[1] = m_frameInfo.pDisplayFrameBuf->pbufVirtCb; -+ pDvdVideoPicture->codecinfo->data[2] = m_frameInfo.pDisplayFrameBuf->pbufVirtCr; -+ pDvdVideoPicture->codecinfo->data[3] = 0; - - return true; - } -@@ -831,3 +830,38 @@ void CDVDVideoCodecIMX::SetDropState(bool bDrop) - CLog::Log(LOGNOTICE, "%s : %d\n", __FUNCTION__, bDrop); - } - } -+ -+/*******************************************/ -+ -+CDVDVideoCodecIMXBuffer::CDVDVideoCodecIMXBuffer(VpuDecHandle handle, VpuDecOutFrameInfo frameInfo) -+ : m_refs(1) -+ , m_vpuHandle(handle) -+ , m_frameInfo(frameInfo) -+{ -+} -+ -+void CDVDVideoCodecIMXBuffer::Lock() -+{ -+ AtomicIncrement(&m_refs); -+} -+ -+long CDVDVideoCodecIMXBuffer::Release() -+{ -+ long count = AtomicDecrement(&m_refs); -+ if (count == 0) -+ { -+ VpuDecRetCode ret = VPU_DecOutFrameDisplayed(m_vpuHandle, m_frameInfo.pDisplayFrameBuf); -+ if(ret != VPU_DEC_RET_SUCCESS) -+ { -+ CLog::Log(LOGERROR, "%s: vpu clear frame display failure: ret=%d \r\n",__FUNCTION__,ret); -+ } -+ delete this; -+ } -+ -+ return count; -+} -+ -+CDVDVideoCodecIMXBuffer::~CDVDVideoCodecIMXBuffer() -+{ -+ assert(m_refs == 0); -+} -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h -index cc0f26c..1531bd8 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h -@@ -23,6 +23,7 @@ - #include - #include "DVDVideoCodec.h" - #include "DVDStreamInfo.h" -+#include "DVDVideoCodecInfo.h" - #include "threads/CriticalSection.h" - #include "utils/BitstreamConverter.h" - -@@ -45,6 +46,24 @@ typedef struct - unsigned int phyMem_size[VPU_DEC_MAX_NUM_MEM_NUM]; - } DecMemInfo; - -+class CDVDVideoCodecIMXBuffer : public CDVDVideoCodecBuffer -+{ -+public: -+ CDVDVideoCodecIMXBuffer(VpuDecHandle handle, VpuDecOutFrameInfo frameInfo); -+ -+ // reference counting -+ virtual void Lock(); -+ virtual long Release(); -+ -+protected: -+ // private because we are reference counted -+ virtual ~CDVDVideoCodecIMXBuffer(); -+ -+ long m_refs; -+ VpuDecHandle m_vpuHandle; // Handle for VPU library calls -+ VpuDecOutFrameInfo m_frameInfo; -+}; -+ - class CDVDVideoCodecIMX : public CDVDVideoCodec - { - public: -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecInfo.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecInfo.h -new file mode 100644 -index 0000000..18078d3 ---- /dev/null -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecInfo.h -@@ -0,0 +1,37 @@ -+/* -+ * Copyright (C) 2010-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 -+ * . -+ * -+ */ -+ -+#ifndef DVDVIDEOCODECINFO_H -+#define DVDVIDEOCODECINFO_H -+ -+#include "cores/VideoRenderers/RenderFormats.h" -+ -+class CDVDVideoCodecBuffer -+{ -+public: -+ // reference counting -+ virtual void Lock() = 0; -+ virtual long Release() = 0; -+ -+ uint8_t* data[4]; // [4] = alpha channel, currently not used -+ int iLineSize[4]; // [4] = alpha channel, currently not used -+}; -+ -+#endif // DVDVIDEOCODECINFO_H -diff --git a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp -index be532ec..98f12f4 100644 ---- a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp -+++ b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp -@@ -996,6 +996,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_YV12_BUFFER: return "YV12BUF"; - case RENDER_FMT_NONE: return "NONE"; - } - return "UNKNOWN"; --- -1.9.3 - - -From 2643aee68ee75afe8384db7cb933e257db7af3f2 Mon Sep 17 00:00:00 2001 -From: "Chris \"Koying\" Browet" -Date: Thu, 13 Feb 2014 17:43:23 +0100 -Subject: [PATCH 04/50] ADD: [imx] direct texture rendering - ---- - xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp | 171 +++++++++++++++++++++ - xbmc/cores/VideoRenderers/LinuxRendererGLES.h | 8 +- - xbmc/cores/VideoRenderers/RenderFormats.h | 1 + - xbmc/cores/VideoRenderers/RenderManager.cpp | 2 +- - .../dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp | 80 ++++------ - .../dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h | 8 +- - .../dvdplayer/DVDCodecs/Video/DVDVideoCodecInfo.h | 5 +- - xbmc/cores/dvdplayer/DVDPlayerVideo.cpp | 1 + - xbmc/windowing/egl/EGLNativeTypeIMX.cpp | 49 +----- - 9 files changed, 224 insertions(+), 101 deletions(-) - -diff --git a/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp b/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp -index bc3a39f..0c8b357 100644 ---- a/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp -+++ b/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp -@@ -79,6 +79,12 @@ static PFNEGLDESTROYIMAGEKHRPROC eglDestroyImageKHR; - static PFNGLEGLIMAGETARGETTEXTURE2DOESPROC glEGLImageTargetTexture2DOES; - #endif - -+#ifdef HAS_IMXVPU -+// GLES extension functions -+#include -+#include -+#endif -+ - #if defined(TARGET_ANDROID) - #include "DVDCodecs/Video/DVDVideoCodecAndroidMediaCodec.h" - #endif -@@ -280,6 +286,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 ) -@@ -606,6 +616,9 @@ unsigned int CLinuxRendererGLES::PreInit() - m_formats.push_back(RENDER_FMT_MEDIACODEC); - #endif - m_formats.push_back(RENDER_FMT_YV12_BUFFER); -+#ifdef HAS_IMXVPU -+ m_formats.push_back(RENDER_FMT_IMXMAP); -+#endif - - // setup the background colour - m_clearColour = (float)(g_advancedSettings.m_videoBlackBarColour & 0xff) / 0xff; -@@ -717,6 +730,12 @@ void CLinuxRendererGLES::LoadShaders(int field) - { - CLog::Log(LOGNOTICE, "GL: Using YV12 Buffer render method"); - } -+ 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"); -@@ -815,6 +834,12 @@ void CLinuxRendererGLES::LoadShaders(int field) - m_textureCreate = &CLinuxRendererGLES::CreateYV12Texture; - m_textureDelete = &CLinuxRendererGLES::DeleteYV12Texture; - } -+ 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 -@@ -966,6 +991,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); -@@ -1592,6 +1621,72 @@ 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]; -+ -+ 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(); -+ -+#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) -@@ -2600,6 +2695,82 @@ void CLinuxRendererGLES::SetTextureFilter(GLenum method) - } - } - -+//******************************************************************************************************** -+// IMXMAP creation, deletion, copying + clearing -+//******************************************************************************************************** -+void CLinuxRendererGLES::UploadIMXMAPTexture(int index) -+{ -+#ifdef HAS_IMXVPU -+ YUVBUFFER& buf = m_buffers[index]; -+ CDVDVideoCodecBuffer* codecinfo = buf.codecinfo; -+ -+ if(codecinfo && codecinfo->IsValid()) -+ { -+ YUVPLANE &plane = m_buffers[index].fields[0][0]; -+ -+ glActiveTexture(GL_TEXTURE0); -+ glBindTexture(m_textureTarget, plane.id); -+ -+ GLuint physical = ~0U; -+ glTexDirectVIVMap(m_textureTarget, codecinfo->iWidth, codecinfo->iHeight, GL_VIV_NV12, -+ (GLvoid **)(&codecinfo->data[0]), &physical); -+ glTexDirectInvalidateVIV(m_textureTarget); -+ -+ glBindTexture(m_textureTarget, 0); -+ -+ plane.flipindex = m_buffers[index].flipindex; -+ } -+ -+ YUVFIELDS &fields = m_buffers[index].fields; -+ YUVPLANE &plane = fields[0][0]; -+ plane.texwidth = codecinfo->iWidth; -+ plane.texheight = codecinfo->iHeight; -+ -+ CalculateTextureSourceRects(index, 1); -+#endif -+} -+void CLinuxRendererGLES::DeleteIMXMAPTexture(int index) -+{ -+ YUVBUFFER &buf = m_buffers[index]; -+ YUVPLANE &plane = buf.fields[0][0]; -+ -+ if(plane.id && glIsTexture(plane.id)) -+ glDeleteTextures(1, &plane.id); -+ plane.id = 0; -+} -+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 -diff --git a/xbmc/cores/VideoRenderers/LinuxRendererGLES.h b/xbmc/cores/VideoRenderers/LinuxRendererGLES.h -index e39a93f..e1916db 100644 ---- a/xbmc/cores/VideoRenderers/LinuxRendererGLES.h -+++ b/xbmc/cores/VideoRenderers/LinuxRendererGLES.h -@@ -90,7 +90,8 @@ enum RenderMethod - RENDER_CVREF = 0x080, - RENDER_BYPASS = 0x100, - RENDER_EGLIMG = 0x200, -- RENDER_MEDIACODEC = 0x400 -+ RENDER_MEDIACODEC = 0x400, -+ RENDER_IMXMAP = 0x800 - }; - - enum RenderQuality -@@ -213,6 +214,10 @@ class CLinuxRendererGLES : public CBaseRenderer - - void UploadYV12BufferTexture(int index); - -+ void UploadIMXMAPTexture(int index); -+ void DeleteIMXMAPTexture(int index); -+ bool CreateIMXMAPTexture(int index); -+ - void CalculateTextureSourceRects(int source, int num_planes); - - // renderers -@@ -223,6 +228,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; - -diff --git a/xbmc/cores/VideoRenderers/RenderFormats.h b/xbmc/cores/VideoRenderers/RenderFormats.h -index 384bcd6..714619e 100644 ---- a/xbmc/cores/VideoRenderers/RenderFormats.h -+++ b/xbmc/cores/VideoRenderers/RenderFormats.h -@@ -38,6 +38,7 @@ enum ERenderFormat { - RENDER_FMT_EGLIMG, - RENDER_FMT_MEDIACODEC, - RENDER_FMT_YV12_BUFFER, -+ RENDER_FMT_IMXMAP, - }; - - #endif -diff --git a/xbmc/cores/VideoRenderers/RenderManager.cpp b/xbmc/cores/VideoRenderers/RenderManager.cpp -index 0aebd2d..653dc52 100644 ---- a/xbmc/cores/VideoRenderers/RenderManager.cpp -+++ b/xbmc/cores/VideoRenderers/RenderManager.cpp -@@ -932,7 +932,7 @@ int CXBMCRenderManager::AddVideoPicture(DVDVideoPicture& pic) - else if(pic.format == RENDER_FMT_MEDIACODEC) - m_pRenderer->AddProcessor(pic.mediacodec, index); - #endif -- else if(pic.format == RENDER_FMT_YV12_BUFFER) -+ else if(pic.format == RENDER_FMT_YV12_BUFFER || pic.format == RENDER_FMT_IMXMAP) - m_pRenderer->AddProcessor(pic.codecinfo, index); - - m_pRenderer->ReleaseImage(index, false); -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp -index 6f29357..7c5c26b 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp -@@ -43,6 +43,7 @@ - #define IMX_MAX_QUEUE_SIZE 1 - // Experiments show that we need at least one more (+1) V4L buffer than the min value returned by the VPU - const int CDVDVideoCodecIMX::m_extraVpuBuffers = IMX_MAX_QUEUE_SIZE + 6; -+VpuDecHandle CDVDVideoCodecIMX::m_vpuHandle = 0; - - bool CDVDVideoCodecIMX::VpuAllocBuffers(VpuMemInfo *pMemBlock) - { -@@ -165,7 +166,7 @@ bool CDVDVideoCodecIMX::VpuOpen(void) - VpuAllocBuffers(&memInfo); - - m_decOpenParam.nReorderEnable = 1; -- m_decOpenParam.nChromaInterleave = 0; -+ m_decOpenParam.nChromaInterleave = 1; - m_decOpenParam.nMapType = 0; - m_decOpenParam.nTiled2LinearEnable = 0; - m_decOpenParam.nEnableFileMode = 0; -@@ -205,11 +206,9 @@ bool CDVDVideoCodecIMX::VpuAllocFrameBuffers(void) - int totalSize=0; - int mvSize=0; - int ySize=0; -- int uSize=0; -- int vSize=0; -+ int uvSize=0; - int yStride=0; -- int uStride=0; -- int vStride=0; -+ int uvStride=0; - unsigned char* ptr; - unsigned char* ptrVirt; - int nAlign; -@@ -227,24 +226,21 @@ bool CDVDVideoCodecIMX::VpuAllocFrameBuffers(void) - ySize=Align(m_initInfo.nPicWidth,FRAME_ALIGN)*Align(m_initInfo.nPicHeight,FRAME_ALIGN); - } - -- //4:2:0 for all video -- uStride=yStride/2; -- vStride=uStride; -- uSize=ySize/4; -- vSize=uSize; -- mvSize=uSize; -+ //NV12 for all video -+ uvStride=yStride; -+ uvSize=ySize/2; -+ mvSize=uvSize/2; - - nAlign=m_initInfo.nAddressAlignment; - if(nAlign>1) - { - ySize=Align(ySize,nAlign); -- uSize=Align(uSize,nAlign); -- vSize=Align(vSize,nAlign); -+ uvSize=Align(uvSize,nAlign); - } - - for (i = 0 ; i < m_vpuFrameBufferNum; i++) - { -- totalSize=(ySize+uSize+vSize+mvSize+nAlign)*1; -+ totalSize=(ySize+uvSize+mvSize+nAlign)*1; - - vpuMem.nSize=totalSize; - ret = VPU_DecGetMem(&vpuMem); -@@ -274,19 +270,19 @@ bool CDVDVideoCodecIMX::VpuAllocFrameBuffers(void) - - /* fill stride info */ - m_vpuFrameBuffers[i].nStrideY=yStride; -- m_vpuFrameBuffers[i].nStrideC=uStride; -+ m_vpuFrameBuffers[i].nStrideC=uvStride; - - /* fill phy addr*/ - m_vpuFrameBuffers[i].pbufY=ptr; - m_vpuFrameBuffers[i].pbufCb=ptr+ySize; -- m_vpuFrameBuffers[i].pbufCr=ptr+ySize+uSize; -- m_vpuFrameBuffers[i].pbufMvCol=ptr+ySize+uSize+vSize; -+ m_vpuFrameBuffers[i].pbufCr=0; -+ m_vpuFrameBuffers[i].pbufMvCol=ptr+ySize+uvSize; - //ptr+=ySize+uSize+vSize+mvSize; - /* fill virt addr */ - m_vpuFrameBuffers[i].pbufVirtY=ptrVirt; - m_vpuFrameBuffers[i].pbufVirtCb=ptrVirt+ySize; -- m_vpuFrameBuffers[i].pbufVirtCr=ptrVirt+ySize+uSize; -- m_vpuFrameBuffers[i].pbufVirtMvCol=ptrVirt+ySize+uSize+vSize; -+ m_vpuFrameBuffers[i].pbufVirtCr=0; -+ m_vpuFrameBuffers[i].pbufVirtMvCol=ptrVirt+ySize+uvSize; - //ptrVirt+=ySize+uSize+vSize+mvSize; - - m_vpuFrameBuffers[i].pbufY_tilebot=0; -@@ -528,7 +524,8 @@ int CDVDVideoCodecIMX::Decode(BYTE *pData, int iSize, double dts, double pts) - } - - #ifdef IMX_PROFILE -- CLog::Log(LOGDEBUG, "%s - delta time decode : %llu - demux size : %d dts : %f - pts : %f\n", __FUNCTION__, -1, iSize, dts, pts); -+ 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 - -@@ -597,11 +594,11 @@ int CDVDVideoCodecIMX::Decode(BYTE *pData, int iSize, double dts, double pts) - { - retry = false; - #ifdef IMX_PROFILE -- //before_dec = get_time(); -+ before_dec = XbmcThreads::SystemClockMillis(); - #endif - 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, -1); -+ 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) -@@ -734,7 +731,7 @@ int CDVDVideoCodecIMX::Decode(BYTE *pData, int iSize, double dts, double pts) - } - - #ifdef IMX_PROFILE -- CLog::Log(LOGDEBUG, "%s - returns %x - duration %lld\n", __FUNCTION__, retStatus, -1); -+ CLog::Log(LOGDEBUG, "%s - returns %x - duration %lld\n", __FUNCTION__, retStatus, XbmcThreads::SystemClockMillis() - previous); - #endif - return retStatus; - -@@ -783,6 +780,7 @@ bool CDVDVideoCodecIMX::GetPicture(DVDVideoPicture* pDvdVideoPicture) - else - pDvdVideoPicture->iFlags &= ~DVP_FLAG_DROPPED; - -+ pDvdVideoPicture->format = RENDER_FMT_IMXMAP; - pDvdVideoPicture->pts = (double)TSManagerSend(m_tsm) / (double)1000.0; - if (!m_usePTS) - { -@@ -791,28 +789,14 @@ bool CDVDVideoCodecIMX::GetPicture(DVDVideoPicture* pDvdVideoPicture) - 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; -- if (m_dropState) -- { -- pDvdVideoPicture->iDisplayWidth = pDvdVideoPicture->iWidth; -- pDvdVideoPicture->iDisplayHeight = pDvdVideoPicture->iHeight; -- } -- else -- { -- pDvdVideoPicture->iDisplayWidth = ((pDvdVideoPicture->iWidth * m_frameInfo.pExtInfo->nQ16ShiftWidthDivHeightRatio) + 32767) >> 16; -- pDvdVideoPicture->iDisplayHeight = pDvdVideoPicture->iHeight; -- } -- -- pDvdVideoPicture->format = RENDER_FMT_YV12_BUFFER; -+ pDvdVideoPicture->iDisplayWidth = m_frameInfo.pExtInfo->FrmCropRect.nRight - m_frameInfo.pExtInfo->FrmCropRect.nLeft; -+ pDvdVideoPicture->iDisplayHeight = m_frameInfo.pExtInfo->FrmCropRect.nBottom - m_frameInfo.pExtInfo->FrmCropRect.nTop; - -- pDvdVideoPicture->codecinfo = new CDVDVideoCodecIMXBuffer(m_vpuHandle, m_frameInfo); -- pDvdVideoPicture->codecinfo->iLineSize[0] = m_frameInfo.pDisplayFrameBuf->nStrideY; -- pDvdVideoPicture->codecinfo->iLineSize[1] = m_frameInfo.pDisplayFrameBuf->nStrideC; -- pDvdVideoPicture->codecinfo->iLineSize[2] = m_frameInfo.pDisplayFrameBuf->nStrideC; -- pDvdVideoPicture->codecinfo->iLineSize[3] = 0; -+ pDvdVideoPicture->codecinfo = new CDVDVideoCodecIMXBuffer(m_frameInfo); -+ pDvdVideoPicture->codecinfo->iWidth = m_frameInfo.pExtInfo->nFrmWidth; -+ pDvdVideoPicture->codecinfo->iHeight = m_frameInfo.pExtInfo->nFrmHeight; - pDvdVideoPicture->codecinfo->data[0] = m_frameInfo.pDisplayFrameBuf->pbufVirtY; -- pDvdVideoPicture->codecinfo->data[1] = m_frameInfo.pDisplayFrameBuf->pbufVirtCb; -- pDvdVideoPicture->codecinfo->data[2] = m_frameInfo.pDisplayFrameBuf->pbufVirtCr; -- pDvdVideoPicture->codecinfo->data[3] = 0; -+ pDvdVideoPicture->codecinfo->data[1] = m_frameInfo.pDisplayFrameBuf->pbufY; - - return true; - } -@@ -833,9 +817,8 @@ void CDVDVideoCodecIMX::SetDropState(bool bDrop) - - /*******************************************/ - --CDVDVideoCodecIMXBuffer::CDVDVideoCodecIMXBuffer(VpuDecHandle handle, VpuDecOutFrameInfo frameInfo) -+CDVDVideoCodecIMXBuffer::CDVDVideoCodecIMXBuffer(VpuDecOutFrameInfo frameInfo) - : m_refs(1) -- , m_vpuHandle(handle) - , m_frameInfo(frameInfo) - { - } -@@ -850,7 +833,7 @@ long CDVDVideoCodecIMXBuffer::Release() - long count = AtomicDecrement(&m_refs); - if (count == 0) - { -- VpuDecRetCode ret = VPU_DecOutFrameDisplayed(m_vpuHandle, m_frameInfo.pDisplayFrameBuf); -+ VpuDecRetCode ret = VPU_DecOutFrameDisplayed(CDVDVideoCodecIMX::m_vpuHandle, m_frameInfo.pDisplayFrameBuf); - if(ret != VPU_DEC_RET_SUCCESS) - { - CLog::Log(LOGERROR, "%s: vpu clear frame display failure: ret=%d \r\n",__FUNCTION__,ret); -@@ -861,6 +844,11 @@ long CDVDVideoCodecIMXBuffer::Release() - return count; - } - -+bool CDVDVideoCodecIMXBuffer::IsValid() -+{ -+ return (CDVDVideoCodecIMX::m_vpuHandle != 0); -+} -+ - CDVDVideoCodecIMXBuffer::~CDVDVideoCodecIMXBuffer() - { - assert(m_refs == 0); -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h -index 1531bd8..5487bfe 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h -@@ -49,23 +49,25 @@ typedef struct - class CDVDVideoCodecIMXBuffer : public CDVDVideoCodecBuffer - { - public: -- CDVDVideoCodecIMXBuffer(VpuDecHandle handle, VpuDecOutFrameInfo frameInfo); -+ CDVDVideoCodecIMXBuffer(VpuDecOutFrameInfo frameInfo); - - // reference counting - virtual void Lock(); - virtual long Release(); -+ virtual bool IsValid(); - - protected: - // private because we are reference counted - virtual ~CDVDVideoCodecIMXBuffer(); - - long m_refs; -- VpuDecHandle m_vpuHandle; // Handle for VPU library calls - VpuDecOutFrameInfo m_frameInfo; - }; - - class CDVDVideoCodecIMX : public CDVDVideoCodec - { -+ friend class CDVDVideoCodecIMXBuffer; -+ - public: - CDVDVideoCodecIMX(); - virtual ~CDVDVideoCodecIMX(); -@@ -94,7 +96,7 @@ class CDVDVideoCodecIMX : public CDVDVideoCodec - const char *m_pFormatName; // Current decoder format name - VpuDecOpenParam m_decOpenParam; // Parameters required to call VPU_DecOpen - DecMemInfo m_decMemInfo; // VPU dedicated memory description -- VpuDecHandle m_vpuHandle; // Handle for VPU library calls -+ static VpuDecHandle m_vpuHandle; // Handle for VPU library calls - VpuDecInitInfo m_initInfo; // Initial info returned from VPU at decoding start - void *m_tsm; // fsl Timestamp manager (from gstreamer implementation) - bool m_tsSyncRequired; // state whether timestamp manager has to be sync'ed -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecInfo.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecInfo.h -index 18078d3..6096bf4 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecInfo.h -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecInfo.h -@@ -21,15 +21,16 @@ - #ifndef DVDVIDEOCODECINFO_H - #define DVDVIDEOCODECINFO_H - --#include "cores/VideoRenderers/RenderFormats.h" -- - class CDVDVideoCodecBuffer - { - public: - // reference counting - virtual void Lock() = 0; - virtual long Release() = 0; -+ virtual bool IsValid() = 0; - -+ uint32_t iWidth; -+ uint32_t iHeight; - uint8_t* data[4]; // [4] = alpha channel, currently not used - int iLineSize[4]; // [4] = alpha channel, currently not used - }; -diff --git a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp -index 98f12f4..efac52b 100644 ---- a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp -+++ b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp -@@ -997,6 +997,7 @@ static std::string GetRenderFormatName(ERenderFormat format) - case RENDER_FMT_BYPASS: return "BYPASS"; - case RENDER_FMT_MEDIACODEC:return "MEDIACODEC"; - case RENDER_FMT_YV12_BUFFER: return "YV12BUF"; -+ case RENDER_FMT_IMXMAP: return "IMXMAP"; - case RENDER_FMT_NONE: return "NONE"; - } - return "UNKNOWN"; -diff --git a/xbmc/windowing/egl/EGLNativeTypeIMX.cpp b/xbmc/windowing/egl/EGLNativeTypeIMX.cpp -index 4ac19c4..b44d4b8 100644 ---- a/xbmc/windowing/egl/EGLNativeTypeIMX.cpp -+++ b/xbmc/windowing/egl/EGLNativeTypeIMX.cpp -@@ -52,7 +52,7 @@ bool CEGLNativeTypeIMX::CheckCompatibility() - void CEGLNativeTypeIMX::Initialize() - { - struct mxcfb_gbl_alpha alpha; -- int fd, fd2; -+ int fd; - - - fd = open("/dev/fb0",O_RDWR); -@@ -61,46 +61,20 @@ void CEGLNativeTypeIMX::Initialize() - CLog::Log(LOGERROR, "%s - Error while opening /dev/fb0.\n", __FUNCTION__); - return; - } -- fd2 = open("/dev/fb1",O_RDWR); -- if (fd2 < 0) -- { -- CLog::Log(LOGERROR, "%s - Error while opening /dev/fb1.\n", __FUNCTION__); -- return; -- } -- - /* Store screen info */ - if (ioctl(fd, FBIOGET_VSCREENINFO, &m_screeninfo) != 0) - { - CLog::Log(LOGERROR, "%s - Error while querying frame buffer.\n", __FUNCTION__); - return; - } -- /* Configure overlay in the same way as BG plane */ -- if (ioctl(fd2, FBIOPUT_VSCREENINFO, &m_screeninfo) != 0) -- { -- CLog::Log(LOGERROR, "%s - Error while setting overlay frame buffer.\n", __FUNCTION__); -- return; -- } - -- /* set fb0 as the only visible layer - ioctl on /dev/fb0 so that fb0 is BG and fb1 is FG */ -- alpha.alpha = 255; -- alpha.enable = 1; -- if (ioctl(fd, MXCFB_SET_GBL_ALPHA, &alpha) != 0) -- { -- CLog::Log(LOGERROR, "%s - Error while initializing frame buffer.\n", __FUNCTION__); -- } -- - /* Unblank the fbs */ - if (ioctl(fd, FBIOBLANK, 0) < 0) - { - CLog::Log(LOGERROR, "%s - Error while unblanking fb0.\n", __FUNCTION__); - } -- if (ioctl(fd2, FBIOBLANK, 0) < 0) -- { -- CLog::Log(LOGERROR, "%s - Error while unblanking fb0.\n", __FUNCTION__); -- } - - close(fd); -- close(fd2); - - return; - } -@@ -109,7 +83,6 @@ void CEGLNativeTypeIMX::Destroy() - { - struct fb_fix_screeninfo fixed_info; - void *fb_buffer; -- struct mxcfb_gbl_alpha alpha; - int fd; - - fd = open("/dev/fb0",O_RDWR); -@@ -118,13 +91,6 @@ void CEGLNativeTypeIMX::Destroy() - CLog::Log(LOGERROR, "%s - Error while opening /dev/fb0.\n", __FUNCTION__); - return; - } -- /* only fb0 visible */ -- alpha.alpha = 255; -- alpha.enable = 1; -- if (ioctl(fd, MXCFB_SET_GBL_ALPHA, &alpha) != 0) -- { -- CLog::Log(LOGERROR, "%s - Error while initializing frame buffer.\n", __FUNCTION__); -- } - - ioctl( fd, FBIOGET_FSCREENINFO, &fixed_info); - /* Black fb0 */ -@@ -140,19 +106,6 @@ void CEGLNativeTypeIMX::Destroy() - } - - close(fd); -- -- /* Blank overlay */ -- fd = open("/dev/fb1",O_RDWR); -- if (fd < 0) -- { -- CLog::Log(LOGERROR, "%s - Error while opening /dev/fb1.\n", __FUNCTION__); -- return; -- } -- if (ioctl(fd, FBIOBLANK, 1) < 0) -- { -- CLog::Log(LOGERROR, "%s - Error while blanking fb1.\n", __FUNCTION__); -- } -- close(fd); - - return; - } --- -1.9.3 - - -From 19981bbbc0007b308d43de31478229f3a109709c Mon Sep 17 00:00:00 2001 -From: smallint -Date: Mon, 17 Feb 2014 22:09:19 +0100 -Subject: [PATCH 05/50] Fixed include and display size issues - ---- - xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp | 6 +++ - .../dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp | 61 ++++++++++++---------- - 2 files changed, 39 insertions(+), 28 deletions(-) - -diff --git a/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp b/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp -index 0c8b357..4f3d042 100644 ---- a/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp -+++ b/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp -@@ -26,6 +26,9 @@ - #endif - - #if HAS_GLES == 2 -+#ifdef HAS_IMXVPU -+#define GL_GLEXT_PROTOTYPES -+#endif - #include "system_gl.h" - - #include -@@ -2727,6 +2730,9 @@ void CLinuxRendererGLES::UploadIMXMAPTexture(int index) - plane.texheight = codecinfo->iHeight; - - CalculateTextureSourceRects(index, 1); -+ -+ CLog::Log(LOGDEBUG, "U %dx%d -> %dx%d", codecinfo->iWidth, codecinfo->iHeight, -+ plane.rect.x2-plane.rect.x1, plane.rect.y2-plane.rect.y1); - #endif - } - void CLinuxRendererGLES::DeleteIMXMAPTexture(int index) -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp -index 7c5c26b..a5d9eeb 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp -@@ -510,6 +510,7 @@ int CDVDVideoCodecIMX::Decode(BYTE *pData, int iSize, double dts, double pts) - int demuxer_bytes = iSize; - uint8_t *demuxer_content = pData; - bool retry = false; -+ bool frameConsumed = false; - - #ifdef IMX_PROFILE - static unsigned long long previous, current; -@@ -548,31 +549,6 @@ int CDVDVideoCodecIMX::Decode(BYTE *pData, int iSize, double dts, double pts) - CLog::Log(LOGERROR,"%s - bitstream_convert error", __FUNCTION__); - } - -- if (pts != DVD_NOPTS_VALUE) -- { -- if (m_tsSyncRequired) -- { -- m_tsSyncRequired = false; -- resyncTSManager(m_tsm, llrint(pts) * 1000, MODE_AI); -- } -- //TSManagerReceive2(m_tsm, llrint(pts) * 1000, iSize); -- TSManagerReceive(m_tsm, llrint(pts) * 1000); -- } -- else -- { -- //If no pts but dts available (AVI container for instance) then use this one -- if (dts != DVD_NOPTS_VALUE) -- { -- if (m_tsSyncRequired) -- { -- m_tsSyncRequired = false; -- resyncTSManager(m_tsm, llrint(dts) * 1000, MODE_AI); -- } -- //TSManagerReceive2(m_tsm, llrint(dts) * 1000, iSize); -- TSManagerReceive(m_tsm, llrint(dts) * 1000); -- } -- } -- - inData.nSize = demuxer_bytes; - inData.pPhyAddr = NULL; - inData.pVirAddr = demuxer_content; -@@ -646,6 +622,7 @@ int CDVDVideoCodecIMX::Decode(BYTE *pData, int iSize, double dts, double pts) - { - CLog::Log(LOGERROR, "%s - VPU error retireving info about consummed frame (%d).\n", __FUNCTION__, ret); - } -+ frameConsumed = true; - // FIXME TSManagerValid2(m_tsm, frameLengthInfo.nFrameLength + frameLengthInfo.nStuffLength, frameLengthInfo.pFrame); - //CLog::Log(LOGDEBUG, "%s - size : %d - key consummed : %x\n", __FUNCTION__, frameLengthInfo.nFrameLength + frameLengthInfo.nStuffLength, frameLengthInfo.pFrame); - }//VPU_DEC_ONE_FRM_CONSUMED -@@ -710,7 +687,6 @@ int CDVDVideoCodecIMX::Decode(BYTE *pData, int iSize, double dts, double pts) - TSManagerSend(m_tsm); - } - -- - if (!(decRet & VPU_DEC_OUTPUT_DIS) && - (inData.nSize != 0)) - { -@@ -725,6 +701,34 @@ int CDVDVideoCodecIMX::Decode(BYTE *pData, int iSize, double dts, double pts) - } while (retry == true); - } //(pData && iSize) - -+ if (frameConsumed) -+ { -+ if (pts != DVD_NOPTS_VALUE) -+ { -+ if (m_tsSyncRequired) -+ { -+ m_tsSyncRequired = false; -+ resyncTSManager(m_tsm, llrint(pts) * 1000, MODE_AI); -+ } -+ //TSManagerReceive2(m_tsm, llrint(pts) * 1000, iSize); -+ TSManagerReceive(m_tsm, llrint(pts) * 1000); -+ } -+ else -+ { -+ //If no pts but dts available (AVI container for instance) then use this one -+ if (dts != DVD_NOPTS_VALUE) -+ { -+ if (m_tsSyncRequired) -+ { -+ m_tsSyncRequired = false; -+ resyncTSManager(m_tsm, llrint(dts) * 1000, MODE_AI); -+ } -+ //TSManagerReceive2(m_tsm, llrint(dts) * 1000, iSize); -+ TSManagerReceive(m_tsm, llrint(dts) * 1000); -+ } -+ } -+ } -+ - if (retStatus == 0) - { - retStatus |= VC_BUFFER; -@@ -789,8 +793,9 @@ bool CDVDVideoCodecIMX::GetPicture(DVDVideoPicture* pDvdVideoPicture) - 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 = m_frameInfo.pExtInfo->FrmCropRect.nRight - m_frameInfo.pExtInfo->FrmCropRect.nLeft; -- pDvdVideoPicture->iDisplayHeight = m_frameInfo.pExtInfo->FrmCropRect.nBottom - m_frameInfo.pExtInfo->FrmCropRect.nTop; -+ -+ pDvdVideoPicture->iDisplayWidth = ((pDvdVideoPicture->iWidth * m_frameInfo.pExtInfo->nQ16ShiftWidthDivHeightRatio) + 32767) >> 16; -+ pDvdVideoPicture->iDisplayHeight = pDvdVideoPicture->iHeight; - - pDvdVideoPicture->codecinfo = new CDVDVideoCodecIMXBuffer(m_frameInfo); - pDvdVideoPicture->codecinfo->iWidth = m_frameInfo.pExtInfo->nFrmWidth; --- -1.9.3 - - -From 4ecfa9bd4f0b0e47c273766477ea94a39d350468 Mon Sep 17 00:00:00 2001 -From: smallint -Date: Mon, 17 Feb 2014 23:26:07 +0100 -Subject: [PATCH 06/50] Removed debug output used for testing - ---- - xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp | 3 --- - 1 file changed, 3 deletions(-) - -diff --git a/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp b/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp -index 4f3d042..2c7f132 100644 ---- a/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp -+++ b/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp -@@ -2730,9 +2730,6 @@ void CLinuxRendererGLES::UploadIMXMAPTexture(int index) - plane.texheight = codecinfo->iHeight; - - CalculateTextureSourceRects(index, 1); -- -- CLog::Log(LOGDEBUG, "U %dx%d -> %dx%d", codecinfo->iWidth, codecinfo->iHeight, -- plane.rect.x2-plane.rect.x1, plane.rect.y2-plane.rect.y1); - #endif - } - void CLinuxRendererGLES::DeleteIMXMAPTexture(int index) --- -1.9.3 - - -From bd888a536c9397a41ad5846acd75f9ea8d450e4b Mon Sep 17 00:00:00 2001 -From: smallint -Date: Tue, 18 Feb 2014 16:07:23 +0000 -Subject: [PATCH 07/50] Attempt to fix potential race condition and - mutlithreading issues ... to be tested - ---- - .../dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp | 130 ++++++++++++++++++--- - .../dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h | 29 +++-- - 2 files changed, 135 insertions(+), 24 deletions(-) - -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp -index a5d9eeb..690ab65 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp -@@ -43,7 +43,7 @@ - #define IMX_MAX_QUEUE_SIZE 1 - // Experiments show that we need at least one more (+1) V4L buffer than the min value returned by the VPU - const int CDVDVideoCodecIMX::m_extraVpuBuffers = IMX_MAX_QUEUE_SIZE + 6; --VpuDecHandle CDVDVideoCodecIMX::m_vpuHandle = 0; -+CCriticalSection CDVDVideoCodecIMX::m_codecBufferLock; - - bool CDVDVideoCodecIMX::VpuAllocBuffers(VpuMemInfo *pMemBlock) - { -@@ -95,6 +95,17 @@ bool CDVDVideoCodecIMX::VpuAllocBuffers(VpuMemInfo *pMemBlock) - return false; - } - -+int CDVDVideoCodecIMX::VpuFindBuffer(void *frameAddr) -+{ -+ int i; -+ for (i=0; iInvalidate(); -+ SAFE_RELEASE(m_outputBuffers[i]); -+ } -+ -+ // Clear memory -+ if (m_outputBuffers != NULL) -+ { -+ delete m_outputBuffers; -+ m_outputBuffers = NULL; -+ } -+ - VpuFreeBuffers(); - m_vpuFrameBufferNum = 0; - -@@ -504,8 +539,8 @@ int CDVDVideoCodecIMX::Decode(BYTE *pData, int iSize, double dts, double pts) - { - VpuDecFrameLengthInfo frameLengthInfo; - VpuBufferNode inData; -- VpuDecRetCode ret; -- int decRet = 0; -+ VpuDecRetCode ret; -+ int decRet = 0, i; - int retStatus = 0; - int demuxer_bytes = iSize; - uint8_t *demuxer_content = pData; -@@ -524,6 +559,21 @@ int CDVDVideoCodecIMX::Decode(BYTE *pData, int iSize, double dts, double pts) - return VC_ERROR; - } - -+ for (i=0; i < m_vpuFrameBufferNum; i++) -+ { -+ if (m_outputBuffers[i]->Rendered()) -+ { -+ ret = VPU_DecOutFrameDisplayed(m_vpuHandle, &m_vpuFrameBuffers[i]); -+#ifdef TRACE_FRAMES -+ CLog::Log(LOGDEBUG, "- %02d\n", i); -+#endif -+ 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); -@@ -797,11 +847,27 @@ bool CDVDVideoCodecIMX::GetPicture(DVDVideoPicture* pDvdVideoPicture) - pDvdVideoPicture->iDisplayWidth = ((pDvdVideoPicture->iWidth * m_frameInfo.pExtInfo->nQ16ShiftWidthDivHeightRatio) + 32767) >> 16; - pDvdVideoPicture->iDisplayHeight = pDvdVideoPicture->iHeight; - -- pDvdVideoPicture->codecinfo = new CDVDVideoCodecIMXBuffer(m_frameInfo); -- pDvdVideoPicture->codecinfo->iWidth = m_frameInfo.pExtInfo->nFrmWidth; -- pDvdVideoPicture->codecinfo->iHeight = m_frameInfo.pExtInfo->nFrmHeight; -- pDvdVideoPicture->codecinfo->data[0] = m_frameInfo.pDisplayFrameBuf->pbufVirtY; -- pDvdVideoPicture->codecinfo->data[1] = m_frameInfo.pDisplayFrameBuf->pbufY; -+ int idx = VpuFindBuffer(m_frameInfo.pDisplayFrameBuf->pbufY); -+ if (idx == -1) -+ { -+ CLog::Log(LOGERROR, "%s - could not find frame buffer\n", __FUNCTION__); -+ } -+ else -+ { -+ CDVDVideoCodecIMXBuffer *buffer = m_outputBuffers[idx]; -+ buffer->Queue(&m_vpuFrameBuffers[idx]); -+ pDvdVideoPicture->codecinfo = buffer; -+ -+#ifdef TRACE_FRAMES -+ CLog::Log(LOGDEBUG, "+ %02d\n", idx); -+#endif -+ -+ pDvdVideoPicture->codecinfo->Lock(); -+ pDvdVideoPicture->codecinfo->iWidth = m_frameInfo.pExtInfo->nFrmWidth; -+ pDvdVideoPicture->codecinfo->iHeight = m_frameInfo.pExtInfo->nFrmHeight; -+ pDvdVideoPicture->codecinfo->data[0] = m_frameInfo.pDisplayFrameBuf->pbufVirtY; -+ pDvdVideoPicture->codecinfo->data[1] = m_frameInfo.pDisplayFrameBuf->pbufY; -+ } - - return true; - } -@@ -822,9 +888,16 @@ void CDVDVideoCodecIMX::SetDropState(bool bDrop) - - /*******************************************/ - --CDVDVideoCodecIMXBuffer::CDVDVideoCodecIMXBuffer(VpuDecOutFrameInfo frameInfo) -+#ifdef TRACE_FRAMES -+CDVDVideoCodecIMXBuffer::CDVDVideoCodecIMXBuffer(int idx) - : m_refs(1) -- , m_frameInfo(frameInfo) -+ , m_idx(idx) -+#else -+CDVDVideoCodecIMXBuffer::CDVDVideoCodecIMXBuffer() -+ : m_refs(1) -+#endif -+ , m_frameBuffer(NULL) -+ , m_rendered(false) - { - } - -@@ -836,13 +909,18 @@ void CDVDVideoCodecIMXBuffer::Lock() - long CDVDVideoCodecIMXBuffer::Release() - { - long count = AtomicDecrement(&m_refs); -- if (count == 0) -+ if (count == 1) - { -- VpuDecRetCode ret = VPU_DecOutFrameDisplayed(CDVDVideoCodecIMX::m_vpuHandle, m_frameInfo.pDisplayFrameBuf); -- if(ret != VPU_DEC_RET_SUCCESS) -- { -- CLog::Log(LOGERROR, "%s: vpu clear frame display failure: ret=%d \r\n",__FUNCTION__,ret); -- } -+ // 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. -+ m_rendered = true; -+ } -+ else if (count == 0) -+ { -+#ifdef TRACE_FRAMES -+ CLog::Log(LOGDEBUG, "~ %02d\n", m_idx); -+#endif -+ - delete this; - } - -@@ -851,7 +929,25 @@ long CDVDVideoCodecIMXBuffer::Release() - - bool CDVDVideoCodecIMXBuffer::IsValid() - { -- return (CDVDVideoCodecIMX::m_vpuHandle != 0); -+ CSingleLock lock(CDVDVideoCodecIMX::m_codecBufferLock); -+ return m_frameBuffer != NULL; -+} -+ -+void CDVDVideoCodecIMXBuffer::Invalidate() -+{ -+ CSingleLock lock(CDVDVideoCodecIMX::m_codecBufferLock); -+ m_frameBuffer = NULL; -+} -+ -+bool CDVDVideoCodecIMXBuffer::Rendered() -+{ -+ return m_rendered; -+} -+ -+void CDVDVideoCodecIMXBuffer::Queue(VpuFrameBuffer *buffer) -+{ -+ m_frameBuffer = buffer; -+ m_rendered = false; - } - - CDVDVideoCodecIMXBuffer::~CDVDVideoCodecIMXBuffer() -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h -index 5487bfe..df568e5 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h -@@ -29,6 +29,7 @@ - - - //#define IMX_PROFILE -+#define TRACE_FRAMES - - /* FIXME TODO Develop real proper CVPUBuffer class */ - #define VPU_DEC_MAX_NUM_MEM_NUM 20 -@@ -49,19 +50,31 @@ typedef struct - class CDVDVideoCodecIMXBuffer : public CDVDVideoCodecBuffer - { - public: -- CDVDVideoCodecIMXBuffer(VpuDecOutFrameInfo frameInfo); -+#ifdef TRACE_FRAMES -+ CDVDVideoCodecIMXBuffer(int idx); -+#else -+ CDVDVideoCodecIMXBuffer(); -+#endif - - // reference counting -- virtual void Lock(); -- virtual long Release(); -- virtual bool IsValid(); -+ virtual void Lock(); -+ virtual long Release(); -+ virtual bool IsValid(); -+ -+ void Invalidate(); -+ bool Rendered(); -+ void Queue(VpuFrameBuffer *buffer); - - protected: - // private because we are reference counted - virtual ~CDVDVideoCodecIMXBuffer(); - -+#ifdef TRACE_FRAMES -+ int m_idx; -+#endif - long m_refs; -- VpuDecOutFrameInfo m_frameInfo; -+ VpuFrameBuffer *m_frameBuffer; -+ bool m_rendered; - }; - - class CDVDVideoCodecIMX : public CDVDVideoCodec -@@ -89,20 +102,23 @@ class CDVDVideoCodecIMX : public CDVDVideoCodec - bool VpuAllocBuffers(VpuMemInfo *); - bool VpuFreeBuffers(void); - bool VpuAllocFrameBuffers(void); -+ int VpuFindBuffer(void *frameAddr); - - static const int m_extraVpuBuffers; // Number of additional buffers for VPU -+ static CCriticalSection m_codecBufferLock; - - 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 - DecMemInfo m_decMemInfo; // VPU dedicated memory description -- static VpuDecHandle m_vpuHandle; // Handle for VPU library calls -+ VpuDecHandle m_vpuHandle; // Handle for VPU library calls - VpuDecInitInfo m_initInfo; // Initial info returned from VPU at decoding start - void *m_tsm; // fsl Timestamp manager (from gstreamer implementation) - bool m_tsSyncRequired; // state whether timestamp manager has to be sync'ed - 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; - VpuMemDesc *m_extraMem; // Table of allocated extra Memory - // VpuMemDesc *m_outputBuffers; // Table of buffers out of VPU (used to call properly VPU_DecOutFrameDisplayed) - int m_frameCounter; // Decoded frames counter -@@ -110,5 +126,4 @@ class CDVDVideoCodecIMX : public CDVDVideoCodec - VpuDecOutFrameInfo m_frameInfo; - CBitstreamConverter *m_converter; - bool m_convert_bitstream; -- - }; --- -1.9.3 - - -From 7a3a957432dfd6f7e7e45cea945b9061080da906 Mon Sep 17 00:00:00 2001 -From: smallint -Date: Tue, 18 Feb 2014 19:19:09 +0100 -Subject: [PATCH 08/50] Fixed buffer reference and added more logs to track a - frames lifetime - ---- - xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp | 2 ++ - .../dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp | 28 ++++++++++++++++++---- - .../dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h | 1 + - 3 files changed, 26 insertions(+), 5 deletions(-) - -diff --git a/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp b/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp -index 2c7f132..5e03110 100644 ---- a/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp -+++ b/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp -@@ -2740,6 +2740,8 @@ void CLinuxRendererGLES::DeleteIMXMAPTexture(int index) - if(plane.id && glIsTexture(plane.id)) - glDeleteTextures(1, &plane.id); - plane.id = 0; -+ -+ SAFE_RELEASE(buf.codecinfo); - } - bool CLinuxRendererGLES::CreateIMXMAPTexture(int index) - { -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp -index 690ab65..75aba7c 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp -@@ -563,10 +563,7 @@ int CDVDVideoCodecIMX::Decode(BYTE *pData, int iSize, double dts, double pts) - { - if (m_outputBuffers[i]->Rendered()) - { -- ret = VPU_DecOutFrameDisplayed(m_vpuHandle, &m_vpuFrameBuffers[i]); --#ifdef TRACE_FRAMES -- CLog::Log(LOGDEBUG, "- %02d\n", i); --#endif -+ ret = m_outputBuffers[i]->ClearDisplay(&m_vpuHandle); - if(ret != VPU_DEC_RET_SUCCESS) - { - CLog::Log(LOGERROR, "%s: vpu clear frame display failure: ret=%d \r\n",__FUNCTION__,ret); -@@ -855,7 +852,7 @@ bool CDVDVideoCodecIMX::GetPicture(DVDVideoPicture* pDvdVideoPicture) - else - { - CDVDVideoCodecIMXBuffer *buffer = m_outputBuffers[idx]; -- buffer->Queue(&m_vpuFrameBuffers[idx]); -+ buffer->Queue(m_frameInfo.pDisplayFrameBuf); - pDvdVideoPicture->codecinfo = buffer; - - #ifdef TRACE_FRAMES -@@ -903,17 +900,28 @@ CDVDVideoCodecIMXBuffer::CDVDVideoCodecIMXBuffer() - - void CDVDVideoCodecIMXBuffer::Lock() - { -+#ifdef TRACE_FRAMES -+ long count = AtomicIncrement(&m_refs); -+ CLog::Log(LOGDEBUG, "R+ %02d - ref : %d\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\n", m_idx, count); -+#endif - 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. - m_rendered = true; -+#ifdef TRACE_FRAMES -+ CLog::Log(LOGDEBUG, "R %02d\n", m_idx); -+#endif - } - else if (count == 0) - { -@@ -950,6 +958,16 @@ void CDVDVideoCodecIMXBuffer::Queue(VpuFrameBuffer *buffer) - m_rendered = false; - } - -+VpuDecRetCode CDVDVideoCodecIMXBuffer::ClearDisplay(VpuDecHandle *handle) -+{ -+ VpuDecRetCode ret = VPU_DecOutFrameDisplayed(*handle, m_frameBuffer); -+#ifdef TRACE_FRAMES -+ CLog::Log(LOGDEBUG, "- %02d\n", m_idx); -+#endif -+ m_rendered = false; -+ return ret; -+} -+ - CDVDVideoCodecIMXBuffer::~CDVDVideoCodecIMXBuffer() - { - assert(m_refs == 0); -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h -index df568e5..1aef626 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h -@@ -64,6 +64,7 @@ class CDVDVideoCodecIMXBuffer : public CDVDVideoCodecBuffer - void Invalidate(); - bool Rendered(); - void Queue(VpuFrameBuffer *buffer); -+ VpuDecRetCode ClearDisplay(VpuDecHandle *handle); - - protected: - // private because we are reference counted --- -1.9.3 - - -From 219cf2b55e64e99102944e38059348676e2db8bc Mon Sep 17 00:00:00 2001 -From: smallint -Date: Tue, 18 Feb 2014 20:03:46 +0100 -Subject: [PATCH 09/50] Missing initialization and extradata handling backport - from wolfgar - ---- - xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp | 13 +++++++------ - 1 file changed, 7 insertions(+), 6 deletions(-) - -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp -index 75aba7c..f3a7adc 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp -@@ -320,6 +320,7 @@ CDVDVideoCodecIMX::CDVDVideoCodecIMX() - memset(&m_decMemInfo, 0, sizeof(DecMemInfo)); - m_vpuHandle = 0; - m_vpuFrameBuffers = NULL; -+ m_outputBuffers = NULL; - m_extraMem = NULL; - m_vpuFrameBufferNum = 0; - m_tsSyncRequired = true; -@@ -393,14 +394,14 @@ bool CDVDVideoCodecIMX::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options) - case CODEC_ID_H264: - m_decOpenParam.CodecFormat = VPU_V_AVC; - m_pFormatName = "iMX-h264"; -- if (hints.extrasize < 7 || hints.extradata == NULL) -+ if (hints.extradata) - { -- CLog::Log(LOGNOTICE, -- "%s - avcC data too small or missing", __FUNCTION__); -- return false; -+ if ( *(char*)hints.extradata == 1 ) -+ { -+ m_converter = new CBitstreamConverter(); -+ m_convert_bitstream = m_converter->Open(hints.codec, (uint8_t *)hints.extradata, hints.extrasize, true); -+ } - } -- 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; --- -1.9.3 - - -From 83b66029c052489db358e739b1d913b61eff1558 Mon Sep 17 00:00:00 2001 -From: smallint -Date: Tue, 18 Feb 2014 22:38:31 +0100 -Subject: [PATCH 10/50] Added safety check to render texture and moved - invalidation of frames before destroying the VPU handle - ---- - xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp | 3 +++ - xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp | 14 +++++++------- - 2 files changed, 10 insertions(+), 7 deletions(-) - -diff --git a/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp b/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp -index 5e03110..cef2f65 100644 ---- a/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp -+++ b/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp -@@ -1632,6 +1632,9 @@ void CLinuxRendererGLES::RenderIMXMAPTexture(int index, int field) - #endif - - YUVPLANE &plane = m_buffers[index].fields[field][0]; -+ CDVDVideoCodecBuffer* codecinfo = m_buffers[index].codecinfo; -+ -+ if((codecinfo == NULL) || !codecinfo->IsValid()) return; - - glDisable(GL_DEPTH_TEST); - -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp -index f3a7adc..6689261 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp -@@ -475,6 +475,13 @@ void CDVDVideoCodecIMX::Dispose(void) - bool VPU_loaded = m_vpuHandle; - int i; - -+ // Invalidate output buffers to prevent the renderer from mapping this memory -+ for (i=0; iInvalidate(); -+ SAFE_RELEASE(m_outputBuffers[i]); -+ } -+ - if (m_vpuHandle) - { - ret = VPU_DecFlushAll(m_vpuHandle); -@@ -490,13 +497,6 @@ void CDVDVideoCodecIMX::Dispose(void) - m_vpuHandle = 0; - } - -- // Invalidate output buffers to prevent the renderer from mapping this memory -- for (i=0; iInvalidate(); -- SAFE_RELEASE(m_outputBuffers[i]); -- } -- - // Clear memory - if (m_outputBuffers != NULL) - { --- -1.9.3 - - -From 63e8ea582169bead998f39593f75fdb80d75194b Mon Sep 17 00:00:00 2001 -From: smallint -Date: Tue, 18 Feb 2014 23:29:48 +0100 -Subject: [PATCH 11/50] Added Reset of buffers - ---- - xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp | 7 ++++++- - 1 file changed, 6 insertions(+), 1 deletion(-) - -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp -index 6689261..a6de84f 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp -@@ -793,13 +793,17 @@ int CDVDVideoCodecIMX::Decode(BYTE *pData, int iSize, double dts, double pts) - - void CDVDVideoCodecIMX::Reset() - { -- int ret; -+ int ret, i; - - CLog::Log(LOGDEBUG, "%s - called\n", __FUNCTION__); - - /* We have to resync timestamp manager */ - m_tsSyncRequired = true; - -+ /* Invalidate all buffers */ -+ for(int i = 0; i < m_vpuFrameBufferNum; i++) -+ m_outputBuffers[i]->Invalidate(); -+ - /* Flush VPU */ - ret = VPU_DecFlushAll(m_vpuHandle); - if (ret != VPU_DEC_RET_SUCCESS) -@@ -946,6 +950,7 @@ void CDVDVideoCodecIMXBuffer::Invalidate() - { - CSingleLock lock(CDVDVideoCodecIMX::m_codecBufferLock); - m_frameBuffer = NULL; -+ m_rendered = false; - } - - bool CDVDVideoCodecIMXBuffer::Rendered() --- -1.9.3 - - -From c69fa85452212c14af8702af054556c4c99fcdf1 Mon Sep 17 00:00:00 2001 -From: smallint -Date: Wed, 19 Feb 2014 00:29:48 +0100 -Subject: [PATCH 12/50] Fixed lost frames when seeking - ---- - .../dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp | 22 +++++++++++++++++----- - .../dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h | 2 +- - 2 files changed, 18 insertions(+), 6 deletions(-) - -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp -index a6de84f..7e26756 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp -@@ -478,7 +478,7 @@ void CDVDVideoCodecIMX::Dispose(void) - // Invalidate output buffers to prevent the renderer from mapping this memory - for (i=0; iInvalidate(); -+ m_outputBuffers[i]->Invalidate(&m_vpuHandle); - SAFE_RELEASE(m_outputBuffers[i]); - } - -@@ -801,8 +801,8 @@ void CDVDVideoCodecIMX::Reset() - m_tsSyncRequired = true; - - /* Invalidate all buffers */ -- for(int i = 0; i < m_vpuFrameBufferNum; i++) -- m_outputBuffers[i]->Invalidate(); -+ for(i = 0; i < m_vpuFrameBufferNum; i++) -+ m_outputBuffers[i]->Invalidate(&m_vpuHandle); - - /* Flush VPU */ - ret = VPU_DecFlushAll(m_vpuHandle); -@@ -923,7 +923,8 @@ long CDVDVideoCodecIMXBuffer::Release() - { - // 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. -- m_rendered = true; -+ if(m_frameBuffer != NULL) -+ m_rendered = true; - #ifdef TRACE_FRAMES - CLog::Log(LOGDEBUG, "R %02d\n", m_idx); - #endif -@@ -946,9 +947,19 @@ bool CDVDVideoCodecIMXBuffer::IsValid() - return m_frameBuffer != NULL; - } - --void CDVDVideoCodecIMXBuffer::Invalidate() -+void CDVDVideoCodecIMXBuffer::Invalidate(VpuDecHandle *handle) - { - CSingleLock lock(CDVDVideoCodecIMX::m_codecBufferLock); -+#ifdef TRACE_FRAMES -+ CLog::Log(LOGDEBUG, "I %02d\n", m_idx); -+#endif -+ if((m_frameBuffer != NULL) && *handle) -+ { -+ VpuDecRetCode 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); -+ } -+ - m_frameBuffer = NULL; - m_rendered = false; - } -@@ -971,6 +982,7 @@ VpuDecRetCode CDVDVideoCodecIMXBuffer::ClearDisplay(VpuDecHandle *handle) - CLog::Log(LOGDEBUG, "- %02d\n", m_idx); - #endif - m_rendered = false; -+ m_frameBuffer = NULL; - return ret; - } - -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h -index 1aef626..b17e51b 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h -@@ -61,7 +61,7 @@ class CDVDVideoCodecIMXBuffer : public CDVDVideoCodecBuffer - virtual long Release(); - virtual bool IsValid(); - -- void Invalidate(); -+ void Invalidate(VpuDecHandle *handle); - bool Rendered(); - void Queue(VpuFrameBuffer *buffer); - VpuDecRetCode ClearDisplay(VpuDecHandle *handle); --- -1.9.3 - - -From b4650f0c0c1596157f3fb49488c72d1daedba531 Mon Sep 17 00:00:00 2001 -From: wolfgar -Date: Wed, 19 Feb 2014 02:18:24 +0100 -Subject: [PATCH 13/50] Change copyright notice to remove explicit mention of - my name and be compliant with xbmc rules for upstreaming - ---- - xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp | 5 +++-- - 1 file changed, 3 insertions(+), 2 deletions(-) - -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp -index 7e26756..58075bc 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp -@@ -1,5 +1,6 @@ --/* -- * Copyright (C) 2013 Stephan Rafin -+/* -+ * 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 --- -1.9.3 - - -From fc61582dc74af0437c91297e6a00d40480edc476 Mon Sep 17 00:00:00 2001 -From: wolfgar -Date: Wed, 19 Feb 2014 03:19:00 +0100 -Subject: [PATCH 14/50] Fix includes for yocto cross toolchain - ---- - xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp b/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp -index cef2f65..f731beb 100644 ---- a/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp -+++ b/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp -@@ -84,8 +84,8 @@ static PFNGLEGLIMAGETARGETTEXTURE2DOESPROC glEGLImageTargetTexture2DOES; - - #ifdef HAS_IMXVPU - // GLES extension functions --#include --#include -+#include -+#include - #endif - - #if defined(TARGET_ANDROID) --- -1.9.3 - - -From fc7068f886d0bf6774ff72b46e7f75ef8830b0d2 Mon Sep 17 00:00:00 2001 -From: wolfgar -Date: Wed, 19 Feb 2014 03:25:10 +0100 -Subject: [PATCH 15/50] pts simplification (merge latest changes from my imxpts - branch) - ---- - .../dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp | 102 +++++++++------------ - .../dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h | 6 +- - 2 files changed, 48 insertions(+), 60 deletions(-) - -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp -index 58075bc..13be3fc 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp -@@ -30,7 +30,6 @@ - #include "threads/SingleLock.h" - #include "utils/log.h" - #include "DVDClock.h" --#include "mfw_gst_ts.h" - #include "threads/Atomics.h" - - -@@ -199,10 +198,6 @@ bool CDVDVideoCodecIMX::VpuOpen(void) - goto VpuOpenError; - } - -- /* Initialize ts manager */ -- m_tsm = createTSManager(0); -- setTSManagerFrameRate(m_tsm, m_hints.fpsrate, m_hints.fpsscale); -- - return true; - - VpuOpenError: -@@ -326,7 +321,6 @@ CDVDVideoCodecIMX::CDVDVideoCodecIMX() - m_vpuFrameBufferNum = 0; - m_tsSyncRequired = true; - m_dropState = false; -- m_tsm = NULL; - m_convert_bitstream = false; - m_frameCounter = 0; - m_usePTS = true; -@@ -523,12 +517,6 @@ void CDVDVideoCodecIMX::Dispose(void) - } - } - -- if (m_tsm != NULL) -- { -- destroyTSManager(m_tsm); -- m_tsm = NULL; -- } -- - if (m_converter) - { - m_converter->Close(); -@@ -547,7 +535,7 @@ int CDVDVideoCodecIMX::Decode(BYTE *pData, int iSize, double dts, double pts) - int demuxer_bytes = iSize; - uint8_t *demuxer_content = pData; - bool retry = false; -- bool frameConsumed = false; -+ int idx; - - #ifdef IMX_PROFILE - static unsigned long long previous, current; -@@ -671,9 +659,25 @@ int CDVDVideoCodecIMX::Decode(BYTE *pData, int iSize, double dts, double pts) - { - CLog::Log(LOGERROR, "%s - VPU error retireving info about consummed frame (%d).\n", __FUNCTION__, ret); - } -- frameConsumed = true; -- // FIXME TSManagerValid2(m_tsm, frameLengthInfo.nFrameLength + frameLengthInfo.nStuffLength, frameLengthInfo.pFrame); -- //CLog::Log(LOGDEBUG, "%s - size : %d - key consummed : %x\n", __FUNCTION__, frameLengthInfo.nFrameLength + frameLengthInfo.nStuffLength, frameLengthInfo.pFrame); -+ if (frameLengthInfo.pFrame) -+ { -+ idx = VpuFindBuffer(frameLengthInfo.pFrame->pbufY); -+ if (idx != -1) -+ { -+ if (pts != DVD_NOPTS_VALUE) -+ { -+ m_outputBuffers[idx]->SetPts(pts); -+ } -+ else if (dts != DVD_NOPTS_VALUE) -+ { -+ m_outputBuffers[idx]->SetPts(dts); -+ } -+ } -+ else -+ { -+ CLog::Log(LOGERROR, "%s - could not find frame buffer\n", __FUNCTION__); -+ } -+ } - }//VPU_DEC_ONE_FRM_CONSUMED - - if ((decRet & VPU_DEC_OUTPUT_DIS) || -@@ -694,12 +698,10 @@ int CDVDVideoCodecIMX::Decode(BYTE *pData, int iSize, double dts, double pts) - - if (decRet & VPU_DEC_OUTPUT_REPEAT) - { -- TSManagerSend(m_tsm); - CLog::Log(LOGDEBUG, "%s - Frame repeat.\n", __FUNCTION__); - } - if (decRet & VPU_DEC_OUTPUT_DROPPED) - { -- TSManagerSend(m_tsm); - CLog::Log(LOGDEBUG, "%s - Frame dropped.\n", __FUNCTION__); - } - if (decRet & VPU_DEC_NO_ENOUGH_BUF) -@@ -708,7 +710,6 @@ int CDVDVideoCodecIMX::Decode(BYTE *pData, int iSize, double dts, double pts) - } - if (decRet & VPU_DEC_SKIP) - { -- TSManagerSend(m_tsm); - CLog::Log(LOGDEBUG, "%s - Frame skipped.\n", __FUNCTION__); - } - if (decRet & VPU_DEC_FLUSH) -@@ -733,7 +734,6 @@ int CDVDVideoCodecIMX::Decode(BYTE *pData, int iSize, double dts, double pts) - if (!(decRet & VPU_DEC_INPUT_USED)) - { - CLog::Log(LOGERROR, "%s - input not used : addr %p size :%d!\n", __FUNCTION__, inData.pVirAddr, inData.nSize); -- TSManagerSend(m_tsm); - } - - if (!(decRet & VPU_DEC_OUTPUT_DIS) && -@@ -750,34 +750,6 @@ int CDVDVideoCodecIMX::Decode(BYTE *pData, int iSize, double dts, double pts) - } while (retry == true); - } //(pData && iSize) - -- if (frameConsumed) -- { -- if (pts != DVD_NOPTS_VALUE) -- { -- if (m_tsSyncRequired) -- { -- m_tsSyncRequired = false; -- resyncTSManager(m_tsm, llrint(pts) * 1000, MODE_AI); -- } -- //TSManagerReceive2(m_tsm, llrint(pts) * 1000, iSize); -- TSManagerReceive(m_tsm, llrint(pts) * 1000); -- } -- else -- { -- //If no pts but dts available (AVI container for instance) then use this one -- if (dts != DVD_NOPTS_VALUE) -- { -- if (m_tsSyncRequired) -- { -- m_tsSyncRequired = false; -- resyncTSManager(m_tsm, llrint(dts) * 1000, MODE_AI); -- } -- //TSManagerReceive2(m_tsm, llrint(dts) * 1000, iSize); -- TSManagerReceive(m_tsm, llrint(dts) * 1000); -- } -- } -- } -- - if (retStatus == 0) - { - retStatus |= VC_BUFFER; -@@ -838,11 +810,6 @@ bool CDVDVideoCodecIMX::GetPicture(DVDVideoPicture* pDvdVideoPicture) - pDvdVideoPicture->iFlags &= ~DVP_FLAG_DROPPED; - - pDvdVideoPicture->format = RENDER_FMT_IMXMAP; -- pDvdVideoPicture->pts = (double)TSManagerSend(m_tsm) / (double)1000.0; -- if (!m_usePTS) -- { -- pDvdVideoPicture->pts = DVD_NOPTS_VALUE; -- } - 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; -@@ -851,18 +818,20 @@ bool CDVDVideoCodecIMX::GetPicture(DVDVideoPicture* pDvdVideoPicture) - pDvdVideoPicture->iDisplayHeight = pDvdVideoPicture->iHeight; - - int idx = VpuFindBuffer(m_frameInfo.pDisplayFrameBuf->pbufY); -- if (idx == -1) -- { -- CLog::Log(LOGERROR, "%s - could not find frame buffer\n", __FUNCTION__); -- } -- else -+ if (idx != -1) - { - CDVDVideoCodecIMXBuffer *buffer = m_outputBuffers[idx]; -+ pDvdVideoPicture->pts = buffer->GetPts(); -+ if (!m_usePTS) -+ { -+ pDvdVideoPicture->pts = DVD_NOPTS_VALUE; -+ } - buffer->Queue(m_frameInfo.pDisplayFrameBuf); - pDvdVideoPicture->codecinfo = buffer; - - #ifdef TRACE_FRAMES - CLog::Log(LOGDEBUG, "+ %02d\n", idx); -+ CLog::Log(LOGDEBUG, "pts %f\n",pDvdVideoPicture->pts); - #endif - - pDvdVideoPicture->codecinfo->Lock(); -@@ -871,6 +840,10 @@ bool CDVDVideoCodecIMX::GetPicture(DVDVideoPicture* pDvdVideoPicture) - pDvdVideoPicture->codecinfo->data[0] = m_frameInfo.pDisplayFrameBuf->pbufVirtY; - pDvdVideoPicture->codecinfo->data[1] = m_frameInfo.pDisplayFrameBuf->pbufY; - } -+ else -+ { -+ CLog::Log(LOGERROR, "%s - could not find frame buffer\n", __FUNCTION__); -+ } - - return true; - } -@@ -901,6 +874,7 @@ CDVDVideoCodecIMXBuffer::CDVDVideoCodecIMXBuffer() - #endif - , m_frameBuffer(NULL) - , m_rendered(false) -+ , m_pts(DVD_NOPTS_VALUE) - { - } - -@@ -963,6 +937,7 @@ void CDVDVideoCodecIMXBuffer::Invalidate(VpuDecHandle *handle) - - m_frameBuffer = NULL; - m_rendered = false; -+ m_pts = DVD_NOPTS_VALUE; - } - - bool CDVDVideoCodecIMXBuffer::Rendered() -@@ -984,9 +959,20 @@ VpuDecRetCode CDVDVideoCodecIMXBuffer::ClearDisplay(VpuDecHandle *handle) - #endif - m_rendered = false; - m_frameBuffer = NULL; -+ m_pts = DVD_NOPTS_VALUE; - return ret; - } - -+void CDVDVideoCodecIMXBuffer::SetPts(double pts) -+{ -+ m_pts = pts; -+} -+ -+double CDVDVideoCodecIMXBuffer::GetPts(void) const -+{ -+ return m_pts; -+} -+ - CDVDVideoCodecIMXBuffer::~CDVDVideoCodecIMXBuffer() - { - assert(m_refs == 0); -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h -index b17e51b..c4418fe 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h -@@ -29,7 +29,7 @@ - - - //#define IMX_PROFILE --#define TRACE_FRAMES -+//#define TRACE_FRAMES - - /* FIXME TODO Develop real proper CVPUBuffer class */ - #define VPU_DEC_MAX_NUM_MEM_NUM 20 -@@ -65,6 +65,8 @@ class CDVDVideoCodecIMXBuffer : public CDVDVideoCodecBuffer - bool Rendered(); - void Queue(VpuFrameBuffer *buffer); - VpuDecRetCode ClearDisplay(VpuDecHandle *handle); -+ void SetPts(double pts); -+ double GetPts(void) const; - - protected: - // private because we are reference counted -@@ -76,6 +78,7 @@ class CDVDVideoCodecIMXBuffer : public CDVDVideoCodecBuffer - long m_refs; - VpuFrameBuffer *m_frameBuffer; - bool m_rendered; -+ double m_pts; - }; - - class CDVDVideoCodecIMX : public CDVDVideoCodec -@@ -114,7 +117,6 @@ class CDVDVideoCodecIMX : public CDVDVideoCodec - DecMemInfo 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 -- void *m_tsm; // fsl Timestamp manager (from gstreamer implementation) - bool m_tsSyncRequired; // state whether timestamp manager has to be sync'ed - bool m_dropState; // Current drop state - int m_vpuFrameBufferNum; // Total number of allocated frame buffers --- -1.9.3 - - -From a9692ba840f915f6182752db771a79b63e0837ef Mon Sep 17 00:00:00 2001 -From: wolfgar -Date: Wed, 19 Feb 2014 04:08:19 +0100 -Subject: [PATCH 16/50] Remove mfw_gst_ts from build - ---- - xbmc/cores/dvdplayer/DVDCodecs/Video/Makefile.in | 2 +- - xbmc/cores/dvdplayer/DVDCodecs/Video/mfw_gst_ts.c | 752 ---------------------- - xbmc/cores/dvdplayer/DVDCodecs/Video/mfw_gst_ts.h | 170 ----- - 3 files changed, 1 insertion(+), 923 deletions(-) - delete mode 100644 xbmc/cores/dvdplayer/DVDCodecs/Video/mfw_gst_ts.c - delete mode 100644 xbmc/cores/dvdplayer/DVDCodecs/Video/mfw_gst_ts.h - -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/Makefile.in b/xbmc/cores/dvdplayer/DVDCodecs/Video/Makefile.in -index 1df37c6..d019a91 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/Makefile.in -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/Makefile.in -@@ -25,7 +25,7 @@ SRCS += OpenMaxVideo.cpp - SRCS += DVDVideoCodecOpenMax.cpp - endif - ifeq (@USE_IMXVPU@,1) --SRCS += DVDVideoCodecIMX.cpp mfw_gst_ts.c -+SRCS += DVDVideoCodecIMX.cpp - endif - ifeq (@USE_LIBAMCODEC@,1) - SRCS += AMLCodec.cpp -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/mfw_gst_ts.c b/xbmc/cores/dvdplayer/DVDCodecs/Video/mfw_gst_ts.c -deleted file mode 100644 -index 86a8fea..0000000 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/mfw_gst_ts.c -+++ /dev/null -@@ -1,752 +0,0 @@ --/* -- * Copyright (c) 2010-2012, Freescale Semiconductor, Inc. All rights reserved. -- * -- */ -- --/* -- * This library is free software; you can redistribute it and/or -- * modify it under the terms of the GNU Library General Public -- * License as published by the Free Software Foundation; either -- * version 2 of the License, or (at your option) any later version. -- * -- * This library is distributed in the hope that it will be useful, -- * but WITHOUT ANY WARRANTY; without even the implied warranty of -- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -- * Library General Public License for more details. -- * -- * You should have received a copy of the GNU Library General Public -- * License along with this library; if not, write to the -- * Free Software Foundation, Inc., 59 Temple Place - Suite 330, -- * Boston, MA 02111-1307, USA. -- */ -- --/* -- * Module Name: TimeStamp.c -- * -- * Description: include TimeStamp stratege for VPU / SW video decoder plugin -- * -- * Portability: This code is written for Linux OS and Gstreamer -- */ -- --/* -- * Changelog: -- 11/2/2010 draft version Lyon Wang -- * -- */ --#include --#include --#include -- --#include "mfw_gst_ts.h" -- -- --const char *debug_env = "ME_DEBUG"; --char *debug = NULL; --int debug_level = 0; -- -- --enum --{ -- DEBUG_LEVEL_ERROR = 1, -- DEBUG_LEVEL_WARNING, -- DEBUG_LEVEL_LOG, -- DEBUG_LEVEL_VERBOSE, --}; -- -- --#define TSM_MESSAGE(level, fmt, ...)\ -- do{\ -- if (debug_level>=(level)){\ -- printf("TSM:"fmt, ##__VA_ARGS__);\ -- }\ -- }while(0) -- --#define TSM_ERROR(...) TSM_MESSAGE(DEBUG_LEVEL_ERROR, ##__VA_ARGS__) --#define TSM_WARNING(...) TSM_MESSAGE(DEBUG_LEVEL_WARNING, ##__VA_ARGS__) --#define TSM_LOG(...) TSM_MESSAGE(DEBUG_LEVEL_LOG, ##__VA_ARGS__) --#define TSM_VERBOSE(...) TSM_MESSAGE(DEBUG_LEVEL_VERBOSE, ##__VA_ARGS__) -- --#define TSM_HISTORY_POWER 5 --#define TSM_HISTORY_SIZE (1<dur_history_total>>TSM_HISTORY_POWER) -- --#define TSM_SECOND ((TSM_TIMESTAMP)1000000000) --#define TSM_DEFAULT_INTERVAL (TSM_SECOND/30) --#define TSM_DEFAULT_TS_BUFFER_SIZE (128) -- --#define TSM_TS_IS_VALID(ts) \ -- ((ts) != TSM_TIMESTAMP_NONE) -- --#define TSM_KEY_IS_VALID(key) \ -- ((key) != TSM_KEY_NONE) -- --#define TSM_DISTANCE(tsm)\ -- (((tsm->rx)>=(tsm->tx))?((tsm->rx)-(tsm->tx)):(tsm->ts_buf_size-(tsm->tx)+(tsm->rx))) -- --#define TSM_PLUS_AGE(tsm)\ -- (TSM_DISTANCE(tsm)+tsm->invalid_ts_count+2) -- --#define TSM_ABS(ts0, ts1)\ -- (((ts0)>(ts1))?((ts0)-(ts1)):((ts1)-(ts0))) -- --#define TSM_TIME_FORMAT "u:%02u:%02u.%09u" -- --#define TSM_TIME_ARGS(t) \ -- TSM_TS_IS_VALID (t) ? \ -- (unsigned int) (((TSM_TIMESTAMP)(t)) / (TSM_SECOND * 60 * 60)) : 99, \ -- TSM_TS_IS_VALID (t) ? \ -- (unsigned int) ((((TSM_TIMESTAMP)(t)) / (TSM_SECOND * 60)) % 60) : 99, \ -- TSM_TS_IS_VALID (t) ? \ -- (unsigned int) ((((TSM_TIMESTAMP)(t)) / TSM_SECOND) % 60) : 99, \ -- TSM_TS_IS_VALID (t) ? \ -- (unsigned int) (((TSM_TIMESTAMP)(t)) % TSM_SECOND) : 999999999 -- --#define TSM_BUFFER_SET(buf, value, size) \ -- do {\ -- int i;\ -- for (i=0;i<(size);i++){\ -- (buf)[i] = (value);\ -- }\ -- }while(0) -- --#define TSM_RECEIVED_NUNBER 512 -- -- --typedef struct --{ -- TSM_TIMESTAMP ts; -- unsigned long long age; -- void *key; --} TSMControl; -- --typedef struct _TSMReceivedEntry --{ -- TSM_TIMESTAMP ts; -- struct _TSMReceivedEntry *next; -- unsigned int used:1; -- unsigned int subentry:1; -- int size; --} TSMReceivedEntry; -- --typedef struct _TSMReceivedEntryMemory --{ -- struct _TSMReceivedEntryMemory *next; -- TSMReceivedEntry entrys[TSM_RECEIVED_NUNBER]; --} TSMReceivedEntryMemory; -- --typedef struct --{ -- TSMReceivedEntry *head; -- TSMReceivedEntry *tail; -- TSMReceivedEntry *free; -- TSMReceivedEntryMemory *memory; -- int cnt; --} TSMRecivedCtl; -- --typedef struct _TSManager --{ -- int first_tx; -- int first_rx; -- int rx; //timestamps received -- int tx; //timestamps transfered -- TSM_TIMESTAMP last_ts_sent; //last time stamp sent -- TSM_TIMESTAMP last_ts_received; -- TSM_TIMESTAMP suspicious_ts; -- -- TSM_TIMESTAMP discont_threshold; -- -- unsigned int invalid_ts_count; -- TSMGR_MODE mode; -- int ts_buf_size; -- int dur_history_tx; -- TSM_TIMESTAMP dur_history_total; -- TSM_TIMESTAMP dur_history_buf[TSM_HISTORY_SIZE]; -- TSMControl *ts_buf; -- unsigned long long age; -- int tx_cnt; -- int rx_cnt; -- int cnt; -- int valid_ts_received:1; -- int big_cnt; -- -- TSMRecivedCtl rctl; --} TSManager; -- -- --static void --tsm_free_received_entry (TSMRecivedCtl * rctl, TSMReceivedEntry * entry) --{ -- entry->next = rctl->free; -- rctl->free = entry; --} -- -- --static TSMReceivedEntry * --tsm_new_received_entry (TSMRecivedCtl * rctl) --{ -- TSMReceivedEntry *ret = NULL; -- if (rctl->free) { -- ret = rctl->free; -- rctl->free = ret->next; -- } else { -- TSMReceivedEntryMemory *p = malloc (sizeof (TSMReceivedEntryMemory)); -- if (p) { -- int i; -- for (i = 1; i < TSM_RECEIVED_NUNBER; i++) { -- TSMReceivedEntry *e = &p->entrys[i]; -- tsm_free_received_entry (rctl, e); -- }; -- -- p->next = rctl->memory; -- rctl->memory = p; -- -- ret = p->entrys; -- } -- } -- return ret; --} -- -- --void --TSManagerReceive2 (void *handle, TSM_TIMESTAMP timestamp, int size) --{ --#define CLEAR_TSM_RENTRY(entry)\ -- do { \ -- (entry)->used = 0; \ -- (entry)->subentry = 0; \ -- (entry)->next = NULL; \ -- } while (0) -- TSManager *tsm = (TSManager *) handle; -- -- TSM_VERBOSE ("receive2 %" TSM_TIME_FORMAT " size %d\n", -- TSM_TIME_ARGS (timestamp), size); -- -- if (tsm) { -- if (size > 0) { -- TSMRecivedCtl *rctl = &tsm->rctl; -- TSMReceivedEntry *e = tsm_new_received_entry (rctl); -- if (e) { -- CLEAR_TSM_RENTRY (e); -- if ((rctl->tail) && (rctl->tail->ts == timestamp)) { -- e->subentry = 1; -- } -- e->ts = timestamp; -- e->size = size; -- if (rctl->tail) { -- rctl->tail->next = e; -- rctl->tail = e; -- } else { -- rctl->head = rctl->tail = e; -- } -- } -- rctl->cnt++; -- } else { -- TSManagerReceive (handle, timestamp); -- } -- } --} -- -- --static TSM_TIMESTAMP --TSManagerGetLastTimeStamp (TSMRecivedCtl * rctl, int size, int use) --{ -- TSM_TIMESTAMP ts = TSM_TIMESTAMP_NONE; -- TSMReceivedEntry *e; -- while ((size > 0) && (e = rctl->head)) { -- ts = ((e->used) ? (TSM_TIMESTAMP_NONE) : (e->ts)); -- if (use) -- e->used = 1; -- if (size >= e->size) { -- rctl->head = e->next; -- if (rctl->head == NULL) { -- rctl->tail = NULL; -- } else { -- if (rctl->head->subentry) { -- rctl->head->used = e->used; -- } -- } -- size -= e->size; -- rctl->cnt--; -- tsm_free_received_entry (rctl, e); -- } else { -- e->size -= size; -- size = 0; -- } -- } -- return ts; --} -- -- --void --TSManagerFlush2 (void *handle, int size) --{ -- TSManager *tsm = (TSManager *) handle; -- if (tsm) { -- TSManagerGetLastTimeStamp (&tsm->rctl, size, 0); -- } -- --} -- -- --/*====================================================================================== --FUNCTION: mfw_gst_receive_ts -- --DESCRIPTION: Check timestamp and do frame dropping if enabled -- --ARGUMENTS PASSED: pTimeStamp_Object - TimeStamp Manager to handle related timestamp -- timestamp - time stamp of the input buffer which has video data. -- --RETURN VALUE: None --PRE-CONDITIONS: None --POST-CONDITIONS: None --IMPORTANT NOTES: None --=======================================================================================*/ --static void --_TSManagerReceive (void *handle, TSM_TIMESTAMP timestamp, void *key) --{ -- TSManager *tsm = (TSManager *) handle; -- -- if (tsm) { -- if (TSM_TS_IS_VALID (timestamp) && (tsm->rx_cnt)) -- tsm->valid_ts_received = 1; -- tsm->rx_cnt++; -- if (tsm->cnt < tsm->ts_buf_size - 1) { -- tsm->cnt++; -- if (tsm->mode == MODE_AI) { -- -- if (TSM_TS_IS_VALID (timestamp)) { -- if (tsm->first_rx) { -- tsm->last_ts_received = timestamp; -- tsm->first_rx = 0; -- } else { -- if (tsm->suspicious_ts) { -- if (timestamp >= tsm->suspicious_ts) { -- tsm->last_ts_received = timestamp; -- } -- tsm->suspicious_ts = 0; -- } -- if ((timestamp > tsm->last_ts_received) -- && (timestamp - tsm->last_ts_received > tsm->discont_threshold)) { -- tsm->suspicious_ts = timestamp; -- timestamp = TSM_TIMESTAMP_NONE; -- } -- } -- } -- -- if (TSM_TS_IS_VALID (timestamp)) // && (TSM_ABS(timestamp, tsm->last_ts_sent)ts_buf[tsm->rx].ts = timestamp; -- tsm->ts_buf[tsm->rx].age = tsm->age + TSM_PLUS_AGE (tsm); -- tsm->ts_buf[tsm->rx].key = key; -- tsm->last_ts_received = timestamp; --#ifdef DEBUG -- //printf("age should %lld %lld\n", tsm->age, tsm->ts_buf[tsm->rx].age); -- //printf("++++++ distance = %d tx=%d, rx=%d, invalid count=%d\n", TSM_DISTANCE(tsm), tsm->tx, tsm->rx,tsm->invalid_ts_count); --#endif -- tsm->rx = ((tsm->rx + 1) % tsm->ts_buf_size); -- } else { -- tsm->invalid_ts_count++; -- } -- } else if (tsm->mode == MODE_FIFO) { -- tsm->ts_buf[tsm->rx].ts = timestamp; -- tsm->rx = ((tsm->rx + 1) % tsm->ts_buf_size); -- } -- TSM_LOG ("++Receive %d:%" TSM_TIME_FORMAT -- ", invalid:%d, size:%d key %p\n", tsm->rx_cnt, -- TSM_TIME_ARGS (timestamp), tsm->invalid_ts_count, tsm->cnt, key); -- } else { -- TSM_ERROR ("Too many timestamps recieved!! (cnt=%d)\n", tsm->cnt); -- } -- } --} -- -- --void --TSManagerValid2 (void *handle, int size, void *key) --{ -- TSManager *tsm = (TSManager *) handle; -- -- TSM_VERBOSE ("valid2 size %d\n", size); -- -- if (tsm) { -- TSM_TIMESTAMP ts; -- ts = TSManagerGetLastTimeStamp (&tsm->rctl, size, 1); -- _TSManagerReceive (tsm, ts, key); -- } --} -- -- --void --TSManagerReceive (void *handle, TSM_TIMESTAMP timestamp) --{ -- _TSManagerReceive (handle, timestamp, TSM_KEY_NONE); --} -- -- --/*====================================================================================== --FUNCTION: TSManagerSend -- --DESCRIPTION: Check timestamp and do frame dropping if enabled -- --ARGUMENTS PASSED: pTimeStamp_Object - TimeStamp Manager to handle related timestamp -- ptimestamp - returned timestamp to use at render -- --RETURN VALUE: None --PRE-CONDITIONS: None --POST-CONDITIONS: None --IMPORTANT NOTES: None --=======================================================================================*/ --static TSM_TIMESTAMP --_TSManagerSend2 (void *handle, void *key, int send) --{ -- TSManager *tsm = (TSManager *) handle; -- int i = tsm->tx; -- int index = -1; -- TSM_TIMESTAMP ts0 = 0, tstmp = TSM_TIMESTAMP_NONE; -- unsigned long long age = 0; -- TSM_TIMESTAMP half_interval = TSM_ADAPTIVE_INTERVAL (tsm) >> 1; -- -- if (tsm) { -- if (send) { -- tsm->tx_cnt++; -- } else { -- tsm->cnt++; -- tsm->invalid_ts_count++; -- } -- if (tsm->cnt > 0) { -- if (send) { -- tsm->cnt--; -- } -- if (tsm->mode == MODE_AI) { -- -- if (tsm->first_tx == 0) { -- tstmp = tsm->last_ts_sent + TSM_ADAPTIVE_INTERVAL (tsm); -- } else { -- tstmp = tsm->last_ts_sent; -- } -- -- while (i != tsm->rx) { -- if (index >= 0) { -- if (tsm->ts_buf[i].ts < ts0) { -- ts0 = tsm->ts_buf[i].ts; -- age = tsm->ts_buf[i].age; -- index = i; -- } -- } else { -- ts0 = tsm->ts_buf[i].ts; -- age = tsm->ts_buf[i].age; -- index = i; -- } -- if ((TSM_KEY_IS_VALID (key)) && (key == tsm->ts_buf[i].key)) -- break; -- i = ((i + 1) % tsm->ts_buf_size); -- } -- if (index >= 0) { -- if ((tsm->invalid_ts_count) && (ts0 >= ((tstmp) + half_interval)) -- && (age > tsm->age)) { -- /* use calculated ts0 */ -- if (send) { -- tsm->invalid_ts_count--; -- } -- } else { -- -- if (send) { -- if (index != tsm->tx) { -- tsm->ts_buf[index] = tsm->ts_buf[tsm->tx]; -- } -- tsm->tx = ((tsm->tx + 1) % tsm->ts_buf_size); -- -- } --#if 0 -- if (ts0 >= ((tstmp) + half_interval)) -- tstmp = tstmp; -- else -- tstmp = ts0; --#else -- tstmp = ts0; --#endif -- } -- -- } else { -- if (send) { -- tsm->invalid_ts_count--; -- } -- } -- -- if (tsm->first_tx == 0) { -- -- if (tstmp > tsm->last_ts_sent) { -- ts0 = (tstmp - tsm->last_ts_sent); -- } else { -- ts0 = 0; -- tstmp = tsm->last_ts_sent; -- } -- -- if (ts0 > TSM_ADAPTIVE_INTERVAL (tsm) * 3 / 2) { -- TSM_WARNING ("Jitter1:%" TSM_TIME_FORMAT " %" TSM_TIME_FORMAT "\n", -- TSM_TIME_ARGS (ts0), -- TSM_TIME_ARGS (TSM_ADAPTIVE_INTERVAL (tsm) * 3 / 2)); -- } else if (ts0 == 0) { -- TSM_WARNING ("Jitter:%" TSM_TIME_FORMAT "\n", TSM_TIME_ARGS (ts0)); -- } -- -- if (send) { -- if ((ts0 < TSM_ADAPTIVE_INTERVAL (tsm) * 2) || (tsm->big_cnt > 3)) { -- tsm->big_cnt = 0; -- tsm->dur_history_total -= -- tsm->dur_history_buf[tsm->dur_history_tx]; -- tsm->dur_history_buf[tsm->dur_history_tx] = ts0; -- tsm->dur_history_tx = -- ((tsm->dur_history_tx + 1) % TSM_HISTORY_SIZE); -- tsm->dur_history_total += ts0; -- } else { -- tsm->big_cnt++; -- } -- } -- } -- -- if (send) { -- tsm->last_ts_sent = tstmp; -- tsm->age++; -- tsm->first_tx = 0; -- } -- -- } else if (tsm->mode == MODE_FIFO) { -- tstmp = tsm->ts_buf[tsm->tx].ts; -- if (send) { -- tsm->tx = ((tsm->tx + 1) % tsm->ts_buf_size); -- } -- ts0 = tstmp - tsm->last_ts_sent; -- if (send) { -- tsm->last_ts_sent = tstmp; -- } -- } -- -- if (send) { -- TSM_LOG ("--Send %d:%" TSM_TIME_FORMAT ", int:%" TSM_TIME_FORMAT -- ", avg:%" TSM_TIME_FORMAT " inkey %p\n", tsm->tx_cnt, -- TSM_TIME_ARGS (tstmp), TSM_TIME_ARGS (ts0), -- TSM_TIME_ARGS (TSM_ADAPTIVE_INTERVAL (tsm)), key); -- } -- -- } else { -- if (tsm->valid_ts_received == 0) { -- if (tsm->first_tx) { -- tstmp = tsm->last_ts_sent; -- } else { -- tstmp = tsm->last_ts_sent + TSM_ADAPTIVE_INTERVAL (tsm); -- } -- if (send) { -- tsm->first_tx = 0; -- tsm->last_ts_sent = tstmp; -- } -- } -- TSM_ERROR ("Too many timestamps send!!\n"); -- } -- -- if (send == 0) { -- tsm->cnt--; -- tsm->invalid_ts_count--; -- } -- -- } -- -- return tstmp; --} -- -- --TSM_TIMESTAMP --TSManagerSend2 (void *handle, void *key) --{ -- return _TSManagerSend2 (handle, key, 1); --} -- -- --TSM_TIMESTAMP --TSManagerQuery2 (void *handle, void *key) --{ -- return _TSManagerSend2 (handle, key, 0); --} -- -- --TSM_TIMESTAMP --TSManagerSend (void *handle) --{ -- return TSManagerSend2 (handle, TSM_KEY_NONE); --} -- -- --TSM_TIMESTAMP --TSManagerQuery (void *handle) --{ -- return TSManagerQuery2 (handle, TSM_KEY_NONE); --} -- -- --void --resyncTSManager (void *handle, TSM_TIMESTAMP synctime, TSMGR_MODE mode) --{ -- TSManager *tsm = (TSManager *) handle; -- if (tsm) { -- TSMRecivedCtl *rctl = &tsm->rctl; -- TSMReceivedEntry *e = rctl->head; -- -- while ((e = rctl->head)) { -- rctl->head = e->next; -- tsm_free_received_entry (rctl, e); -- }; -- rctl->cnt = 0; -- -- rctl->tail = NULL; -- -- tsm->first_tx = 1; -- tsm->first_rx = 1; -- tsm->suspicious_ts = 0; -- -- if (TSM_TS_IS_VALID (synctime)) -- tsm->last_ts_sent = synctime; -- -- tsm->tx = tsm->rx = 0; -- tsm->invalid_ts_count = 0; -- tsm->mode = mode; -- tsm->age = 0; -- tsm->rx_cnt = tsm->tx_cnt = tsm->cnt = 0; -- tsm->valid_ts_received = 0; -- -- tsm->big_cnt = 0; -- } --} -- -- --/*====================================================================================== --FUNCTION: mfw_gst_init_ts -- --DESCRIPTION: malloc and initialize timestamp strcture -- --ARGUMENTS PASSED: ppTimeStamp_Object - pointer of TimeStamp Manager to handle related timestamp -- --RETURN VALUE: TimeStamp structure pointer --PRE-CONDITIONS: None --POST-CONDITIONS: None --IMPORTANT NOTES: None --=======================================================================================*/ --void * --createTSManager (int ts_buf_size) --{ -- TSManager *tsm = (TSManager *) malloc (sizeof (TSManager)); -- debug = getenv (debug_env); -- if (debug) { -- debug_level = atoi (debug); -- } -- // printf("debug = %s \n ++++++++++++++++++++++++++++",debug); -- if (tsm) { -- memset (tsm, 0, sizeof (TSManager)); -- if (ts_buf_size <= 0) { -- ts_buf_size = TSM_DEFAULT_TS_BUFFER_SIZE; -- } -- tsm->ts_buf_size = ts_buf_size; -- tsm->ts_buf = malloc (sizeof (TSMControl) * ts_buf_size); -- -- if (tsm->ts_buf == NULL) { -- goto fail; -- } -- -- resyncTSManager (tsm, (TSM_TIMESTAMP) 0, MODE_AI); -- -- tsm->dur_history_tx = 0; -- TSM_BUFFER_SET (tsm->dur_history_buf, TSM_DEFAULT_INTERVAL, -- TSM_HISTORY_SIZE); -- tsm->dur_history_total = TSM_DEFAULT_INTERVAL << TSM_HISTORY_POWER; -- -- tsm->discont_threshold = 10000000000LL; // 10s -- } -- return tsm; --fail: -- if (tsm) { -- if (tsm->ts_buf) { -- free (tsm->ts_buf); -- } -- free (tsm); -- tsm = NULL; -- } -- return tsm; --} -- -- --void --destroyTSManager (void *handle) --{ -- TSManager *tsm = (TSManager *) handle; -- if (tsm) { -- TSMRecivedCtl *rctl = &tsm->rctl; -- TSMReceivedEntryMemory *rmem; -- if (tsm->ts_buf) { -- free (tsm->ts_buf); -- } -- -- while ((rmem = rctl->memory)) { -- rctl->memory = rmem->next; -- free (rmem); -- } -- free (tsm); -- tsm = NULL; -- } --} -- -- --void --setTSManagerFrameRate (void *handle, int fps_n, int fps_d) --//void setTSManagerFrameRate(void * handle, float framerate) --{ -- TSManager *tsm = (TSManager *) handle; -- TSM_TIMESTAMP ts; -- if ((fps_n > 0) && (fps_d > 0) && (fps_n / fps_d <= 80)) -- ts = TSM_SECOND * fps_d / fps_n; -- else -- ts = TSM_DEFAULT_INTERVAL; -- // TSM_TIMESTAMP ts = TSM_SECOND / framerate; -- -- if (tsm) { -- TSM_BUFFER_SET (tsm->dur_history_buf, ts, TSM_HISTORY_SIZE); -- tsm->dur_history_total = (ts << TSM_HISTORY_POWER); -- if (debug) -- TSM_LOG ("Set frame intrval:%" TSM_TIME_FORMAT "\n", TSM_TIME_ARGS (ts)); -- } --} -- -- --TSM_TIMESTAMP --getTSManagerFrameInterval (void *handle) --{ -- TSManager *tsm = (TSManager *) handle; -- TSM_TIMESTAMP ts = 0; -- if (tsm) { -- ts = TSM_ADAPTIVE_INTERVAL (tsm); -- } -- return ts; --} -- -- --TSM_TIMESTAMP --getTSManagerPosition (void *handle) --{ -- TSManager *tsm = (TSManager *) handle; -- TSM_TIMESTAMP ts = 0; -- if (tsm) { -- ts = tsm->last_ts_sent; -- } -- return ts; --} -- -- --int --getTSManagerPreBufferCnt (void *handle) --{ -- int i = 0; -- TSManager *tsm = (TSManager *) handle; -- if (tsm) { -- i = tsm->rctl.cnt; -- } -- return i; --} -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/mfw_gst_ts.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/mfw_gst_ts.h -deleted file mode 100644 -index f5d66c4..0000000 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/mfw_gst_ts.h -+++ /dev/null -@@ -1,170 +0,0 @@ --/* -- * Copyright (c) 2010-2012, Freescale Semiconductor, Inc. All rights reserved. -- * -- */ -- --/* -- * This library is free software; you can redistribute it and/or -- * modify it under the terms of the GNU Library General Public -- * License as published by the Free Software Foundation; either -- * version 2 of the License, or (at your option) any later version. -- * -- * This library is distributed in the hope that it will be useful, -- * but WITHOUT ANY WARRANTY; without even the implied warranty of -- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -- * Library General Public License for more details. -- * -- * You should have received a copy of the GNU Library General Public -- * License along with this library; if not, write to the -- * Free Software Foundation, Inc., 59 Temple Place - Suite 330, -- * Boston, MA 02111-1307, USA. -- */ -- --/* -- * Module Name: TimeStamp.h -- * -- * Description: include TimeStamp stratege for VPU / SW video decoder plugin -- * -- * Portability: This code is written for Linux OS and Gstreamer -- */ -- --/* -- * Changelog: -- 11/2/2010 draft version Lyon Wang -- * -- */ -- --#ifndef _TIMESTAMP_H_ --#define _TIMESTAMP_H_ -- -- --/** -- * GST_CLOCK_TIME_NONE: -- * -- * Constant to define an undefined clock time. -- */ -- --typedef long long TSM_TIMESTAMP; -- --typedef enum --{ -- MODE_AI, -- MODE_FIFO, --} TSMGR_MODE; -- --#define TSM_TIMESTAMP_NONE ((long long)(-1)) --#define TSM_KEY_NONE ((void *)0) -- --/** -- * GST_CLOCK_TIME_IS_VALID: -- * @time: clock time to validate -- * -- * Tests if a given #GstClockTime represents a valid defined time. -- */ -- --#ifdef __cplusplus --#define EXTERN --#else --#define EXTERN extern --#endif -- --#ifdef __cplusplus --extern "C" --{ --#endif -- --/*! -- * This function receive timestamp into timestamp manager. -- * -- * @param handle handle of timestamp manager. -- * -- * @param timestamp timestamp received -- * -- * @return -- */ -- EXTERN void TSManagerReceive (void *handle, TSM_TIMESTAMP timestamp); -- -- EXTERN void TSManagerReceive2 (void *handle, TSM_TIMESTAMP timestamp, -- int size); -- -- EXTERN void TSManagerFlush2 (void *handle, int size); -- -- EXTERN void TSManagerValid2 (void *handle, int size, void *key); -- --/*! -- * This function send the timestamp for next output frame. -- * -- * @param handle handle of timestamp manager. -- * -- * @return timestamp for next output frame. -- */ -- EXTERN TSM_TIMESTAMP TSManagerSend (void *handle); -- -- EXTERN TSM_TIMESTAMP TSManagerSend2 (void *handle, void *key); -- -- EXTERN TSM_TIMESTAMP TSManagerQuery2 (void *handle, void *key); -- -- EXTERN TSM_TIMESTAMP TSManagerQuery (void *handle); --/*! -- * This function resync timestamp handler when reset and seek -- * -- * @param handle handle of timestamp manager. -- * -- * @param synctime the postion time needed to set, if value invalid, position keeps original -- * -- * @param mode playing mode (AI or FIFO) -- * -- * @return -- */ -- EXTERN void resyncTSManager (void *handle, TSM_TIMESTAMP synctime, -- TSMGR_MODE mode); --/*! -- * This function create and reset timestamp handler -- * -- * @param ts_buf_size time stamp queue buffer size -- * -- * @return -- */ -- EXTERN void *createTSManager (int ts_buf_size); --/*! -- * This function destory timestamp handler -- * -- * @param handle handle of timestamp manager. -- * -- * @return -- */ -- EXTERN void destroyTSManager (void *handle); --/*! -- * This function set history buffer frame interval by fps_n and fps_d -- * -- * @param handle handle of timestamp manager. -- * -- * @param framerate the framerate to be set -- * -- * @return -- */ -- EXTERN void setTSManagerFrameRate (void *handle, int fps_n, int fps_d); --//EXTERN void setTSManagerFrameRate(void * handle, float framerate); --/*! -- * This function set the current calculated Frame Interval -- * -- * @param handle handle of timestamp manager. -- * -- * @return -- */ -- EXTERN TSM_TIMESTAMP getTSManagerFrameInterval (void *handle); --/*! -- * This function get the current time stamp postion -- * -- * @param handle handle of timestamp manager. -- * -- * @return -- */ -- EXTERN TSM_TIMESTAMP getTSManagerPosition (void *handle); -- EXTERN int getTSManagerPreBufferCnt (void *handle); -- --#ifdef __cplusplus --} --#endif -- --#endif /*_TIMESTAMP_H_ */ --- -1.9.3 - - -From 99fa8a5470edb26a19c820521192ace57f7d5ff2 Mon Sep 17 00:00:00 2001 -From: "Chris \"Koying\" Browet" -Date: Wed, 19 Feb 2014 12:35:40 +0100 -Subject: [PATCH 17/50] FIX: [imx] cosmetics - ---- - .../dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp | 73 ++++++++++------------ - .../dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h | 2 +- - xbmc/windowing/egl/EGLNativeTypeIMX.cpp | 8 +-- - xbmc/windowing/egl/EGLNativeTypeIMX.h | 4 +- - 4 files changed, 39 insertions(+), 48 deletions(-) - mode change 100644 => 100755 xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp - mode change 100644 => 100755 xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h - mode change 100644 => 100755 xbmc/windowing/egl/EGLNativeTypeIMX.cpp - mode change 100644 => 100755 xbmc/windowing/egl/EGLNativeTypeIMX.h - -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp -old mode 100644 -new mode 100755 -index 13be3fc..e7e472b ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp -@@ -97,8 +97,7 @@ bool CDVDVideoCodecIMX::VpuAllocBuffers(VpuMemInfo *pMemBlock) - - int CDVDVideoCodecIMX::VpuFindBuffer(void *frameAddr) - { -- int i; -- for (i=0; i1) - { - ptr=(unsigned char*)Align(ptr,nAlign); - ptrVirt=(unsigned char*)Align(ptrVirt,nAlign); - } - -- /* fill stride info */ -+ // fill stride info - m_vpuFrameBuffers[i].nStrideY=yStride; - m_vpuFrameBuffers[i].nStrideC=uvStride; - -- /* fill phy addr*/ -+ // 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; - //ptr+=ySize+uSize+vSize+mvSize; -- /* fill virt addr */ -+ // fill virt addr - m_vpuFrameBuffers[i].pbufVirtY=ptrVirt; - m_vpuFrameBuffers[i].pbufVirtCb=ptrVirt+ySize; - m_vpuFrameBuffers[i].pbufVirtCr=0; -@@ -363,10 +360,9 @@ bool CDVDVideoCodecIMX::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options) - } - if (m_hints.extrasize) - { -- unsigned int i; - char buf[4096]; - -- for (i = 0; i < m_hints.extrasize; i++) -+ for (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); - } -@@ -429,19 +425,19 @@ bool CDVDVideoCodecIMX::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options) - m_pFormatName = "iMX-vp8"; - break; - case CODEC_ID_MSMPEG4V3: -- m_decOpenParam.CodecFormat = VPU_V_XVID; /* VPU_V_DIVX3 */ -+ m_decOpenParam.CodecFormat = VPU_V_XVID; // VPU_V_DIVX3 - m_pFormatName = "iMX-divx3"; - 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_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_decOpenParam.CodecFormat = VPU_V_XVID; // VPU_V_DIVX56 - m_pFormatName = "iMX-divx5"; - break; - case _4CC('X','V','I','D'): -@@ -468,10 +464,9 @@ void CDVDVideoCodecIMX::Dispose(void) - { - VpuDecRetCode ret; - bool VPU_loaded = m_vpuHandle; -- int i; - - // Invalidate output buffers to prevent the renderer from mapping this memory -- for (i=0; iInvalidate(&m_vpuHandle); - SAFE_RELEASE(m_outputBuffers[i]); -@@ -530,7 +525,7 @@ int CDVDVideoCodecIMX::Decode(BYTE *pData, int iSize, double dts, double pts) - VpuDecFrameLengthInfo frameLengthInfo; - VpuBufferNode inData; - VpuDecRetCode ret; -- int decRet = 0, i; -+ int decRet = 0; - int retStatus = 0; - int demuxer_bytes = iSize; - uint8_t *demuxer_content = pData; -@@ -549,7 +544,7 @@ int CDVDVideoCodecIMX::Decode(BYTE *pData, int iSize, double dts, double pts) - return VC_ERROR; - } - -- for (i=0; i < m_vpuFrameBufferNum; i++) -+ for (int i=0; i < m_vpuFrameBufferNum; i++) - { - if (m_outputBuffers[i]->Rendered()) - { -@@ -589,7 +584,7 @@ int CDVDVideoCodecIMX::Decode(BYTE *pData, int iSize, double dts, double pts) - inData.nSize = demuxer_bytes; - inData.pPhyAddr = NULL; - inData.pVirAddr = demuxer_content; -- /* FIXME TODO VP8 & DivX3 require specific sCodecData values */ -+ // FIXME TODO VP8 & DivX3 require specific sCodecData values - if ((m_decOpenParam.CodecFormat == VPU_V_MPEG2) || - (m_decOpenParam.CodecFormat == VPU_V_VC1_AP)|| - (m_decOpenParam.CodecFormat == VPU_V_XVID)) -@@ -621,7 +616,7 @@ int CDVDVideoCodecIMX::Decode(BYTE *pData, int iSize, double dts, double pts) - } - - if (decRet & VPU_DEC_INIT_OK) -- /* VPU decoding init OK : We can retrieve stream info */ -+ // VPU decoding init OK : We can retrieve stream info - { - ret = VPU_DecGetInitialInfo(m_vpuHandle, &m_initInfo); - if (ret == VPU_DEC_RET_SUCCESS) -@@ -650,7 +645,7 @@ int CDVDVideoCodecIMX::Decode(BYTE *pData, int iSize, double dts, double pts) - CLog::Log(LOGERROR, "%s - VPU get initial info failed (%d).\n", __FUNCTION__, ret); - goto out_error; - } -- }//VPU_DEC_INIT_OK -+ } //VPU_DEC_INIT_OK - - if (decRet & VPU_DEC_ONE_FRM_CONSUMED) - { -@@ -665,24 +660,20 @@ int CDVDVideoCodecIMX::Decode(BYTE *pData, int iSize, double dts, double pts) - if (idx != -1) - { - if (pts != DVD_NOPTS_VALUE) -- { - m_outputBuffers[idx]->SetPts(pts); -- } - else if (dts != DVD_NOPTS_VALUE) -- { - m_outputBuffers[idx]->SetPts(dts); -- } - } - else - { - CLog::Log(LOGERROR, "%s - could not find frame buffer\n", __FUNCTION__); - } - } -- }//VPU_DEC_ONE_FRM_CONSUMED -+ } //VPU_DEC_ONE_FRM_CONSUMED - - if ((decRet & VPU_DEC_OUTPUT_DIS) || - (decRet & VPU_DEC_OUTPUT_MOSAIC_DIS)) -- /* Frame ready to be displayed */ -+ // Frame ready to be displayed - { - if (retStatus & VC_PICTURE) - CLog::Log(LOGERROR, "%s - Second picture in the same decode call !\n", __FUNCTION__); -@@ -739,9 +730,9 @@ int CDVDVideoCodecIMX::Decode(BYTE *pData, int iSize, double dts, double pts) - if (!(decRet & VPU_DEC_OUTPUT_DIS) && - (inData.nSize != 0)) - { -- /* 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 -- */ -+ // 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; - retry = true; -@@ -766,18 +757,18 @@ int CDVDVideoCodecIMX::Decode(BYTE *pData, int iSize, double dts, double pts) - - void CDVDVideoCodecIMX::Reset() - { -- int ret, i; -+ int ret; - - CLog::Log(LOGDEBUG, "%s - called\n", __FUNCTION__); - -- /* We have to resync timestamp manager */ -+ // We have to resync timestamp manager - m_tsSyncRequired = true; - -- /* Invalidate all buffers */ -- for(i = 0; i < m_vpuFrameBufferNum; i++) -+ // Invalidate all buffers -+ for(int i=0; i < m_vpuFrameBufferNum; i++) - m_outputBuffers[i]->Invalidate(&m_vpuHandle); - -- /* Flush VPU */ -+ // Flush VPU - ret = VPU_DecFlushAll(m_vpuHandle); - if (ret != VPU_DEC_RET_SUCCESS) - { -@@ -851,10 +842,10 @@ bool CDVDVideoCodecIMX::GetPicture(DVDVideoPicture* pDvdVideoPicture) - 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 !) -- */ -+ // 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; -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h -old mode 100644 -new mode 100755 -index c4418fe..ac0345f ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h -@@ -31,7 +31,7 @@ - //#define IMX_PROFILE - //#define TRACE_FRAMES - --/* FIXME TODO Develop real proper CVPUBuffer class */ -+// FIXME TODO Develop real proper CVPUBuffer class - #define VPU_DEC_MAX_NUM_MEM_NUM 20 - typedef struct - { -diff --git a/xbmc/windowing/egl/EGLNativeTypeIMX.cpp b/xbmc/windowing/egl/EGLNativeTypeIMX.cpp -old mode 100644 -new mode 100755 -index b44d4b8..bd83877 ---- a/xbmc/windowing/egl/EGLNativeTypeIMX.cpp -+++ b/xbmc/windowing/egl/EGLNativeTypeIMX.cpp -@@ -61,14 +61,14 @@ void CEGLNativeTypeIMX::Initialize() - CLog::Log(LOGERROR, "%s - Error while opening /dev/fb0.\n", __FUNCTION__); - return; - } -- /* Store screen info */ -+ // Store screen info - if (ioctl(fd, FBIOGET_VSCREENINFO, &m_screeninfo) != 0) - { - CLog::Log(LOGERROR, "%s - Error while querying frame buffer.\n", __FUNCTION__); - return; - } - -- /* Unblank the fbs */ -+ // Unblank the fbs - if (ioctl(fd, FBIOBLANK, 0) < 0) - { - CLog::Log(LOGERROR, "%s - Error while unblanking fb0.\n", __FUNCTION__); -@@ -93,7 +93,7 @@ void CEGLNativeTypeIMX::Destroy() - } - - ioctl( fd, FBIOGET_FSCREENINFO, &fixed_info); -- /* Black fb0 */ -+ // Black fb0 - fb_buffer = mmap(NULL, fixed_info.smem_len, PROT_WRITE, MAP_SHARED, fd, 0); - if (fb_buffer == MAP_FAILED) - { -@@ -112,7 +112,7 @@ void CEGLNativeTypeIMX::Destroy() - - bool CEGLNativeTypeIMX::CreateNativeDisplay() - { -- /* EGL will be rendered on fb0 */ -+ // EGL will be rendered on fb0 - m_display = fbGetDisplayByIndex(0); - m_nativeDisplay = &m_display; - return true; -diff --git a/xbmc/windowing/egl/EGLNativeTypeIMX.h b/xbmc/windowing/egl/EGLNativeTypeIMX.h -old mode 100644 -new mode 100755 -index 61d5833..b9162ee ---- a/xbmc/windowing/egl/EGLNativeTypeIMX.h -+++ b/xbmc/windowing/egl/EGLNativeTypeIMX.h -@@ -28,11 +28,11 @@ class CEGLNativeTypeIMX : public CEGLNativeType - public: - CEGLNativeTypeIMX(); - virtual ~CEGLNativeTypeIMX(); -- virtual std::string GetNativeName() const { return "iMX"; }; -+ virtual std::string GetNativeName() const { return "iMX"; } - virtual bool CheckCompatibility(); - virtual void Initialize(); - virtual void Destroy(); -- virtual int GetQuirks() { return EGL_QUIRK_NONE; }; -+ virtual int GetQuirks() { return EGL_QUIRK_NONE; } - - virtual bool CreateNativeDisplay(); - virtual bool CreateNativeWindow(); --- -1.9.3 - - -From c36564c00b617d823bacc08493379a141f455c52 Mon Sep 17 00:00:00 2001 -From: "Chris \"Koying\" Browet" -Date: Wed, 19 Feb 2014 12:41:34 +0100 -Subject: [PATCH 18/50] FIX: [imx] avoid potential segfault - ---- - xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp | 10 ++++------ - 1 file changed, 4 insertions(+), 6 deletions(-) - mode change 100644 => 100755 xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp - -diff --git a/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp b/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp -old mode 100644 -new mode 100755 -index f731beb..4c286f8 ---- a/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp -+++ b/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp -@@ -2725,14 +2725,12 @@ void CLinuxRendererGLES::UploadIMXMAPTexture(int index) - glBindTexture(m_textureTarget, 0); - - plane.flipindex = m_buffers[index].flipindex; -- } -+ plane.texwidth = codecinfo->iWidth; -+ plane.texheight = codecinfo->iHeight; - -- YUVFIELDS &fields = m_buffers[index].fields; -- YUVPLANE &plane = fields[0][0]; -- plane.texwidth = codecinfo->iWidth; -- plane.texheight = codecinfo->iHeight; -+ CalculateTextureSourceRects(index, 1); -+ } - -- CalculateTextureSourceRects(index, 1); - #endif - } - void CLinuxRendererGLES::DeleteIMXMAPTexture(int index) --- -1.9.3 - - -From 4551494f84316b09978fd66eceb5a8742de9dd6c Mon Sep 17 00:00:00 2001 -From: "Chris \"Koying\" Browet" -Date: Wed, 19 Feb 2014 13:00:37 +0100 -Subject: [PATCH 19/50] FIX: [imx] CDVDVideoCodecIMXBuffer optimizations - ---- - .../dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp | 37 ++++++++-------------- - .../dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h | 3 +- - 2 files changed, 15 insertions(+), 25 deletions(-) - -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp -index e7e472b..2b9002a 100755 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp -@@ -468,7 +468,7 @@ void CDVDVideoCodecIMX::Dispose(void) - // Invalidate output buffers to prevent the renderer from mapping this memory - for (int i=0; iInvalidate(&m_vpuHandle); -+ m_outputBuffers[i]->ReleaseFramebuffer(&m_vpuHandle); - SAFE_RELEASE(m_outputBuffers[i]); - } - -@@ -548,7 +548,7 @@ int CDVDVideoCodecIMX::Decode(BYTE *pData, int iSize, double dts, double pts) - { - if (m_outputBuffers[i]->Rendered()) - { -- ret = m_outputBuffers[i]->ClearDisplay(&m_vpuHandle); -+ 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); -@@ -766,7 +766,7 @@ void CDVDVideoCodecIMX::Reset() - - // Invalidate all buffers - for(int i=0; i < m_vpuFrameBufferNum; i++) -- m_outputBuffers[i]->Invalidate(&m_vpuHandle); -+ m_outputBuffers[i]->ReleaseFramebuffer(&m_vpuHandle); - - // Flush VPU - ret = VPU_DecFlushAll(m_vpuHandle); -@@ -913,24 +913,6 @@ bool CDVDVideoCodecIMXBuffer::IsValid() - return m_frameBuffer != NULL; - } - --void CDVDVideoCodecIMXBuffer::Invalidate(VpuDecHandle *handle) --{ -- CSingleLock lock(CDVDVideoCodecIMX::m_codecBufferLock); --#ifdef TRACE_FRAMES -- CLog::Log(LOGDEBUG, "I %02d\n", m_idx); --#endif -- if((m_frameBuffer != NULL) && *handle) -- { -- VpuDecRetCode 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); -- } -- -- m_frameBuffer = NULL; -- m_rendered = false; -- m_pts = DVD_NOPTS_VALUE; --} -- - bool CDVDVideoCodecIMXBuffer::Rendered() - { - return m_rendered; -@@ -938,13 +920,22 @@ bool CDVDVideoCodecIMXBuffer::Rendered() - - void CDVDVideoCodecIMXBuffer::Queue(VpuFrameBuffer *buffer) - { -+ CSingleLock lock(CDVDVideoCodecIMX::m_codecBufferLock); - m_frameBuffer = buffer; - m_rendered = false; - } - --VpuDecRetCode CDVDVideoCodecIMXBuffer::ClearDisplay(VpuDecHandle *handle) -+VpuDecRetCode CDVDVideoCodecIMXBuffer::ReleaseFramebuffer(VpuDecHandle *handle) - { -- VpuDecRetCode ret = VPU_DecOutFrameDisplayed(*handle, m_frameBuffer); -+ CSingleLock lock(CDVDVideoCodecIMX::m_codecBufferLock); -+ 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\n", m_idx); - #endif -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h -index ac0345f..1b9a2b8 100755 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h -@@ -61,10 +61,9 @@ class CDVDVideoCodecIMXBuffer : public CDVDVideoCodecBuffer - virtual long Release(); - virtual bool IsValid(); - -- void Invalidate(VpuDecHandle *handle); - bool Rendered(); - void Queue(VpuFrameBuffer *buffer); -- VpuDecRetCode ClearDisplay(VpuDecHandle *handle); -+ VpuDecRetCode ReleaseFramebuffer(VpuDecHandle *handle); - void SetPts(double pts); - double GetPts(void) const; - --- -1.9.3 - - -From c0d8a8ea4e35080dc0ff9624c36657d9d35c632f Mon Sep 17 00:00:00 2001 -From: smallint -Date: Fri, 21 Feb 2014 07:04:02 +0000 -Subject: [PATCH 20/50] chmod -x - xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp - xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp - xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h - ---- - xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp | 0 - xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp | 0 - xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h | 0 - 3 files changed, 0 insertions(+), 0 deletions(-) - mode change 100755 => 100644 xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp - mode change 100755 => 100644 xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp - mode change 100755 => 100644 xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h - -diff --git a/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp b/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp -old mode 100755 -new mode 100644 -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp -old mode 100755 -new mode 100644 -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h -old mode 100755 -new mode 100644 --- -1.9.3 - - -From e3f2a17d37ae08cae2e2eccc6120e6a5b0e0869c Mon Sep 17 00:00:00 2001 -From: "Chris \"Koying\" Browet" -Date: Thu, 20 Feb 2014 17:42:39 +0100 -Subject: [PATCH 21/50] ADD: [imx] dynamic resolutions / refresh rates - ---- - xbmc/windowing/egl/EGLNativeTypeIMX.cpp | 199 ++++++++++++++++++++++---------- - xbmc/windowing/egl/EGLNativeTypeIMX.h | 14 +-- - 2 files changed, 144 insertions(+), 69 deletions(-) - -diff --git a/xbmc/windowing/egl/EGLNativeTypeIMX.cpp b/xbmc/windowing/egl/EGLNativeTypeIMX.cpp -index bd83877..3e3e45e 100755 ---- a/xbmc/windowing/egl/EGLNativeTypeIMX.cpp -+++ b/xbmc/windowing/egl/EGLNativeTypeIMX.cpp -@@ -27,6 +27,7 @@ - #include - #include - #include "utils/log.h" -+#include "utils/RegExp.h" - #include "utils/StringUtils.h" - #include "guilib/gui3d.h" - -@@ -36,13 +37,12 @@ CEGLNativeTypeIMX::CEGLNativeTypeIMX() - - CEGLNativeTypeIMX::~CEGLNativeTypeIMX() - { --} -+} - - bool CEGLNativeTypeIMX::CheckCompatibility() - { -- char name[256] = {0}; -- get_sysfs_str("/sys/class/graphics/fb0/device/modalias", name, 255); -- CStdString strName = name; -+ std::string strName; -+ get_sysfs_str("/sys/class/graphics/fb0/device/modalias", strName); - StringUtils::Trim(strName); - if (strName == "platform:mxc_sdc_fb") - return true; -@@ -50,32 +50,38 @@ bool CEGLNativeTypeIMX::CheckCompatibility() - } - - void CEGLNativeTypeIMX::Initialize() --{ -- struct mxcfb_gbl_alpha alpha; -+{ - int fd; - -- - fd = open("/dev/fb0",O_RDWR); - if (fd < 0) - { - CLog::Log(LOGERROR, "%s - Error while opening /dev/fb0.\n", __FUNCTION__); - return; - } -- // Store screen info -- if (ioctl(fd, FBIOGET_VSCREENINFO, &m_screeninfo) != 0) -- { -- CLog::Log(LOGERROR, "%s - Error while querying frame buffer.\n", __FUNCTION__); -- return; -- } -- -- // Unblank the fbs -+ -+ // 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; - } - -@@ -90,23 +96,23 @@ void CEGLNativeTypeIMX::Destroy() - { - CLog::Log(LOGERROR, "%s - Error while opening /dev/fb0.\n", __FUNCTION__); - return; -- } -- -- ioctl( fd, FBIOGET_FSCREENINFO, &fixed_info); -+ } -+ -+ 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 -+ else - { - memset(fb_buffer, 0x0, fixed_info.smem_len); - munmap(fb_buffer, fixed_info.smem_len); - } -- -- close(fd); -- -+ -+ close(fd); -+ - return; - } - -@@ -120,15 +126,17 @@ bool CEGLNativeTypeIMX::CreateNativeDisplay() - - bool CEGLNativeTypeIMX::CreateNativeWindow() - { -- m_window = fbCreateWindow(m_display, 0, 0, m_screeninfo.xres, m_screeninfo.yres); -+ m_window = fbCreateWindow(m_display, 0, 0, 0, 0); - m_nativeWindow = &m_window; - return true; --} -+} - - bool CEGLNativeTypeIMX::GetNativeDisplay(XBNativeDisplayType **nativeDisplay) const - { - if (!nativeDisplay) - return false; -+ if (!m_nativeDisplay) -+ return false; - *nativeDisplay = (XBNativeDisplayType*)m_nativeDisplay; - return true; - } -@@ -137,67 +145,76 @@ 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() - { -+ if (m_display) -+ fbDestroyDisplay(m_display); -+ m_display = NULL; - return true; - } - - bool CEGLNativeTypeIMX::DestroyNativeWindow() - { -+ if (m_window) -+ fbDestroyWindow(m_window); -+ m_window = NULL; - return true; - } - - bool CEGLNativeTypeIMX::GetNativeResolution(RESOLUTION_INFO *res) const - { -- double drate = 0, hrate = 0, vrate = 0; -- if (!res) -+ 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; - -- drate = 1e12 / m_screeninfo.pixclock; -- hrate = drate / (m_screeninfo.left_margin + m_screeninfo.xres + m_screeninfo.right_margin + m_screeninfo.hsync_len); -- vrate = hrate / (m_screeninfo.upper_margin + m_screeninfo.yres + m_screeninfo.lower_margin + m_screeninfo.vsync_len); -+ DestroyNativeWindow(); -+ DestroyNativeDisplay(); - -- res->iWidth = m_screeninfo.xres; -- res->iHeight = m_screeninfo.yres; -- res->iScreenWidth = res->iWidth; -- res->iScreenHeight = res->iHeight; -- res->fRefreshRate = lrint(vrate); -- res->dwFlags= D3DPRESENTFLAG_PROGRESSIVE; -- 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" : ""); -+ set_sysfs_str("/sys/class/graphics/fb0/mode", res.strId); - -- return res->iWidth > 0 && res->iHeight> 0; --} -+ CreateNativeDisplay(); - --bool CEGLNativeTypeIMX::SetNativeResolution(const RESOLUTION_INFO &res) --{ -- return false; -+ CLog::Log(LOGDEBUG, "%s: %s",__FUNCTION__, res.strId.c_str()); -+ 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; -+ StringUtils::SplitString(valstr, "\n", probe_str); -+ -+ resolutions.clear(); - RESOLUTION_INFO res; -- bool ret = false; -- ret = GetNativeResolution(&res); -- if (ret && res.iWidth > 1 && res.iHeight > 1) -+ for (size_t i = 0; i < probe_str.size(); i++) - { -- resolutions.push_back(res); -- return true; -+ if(!StringUtils::StartsWith(probe_str[i], "S:")) -+ continue; -+ if(ModeToResolution(probe_str[i], &res)) -+ resolutions.push_back(res); - } -- return false; -+ return resolutions.size() > 0; - } - - bool CEGLNativeTypeIMX::GetPreferredResolution(RESOLUTION_INFO *res) const - { -- return false; -+ return GetNativeResolution(res); - } - - bool CEGLNativeTypeIMX::ShowWindow(bool show) -@@ -206,20 +223,80 @@ bool CEGLNativeTypeIMX::ShowWindow(bool show) - return false; - } - --int CEGLNativeTypeIMX::get_sysfs_str(const char *path, char *valstr, const int size) const -+int CEGLNativeTypeIMX::get_sysfs_str(std::string path, std::string& valstr) const - { -- int fd = open(path, O_RDONLY); -+ int len; -+ char buf[256] = {0}; -+ -+ int fd = open(path.c_str(), O_RDONLY); - if (fd >= 0) - { -- int len = read(fd, valstr, size - 1); -- if (len != -1 ) -- valstr[len] = '\0'; -+ while ((len = read(fd, buf, 255)) > 0) -+ valstr.append(buf, len); - close(fd); - } - else - { -- sprintf(valstr, "%s", "fail"); -+ 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 -index b9162ee..df7b3b7 100755 ---- a/xbmc/windowing/egl/EGLNativeTypeIMX.h -+++ b/xbmc/windowing/egl/EGLNativeTypeIMX.h -@@ -48,15 +48,13 @@ class CEGLNativeTypeIMX : public CEGLNativeType - virtual bool GetPreferredResolution(RESOLUTION_INFO *res) const; - - virtual bool ShowWindow(bool show); -- -- protected: -- int get_sysfs_str(const char *path, char *valstr, const int size) const; -- bool ModeToResolution(const char *mode, RESOLUTION_INFO *res) const; -- -- EGLNativeDisplayType m_display; -- EGLNativeWindowType m_window; - - protected: -- struct fb_var_screeninfo m_screeninfo; -+ 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; - }; --- -1.9.3 - - -From 62d3f035c8ed7a303f13daf766cc40ab3b8f7a28 Mon Sep 17 00:00:00 2001 -From: "Chris \"Koying\" Browet" -Date: Fri, 21 Feb 2014 13:02:34 +0100 -Subject: [PATCH 22/50] Merge pull request #9 - -FIX: [imx] runtime vivante egl extensions ---- - xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp | 18 ++++++++++++------ - 1 file changed, 12 insertions(+), 6 deletions(-) - -diff --git a/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp b/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp -index 4c286f8..1c2fc86 100644 ---- a/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp -+++ b/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp -@@ -26,9 +26,6 @@ - #endif - - #if HAS_GLES == 2 --#ifdef HAS_IMXVPU --#define GL_GLEXT_PROTOTYPES --#endif - #include "system_gl.h" - - #include -@@ -83,9 +80,12 @@ static PFNGLEGLIMAGETARGETTEXTURE2DOESPROC glEGLImageTargetTexture2DOES; - #endif - - #ifdef HAS_IMXVPU --// GLES extension functions --#include --#include -+#include "windowing/egl/EGLWrapper.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) -@@ -163,6 +163,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() --- -1.9.3 - - -From 0f0ed66d8be81510f07a80f9ba7b851f75d96b79 Mon Sep 17 00:00:00 2001 -From: "Chris \"Koying\" Browet" -Date: Mon, 24 Feb 2014 11:18:51 +0100 -Subject: [PATCH 23/50] FIX: cross-complation - ---- - xbmc/cores/VideoRenderers/RenderManager.cpp | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/xbmc/cores/VideoRenderers/RenderManager.cpp b/xbmc/cores/VideoRenderers/RenderManager.cpp -index 653dc52..8b5aee6 100644 ---- a/xbmc/cores/VideoRenderers/RenderManager.cpp -+++ b/xbmc/cores/VideoRenderers/RenderManager.cpp -@@ -932,8 +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_YV12_BUFFER || pic.format == RENDER_FMT_IMXMAP) - m_pRenderer->AddProcessor(pic.codecinfo, index); -+#endif - - m_pRenderer->ReleaseImage(index, false); - --- -1.9.3 - - -From 5a10d02debd4a697424458d0f8c15f835e0418f1 Mon Sep 17 00:00:00 2001 -From: wolfgar -Date: Mon, 24 Feb 2014 22:55:58 +0100 -Subject: [PATCH 24/50] Fix mode (remove x) on EGLNativeTypeIMX.* files - ---- - xbmc/windowing/egl/EGLNativeTypeIMX.cpp | 0 - xbmc/windowing/egl/EGLNativeTypeIMX.h | 0 - 2 files changed, 0 insertions(+), 0 deletions(-) - mode change 100755 => 100644 xbmc/windowing/egl/EGLNativeTypeIMX.cpp - mode change 100755 => 100644 xbmc/windowing/egl/EGLNativeTypeIMX.h - -diff --git a/xbmc/windowing/egl/EGLNativeTypeIMX.cpp b/xbmc/windowing/egl/EGLNativeTypeIMX.cpp -old mode 100755 -new mode 100644 -diff --git a/xbmc/windowing/egl/EGLNativeTypeIMX.h b/xbmc/windowing/egl/EGLNativeTypeIMX.h -old mode 100755 -new mode 100644 --- -1.9.3 - - -From 697afedca97e49d5eae3ec6445f4c1adb31a8a2c Mon Sep 17 00:00:00 2001 -From: "Chris \"Koying\" Browet" -Date: Fri, 21 Feb 2014 16:48:09 +0100 -Subject: [PATCH 25/50] CHG: [imx] force vsync depending on FB_MULTI_BUFFER - value - ---- - xbmc/windowing/egl/EGLNativeTypeIMX.cpp | 12 +++++++++++- - 1 file changed, 11 insertions(+), 1 deletion(-) - -diff --git a/xbmc/windowing/egl/EGLNativeTypeIMX.cpp b/xbmc/windowing/egl/EGLNativeTypeIMX.cpp -index 3e3e45e..3d32705 100644 ---- a/xbmc/windowing/egl/EGLNativeTypeIMX.cpp -+++ b/xbmc/windowing/egl/EGLNativeTypeIMX.cpp -@@ -29,7 +29,9 @@ - #include "utils/log.h" - #include "utils/RegExp.h" - #include "utils/StringUtils.h" -+#include "utils/Environment.h" - #include "guilib/gui3d.h" -+#include "windowing/WindowingFactory.h" - - CEGLNativeTypeIMX::CEGLNativeTypeIMX() - { -@@ -118,6 +120,9 @@ void CEGLNativeTypeIMX::Destroy() - - bool CEGLNativeTypeIMX::CreateNativeDisplay() - { -+ // Force double-buffering -+ CEnvironment::setenv("FB_MULTI_BUFFER", "2", 0); -+ - // EGL will be rendered on fb0 - m_display = fbGetDisplayByIndex(0); - m_nativeDisplay = &m_display; -@@ -219,7 +224,12 @@ bool CEGLNativeTypeIMX::GetPreferredResolution(RESOLUTION_INFO *res) const - - bool CEGLNativeTypeIMX::ShowWindow(bool show) - { -- // CLog::Log(LOGERROR, "%s - call CEGLNativeTypeIMX::ShowWindow with %d.\n", __FUNCTION__, 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; - } - --- -1.9.3 - - -From 7f1781e62459d810d391c60f8062ef05518c7295 Mon Sep 17 00:00:00 2001 -From: smallint -Date: Wed, 26 Feb 2014 18:37:05 +0100 -Subject: [PATCH 26/50] FIX: [imx] drop decoder frames which are returned with - flag VPU_DEC_OUTPUT_MOSAIC_DIS set - ---- - .../dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp | 31 ++++++++++++++++++++-- - 1 file changed, 29 insertions(+), 2 deletions(-) - -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp -index 2b9002a..c85bd8a 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp -@@ -671,8 +671,7 @@ int CDVDVideoCodecIMX::Decode(BYTE *pData, int iSize, double dts, double pts) - } - } //VPU_DEC_ONE_FRM_CONSUMED - -- if ((decRet & VPU_DEC_OUTPUT_DIS) || -- (decRet & VPU_DEC_OUTPUT_MOSAIC_DIS)) -+ if (decRet & VPU_DEC_OUTPUT_DIS) - // Frame ready to be displayed - { - if (retStatus & VC_PICTURE) -@@ -687,6 +686,34 @@ int CDVDVideoCodecIMX::Decode(BYTE *pData, int iSize, double dts, double pts) - 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; -+ } -+ -+ // Release associated pts -+ idx = VpuFindBuffer(m_frameInfo.pDisplayFrameBuf->pbufY); -+ if (idx != -1) -+ m_outputBuffers[idx]->SetPts(DVD_NOPTS_VALUE); -+ else -+ CLog::Log(LOGERROR, "%s - could not find frame buffer\n", __FUNCTION__); -+ -+ // 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__); --- -1.9.3 - - -From c949c1ad3887a80427d8b4bd6f759ff65984165e Mon Sep 17 00:00:00 2001 -From: smallint -Date: Thu, 27 Feb 2014 07:26:21 +0000 -Subject: [PATCH 27/50] FIX: [imx] removed unnecessary block that releases an - associated pts - ---- - xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp | 7 ------- - 1 file changed, 7 deletions(-) - -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp -index c85bd8a..46ddaac 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp -@@ -698,13 +698,6 @@ int CDVDVideoCodecIMX::Decode(BYTE *pData, int iSize, double dts, double pts) - goto out_error; - } - -- // Release associated pts -- idx = VpuFindBuffer(m_frameInfo.pDisplayFrameBuf->pbufY); -- if (idx != -1) -- m_outputBuffers[idx]->SetPts(DVD_NOPTS_VALUE); -- else -- CLog::Log(LOGERROR, "%s - could not find frame buffer\n", __FUNCTION__); -- - // Display frame - ret = VPU_DecOutFrameDisplayed(m_vpuHandle, m_frameInfo.pDisplayFrameBuf); - if(ret != VPU_DEC_RET_SUCCESS) --- -1.9.3 - - -From e93342c198785a88ba915e6dd87ad4c4a6cdc211 Mon Sep 17 00:00:00 2001 -From: "Chris \"koying\" Browet" -Date: Thu, 27 Feb 2014 09:49:49 +0000 -Subject: [PATCH 28/50] FIX: [imx] Do not force resolution if the same as - current - ---- - xbmc/windowing/egl/EGLNativeTypeIMX.cpp | 7 +++++++ - 1 file changed, 7 insertions(+) - -diff --git a/xbmc/windowing/egl/EGLNativeTypeIMX.cpp b/xbmc/windowing/egl/EGLNativeTypeIMX.cpp -index 3d32705..729fe56 100644 ---- a/xbmc/windowing/egl/EGLNativeTypeIMX.cpp -+++ b/xbmc/windowing/egl/EGLNativeTypeIMX.cpp -@@ -34,6 +34,8 @@ - #include "windowing/WindowingFactory.h" - - CEGLNativeTypeIMX::CEGLNativeTypeIMX() -+ : m_display(NULL) -+ , m_window(NULL) - { - } - -@@ -184,6 +186,11 @@ 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(); - --- -1.9.3 - - -From 46fa92730fa659b4bc3aa86f0857ffec4cb7eb65 Mon Sep 17 00:00:00 2001 -From: "Chris \"Koying\" Browet" -Date: Thu, 27 Feb 2014 11:58:31 +0100 -Subject: [PATCH 29/50] FIX: [imx] dynamic allocation of buffer array - ---- - .../dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp | 68 +++++++++++++--------- - .../dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h | 22 ++++--- - 2 files changed, 53 insertions(+), 37 deletions(-) - -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp -index 46ddaac..d0d035a 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp -@@ -48,7 +48,7 @@ CCriticalSection CDVDVideoCodecIMX::m_codecBufferLock; - bool CDVDVideoCodecIMX::VpuAllocBuffers(VpuMemInfo *pMemBlock) - { - int i, size; -- unsigned char * ptr; -+ void* ptr; - VpuMemDesc vpuMem; - VpuDecRetCode ret; - -@@ -57,7 +57,7 @@ bool CDVDVideoCodecIMX::VpuAllocBuffers(VpuMemInfo *pMemBlock) - size = pMemBlock->MemSubBlock[i].nAlignment + pMemBlock->MemSubBlock[i].nSize; - if (pMemBlock->MemSubBlock[i].MemType == VPU_MEM_VIRT) - { // Allocate standard virtual memory -- ptr = (unsigned char *)malloc(size); -+ ptr = malloc(size); - if(ptr == NULL) - { - CLog::Log(LOGERROR, "%s - Unable to malloc %d bytes.\n", __FUNCTION__, size); -@@ -65,8 +65,9 @@ bool CDVDVideoCodecIMX::VpuAllocBuffers(VpuMemInfo *pMemBlock) - } - pMemBlock->MemSubBlock[i].pVirtAddr = (unsigned char*)Align(ptr, pMemBlock->MemSubBlock[i].nAlignment); - -- m_decMemInfo.virtMem[m_decMemInfo.nVirtNum] = (unsigned int)ptr; - 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 -@@ -80,11 +81,12 @@ bool CDVDVideoCodecIMX::VpuAllocBuffers(VpuMemInfo *pMemBlock) - 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.phyMem_phyAddr[m_decMemInfo.nPhyNum] = (unsigned int)vpuMem.nPhyAddr; -- m_decMemInfo.phyMem_virtAddr[m_decMemInfo.nPhyNum] = (unsigned int)vpuMem.nVirtAddr; -- m_decMemInfo.phyMem_cpuAddr[m_decMemInfo.nPhyNum] = (unsigned int)vpuMem.nCpuAddr; -- m_decMemInfo.phyMem_size[m_decMemInfo.nPhyNum] = size; - 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; - } - } - -@@ -111,29 +113,39 @@ bool CDVDVideoCodecIMX::VpuFreeBuffers(void) - VpuDecRetCode vpuRet; - bool ret = true; - -- //free virtual mem -- for(int i=0; i -Date: Sat, 1 Mar 2014 07:52:01 +0100 -Subject: [PATCH 30/50] fix CheckCompatibility for newer kernel - -on newer kernel (3.10.30), - cat /sys/class/graphics/fb0/device/modalias returns "platform:mxc_sdc_fb.28" ---- - xbmc/windowing/egl/EGLNativeTypeIMX.cpp | 4 +++- - 1 file changed, 3 insertions(+), 1 deletion(-) - -diff --git a/xbmc/windowing/egl/EGLNativeTypeIMX.cpp b/xbmc/windowing/egl/EGLNativeTypeIMX.cpp -index 729fe56..65063e9 100644 ---- a/xbmc/windowing/egl/EGLNativeTypeIMX.cpp -+++ b/xbmc/windowing/egl/EGLNativeTypeIMX.cpp -@@ -46,9 +46,11 @@ CEGLNativeTypeIMX::~CEGLNativeTypeIMX() - bool CEGLNativeTypeIMX::CheckCompatibility() - { - std::string strName; -+ std::string str2 ("mxc"); - get_sysfs_str("/sys/class/graphics/fb0/device/modalias", strName); - StringUtils::Trim(strName); -- if (strName == "platform:mxc_sdc_fb") -+ size_t found = strName.find(str2); -+ if (found!=std::string::npos) - return true; - return false; - } --- -1.9.3 - - -From a638454b9612f3c19031bc943e7d6aee1da2471d Mon Sep 17 00:00:00 2001 -From: Chris Browet -Date: Sat, 1 Mar 2014 09:06:02 +0100 -Subject: [PATCH 31/50] fixup: remove obsolete comment - ---- - xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h | 1 - - 1 file changed, 1 deletion(-) - -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h -index 139d918..d71e975 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h -@@ -31,7 +31,6 @@ - //#define IMX_PROFILE - //#define TRACE_FRAMES - --// FIXME TODO Develop real proper CVPUBuffer class - class CDecMemInfo - { - public: --- -1.9.3 - - -From bc1badb6a2cffb688cc2e52bcee2b85b9ae7a760 Mon Sep 17 00:00:00 2001 -From: "Chris \"Koying\" Browet" -Date: Sat, 1 Mar 2014 09:32:24 +0100 -Subject: [PATCH 32/50] FIX: [imx] force mod 16 output frame size - ---- - xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp | 5 +++++ - 1 file changed, 5 insertions(+) - -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp -index d0d035a..8d9a5e6 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp -@@ -695,6 +695,11 @@ int CDVDVideoCodecIMX::Decode(BYTE *pData, int iSize, double dts, double pts) - 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 - --- -1.9.3 - - -From 2ca01100dedb1988d19d94bd1d2b82dd02387f54 Mon Sep 17 00:00:00 2001 -From: smallint -Date: Sat, 1 Mar 2014 10:23:37 +0100 -Subject: [PATCH 33/50] [imx] Add IPU hardware deinterlacing support - ---- - xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp | 3 +- - .../dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp | 457 +++++++++++++++++++-- - .../dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h | 106 ++++- - 3 files changed, 516 insertions(+), 50 deletions(-) - -diff --git a/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp b/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp -index 1c2fc86..980c1a3 100644 ---- a/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp -+++ b/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp -@@ -2724,8 +2724,9 @@ void CLinuxRendererGLES::UploadIMXMAPTexture(int index) - glBindTexture(m_textureTarget, plane.id); - - GLuint physical = ~0U; -+ GLvoid *virt = (GLvoid*)codecinfo->data[0]; - glTexDirectVIVMap(m_textureTarget, codecinfo->iWidth, codecinfo->iHeight, GL_VIV_NV12, -- (GLvoid **)(&codecinfo->data[0]), &physical); -+ (GLvoid **)&virt, &physical); - glTexDirectInvalidateVIV(m_textureTarget); - - glBindTexture(m_textureTarget, 0); -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp -index 8d9a5e6..233e765 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp -@@ -1,4 +1,4 @@ --/* -+/* - * Copyright (C) 2010-2013 Team XBMC - * http://www.xbmc.org - * -@@ -18,15 +18,16 @@ - * - */ - --#include - #include "DVDVideoCodecIMX.h" - --#include - #include -+#include - #include - #include - #include - #include -+#include -+#include - #include "threads/SingleLock.h" - #include "utils/log.h" - #include "DVDClock.h" -@@ -38,11 +39,13 @@ - #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)) --#define min(a, b) (adata[1] -+#define GET_VIRT_ADDR(buf) (buf)->data[0] -+ - // Experiments show that we need at least one more (+1) V4L buffer than the min value returned by the VPU --const int CDVDVideoCodecIMX::m_extraVpuBuffers = IMX_MAX_QUEUE_SIZE + 6; -+const int CDVDVideoCodecIMX::m_extraVpuBuffers = 6; - CCriticalSection CDVDVideoCodecIMX::m_codecBufferLock; - - bool CDVDVideoCodecIMX::VpuAllocBuffers(VpuMemInfo *pMemBlock) -@@ -316,19 +319,37 @@ bool CDVDVideoCodecIMX::VpuAllocFrameBuffers(void) - #endif - } - -+ if (m_initInfo.nInterlace && (m_modeDeinterlace>0)) -+ { -+ if ((m_initInfo.nPicWidth>1024) || (m_initInfo.nPicHeight>1024)) -+ { -+ CLog::Log(LOGNOTICE, "IMX: Disable hardware deinterlacing for HD playback\n"); -+ m_modeDeinterlace = 0; -+ } -+ else -+ { -+ CLog::Log(LOGNOTICE, "IMX: Enable hardware deinterlacing\n"); -+ if (!m_deinterlacer.Init(m_initInfo.nPicWidth, m_initInfo.nPicHeight, GetAllowedReferences()+1, nAlign)) -+ { -+ CLog::Log(LOGWARNING, "IMX: Failed to initialize IPU buffers: deinterlacing disabled\n"); -+ m_modeDeinterlace = 0; -+ } -+ } -+ } -+ else -+ m_modeDeinterlace = 0; -+ - return true; - } - - CDVDVideoCodecIMX::CDVDVideoCodecIMX() - { -- m_vpuHandle = 0; - m_pFormatName = "iMX-xxx"; - m_vpuHandle = 0; - m_vpuFrameBuffers = NULL; - m_outputBuffers = NULL; - m_extraMem = NULL; - m_vpuFrameBufferNum = 0; -- m_tsSyncRequired = true; - m_dropState = false; - m_convert_bitstream = false; - m_frameCounter = 0; -@@ -337,6 +358,10 @@ CDVDVideoCodecIMX::CDVDVideoCodecIMX() - { - m_usePTS = false; - } -+ m_modeDeinterlace = 1; // Default is high motion if requested -+ const char *deintEntry = getenv("IMX_DEINT_MOTION"); -+ if (deintEntry != NULL) -+ m_modeDeinterlace = atoi(deintEntry); - m_converter = NULL; - m_convert_bitstream = false; - } -@@ -499,6 +524,9 @@ void CDVDVideoCodecIMX::Dispose(void) - m_vpuHandle = 0; - } - -+ m_frameCounter = 0; -+ m_deinterlacer.Close(); -+ - // Clear memory - if (m_outputBuffers != NULL) - { -@@ -542,6 +570,7 @@ int CDVDVideoCodecIMX::Decode(BYTE *pData, int iSize, double dts, double pts) - int demuxer_bytes = iSize; - uint8_t *demuxer_content = pData; - bool retry = false; -+ bool frameConsumed = false; - int idx; - - #ifdef IMX_PROFILE -@@ -681,6 +710,7 @@ int CDVDVideoCodecIMX::Decode(BYTE *pData, int iSize, double dts, double pts) - CLog::Log(LOGERROR, "%s - could not find frame buffer\n", __FUNCTION__); - } - } -+ frameConsumed = true; - } //VPU_DEC_ONE_FRM_CONSUMED - - if (decRet & VPU_DEC_OUTPUT_DIS) -@@ -798,13 +828,13 @@ void CDVDVideoCodecIMX::Reset() - - CLog::Log(LOGDEBUG, "%s - called\n", __FUNCTION__); - -- // We have to resync timestamp manager -- m_tsSyncRequired = true; -- - // Invalidate all buffers - for(int i=0; i < m_vpuFrameBufferNum; i++) - m_outputBuffers[i]->ReleaseFramebuffer(&m_vpuHandle); - -+ m_frameCounter = 0; -+ m_deinterlacer.Reset(); -+ - // Flush VPU - ret = VPU_DecFlushAll(m_vpuHandle); - if (ret != VPU_DEC_RET_SUCCESS) -@@ -831,6 +861,7 @@ bool CDVDVideoCodecIMX::ClearPicture(DVDVideoPicture* pDvdVideoPicture) - - bool CDVDVideoCodecIMX::GetPicture(DVDVideoPicture* pDvdVideoPicture) - { -+ m_frameCounter++; - pDvdVideoPicture->iFlags = DVP_FLAG_ALLOCATED; - if (m_dropState) - pDvdVideoPicture->iFlags |= DVP_FLAG_DROPPED; -@@ -849,24 +880,28 @@ bool CDVDVideoCodecIMX::GetPicture(DVDVideoPicture* pDvdVideoPicture) - if (idx != -1) - { - CDVDVideoCodecIMXBuffer *buffer = m_outputBuffers[idx]; -+ CDVDVideoCodecIPUBuffer *ipuBuffer = NULL; -+ - pDvdVideoPicture->pts = buffer->GetPts(); - if (!m_usePTS) - { - pDvdVideoPicture->pts = DVD_NOPTS_VALUE; - } -- buffer->Queue(m_frameInfo.pDisplayFrameBuf); -- pDvdVideoPicture->codecinfo = buffer; -+ -+ buffer->Queue(&m_frameInfo); - - #ifdef TRACE_FRAMES -- CLog::Log(LOGDEBUG, "+ %02d\n", idx); -- CLog::Log(LOGDEBUG, "pts %f\n",pDvdVideoPicture->pts); -+ CLog::Log(LOGDEBUG, "+ %02d pts %f (VPU)\n", idx, pDvdVideoPicture->pts); - #endif - -+ ipuBuffer = m_deinterlacer.Process(buffer, m_frameInfo.eFieldType, m_modeDeinterlace > 1); -+ -+ if (ipuBuffer) -+ pDvdVideoPicture->codecinfo = ipuBuffer; -+ else -+ pDvdVideoPicture->codecinfo = buffer; -+ - pDvdVideoPicture->codecinfo->Lock(); -- pDvdVideoPicture->codecinfo->iWidth = m_frameInfo.pExtInfo->nFrmWidth; -- pDvdVideoPicture->codecinfo->iHeight = m_frameInfo.pExtInfo->nFrmHeight; -- pDvdVideoPicture->codecinfo->data[0] = m_frameInfo.pDisplayFrameBuf->pbufVirtY; -- pDvdVideoPicture->codecinfo->data[1] = m_frameInfo.pDisplayFrameBuf->pbufY; - } - else - { -@@ -910,7 +945,7 @@ void CDVDVideoCodecIMXBuffer::Lock() - { - #ifdef TRACE_FRAMES - long count = AtomicIncrement(&m_refs); -- CLog::Log(LOGDEBUG, "R+ %02d - ref : %d\n", m_idx, count); -+ CLog::Log(LOGDEBUG, "R+ %02d - ref : %d (VPU)\n", m_idx, count); - #else - AtomicIncrement(&m_refs); - #endif -@@ -920,24 +955,22 @@ long CDVDVideoCodecIMXBuffer::Release() - { - long count = AtomicDecrement(&m_refs); - #ifdef TRACE_FRAMES -- CLog::Log(LOGDEBUG, "R- %02d - ref : %d\n", m_idx, count); -+ CLog::Log(LOGDEBUG, "R- %02d - ref : %d (VPU)\n", m_idx, count); - #endif - 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; - #ifdef TRACE_FRAMES -- CLog::Log(LOGDEBUG, "R %02d\n", m_idx); -+ CLog::Log(LOGDEBUG, "R %02d (VPU)\n", m_idx); - #endif -+ } - } - else if (count == 0) - { --#ifdef TRACE_FRAMES -- CLog::Log(LOGDEBUG, "~ %02d\n", m_idx); --#endif -- - delete this; - } - -@@ -950,16 +983,21 @@ bool CDVDVideoCodecIMXBuffer::IsValid() - return m_frameBuffer != NULL; - } - --bool CDVDVideoCodecIMXBuffer::Rendered() -+bool CDVDVideoCodecIMXBuffer::Rendered() const - { - return m_rendered; - } - --void CDVDVideoCodecIMXBuffer::Queue(VpuFrameBuffer *buffer) -+void CDVDVideoCodecIMXBuffer::Queue(VpuDecOutFrameInfo *frameInfo) - { - CSingleLock lock(CDVDVideoCodecIMX::m_codecBufferLock); -- m_frameBuffer = buffer; -+ m_frameBuffer = frameInfo->pDisplayFrameBuf; - m_rendered = false; -+ -+ iWidth = frameInfo->pExtInfo->nFrmWidth; -+ iHeight = frameInfo->pExtInfo->nFrmHeight; -+ GET_VIRT_ADDR(this) = m_frameBuffer->pbufVirtY; -+ GET_PHYS_ADDR(this) = m_frameBuffer->pbufY; - } - - VpuDecRetCode CDVDVideoCodecIMXBuffer::ReleaseFramebuffer(VpuDecHandle *handle) -@@ -974,7 +1012,7 @@ VpuDecRetCode CDVDVideoCodecIMXBuffer::ReleaseFramebuffer(VpuDecHandle *handle) - CLog::Log(LOGERROR, "%s: vpu clear frame display failure: ret=%d \r\n",__FUNCTION__,ret); - } - #ifdef TRACE_FRAMES -- CLog::Log(LOGDEBUG, "- %02d\n", m_idx); -+ CLog::Log(LOGDEBUG, "- %02d (VPU)\n", m_idx); - #endif - m_rendered = false; - m_frameBuffer = NULL; -@@ -995,4 +1033,363 @@ double CDVDVideoCodecIMXBuffer::GetPts(void) const - CDVDVideoCodecIMXBuffer::~CDVDVideoCodecIMXBuffer() - { - assert(m_refs == 0); -+#ifdef TRACE_FRAMES -+ CLog::Log(LOGDEBUG, "~ %02d (VPU)\n", m_idx); -+#endif -+} -+ -+#ifdef TRACE_FRAMES -+CDVDVideoCodecIPUBuffer::CDVDVideoCodecIPUBuffer(int idx) -+ : m_refs(1) -+ , m_idx(idx) -+#else -+CDVDVideoCodecIPUBuffer::CDVDVideoCodecIPUBuffer() -+ : m_refs(1) -+#endif -+ , m_source(NULL) -+ , m_pPhyAddr(NULL) -+ , m_pVirtAddr(NULL) -+ , m_nSize(0) -+{ -+} -+ -+CDVDVideoCodecIPUBuffer::~CDVDVideoCodecIPUBuffer() -+{ -+ assert(m_refs == 0); -+#ifdef TRACE_FRAMES -+ CLog::Log(LOGDEBUG, "~ %02d (IPU)\n", m_idx); -+#endif -+} -+ -+void CDVDVideoCodecIPUBuffer::Lock() -+{ -+#ifdef TRACE_FRAMES -+ long count = AtomicIncrement(&m_refs); -+ CLog::Log(LOGDEBUG, "R+ %02d - ref : %d (IPU)\n", m_idx, count); -+#else -+ AtomicIncrement(&m_refs); -+#endif -+ -+} -+ -+long CDVDVideoCodecIPUBuffer::Release() -+{ -+ long count = AtomicDecrement(&m_refs); -+#ifdef TRACE_FRAMES -+ CLog::Log(LOGDEBUG, "R- %02d - ref : %d (IPU)\n", m_idx, count); -+#endif -+ if (count == 1) -+ { -+ ReleaseFrameBuffer(); -+ } -+ else if (count == 0) -+ { -+ delete this; -+ } -+ -+ return count; -+} -+ -+bool CDVDVideoCodecIPUBuffer::IsValid() -+{ -+ CSingleLock lock(CDVDVideoCodecIMX::m_codecBufferLock); -+ return (m_source != NULL) && m_pPhyAddr; -+} -+ -+bool CDVDVideoCodecIPUBuffer::Process(int fd, CDVDVideoCodecBuffer *currentBuffer, -+ CDVDVideoCodecBuffer *previousBuffer, VpuFieldType fieldType) -+{ -+ struct ipu_task task; -+ memset(&task, 0, sizeof(task)); -+ task.priority = IPU_TASK_PRIORITY_HIGH; -+ -+ SAFE_RELEASE(m_source); -+ -+ iWidth = currentBuffer->iWidth; -+ iHeight = currentBuffer->iHeight; -+ -+ // Input is the VPU decoded frame -+ task.input.width = iWidth; -+ task.input.height = iHeight; -+ task.input.format = IPU_PIX_FMT_NV12; -+ task.input.paddr = (int)GET_PHYS_ADDR(currentBuffer); -+ -+ // Output is our IPU buffer -+ task.output.width = iWidth; -+ task.output.height = iHeight; -+ task.output.format = IPU_PIX_FMT_NV12; -+ task.output.paddr = (int)GET_PHYS_ADDR(this); -+ -+ // Fill previous buffer address -+ if (previousBuffer) -+ task.input.paddr_n = (int)GET_PHYS_ADDR(previousBuffer); -+ -+ task.input.deinterlace.enable = 1; -+ task.input.deinterlace.motion = task.input.paddr_n?LOW_MOTION:HIGH_MOTION; -+ -+ switch (fieldType) -+ { -+ case VPU_FIELD_TOP: -+ task.input.deinterlace.field_fmt = IPU_DEINTERLACE_FIELD_TOP; -+ break; -+ case VPU_FIELD_BOTTOM: -+ task.input.deinterlace.field_fmt = IPU_DEINTERLACE_FIELD_BOTTOM; -+ break; -+ /* -+ case VPU_FIELD_TB: -+ task.input.deinterlace.field_fmt = IPU_DEINTERLACE_FIELD_TOP; -+ break; -+ case VPU_FIELD_BT: -+ task.input.deinterlace.field_fmt = IPU_DEINTERLACE_FIELD_BOTTOM; -+ break; -+ */ -+ default: -+ break; -+ } -+ -+ int ret = ioctl(fd, IPU_QUEUE_TASK, &task); -+ if (ret < 0) -+ { -+ CLog::Log(LOGERROR, "IPU task failed: %s\n", strerror(errno)); -+ return false; -+ } -+ -+ currentBuffer->Lock(); -+ -+ // Remember the source buffer. This is actually not necessary since the output -+ // buffer is the one that is used by the renderer. But keep it bound for now -+ // since this state is used in IsValid which then needs to become a flag in -+ // this class. -+ m_source = currentBuffer; -+ m_source->Lock(); -+ -+ currentBuffer->Release(); -+ -+ return true; -+} -+ -+void CDVDVideoCodecIPUBuffer::ReleaseFrameBuffer() -+{ -+#ifdef TRACE_FRAMES -+ CLog::Log(LOGDEBUG, "- %02d (IPU)\n", m_idx); -+#endif -+ CSingleLock lock(CDVDVideoCodecIMX::m_codecBufferLock); -+ SAFE_RELEASE(m_source); -+} -+ -+bool CDVDVideoCodecIPUBuffer::Allocate(int fd, int width, int height, int nAlign) -+{ -+ uint8_t *phyAddr, *virtAddr; -+ m_iWidth = Align(width,FRAME_ALIGN); -+ m_iHeight = Align(height,(2*FRAME_ALIGN)); -+ // NV12 == 12 bpp -+ m_nSize = m_iWidth*m_iHeight*12/8; -+ m_pPhyAddr = m_nSize; -+ -+ GET_PHYS_ADDR(this) = GET_VIRT_ADDR(this) = NULL; -+ -+ int r = ioctl(fd, IPU_ALLOC, &m_pPhyAddr); -+ if (r < 0) -+ { -+ m_pPhyAddr = 0; -+ CLog::Log(LOGERROR, "ioctl IPU_ALLOC fail: disable deinterlacing: %s\n", strerror(errno)); -+ return false; -+ } -+ -+ CLog::Log(LOGNOTICE, "IPU: alloc %d bytes for frame of %dx%d at 0x%x\n", -+ m_nSize, m_iWidth, m_iHeight, m_pPhyAddr); -+ -+ m_pVirtAddr = (uint8_t*)mmap(0, m_nSize, PROT_READ | PROT_WRITE, MAP_SHARED, -+ fd, m_pPhyAddr); -+ if (!m_pVirtAddr) -+ { -+ CLog::Log(LOGERROR, "IPU mmap failed: disable deinterlacing: %s\n", strerror(errno)); -+ return false; -+ } -+ -+ if (nAlign>1) -+ { -+ GET_PHYS_ADDR(this) = (uint8_t*)Align(m_pPhyAddr, nAlign); -+ GET_VIRT_ADDR(this) = (uint8_t*)Align(m_pVirtAddr, nAlign); -+ } -+ else -+ { -+ GET_PHYS_ADDR(this) = (uint8_t*)m_pPhyAddr; -+ GET_VIRT_ADDR(this) = (uint8_t*)m_pVirtAddr; -+ } -+ -+ return true; -+} -+ -+bool CDVDVideoCodecIPUBuffer::Free(int fd) -+{ -+ CSingleLock lock(CDVDVideoCodecIMX::m_codecBufferLock); -+ bool ret = true; -+ -+ // Unmap virtual memory -+ if (m_pVirtAddr != NULL) -+ { -+ if(munmap(m_pVirtAddr, m_nSize)) -+ { -+ CLog::Log(LOGERROR, "IPU unmap failed: %s\n", strerror(errno)); -+ ret = false; -+ } -+ -+ m_pVirtAddr = NULL; -+ } -+ -+ // Free IPU memory -+ if (m_pPhyAddr) -+ { -+ if (ioctl(fd, IPU_FREE, &m_pPhyAddr)) -+ { -+ CLog::Log(LOGERROR, "IPU free buffer 0x%x failed: %s\n", -+ m_pPhyAddr, strerror(errno)); -+ ret = false; -+ } -+ -+ m_pPhyAddr = 0; -+ } -+ -+ GET_PHYS_ADDR(this) = GET_VIRT_ADDR(this) = NULL; -+ SAFE_RELEASE(m_source); -+ -+ return ret; -+} -+ -+CDVDVideoCodecIPUBuffers::CDVDVideoCodecIPUBuffers() -+ : m_ipuHandle(0) -+ , m_bufferNum(0) -+ , m_buffers(NULL) -+ , m_lastBuffer(NULL) -+{ -+} -+ -+CDVDVideoCodecIPUBuffers::~CDVDVideoCodecIPUBuffers() -+{ -+ Close(); -+} -+ -+bool CDVDVideoCodecIPUBuffers::Init(int width, int height, int numBuffers, int nAlign) -+{ -+ if (numBuffers<=0) -+ { -+ CLog::Log(LOGERROR, "IPU Init: invalid number of buffers: %d\n", numBuffers); -+ return false; -+ } -+ -+ m_ipuHandle = open("/dev/mxc_ipu", O_RDWR, 0); -+ if (m_ipuHandle<=0) -+ { -+ CLog::Log(LOGWARNING, "Failed to initialize IPU: deinterlacing disabled: %s\n", -+ strerror(errno)); -+ m_ipuHandle = 0; -+ return false; -+ } -+ -+ m_bufferNum = numBuffers; -+ m_buffers = new CDVDVideoCodecIPUBuffer*[m_bufferNum]; -+ -+ for (int i=0; i < m_bufferNum; i++ ) -+ { -+#ifdef TRACE_FRAMES -+ m_buffers[i] = new CDVDVideoCodecIPUBuffer(i); -+#else -+ m_buffers[i] = new CDVDVideoCodecIPUBuffer; -+#endif -+ if (!m_buffers[i]->Allocate(m_ipuHandle, width, height, nAlign)) -+ { -+ Close(); -+ return false; -+ } -+ } -+ -+ return true; -+} -+ -+bool CDVDVideoCodecIPUBuffers::Reset() -+{ -+ SAFE_RELEASE(m_lastBuffer); -+ for (int i=0; i < m_bufferNum; i++) -+ m_buffers[i]->ReleaseFrameBuffer(); -+} -+ -+bool CDVDVideoCodecIPUBuffers::Close() -+{ -+ bool ret = true; -+ -+ if (m_ipuHandle) -+ { -+ for (int i=0; i < m_bufferNum; i++) -+ { -+ if (m_buffers[i] == NULL ) continue; -+ if (!m_buffers[i]->Free(m_ipuHandle)) -+ ret = false; -+ } -+ -+ // Close IPU device -+ if (close(m_ipuHandle)) -+ { -+ CLog::Log(LOGERROR, "IPU failed to close interface: %s\n", strerror(errno)); -+ ret = false; -+ } -+ -+ m_ipuHandle = 0; -+ } -+ -+ if (m_buffers) -+ { -+ for (int i=0; i < m_bufferNum; i++) -+ SAFE_RELEASE(m_buffers[i]); -+ -+ delete m_buffers; -+ m_buffers = NULL; -+ } -+ -+ m_bufferNum = 0; -+ SAFE_RELEASE(m_lastBuffer); -+ return true; -+} -+ -+CDVDVideoCodecIPUBuffer * -+CDVDVideoCodecIPUBuffers::Process(CDVDVideoCodecBuffer *sourceBuffer, -+ VpuFieldType fieldType, bool lowMotion) -+{ -+ CDVDVideoCodecIPUBuffer *target = NULL; -+ bool ret = true; -+ -+ if (!m_bufferNum || (fieldType==VPU_FIELD_NONE)) return NULL; -+ -+ for (int i=0; i < m_bufferNum; i++ ) -+ { -+ if (!m_buffers[i]->Rendered()) continue; -+ -+ // IPU process: -+ // SRC: Current VPU physical buffer address + last VPU buffer address -+ // DST: IPU buffer[i] -+ CDVDVideoCodecBuffer *last = lowMotion?m_lastBuffer:NULL; -+ ret = m_buffers[i]->Process(m_ipuHandle, sourceBuffer, last, fieldType); -+ if (ret) -+ { -+#ifdef TRACE_FRAMES -+ CLog::Log(LOGDEBUG, "+ %02d (IPU)\n", i); -+#endif -+ target = m_buffers[i]; -+ } -+ break; -+ } -+ -+ // Buffers are there but there is no free one, this is an error! -+ // Rendering will continue with unprocessed frames ... -+ if (ret && target==NULL) -+ { -+ CLog::Log(LOGERROR, "Deinterlacing: did not find free buffer, forward unprocessed frame\n"); -+ } -+ -+ SAFE_RELEASE(m_lastBuffer); -+ m_lastBuffer = sourceBuffer; -+ if (m_lastBuffer != NULL) -+ m_lastBuffer->Lock(); -+ -+ return target; - } -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h -index d71e975..71a0d39 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h -@@ -19,7 +19,6 @@ - * - */ - #include --#include - #include - #include "DVDVideoCodec.h" - #include "DVDStreamInfo.h" -@@ -50,6 +49,8 @@ class CDecMemInfo - VpuMemDesc* phyMem; - }; - -+class CDVDVideoCodecIPUBuffer; -+ - class CDVDVideoCodecIMXBuffer : public CDVDVideoCodecBuffer - { - public: -@@ -60,32 +61,98 @@ class CDVDVideoCodecIMXBuffer : public CDVDVideoCodecBuffer - #endif - - // reference counting -- virtual void Lock(); -- virtual long Release(); -- virtual bool IsValid(); -+ virtual void Lock(); -+ virtual long Release(); -+ virtual bool IsValid(); - -- bool Rendered(); -- void Queue(VpuFrameBuffer *buffer); -- VpuDecRetCode ReleaseFramebuffer(VpuDecHandle *handle); -- void SetPts(double pts); -- double GetPts(void) const; -+ bool Rendered() const; -+ void Queue(VpuDecOutFrameInfo *frameInfo); -+ VpuDecRetCode ReleaseFramebuffer(VpuDecHandle *handle); -+ void SetPts(double pts); -+ double GetPts(void) const; - - protected: - // private because we are reference counted -- virtual ~CDVDVideoCodecIMXBuffer(); -+ virtual ~CDVDVideoCodecIMXBuffer(); -+ -+#ifdef TRACE_FRAMES -+ int m_idx; -+#endif -+ long m_refs; -+ VpuFrameBuffer *m_frameBuffer; -+ bool m_rendered; -+ double m_pts; -+}; -+ -+// Shared buffer that holds an IPU allocated memory block and serves as target -+// for IPU operations such as deinterlacing, rotation or color conversion. -+class CDVDVideoCodecIPUBuffer : public CDVDVideoCodecBuffer -+{ -+public: -+#ifdef TRACE_FRAMES -+ CDVDVideoCodecIPUBuffer(int idx); -+#else -+ CDVDVideoCodecIPUBuffer(); -+#endif -+ -+ // reference counting -+ virtual void Lock(); -+ virtual long Release(); -+ virtual bool IsValid(); -+ -+ // Returns whether the buffer is ready to be used -+ bool Rendered() const { return m_source == NULL; } -+ bool Process(int fd, CDVDVideoCodecBuffer *currentBuffer, -+ CDVDVideoCodecBuffer *previousBuffer, VpuFieldType fieldType); -+ void ReleaseFrameBuffer(); -+ -+ bool Allocate(int fd, int width, int height, int nAlign); -+ bool Free(int fd); - -+private: -+ virtual ~CDVDVideoCodecIPUBuffer(); -+ -+private: - #ifdef TRACE_FRAMES -- int m_idx; -+ int m_idx; - #endif -- long m_refs; -- VpuFrameBuffer *m_frameBuffer; -- bool m_rendered; -- double m_pts; -+ long m_refs; -+ CDVDVideoCodecBuffer *m_source; -+ int m_pPhyAddr; -+ uint8_t *m_pVirtAddr; -+ int m_iWidth; -+ int m_iHeight; -+ int m_nSize; - }; - -+// Collection class that manages a pool of IPU buffers that are used for -+// deinterlacing. In future they can also serve rotation or color conversion -+// buffers. -+class CDVDVideoCodecIPUBuffers -+{ -+ public: -+ CDVDVideoCodecIPUBuffers(); -+ ~CDVDVideoCodecIPUBuffers(); -+ -+ bool Init(int width, int height, int numBuffers, int nAlign); -+ bool Reset(); -+ bool Close(); -+ -+ CDVDVideoCodecIPUBuffer *Process(CDVDVideoCodecBuffer *sourceBuffer, -+ VpuFieldType fieldType, bool lowMotion); -+ -+ private: -+ int m_ipuHandle; -+ int m_bufferNum; -+ CDVDVideoCodecIPUBuffer **m_buffers; -+ CDVDVideoCodecBuffer *m_lastBuffer; -+}; -+ -+ - class CDVDVideoCodecIMX : public CDVDVideoCodec - { - friend class CDVDVideoCodecIMXBuffer; -+ friend class CDVDVideoCodecIPUBuffer; - - public: - CDVDVideoCodecIMX(); -@@ -104,10 +171,10 @@ class CDVDVideoCodecIMX : public CDVDVideoCodec - - protected: - -- bool VpuOpen(void); -+ bool VpuOpen(); - bool VpuAllocBuffers(VpuMemInfo *); -- bool VpuFreeBuffers(void); -- bool VpuAllocFrameBuffers(void); -+ bool VpuFreeBuffers(); -+ bool VpuAllocFrameBuffers(); - int VpuFindBuffer(void *frameAddr); - - static const int m_extraVpuBuffers; // Number of additional buffers for VPU -@@ -119,15 +186,16 @@ class CDVDVideoCodecIMX : public CDVDVideoCodec - 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_tsSyncRequired; // state whether timestamp manager has to be sync'ed - bool m_dropState; // Current drop state - int m_vpuFrameBufferNum; // Total number of allocated frame buffers - VpuFrameBuffer *m_vpuFrameBuffers; // Table of VPU frame buffers description -+ CDVDVideoCodecIPUBuffers m_deinterlacer; - CDVDVideoCodecIMXBuffer **m_outputBuffers; - VpuMemDesc *m_extraMem; // Table of allocated extra Memory - // VpuMemDesc *m_outputBuffers; // Table of buffers out of VPU (used to call properly VPU_DecOutFrameDisplayed) - int m_frameCounter; // Decoded frames counter - bool m_usePTS; // State whether pts out of decoding process should be used -+ int m_modeDeinterlace; // Deinterlacer mode: 0=off, 1=high, 2..=low - VpuDecOutFrameInfo m_frameInfo; - CBitstreamConverter *m_converter; - bool m_convert_bitstream; --- -1.9.3 - - -From 53e42f3dd2fe3a5fbc0c02027a452b844fa455f5 Mon Sep 17 00:00:00 2001 -From: tomlohave -Date: Sun, 2 Mar 2014 17:26:30 +0100 -Subject: [PATCH 34/50] fix CheckCompatibility for newer kernel (try2) - -Use "mxc_sdc_fb" instead of "mxc" as requested by Chris ---- - xbmc/windowing/egl/EGLNativeTypeIMX.cpp | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/xbmc/windowing/egl/EGLNativeTypeIMX.cpp b/xbmc/windowing/egl/EGLNativeTypeIMX.cpp -index 65063e9..91e223f 100644 ---- a/xbmc/windowing/egl/EGLNativeTypeIMX.cpp -+++ b/xbmc/windowing/egl/EGLNativeTypeIMX.cpp -@@ -46,7 +46,7 @@ CEGLNativeTypeIMX::~CEGLNativeTypeIMX() - bool CEGLNativeTypeIMX::CheckCompatibility() - { - std::string strName; -- std::string str2 ("mxc"); -+ std::string str2 ("mxc_sdc_fb"); - get_sysfs_str("/sys/class/graphics/fb0/device/modalias", strName); - StringUtils::Trim(strName); - size_t found = strName.find(str2); --- -1.9.3 - - -From a8d428bc497703232a089c85ec0b284e9bff6ee1 Mon Sep 17 00:00:00 2001 -From: wolfgar -Date: Sun, 2 Mar 2014 03:05:46 +0100 -Subject: [PATCH 35/50] Properly track pts in case the associated frame is - consumed at next ::Decode call - ---- - .../dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp | 40 +++++++++++++++++----- - .../dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h | 2 ++ - 2 files changed, 34 insertions(+), 8 deletions(-) - -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp -index 233e765..26ba552 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp -@@ -364,6 +364,8 @@ CDVDVideoCodecIMX::CDVDVideoCodecIMX() - m_modeDeinterlace = atoi(deintEntry); - m_converter = NULL; - m_convert_bitstream = false; -+ m_bytesToBeConsumed = 0; -+ m_previousPts = DVD_NOPTS_VALUE; - } - - CDVDVideoCodecIMX::~CDVDVideoCodecIMX() -@@ -608,9 +610,10 @@ int CDVDVideoCodecIMX::Decode(BYTE *pData, int iSize, double dts, double pts) - ((unsigned int *)pData)[0] = htonl(iSize-4); - */ - -- if (pData && iSize) -+ if ((pData && iSize) || -+ (m_bytesToBeConsumed)) - { -- if (m_convert_bitstream) -+ if ((m_convert_bitstream) && (iSize)) - { - // convert demuxer packet from bitstream to bytestream (AnnexB) - if (m_converter->Convert(demuxer_content, demuxer_bytes)) -@@ -645,6 +648,7 @@ int CDVDVideoCodecIMX::Decode(BYTE *pData, int iSize, double dts, double pts) - #ifdef IMX_PROFILE - before_dec = XbmcThreads::SystemClockMillis(); - #endif -+ 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); -@@ -695,20 +699,24 @@ int CDVDVideoCodecIMX::Decode(BYTE *pData, int iSize, double dts, double pts) - { - 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 (pts != DVD_NOPTS_VALUE) -+ if (m_previousPts != DVD_NOPTS_VALUE) -+ { -+ m_outputBuffers[idx]->SetPts(m_previousPts); -+ m_previousPts = DVD_NOPTS_VALUE; -+ } -+ else - m_outputBuffers[idx]->SetPts(pts); -- else if (dts != DVD_NOPTS_VALUE) -- m_outputBuffers[idx]->SetPts(dts); - } - else -- { - CLog::Log(LOGERROR, "%s - could not find frame buffer\n", __FUNCTION__); -- } - } - frameConsumed = true; - } //VPU_DEC_ONE_FRM_CONSUMED -@@ -804,7 +812,6 @@ int CDVDVideoCodecIMX::Decode(BYTE *pData, int iSize, double dts, double pts) - inData.nSize = 0; - retry = true; - } -- - } while (retry == true); - } //(pData && iSize) - -@@ -813,6 +820,21 @@ int CDVDVideoCodecIMX::Decode(BYTE *pData, int iSize, double dts, double pts) - 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; -+ if (retStatus & VC_PICTURE) -+ // If a picture was produced and some data are still to -+ // be consumed, do not ask for additional buffer as -+ // we likely already have enough data to produce a -+ // new output frame at next call -+ retStatus &= (~VC_BUFFER); -+ } -+ - #ifdef IMX_PROFILE - CLog::Log(LOGDEBUG, "%s - returns %x - duration %lld\n", __FUNCTION__, retStatus, XbmcThreads::SystemClockMillis() - previous); - #endif -@@ -834,6 +856,8 @@ void CDVDVideoCodecIMX::Reset() - - m_frameCounter = 0; - m_deinterlacer.Reset(); -+ m_bytesToBeConsumed = 0; -+ m_previousPts = DVD_NOPTS_VALUE; - - // Flush VPU - ret = VPU_DecFlushAll(m_vpuHandle); -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h -index 71a0d39..1cfb2a4 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h -@@ -199,4 +199,6 @@ class CDVDVideoCodecIMX : public CDVDVideoCodec - VpuDecOutFrameInfo m_frameInfo; - CBitstreamConverter *m_converter; - bool m_convert_bitstream; -+ int m_bytesToBeConsumed; // Remaining bytes in VPU -+ double m_previousPts; // Enable to keep pts when needed - }; --- -1.9.3 - - -From 0d61cd9f8cff6351cabcc4bf2f1f9d20207c4d73 Mon Sep 17 00:00:00 2001 -From: "Chris \"Koying\" Browet" -Date: Fri, 28 Feb 2014 12:48:26 +0100 -Subject: [PATCH 36/50] [imx] attempt to recover audio from resolution change - ---- - xbmc/windowing/egl/EGLNativeTypeIMX.cpp | 5 +++++ - 1 file changed, 5 insertions(+) - -diff --git a/xbmc/windowing/egl/EGLNativeTypeIMX.cpp b/xbmc/windowing/egl/EGLNativeTypeIMX.cpp -index 91e223f..4ffa708 100644 ---- a/xbmc/windowing/egl/EGLNativeTypeIMX.cpp -+++ b/xbmc/windowing/egl/EGLNativeTypeIMX.cpp -@@ -32,6 +32,7 @@ - #include "utils/Environment.h" - #include "guilib/gui3d.h" - #include "windowing/WindowingFactory.h" -+#include "cores/AudioEngine/AEFactory.h" - - CEGLNativeTypeIMX::CEGLNativeTypeIMX() - : m_display(NULL) -@@ -201,6 +202,10 @@ bool CEGLNativeTypeIMX::SetNativeResolution(const RESOLUTION_INFO &res) - CreateNativeDisplay(); - - CLog::Log(LOGDEBUG, "%s: %s",__FUNCTION__, res.strId.c_str()); -+ -+ // Reset AE -+ CAEFactory::DeviceChange(); -+ - return true; - } - --- -1.9.3 - - -From 56e81c54c84b4f7992ed932d224d23fe7e95d0bd Mon Sep 17 00:00:00 2001 -From: "Chris \"koying\" Browet" -Date: Fri, 28 Feb 2014 19:12:16 +0000 -Subject: [PATCH 37/50] [imx] A VPU_DEC_FLUSH should amount to a Reset() - ---- - xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp | 6 +----- - 1 file changed, 1 insertion(+), 5 deletions(-) - -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp -index 26ba552..44bfe34 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp -@@ -781,11 +781,7 @@ int CDVDVideoCodecIMX::Decode(BYTE *pData, int iSize, double dts, double pts) - if (decRet & VPU_DEC_FLUSH) - { - CLog::Log(LOGNOTICE, "%s - VPU requires a flush.\n", __FUNCTION__); -- ret = VPU_DecFlushAll(m_vpuHandle); -- if (ret != VPU_DEC_RET_SUCCESS) -- { -- CLog::Log(LOGERROR, "%s - VPU flush failed(%d).\n", __FUNCTION__, ret); -- } -+ Reset(); - retStatus = VC_FLUSHED; - } - if (decRet & VPU_DEC_OUTPUT_EOS) --- -1.9.3 - - -From 4fc825be17c2258265581b1055dff94c8249f35d Mon Sep 17 00:00:00 2001 -From: "Chris \"Koying\" Browet" -Date: Tue, 4 Mar 2014 12:48:32 +0100 -Subject: [PATCH 38/50] CHG: [imx] decouple compile options for vpu & fb - ---- - configure.in | 9 +++++++++ - xbmc/windowing/egl/EGLWrapper.cpp | 2 +- - xbmc/windowing/egl/Makefile.in | 2 +- - 3 files changed, 11 insertions(+), 2 deletions(-) - -diff --git a/configure.in b/configure.in -index 5d46d24..891e9c2 100644 ---- a/configure.in -+++ b/configure.in -@@ -992,6 +992,15 @@ else - AC_MSG_RESULT($wayland_disabled) - fi - -+# i.MX6 -+AC_MSG_CHECKING([for i.MX framebuffer support]) -+AC_CHECK_HEADER([linux/mxcfb.h], have_imxfb=yes,have_imxfb=no) -+AC_MSG_RESULT($have_imxfb) -+if test "x$have_imxfb" = "xyes"; then -+ AC_DEFINE([HAS_IMXFB], [1], [Whether i.MX framebuffer support is enabled.]) -+ AC_SUBST([USE_IMXFB], 1) -+fi -+ - # Checks for platforms libraries. - if test "$use_gles" = "yes"; then - use_gl="no" -diff --git a/xbmc/windowing/egl/EGLWrapper.cpp b/xbmc/windowing/egl/EGLWrapper.cpp -index 717b369..4d74be5 100644 ---- a/xbmc/windowing/egl/EGLWrapper.cpp -+++ b/xbmc/windowing/egl/EGLWrapper.cpp -@@ -85,7 +85,7 @@ bool CEGLWrapper::Initialize(const std::string &implementation) - (nativeGuess = CreateEGLNativeType(implementation)) || - (nativeGuess = CreateEGLNativeType(implementation)) || - (nativeGuess = CreateEGLNativeType(implementation)) --#ifdef HAS_IMXVPU -+#ifdef HAS_IMXFB - || (nativeGuess = CreateEGLNativeType(implementation)) - #endif - ) -diff --git a/xbmc/windowing/egl/Makefile.in b/xbmc/windowing/egl/Makefile.in -index 85abb44..ec84c1d 100644 ---- a/xbmc/windowing/egl/Makefile.in -+++ b/xbmc/windowing/egl/Makefile.in -@@ -24,7 +24,7 @@ SRCS+= wayland/Callback.cpp \ - wayland/XBMCSurface.cpp - endif - --ifeq (@USE_IMXVPU@,1) -+ifeq (@USE_IMXFB@,1) - SRCS+= EGLNativeTypeIMX.cpp - endif - --- -1.9.3 - - -From 2d4368023f913e33210d8017379662de7fe79b3d Mon Sep 17 00:00:00 2001 -From: "Chris \"koying\" Browet" -Date: Mon, 3 Mar 2014 18:46:45 +0000 -Subject: [PATCH 39/50] FIX: [imx] lower log spam - ---- - xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp | 4 +++- - 1 file changed, 3 insertions(+), 1 deletion(-) - -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp -index 44bfe34..a6f3712 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp -@@ -941,7 +941,9 @@ void CDVDVideoCodecIMX::SetDropState(bool bDrop) - if (m_dropState != bDrop) - { - m_dropState = bDrop; -- CLog::Log(LOGNOTICE, "%s : %d\n", __FUNCTION__, bDrop); -+#ifdef TRACE_FRAMES -+ CLog::Log(LOGDEBUG, "%s : %d\n", __FUNCTION__, bDrop); -+#endif - } - } - --- -1.9.3 - - -From 9998d4bcb880237eeea8c93d591cfde46c12220e Mon Sep 17 00:00:00 2001 -From: wolfgar -Date: Sat, 15 Mar 2014 02:30:15 +0100 -Subject: [PATCH 40/50] Revert to sw decoding for AVC hi10 profile and divX3 - codecs - ---- - xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp | 9 +++++---- - 1 file changed, 5 insertions(+), 4 deletions(-) - -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp -index a6f3712..4110f83 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp -@@ -422,6 +422,11 @@ bool CDVDVideoCodecIMX::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options) - 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) -@@ -463,10 +468,6 @@ bool CDVDVideoCodecIMX::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options) - m_decOpenParam.CodecFormat = VPU_V_VP8; - m_pFormatName = "iMX-vp8"; - break; -- case CODEC_ID_MSMPEG4V3: -- m_decOpenParam.CodecFormat = VPU_V_XVID; // VPU_V_DIVX3 -- m_pFormatName = "iMX-divx3"; -- break; - case CODEC_ID_MPEG4: - switch(m_hints.codec_tag) - { --- -1.9.3 - - -From 089903e6b8742ab924aad0a3bacf1c49be4a0e26 Mon Sep 17 00:00:00 2001 -From: wolfgar -Date: Sun, 16 Mar 2014 01:53:02 +0100 -Subject: [PATCH 41/50] Add VPU support for MPEG1 - ---- - xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp | 4 ++++ - 1 file changed, 4 insertions(+) - -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp -index 4110f83..a4f6ede 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp -@@ -412,6 +412,10 @@ bool CDVDVideoCodecIMX::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options) - 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; --- -1.9.3 - - -From 11dc7dcbc0de3cced6cd6011cd9fda59b7326723 Mon Sep 17 00:00:00 2001 -From: wolfgar -Date: Sun, 16 Mar 2014 23:53:01 +0100 -Subject: [PATCH 42/50] Avoid to invoke VPU decoding without additional data - when we are not specifically in PR28 context as it improves VC1 issue - reported in #41 To do so, Test if frame size (and thus - VPU_DEC_ONE_FRM_CONSUMED) is handled before dealing with m_bytesToBeConsumed - ---- - xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp | 15 ++++++++++++++- - xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h | 1 + - 2 files changed, 15 insertions(+), 1 deletion(-) - -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp -index a4f6ede..9c23de2 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp -@@ -211,6 +211,18 @@ bool CDVDVideoCodecIMX::VpuOpen(void) - goto VpuOpenError; - } - -+ // Note that libvpufsl (file vpu_wrapper.c) associates VPU_DEC_CAP_FRAMESIZE -+ // capability to the value of nDecFrameRptEnabled which is in fact directly -+ // related to the ability to generate VPU_DEC_ONE_FRM_CONSUMED even if the -+ // naming is misleading... -+ ret = VPU_DecGetCapability(m_vpuHandle, VPU_DEC_CAP_FRAMESIZE, ¶m); -+ m_frameReported = (param != 0); -+ if (ret != VPU_DEC_RET_SUCCESS) -+ { -+ CLog::Log(LOGERROR, "%s - iMX VPU get framesize capability failed (%d).\n", __FUNCTION__, ret); -+ m_frameReported = false; -+ } -+ - return true; - - VpuOpenError: -@@ -653,7 +665,8 @@ int CDVDVideoCodecIMX::Decode(BYTE *pData, int iSize, double dts, double pts) - #ifdef IMX_PROFILE - before_dec = XbmcThreads::SystemClockMillis(); - #endif -- m_bytesToBeConsumed += inData.nSize; -+ 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); -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h -index 1cfb2a4..6c935f1 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h -@@ -201,4 +201,5 @@ class CDVDVideoCodecIMX : public CDVDVideoCodec - bool m_convert_bitstream; - 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 - }; --- -1.9.3 - - -From 959f937091defba1c706df51452044e7e1a2cdbb Mon Sep 17 00:00:00 2001 -From: wolfgar -Date: Wed, 19 Mar 2014 03:08:48 +0100 -Subject: [PATCH 43/50] Handle dts properly instead of reverting to NOPTS when - only dts is available (no pts provided) Also try to decode harder - ---- - .../dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp | 56 ++++++++++------------ - .../dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h | 2 + - 2 files changed, 26 insertions(+), 32 deletions(-) - -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp -index 9c23de2..ffbfd59 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp -@@ -46,6 +46,7 @@ - - // Experiments show that we need at least one more (+1) V4L 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) -@@ -413,7 +414,7 @@ bool CDVDVideoCodecIMX::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options) - { - char buf[4096]; - -- for (int i=0; i < m_hints.extrasize; i++) -+ 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); - } -@@ -588,8 +589,7 @@ int CDVDVideoCodecIMX::Decode(BYTE *pData, int iSize, double dts, double pts) - int retStatus = 0; - int demuxer_bytes = iSize; - uint8_t *demuxer_content = pData; -- bool retry = false; -- bool frameConsumed = false; -+ int retries = 0; - int idx; - - #ifdef IMX_PROFILE -@@ -622,11 +622,6 @@ int CDVDVideoCodecIMX::Decode(BYTE *pData, int iSize, double dts, double pts) - previous = current; - #endif - --/* FIXME tests -- CLog::Log(LOGDEBUG, "%s - demux size : %d dts : %f - pts : %f - %x %x %x %x\n", __FUNCTION__, iSize, dts, pts, ((unsigned int *)pData)[0], ((unsigned int *)pData)[1], ((unsigned int *)pData)[2], ((unsigned int *)pData)[3]); -- ((unsigned int *)pData)[0] = htonl(iSize-4); --*/ -- - if ((pData && iSize) || - (m_bytesToBeConsumed)) - { -@@ -659,9 +654,8 @@ int CDVDVideoCodecIMX::Decode(BYTE *pData, int iSize, double dts, double pts) - inData.sCodecData.nSize = 0; - } - -- do // Decode as long as the VPU consumes data -+ while (true) // Decode as long as the VPU consumes data - { -- retry = false; - #ifdef IMX_PROFILE - before_dec = XbmcThreads::SystemClockMillis(); - #endif -@@ -736,7 +730,6 @@ int CDVDVideoCodecIMX::Decode(BYTE *pData, int iSize, double dts, double pts) - else - CLog::Log(LOGERROR, "%s - could not find frame buffer\n", __FUNCTION__); - } -- frameConsumed = true; - } //VPU_DEC_ONE_FRM_CONSUMED - - if (decRet & VPU_DEC_OUTPUT_DIS) -@@ -806,27 +799,30 @@ int CDVDVideoCodecIMX::Decode(BYTE *pData, int iSize, double dts, double pts) - { - CLog::Log(LOGNOTICE, "%s - EOS encountered.\n", __FUNCTION__); - } -- if (decRet & VPU_DEC_NO_ENOUGH_INBUF) -+ if ((decRet & VPU_DEC_NO_ENOUGH_INBUF) || -+ (decRet & VPU_DEC_OUTPUT_DIS)) - { - // We are done with VPU decoder that time - break; - } -- if (!(decRet & VPU_DEC_INPUT_USED)) -+ -+ retries++; -+ if (retries >= m_maxVpuDecodeLoops) - { -- CLog::Log(LOGERROR, "%s - input not used : addr %p size :%d!\n", __FUNCTION__, inData.pVirAddr, inData.nSize); -+ CLog::Log(LOGERROR, "%s - Leaving VPU decoding loop after %d iterations\n", __FUNCTION__, m_maxVpuDecodeLoops); -+ break; - } - -- if (!(decRet & VPU_DEC_OUTPUT_DIS) && -- (inData.nSize != 0)) -+ if (!(decRet & VPU_DEC_INPUT_USED)) - { -- // 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; -- retry = true; -+ CLog::Log(LOGERROR, "%s - input not used : addr %p size :%d!\n", __FUNCTION__, inData.pVirAddr, inData.nSize); - } -- } while (retry == true); -+ -+ // 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) -@@ -841,13 +837,9 @@ int CDVDVideoCodecIMX::Decode(BYTE *pData, int iSize, double dts, double pts) - // This pts is related to the frame that will be consumed - // at next call... - m_previousPts = pts; -- if (retStatus & VC_PICTURE) -- // If a picture was produced and some data are still to -- // be consumed, do not ask for additional buffer as -- // we likely already have enough data to produce a -- // new output frame at next call -- retStatus &= (~VC_BUFFER); - } -+ // 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); -@@ -921,17 +913,18 @@ bool CDVDVideoCodecIMX::GetPicture(DVDVideoPicture* pDvdVideoPicture) - CDVDVideoCodecIPUBuffer *ipuBuffer = NULL; - - 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); - - #ifdef TRACE_FRAMES -- CLog::Log(LOGDEBUG, "+ %02d pts %f (VPU)\n", idx, pDvdVideoPicture->pts); -+ CLog::Log(LOGDEBUG, "+ %02d dts %f pts %f (VPU)\n", idx, pDvdVideoPicture->dts, pDvdVideoPicture->pts); - #endif -- - ipuBuffer = m_deinterlacer.Process(buffer, m_frameInfo.eFieldType, m_modeDeinterlace > 1); - - if (ipuBuffer) -@@ -1219,7 +1212,6 @@ void CDVDVideoCodecIPUBuffer::ReleaseFrameBuffer() - - bool CDVDVideoCodecIPUBuffer::Allocate(int fd, int width, int height, int nAlign) - { -- uint8_t *phyAddr, *virtAddr; - m_iWidth = Align(width,FRAME_ALIGN); - m_iHeight = Align(height,(2*FRAME_ALIGN)); - // NV12 == 12 bpp -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h -index 6c935f1..1ae2618 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h -@@ -178,6 +178,7 @@ class CDVDVideoCodecIMX : public CDVDVideoCodec - 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; - - CDVDStreamInfo m_hints; // Hints from demuxer at stream opening -@@ -202,4 +203,5 @@ class CDVDVideoCodecIMX : public CDVDVideoCodec - 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 - }; --- -1.9.3 - - -From 84692dca572b0a8e100af3944d90dcd39f583d61 Mon Sep 17 00:00:00 2001 -From: smallint -Date: Sun, 2 Mar 2014 17:13:52 +0100 -Subject: [PATCH 44/50] [imx] Move deinterlacing processing into render thread - ---- - xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp | 40 ++++++++- - .../dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp | 95 ++++++++++++++-------- - .../dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h | 6 ++ - 3 files changed, 103 insertions(+), 38 deletions(-) - -diff --git a/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp b/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp -index 980c1a3..8b0f555 100644 ---- a/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp -+++ b/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp -@@ -81,6 +81,8 @@ static PFNGLEGLIMAGETARGETTEXTURE2DOESPROC glEGLImageTargetTexture2DOES; - - #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); -@@ -1640,7 +1642,15 @@ void CLinuxRendererGLES::RenderIMXMAPTexture(int index, int field) - YUVPLANE &plane = m_buffers[index].fields[field][0]; - CDVDVideoCodecBuffer* codecinfo = m_buffers[index].codecinfo; - -- if((codecinfo == NULL) || !codecinfo->IsValid()) return; -+ if(codecinfo == NULL) return; -+ -+ CDVDVideoCodecIMX::Enter(); -+ -+ if(!codecinfo->IsValid()) -+ { -+ CDVDVideoCodecIMX::Leave(); -+ return; -+ } - - glDisable(GL_DEPTH_TEST); - -@@ -1693,6 +1703,8 @@ void CLinuxRendererGLES::RenderIMXMAPTexture(int index, int field) - glBindTexture(m_textureTarget, 0); - VerifyGLState(); - -+ CDVDVideoCodecIMX::Leave(); -+ - #ifdef DEBUG_VERBOSE - CLog::Log(LOGDEBUG, "RenderIMXMAPTexture %d: tm:%d\n", index, XbmcThreads::SystemClockMillis() - time); - #endif -@@ -2716,9 +2728,31 @@ void CLinuxRendererGLES::UploadIMXMAPTexture(int index) - YUVBUFFER& buf = m_buffers[index]; - CDVDVideoCodecBuffer* codecinfo = buf.codecinfo; - -- if(codecinfo && codecinfo->IsValid()) -+ if(codecinfo) - { -+ CDVDVideoCodecIMX::Enter(); -+ -+ if(!codecinfo->IsValid()) -+ { -+ CDVDVideoCodecIMX::Leave(); -+ return; -+ } -+ - YUVPLANE &plane = m_buffers[index].fields[0][0]; -+ CDVDVideoCodecIPUBuffers *deinterlacer = (CDVDVideoCodecIPUBuffers*)codecinfo->data[2]; -+ -+ if (deinterlacer) -+ { -+ CDVDVideoCodecBuffer *deint; -+ deint = deinterlacer->Process(codecinfo, (VpuFieldType)(int)codecinfo->data[3], false); -+ if (deint) -+ { -+ SAFE_RELEASE(buf.codecinfo); -+ buf.codecinfo = deint; -+ buf.codecinfo->Lock(); -+ codecinfo = buf.codecinfo; -+ } -+ } - - glActiveTexture(GL_TEXTURE0); - glBindTexture(m_textureTarget, plane.id); -@@ -2736,6 +2770,8 @@ void CLinuxRendererGLES::UploadIMXMAPTexture(int index) - plane.texheight = codecinfo->iHeight; - - CalculateTextureSourceRects(index, 1); -+ -+ CDVDVideoCodecIMX::Leave(); - } - - #endif -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp -index ffbfd59..752bfb9 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp -@@ -43,6 +43,8 @@ - // Extrace physical and virtual addresses from CDVDVideoCodecBuffer pointers - #define GET_PHYS_ADDR(buf) (buf)->data[1] - #define GET_VIRT_ADDR(buf) (buf)->data[0] -+#define GET_DEINTERLACER(buf) (buf)->data[2] -+#define GET_FIELDTYPE(buf) (buf)->data[3] - - // Experiments show that we need at least one more (+1) V4L buffer than the min value returned by the VPU - const int CDVDVideoCodecIMX::m_extraVpuBuffers = 6; -@@ -334,20 +336,12 @@ bool CDVDVideoCodecIMX::VpuAllocFrameBuffers(void) - - if (m_initInfo.nInterlace && (m_modeDeinterlace>0)) - { -- if ((m_initInfo.nPicWidth>1024) || (m_initInfo.nPicHeight>1024)) -+ CLog::Log(LOGNOTICE, "IMX: Enable hardware deinterlacing\n"); -+ if (!m_deinterlacer.Init(m_initInfo.nPicWidth, m_initInfo.nPicHeight, GetAllowedReferences()+1, nAlign)) - { -- CLog::Log(LOGNOTICE, "IMX: Disable hardware deinterlacing for HD playback\n"); -+ CLog::Log(LOGWARNING, "IMX: Failed to initialize IPU buffers: deinterlacing disabled\n"); - m_modeDeinterlace = 0; - } -- else -- { -- CLog::Log(LOGNOTICE, "IMX: Enable hardware deinterlacing\n"); -- if (!m_deinterlacer.Init(m_initInfo.nPicWidth, m_initInfo.nPicHeight, GetAllowedReferences()+1, nAlign)) -- { -- CLog::Log(LOGWARNING, "IMX: Failed to initialize IPU buffers: deinterlacing disabled\n"); -- m_modeDeinterlace = 0; -- } -- } - } - else - m_modeDeinterlace = 0; -@@ -522,6 +516,9 @@ void CDVDVideoCodecIMX::Dispose(void) - VpuDecRetCode ret; - bool VPU_loaded = m_vpuHandle; - -+ // Block render thread from using that framebuffers -+ Enter(); -+ - // Invalidate output buffers to prevent the renderer from mapping this memory - for (int i=0; iiFlags = DVP_FLAG_ALLOCATED; - if (m_dropState) - pDvdVideoPicture->iFlags |= DVP_FLAG_DROPPED; -@@ -910,7 +910,6 @@ bool CDVDVideoCodecIMX::GetPicture(DVDVideoPicture* pDvdVideoPicture) - if (idx != -1) - { - CDVDVideoCodecIMXBuffer *buffer = m_outputBuffers[idx]; -- CDVDVideoCodecIPUBuffer *ipuBuffer = NULL; - - pDvdVideoPicture->pts = buffer->GetPts(); - pDvdVideoPicture->dts = m_dts; -@@ -925,13 +924,10 @@ bool CDVDVideoCodecIMX::GetPicture(DVDVideoPicture* pDvdVideoPicture) - #ifdef TRACE_FRAMES - CLog::Log(LOGDEBUG, "+ %02d dts %f pts %f (VPU)\n", idx, pDvdVideoPicture->dts, pDvdVideoPicture->pts); - #endif -- ipuBuffer = m_deinterlacer.Process(buffer, m_frameInfo.eFieldType, m_modeDeinterlace > 1); - -- if (ipuBuffer) -- pDvdVideoPicture->codecinfo = ipuBuffer; -- else -- pDvdVideoPicture->codecinfo = buffer; -+ GET_DEINTERLACER(buffer) = (uint8_t*)&m_deinterlacer; - -+ pDvdVideoPicture->codecinfo = buffer; - pDvdVideoPicture->codecinfo->Lock(); - } - else -@@ -958,6 +954,16 @@ void CDVDVideoCodecIMX::SetDropState(bool bDrop) - } - } - -+void CDVDVideoCodecIMX::Enter() -+{ -+ m_codecBufferLock.lock(); -+} -+ -+void CDVDVideoCodecIMX::Leave() -+{ -+ m_codecBufferLock.unlock(); -+} -+ - /*******************************************/ - - #ifdef TRACE_FRAMES -@@ -1012,7 +1018,6 @@ long CDVDVideoCodecIMXBuffer::Release() - - bool CDVDVideoCodecIMXBuffer::IsValid() - { -- CSingleLock lock(CDVDVideoCodecIMX::m_codecBufferLock); - return m_frameBuffer != NULL; - } - -@@ -1023,7 +1028,8 @@ bool CDVDVideoCodecIMXBuffer::Rendered() const - - void CDVDVideoCodecIMXBuffer::Queue(VpuDecOutFrameInfo *frameInfo) - { -- CSingleLock lock(CDVDVideoCodecIMX::m_codecBufferLock); -+ // No lock necessary because at the time Queue there is definitely no -+ // thread that is still holding a reference - m_frameBuffer = frameInfo->pDisplayFrameBuf; - m_rendered = false; - -@@ -1031,11 +1037,13 @@ void CDVDVideoCodecIMXBuffer::Queue(VpuDecOutFrameInfo *frameInfo) - iHeight = frameInfo->pExtInfo->nFrmHeight; - GET_VIRT_ADDR(this) = m_frameBuffer->pbufVirtY; - GET_PHYS_ADDR(this) = m_frameBuffer->pbufY; -+ GET_FIELDTYPE(this) = (uint8_t*)frameInfo->eFieldType; - } - - VpuDecRetCode CDVDVideoCodecIMXBuffer::ReleaseFramebuffer(VpuDecHandle *handle) - { -- CSingleLock lock(CDVDVideoCodecIMX::m_codecBufferLock); -+ // 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) -@@ -1047,6 +1055,7 @@ VpuDecRetCode CDVDVideoCodecIMXBuffer::ReleaseFramebuffer(VpuDecHandle *handle) - #ifdef TRACE_FRAMES - CLog::Log(LOGDEBUG, "- %02d (VPU)\n", m_idx); - #endif -+ GET_DEINTERLACER(this) = NULL; - m_rendered = false; - m_frameBuffer = NULL; - m_pts = DVD_NOPTS_VALUE; -@@ -1125,8 +1134,7 @@ long CDVDVideoCodecIPUBuffer::Release() - - bool CDVDVideoCodecIPUBuffer::IsValid() - { -- CSingleLock lock(CDVDVideoCodecIMX::m_codecBufferLock); -- return (m_source != NULL) && m_pPhyAddr; -+ return m_source && m_source->IsValid() && m_pPhyAddr; - } - - bool CDVDVideoCodecIPUBuffer::Process(int fd, CDVDVideoCodecBuffer *currentBuffer, -@@ -1138,27 +1146,27 @@ bool CDVDVideoCodecIPUBuffer::Process(int fd, CDVDVideoCodecBuffer *currentBuffe - - SAFE_RELEASE(m_source); - -- iWidth = currentBuffer->iWidth; -- iHeight = currentBuffer->iHeight; -+ iWidth = currentBuffer->iWidth; -+ iHeight = currentBuffer->iHeight; - - // Input is the VPU decoded frame -- task.input.width = iWidth; -- task.input.height = iHeight; -- task.input.format = IPU_PIX_FMT_NV12; -- task.input.paddr = (int)GET_PHYS_ADDR(currentBuffer); -+ task.input.width = iWidth; -+ task.input.height = iHeight; -+ task.input.format = IPU_PIX_FMT_NV12; -+ task.input.paddr = (int)GET_PHYS_ADDR(currentBuffer); - - // Output is our IPU buffer -- task.output.width = iWidth; -- task.output.height = iHeight; -- task.output.format = IPU_PIX_FMT_NV12; -- task.output.paddr = (int)GET_PHYS_ADDR(this); -+ task.output.width = iWidth; -+ task.output.height = iHeight; -+ task.output.format = IPU_PIX_FMT_NV12; -+ task.output.paddr = (int)GET_PHYS_ADDR(this); - - // Fill previous buffer address - if (previousBuffer) - task.input.paddr_n = (int)GET_PHYS_ADDR(previousBuffer); - -- task.input.deinterlace.enable = 1; -- task.input.deinterlace.motion = task.input.paddr_n?LOW_MOTION:HIGH_MOTION; -+ task.input.deinterlace.enable = 1; -+ task.input.deinterlace.motion = task.input.paddr_n?LOW_MOTION:HIGH_MOTION; - - switch (fieldType) - { -@@ -1180,7 +1188,13 @@ bool CDVDVideoCodecIPUBuffer::Process(int fd, CDVDVideoCodecBuffer *currentBuffe - break; - } - -+#ifdef IMX_PROFILE -+ unsigned int time = XbmcThreads::SystemClockMillis(); -+#endif - int ret = ioctl(fd, IPU_QUEUE_TASK, &task); -+#ifdef IMX_PROFILE -+ CLog::Log(LOGDEBUG, "DEINT: tm:%d\n", XbmcThreads::SystemClockMillis() - time); -+#endif - if (ret < 0) - { - CLog::Log(LOGERROR, "IPU task failed: %s\n", strerror(errno)); -@@ -1250,6 +1264,8 @@ bool CDVDVideoCodecIPUBuffer::Allocate(int fd, int width, int height, int nAlign - GET_VIRT_ADDR(this) = (uint8_t*)m_pVirtAddr; - } - -+ GET_DEINTERLACER(this) = NULL; -+ - return true; - } - -@@ -1290,7 +1306,8 @@ bool CDVDVideoCodecIPUBuffer::Free(int fd) - } - - CDVDVideoCodecIPUBuffers::CDVDVideoCodecIPUBuffers() -- : m_ipuHandle(0) -+ : m_bEnabled(true) -+ , m_ipuHandle(0) - , m_bufferNum(0) - , m_buffers(NULL) - , m_lastBuffer(NULL) -@@ -1346,6 +1363,11 @@ bool CDVDVideoCodecIPUBuffers::Reset() - m_buffers[i]->ReleaseFrameBuffer(); - } - -+bool CDVDVideoCodecIPUBuffers::SetEnabled(bool enabled) -+{ -+ m_bEnabled = enabled; -+} -+ - bool CDVDVideoCodecIPUBuffers::Close() - { - bool ret = true; -@@ -1390,7 +1412,8 @@ CDVDVideoCodecIPUBuffers::Process(CDVDVideoCodecBuffer *sourceBuffer, - CDVDVideoCodecIPUBuffer *target = NULL; - bool ret = true; - -- if (!m_bufferNum || (fieldType==VPU_FIELD_NONE)) return NULL; -+ if (!m_bEnabled || !m_bufferNum) -+ return NULL; - - for (int i=0; i < m_bufferNum; i++ ) - { -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h -index 1ae2618..1b1786e 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h -@@ -75,6 +75,7 @@ class CDVDVideoCodecIMXBuffer : public CDVDVideoCodecBuffer - // private because we are reference counted - virtual ~CDVDVideoCodecIMXBuffer(); - -+private: - #ifdef TRACE_FRAMES - int m_idx; - #endif -@@ -136,12 +137,14 @@ class CDVDVideoCodecIPUBuffers - - bool Init(int width, int height, int numBuffers, int nAlign); - bool Reset(); -+ bool SetEnabled(bool); - bool Close(); - - CDVDVideoCodecIPUBuffer *Process(CDVDVideoCodecBuffer *sourceBuffer, - VpuFieldType fieldType, bool lowMotion); - - private: -+ bool m_bEnabled; - int m_ipuHandle; - int m_bufferNum; - CDVDVideoCodecIPUBuffer **m_buffers; -@@ -169,6 +172,9 @@ class CDVDVideoCodecIMX : public CDVDVideoCodec - virtual const char* GetName(void) { return (const char*)m_pFormatName; } - virtual unsigned GetAllowedReferences(); - -+ static void Enter(); -+ static void Leave(); -+ - protected: - - bool VpuOpen(); --- -1.9.3 - - -From 1569163ab1b9ccdf89036d59bce2173b4c5a8941 Mon Sep 17 00:00:00 2001 -From: smallint -Date: Mon, 3 Mar 2014 19:39:17 +0100 -Subject: [PATCH 45/50] ADD: [imx] Deinterlacing options configurable from gui - ---- - xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp | 38 +++++++++++++++++----- - .../dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp | 15 +++++++-- - .../dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h | 2 +- - 3 files changed, 42 insertions(+), 13 deletions(-) - -diff --git a/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp b/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp -index 8b0f555..8a28e3b 100644 ---- a/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp -+++ b/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp -@@ -2725,7 +2725,7 @@ void CLinuxRendererGLES::SetTextureFilter(GLenum method) - void CLinuxRendererGLES::UploadIMXMAPTexture(int index) - { - #ifdef HAS_IMXVPU -- YUVBUFFER& buf = m_buffers[index]; -+ YUVBUFFER& buf = m_buffers[index]; - CDVDVideoCodecBuffer* codecinfo = buf.codecinfo; - - if(codecinfo) -@@ -2740,18 +2740,27 @@ void CLinuxRendererGLES::UploadIMXMAPTexture(int index) - - YUVPLANE &plane = m_buffers[index].fields[0][0]; - CDVDVideoCodecIPUBuffers *deinterlacer = (CDVDVideoCodecIPUBuffers*)codecinfo->data[2]; -+ EDEINTERLACEMODE deinterlacemode = CMediaSettings::Get().GetCurrentVideoSettings().m_DeinterlaceMode; -+ EINTERLACEMETHOD interlacemethod = CMediaSettings::Get().GetCurrentVideoSettings().m_InterlaceMethod; - - if (deinterlacer) - { -- CDVDVideoCodecBuffer *deint; -- deint = deinterlacer->Process(codecinfo, (VpuFieldType)(int)codecinfo->data[3], false); -- if (deint) -+ if (deinterlacemode != VS_DEINTERLACEMODE_OFF) - { -- SAFE_RELEASE(buf.codecinfo); -- buf.codecinfo = deint; -- buf.codecinfo->Lock(); -- codecinfo = buf.codecinfo; -+ deinterlacer->SetEnabled(true); -+ CDVDVideoCodecBuffer *deint; -+ deint = deinterlacer->Process(codecinfo, (VpuFieldType)(int)codecinfo->data[3], -+ interlacemethod == VS_INTERLACEMETHOD_DEINTERLACE); -+ if (deint) -+ { -+ SAFE_RELEASE(buf.codecinfo); -+ buf.codecinfo = deint; -+ buf.codecinfo->Lock(); -+ codecinfo = buf.codecinfo; -+ } - } -+ else -+ deinterlacer->SetEnabled(false); - } - - glActiveTexture(GL_TEXTURE0); -@@ -2886,9 +2895,14 @@ bool CLinuxRendererGLES::Supports(EDEINTERLACEMODE mode) - if(m_renderMethod & RENDER_CVREF) - return false; - -+#ifdef HAS_IMXVPU -+ if(mode == VS_DEINTERLACEMODE_AUTO) -+ return true; -+#else - if(mode == VS_DEINTERLACEMODE_AUTO - || mode == VS_DEINTERLACEMODE_FORCE) - return true; -+#endif - - return false; - } -@@ -2917,6 +2931,7 @@ bool CLinuxRendererGLES::Supports(EINTERLACEMETHOD method) - if(method == VS_INTERLACEMETHOD_AUTO) - return true; - -+#ifndef HAS_IMXVPU - #if defined(__i386__) || defined(__x86_64__) - if(method == VS_INTERLACEMETHOD_DEINTERLACE - || method == VS_INTERLACEMETHOD_DEINTERLACE_HALF -@@ -2925,6 +2940,11 @@ bool CLinuxRendererGLES::Supports(EINTERLACEMETHOD method) - if(method == VS_INTERLACEMETHOD_SW_BLEND) - #endif - return true; -+#else -+ if(method == VS_INTERLACEMETHOD_DEINTERLACE -+ || method == VS_INTERLACEMETHOD_DEINTERLACE_HALF) -+ return true; -+#endif - - return false; - } -@@ -2965,7 +2985,7 @@ EINTERLACEMETHOD CLinuxRendererGLES::AutoInterlaceMethod() - if(m_renderMethod & RENDER_CVREF) - return VS_INTERLACEMETHOD_NONE; - --#if defined(__i386__) || defined(__x86_64__) -+#if defined(__i386__) || defined(__x86_64__) || defined(HAS_IMXVPU) - return VS_INTERLACEMETHOD_DEINTERLACE_HALF; - #else - return VS_INTERLACEMETHOD_SW_BLEND; -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp -index 752bfb9..11d06d7 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp -@@ -890,6 +890,15 @@ bool CDVDVideoCodecIMX::ClearPicture(DVDVideoPicture* pDvdVideoPicture) - - 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; -@@ -1028,8 +1037,8 @@ bool CDVDVideoCodecIMXBuffer::Rendered() const - - void CDVDVideoCodecIMXBuffer::Queue(VpuDecOutFrameInfo *frameInfo) - { -- // No lock necessary because at the time Queue there is definitely no -- // thread that is still holding a reference -+ // No lock necessary because at this time there is definitely no -+ // thread still holding a reference - m_frameBuffer = frameInfo->pDisplayFrameBuf; - m_rendered = false; - -@@ -1363,7 +1372,7 @@ bool CDVDVideoCodecIPUBuffers::Reset() - m_buffers[i]->ReleaseFrameBuffer(); - } - --bool CDVDVideoCodecIPUBuffers::SetEnabled(bool enabled) -+void CDVDVideoCodecIPUBuffers::SetEnabled(bool enabled) - { - m_bEnabled = enabled; - } -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h -index 1b1786e..37d5734 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h -@@ -137,7 +137,7 @@ class CDVDVideoCodecIPUBuffers - - bool Init(int width, int height, int numBuffers, int nAlign); - bool Reset(); -- bool SetEnabled(bool); -+ void SetEnabled(bool); - bool Close(); - - CDVDVideoCodecIPUBuffer *Process(CDVDVideoCodecBuffer *sourceBuffer, --- -1.9.3 - - -From c9bcc7162227cd22a5dd6f800696bd9f3ce9f6ec Mon Sep 17 00:00:00 2001 -From: smallint -Date: Tue, 11 Mar 2014 20:49:40 +0100 -Subject: [PATCH 46/50] [imx] Cleanups after code review - ---- - xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp | 28 ++++++++++++---------- - .../dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp | 21 +++++++--------- - .../dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h | 2 -- - 3 files changed, 25 insertions(+), 26 deletions(-) - -diff --git a/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp b/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp -index 8a28e3b..6490fd0 100644 ---- a/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp -+++ b/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp -@@ -2740,15 +2740,15 @@ void CLinuxRendererGLES::UploadIMXMAPTexture(int index) - - YUVPLANE &plane = m_buffers[index].fields[0][0]; - CDVDVideoCodecIPUBuffers *deinterlacer = (CDVDVideoCodecIPUBuffers*)codecinfo->data[2]; -- EDEINTERLACEMODE deinterlacemode = CMediaSettings::Get().GetCurrentVideoSettings().m_DeinterlaceMode; -- EINTERLACEMETHOD interlacemethod = CMediaSettings::Get().GetCurrentVideoSettings().m_InterlaceMethod; - - if (deinterlacer) - { -+ EDEINTERLACEMODE deinterlacemode = CMediaSettings::Get().GetCurrentVideoSettings().m_DeinterlaceMode; -+ - if (deinterlacemode != VS_DEINTERLACEMODE_OFF) - { -- deinterlacer->SetEnabled(true); - CDVDVideoCodecBuffer *deint; -+ EINTERLACEMETHOD interlacemethod = CMediaSettings::Get().GetCurrentVideoSettings().m_InterlaceMethod; - deint = deinterlacer->Process(codecinfo, (VpuFieldType)(int)codecinfo->data[3], - interlacemethod == VS_INTERLACEMETHOD_DEINTERLACE); - if (deint) -@@ -2759,8 +2759,6 @@ void CLinuxRendererGLES::UploadIMXMAPTexture(int index) - codecinfo = buf.codecinfo; - } - } -- else -- deinterlacer->SetEnabled(false); - } - - glActiveTexture(GL_TEXTURE0); -@@ -2931,7 +2929,15 @@ bool CLinuxRendererGLES::Supports(EINTERLACEMETHOD method) - if(method == VS_INTERLACEMETHOD_AUTO) - return true; - --#ifndef HAS_IMXVPU -+ if(m_renderMethod & RENDER_IMXMAP) -+ { -+ if(method == VS_INTERLACEMETHOD_DEINTERLACE -+ || method == VS_INTERLACEMETHOD_DEINTERLACE_HALF) -+ return true; -+ else -+ return false; -+ } -+ - #if defined(__i386__) || defined(__x86_64__) - if(method == VS_INTERLACEMETHOD_DEINTERLACE - || method == VS_INTERLACEMETHOD_DEINTERLACE_HALF -@@ -2940,11 +2946,6 @@ bool CLinuxRendererGLES::Supports(EINTERLACEMETHOD method) - if(method == VS_INTERLACEMETHOD_SW_BLEND) - #endif - return true; --#else -- if(method == VS_INTERLACEMETHOD_DEINTERLACE -- || method == VS_INTERLACEMETHOD_DEINTERLACE_HALF) -- return true; --#endif - - return false; - } -@@ -2985,7 +2986,10 @@ EINTERLACEMETHOD CLinuxRendererGLES::AutoInterlaceMethod() - if(m_renderMethod & RENDER_CVREF) - return VS_INTERLACEMETHOD_NONE; - --#if defined(__i386__) || defined(__x86_64__) || defined(HAS_IMXVPU) -+ if(m_renderMethod & RENDER_IMXMAP) -+ return VS_INTERLACEMETHOD_DEINTERLACE_HALF; -+ -+#if defined(__i386__) || defined(__x86_64__) - return VS_INTERLACEMETHOD_DEINTERLACE_HALF; - #else - return VS_INTERLACEMETHOD_SW_BLEND; -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp -index 11d06d7..4dc3169 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp -@@ -342,6 +342,11 @@ bool CDVDVideoCodecIMX::VpuAllocFrameBuffers(void) - CLog::Log(LOGWARNING, "IMX: Failed to initialize IPU buffers: deinterlacing disabled\n"); - m_modeDeinterlace = 0; - } -+ else -+ { -+ for (int i=0 ; i < m_vpuFrameBufferNum; i++) -+ GET_DEINTERLACER(m_outputBuffers[i]) = (uint8_t*)&m_deinterlacer; -+ } - } - else - m_modeDeinterlace = 0; -@@ -934,8 +939,6 @@ bool CDVDVideoCodecIMX::GetPicture(DVDVideoPicture* pDvdVideoPicture) - CLog::Log(LOGDEBUG, "+ %02d dts %f pts %f (VPU)\n", idx, pDvdVideoPicture->dts, pDvdVideoPicture->pts); - #endif - -- GET_DEINTERLACER(buffer) = (uint8_t*)&m_deinterlacer; -- - pDvdVideoPicture->codecinfo = buffer; - pDvdVideoPicture->codecinfo->Lock(); - } -@@ -987,6 +990,7 @@ CDVDVideoCodecIMXBuffer::CDVDVideoCodecIMXBuffer() - , m_rendered(false) - , m_pts(DVD_NOPTS_VALUE) - { -+ GET_DEINTERLACER(this) = NULL; - } - - void CDVDVideoCodecIMXBuffer::Lock() -@@ -1064,7 +1068,6 @@ VpuDecRetCode CDVDVideoCodecIMXBuffer::ReleaseFramebuffer(VpuDecHandle *handle) - #ifdef TRACE_FRAMES - CLog::Log(LOGDEBUG, "- %02d (VPU)\n", m_idx); - #endif -- GET_DEINTERLACER(this) = NULL; - m_rendered = false; - m_frameBuffer = NULL; - m_pts = DVD_NOPTS_VALUE; -@@ -1315,8 +1318,7 @@ bool CDVDVideoCodecIPUBuffer::Free(int fd) - } - - CDVDVideoCodecIPUBuffers::CDVDVideoCodecIPUBuffers() -- : m_bEnabled(true) -- , m_ipuHandle(0) -+ : m_ipuHandle(0) - , m_bufferNum(0) - , m_buffers(NULL) - , m_lastBuffer(NULL) -@@ -1348,7 +1350,7 @@ bool CDVDVideoCodecIPUBuffers::Init(int width, int height, int numBuffers, int n - m_bufferNum = numBuffers; - m_buffers = new CDVDVideoCodecIPUBuffer*[m_bufferNum]; - -- for (int i=0; i < m_bufferNum; i++ ) -+ for (int i=0; i < m_bufferNum; i++) - { - #ifdef TRACE_FRAMES - m_buffers[i] = new CDVDVideoCodecIPUBuffer(i); -@@ -1372,11 +1374,6 @@ bool CDVDVideoCodecIPUBuffers::Reset() - m_buffers[i]->ReleaseFrameBuffer(); - } - --void CDVDVideoCodecIPUBuffers::SetEnabled(bool enabled) --{ -- m_bEnabled = enabled; --} -- - bool CDVDVideoCodecIPUBuffers::Close() - { - bool ret = true; -@@ -1421,7 +1418,7 @@ CDVDVideoCodecIPUBuffers::Process(CDVDVideoCodecBuffer *sourceBuffer, - CDVDVideoCodecIPUBuffer *target = NULL; - bool ret = true; - -- if (!m_bEnabled || !m_bufferNum) -+ if (!m_bufferNum) - return NULL; - - for (int i=0; i < m_bufferNum; i++ ) -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h -index 37d5734..a76575f 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h -@@ -137,14 +137,12 @@ class CDVDVideoCodecIPUBuffers - - bool Init(int width, int height, int numBuffers, int nAlign); - bool Reset(); -- void SetEnabled(bool); - bool Close(); - - CDVDVideoCodecIPUBuffer *Process(CDVDVideoCodecBuffer *sourceBuffer, - VpuFieldType fieldType, bool lowMotion); - - private: -- bool m_bEnabled; - int m_ipuHandle; - int m_bufferNum; - CDVDVideoCodecIPUBuffer **m_buffers; --- -1.9.3 - - -From 98e8973ef0a51844af3f34067cad1ff78504748e Mon Sep 17 00:00:00 2001 -From: smallint -Date: Fri, 14 Mar 2014 15:27:24 +0000 -Subject: [PATCH 47/50] [imx] Fixed low motion deinterlacing picture jumps - ---- - .../dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp | 129 ++++++++++++++------- - .../dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h | 64 +++++----- - 2 files changed, 121 insertions(+), 72 deletions(-) - -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp -index 4dc3169..782510f 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp -@@ -334,22 +334,19 @@ bool CDVDVideoCodecIMX::VpuAllocFrameBuffers(void) - #endif - } - -- if (m_initInfo.nInterlace && (m_modeDeinterlace>0)) -+ if (m_initInfo.nInterlace) - { - CLog::Log(LOGNOTICE, "IMX: Enable hardware deinterlacing\n"); - if (!m_deinterlacer.Init(m_initInfo.nPicWidth, m_initInfo.nPicHeight, GetAllowedReferences()+1, nAlign)) - { - CLog::Log(LOGWARNING, "IMX: Failed to initialize IPU buffers: deinterlacing disabled\n"); -- m_modeDeinterlace = 0; - } - else - { -- for (int i=0 ; i < m_vpuFrameBufferNum; i++) -+ for (int i=0; iReleaseFramebuffer(&m_vpuHandle); -@@ -933,14 +935,30 @@ bool CDVDVideoCodecIMX::GetPicture(DVDVideoPicture* pDvdVideoPicture) - pDvdVideoPicture->dts = DVD_NOPTS_VALUE; - } - -- buffer->Queue(&m_frameInfo); -+ 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 - -+ /* -+ // This does not work reliably since some streams do not report -+ // correctly if a frame is interlaced. -+ if (m_frameInfo.eFieldType != VPU_FIELD_NONE) -+ GET_DEINTERLACER(buffer) = (uint8_t*)&m_deinterlacer; -+ else -+ GET_DEINTERLACER(buffer) = NULL; -+ */ -+ - pDvdVideoPicture->codecinfo = buffer; - pDvdVideoPicture->codecinfo->Lock(); -+ -+ // Save last buffer -+ if (m_lastBuffer) -+ SAFE_RELEASE(m_lastBuffer); -+ -+ m_lastBuffer = buffer; -+ m_lastBuffer->Lock(); - } - else - { -@@ -989,6 +1007,7 @@ CDVDVideoCodecIMXBuffer::CDVDVideoCodecIMXBuffer() - , m_frameBuffer(NULL) - , m_rendered(false) - , m_pts(DVD_NOPTS_VALUE) -+ , m_previousBuffer(NULL) - { - GET_DEINTERLACER(this) = NULL; - } -@@ -1009,6 +1028,11 @@ long CDVDVideoCodecIMXBuffer::Release() - #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 -@@ -1016,6 +1040,7 @@ long CDVDVideoCodecIMXBuffer::Release() - if(m_frameBuffer != NULL) - { - m_rendered = true; -+ SAFE_RELEASE(m_previousBuffer); - #ifdef TRACE_FRAMES - CLog::Log(LOGDEBUG, "R %02d (VPU)\n", m_idx); - #endif -@@ -1039,12 +1064,16 @@ bool CDVDVideoCodecIMXBuffer::Rendered() const - return m_rendered; - } - --void CDVDVideoCodecIMXBuffer::Queue(VpuDecOutFrameInfo *frameInfo) -+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(); - - iWidth = frameInfo->pExtInfo->nFrmWidth; - iHeight = frameInfo->pExtInfo->nFrmHeight; -@@ -1071,6 +1100,8 @@ VpuDecRetCode CDVDVideoCodecIMXBuffer::ReleaseFramebuffer(VpuDecHandle *handle) - m_rendered = false; - m_frameBuffer = NULL; - m_pts = DVD_NOPTS_VALUE; -+ SAFE_RELEASE(m_previousBuffer); -+ - return ret; - } - -@@ -1084,6 +1115,11 @@ double CDVDVideoCodecIMXBuffer::GetPts(void) const - return m_pts; - } - -+CDVDVideoCodecIMXBuffer *CDVDVideoCodecIMXBuffer::GetPreviousBuffer() const -+{ -+ return m_previousBuffer; -+} -+ - CDVDVideoCodecIMXBuffer::~CDVDVideoCodecIMXBuffer() - { - assert(m_refs == 0); -@@ -1149,23 +1185,29 @@ bool CDVDVideoCodecIPUBuffer::IsValid() - return m_source && m_source->IsValid() && m_pPhyAddr; - } - --bool CDVDVideoCodecIPUBuffer::Process(int fd, CDVDVideoCodecBuffer *currentBuffer, -- CDVDVideoCodecBuffer *previousBuffer, VpuFieldType fieldType) -+bool CDVDVideoCodecIPUBuffer::Process(int fd, CDVDVideoCodecIMXBuffer *buffer, -+ VpuFieldType fieldType, int fieldFmt, -+ bool lowMotion) - { -+ CDVDVideoCodecIMXBuffer *previousBuffer; - struct ipu_task task; - memset(&task, 0, sizeof(task)); - task.priority = IPU_TASK_PRIORITY_HIGH; - -+ if (lowMotion) -+ previousBuffer = buffer->GetPreviousBuffer(); -+ else -+ previousBuffer = NULL; -+ - SAFE_RELEASE(m_source); - -- iWidth = currentBuffer->iWidth; -- iHeight = currentBuffer->iHeight; -+ iWidth = buffer->iWidth; -+ iHeight = buffer->iHeight; - - // Input is the VPU decoded frame - task.input.width = iWidth; - task.input.height = iHeight; - task.input.format = IPU_PIX_FMT_NV12; -- task.input.paddr = (int)GET_PHYS_ADDR(currentBuffer); - - // Output is our IPU buffer - task.output.width = iWidth; -@@ -1173,29 +1215,32 @@ bool CDVDVideoCodecIPUBuffer::Process(int fd, CDVDVideoCodecBuffer *currentBuffe - task.output.format = IPU_PIX_FMT_NV12; - task.output.paddr = (int)GET_PHYS_ADDR(this); - -- // Fill previous buffer address -- if (previousBuffer) -- task.input.paddr_n = (int)GET_PHYS_ADDR(previousBuffer); -+ // Fill current and next buffer address -+ if (lowMotion && previousBuffer && previousBuffer->IsValid()) -+ { -+ task.input.paddr = (int)GET_PHYS_ADDR(previousBuffer); -+ task.input.paddr_n = (int)GET_PHYS_ADDR(buffer); -+ task.input.deinterlace.motion = LOW_MOTION; -+ } -+ else -+ { -+ task.input.paddr = (int)GET_PHYS_ADDR(buffer); -+ task.input.deinterlace.motion = HIGH_MOTION; -+ } - - task.input.deinterlace.enable = 1; -- task.input.deinterlace.motion = task.input.paddr_n?LOW_MOTION:HIGH_MOTION; -+ task.input.deinterlace.field_fmt = fieldFmt; - - switch (fieldType) - { - case VPU_FIELD_TOP: -- task.input.deinterlace.field_fmt = IPU_DEINTERLACE_FIELD_TOP; -- break; -- case VPU_FIELD_BOTTOM: -- task.input.deinterlace.field_fmt = IPU_DEINTERLACE_FIELD_BOTTOM; -- break; -- /* - case VPU_FIELD_TB: -- task.input.deinterlace.field_fmt = IPU_DEINTERLACE_FIELD_TOP; -+ task.input.deinterlace.field_fmt |= IPU_DEINTERLACE_FIELD_TOP; - break; -+ case VPU_FIELD_BOTTOM: - case VPU_FIELD_BT: -- task.input.deinterlace.field_fmt = IPU_DEINTERLACE_FIELD_BOTTOM; -+ task.input.deinterlace.field_fmt |= IPU_DEINTERLACE_FIELD_BOTTOM; - break; -- */ - default: - break; - } -@@ -1213,16 +1258,16 @@ bool CDVDVideoCodecIPUBuffer::Process(int fd, CDVDVideoCodecBuffer *currentBuffe - return false; - } - -- currentBuffer->Lock(); -+ buffer->Lock(); - - // Remember the source buffer. This is actually not necessary since the output - // buffer is the one that is used by the renderer. But keep it bound for now - // since this state is used in IsValid which then needs to become a flag in - // this class. -- m_source = currentBuffer; -+ m_source = buffer; - m_source->Lock(); - -- currentBuffer->Release(); -+ buffer->Release(); - - return true; - } -@@ -1321,7 +1366,7 @@ CDVDVideoCodecIPUBuffers::CDVDVideoCodecIPUBuffers() - : m_ipuHandle(0) - , m_bufferNum(0) - , m_buffers(NULL) -- , m_lastBuffer(NULL) -+ , m_currentFieldFmt(0) - { - } - -@@ -1349,6 +1394,7 @@ bool CDVDVideoCodecIPUBuffers::Init(int width, int height, int numBuffers, int n - - m_bufferNum = numBuffers; - m_buffers = new CDVDVideoCodecIPUBuffer*[m_bufferNum]; -+ m_currentFieldFmt = 0; - - for (int i=0; i < m_bufferNum; i++) - { -@@ -1369,9 +1415,9 @@ bool CDVDVideoCodecIPUBuffers::Init(int width, int height, int numBuffers, int n - - bool CDVDVideoCodecIPUBuffers::Reset() - { -- SAFE_RELEASE(m_lastBuffer); - for (int i=0; i < m_bufferNum; i++) - m_buffers[i]->ReleaseFrameBuffer(); -+ m_currentFieldFmt = 0; - } - - bool CDVDVideoCodecIPUBuffers::Close() -@@ -1407,7 +1453,6 @@ bool CDVDVideoCodecIPUBuffers::Close() - } - - m_bufferNum = 0; -- SAFE_RELEASE(m_lastBuffer); - return true; - } - -@@ -1418,7 +1463,8 @@ CDVDVideoCodecIPUBuffers::Process(CDVDVideoCodecBuffer *sourceBuffer, - CDVDVideoCodecIPUBuffer *target = NULL; - bool ret = true; - -- if (!m_bufferNum) -+ // TODO: Needs further checks on real streams -+ if (!m_bufferNum /*|| (fieldType == VPU_FIELD_NONE)*/) - return NULL; - - for (int i=0; i < m_bufferNum; i++ ) -@@ -1428,8 +1474,9 @@ CDVDVideoCodecIPUBuffers::Process(CDVDVideoCodecBuffer *sourceBuffer, - // IPU process: - // SRC: Current VPU physical buffer address + last VPU buffer address - // DST: IPU buffer[i] -- CDVDVideoCodecBuffer *last = lowMotion?m_lastBuffer:NULL; -- ret = m_buffers[i]->Process(m_ipuHandle, sourceBuffer, last, fieldType); -+ ret = m_buffers[i]->Process(m_ipuHandle, (CDVDVideoCodecIMXBuffer*)sourceBuffer, -+ fieldType, m_currentFieldFmt/* | IPU_DEINTERLACE_RATE_EN*/, -+ lowMotion); - if (ret) - { - #ifdef TRACE_FRAMES -@@ -1447,10 +1494,8 @@ CDVDVideoCodecIPUBuffers::Process(CDVDVideoCodecBuffer *sourceBuffer, - CLog::Log(LOGERROR, "Deinterlacing: did not find free buffer, forward unprocessed frame\n"); - } - -- SAFE_RELEASE(m_lastBuffer); -- m_lastBuffer = sourceBuffer; -- if (m_lastBuffer != NULL) -- m_lastBuffer->Lock(); -+ // Toggle frame index bit -+ //m_currentFieldFmt ^= IPU_DEINTERLACE_RATE_FRAME1; - - return target; - } -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h -index a76575f..05722ce 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h -@@ -66,12 +66,14 @@ class CDVDVideoCodecIMXBuffer : public CDVDVideoCodecBuffer - virtual bool IsValid(); - - bool Rendered() const; -- void Queue(VpuDecOutFrameInfo *frameInfo); -+ void Queue(VpuDecOutFrameInfo *frameInfo, -+ CDVDVideoCodecIMXBuffer *previous); - VpuDecRetCode ReleaseFramebuffer(VpuDecHandle *handle); - void SetPts(double pts); - double GetPts(void) const; -+ CDVDVideoCodecIMXBuffer *GetPreviousBuffer() const; - --protected: -+private: - // private because we are reference counted - virtual ~CDVDVideoCodecIMXBuffer(); - -@@ -83,6 +85,8 @@ class CDVDVideoCodecIMXBuffer : public CDVDVideoCodecBuffer - VpuFrameBuffer *m_frameBuffer; - bool m_rendered; - double m_pts; -+ CDVDVideoCodecIMXBuffer *m_previousBuffer; // Holds a the reference counted -+ // previous buffer - }; - - // Shared buffer that holds an IPU allocated memory block and serves as target -@@ -103,8 +107,9 @@ class CDVDVideoCodecIPUBuffer : public CDVDVideoCodecBuffer - - // Returns whether the buffer is ready to be used - bool Rendered() const { return m_source == NULL; } -- bool Process(int fd, CDVDVideoCodecBuffer *currentBuffer, -- CDVDVideoCodecBuffer *previousBuffer, VpuFieldType fieldType); -+ bool Process(int fd, CDVDVideoCodecIMXBuffer *buffer, -+ VpuFieldType fieldType, int fieldFmt, -+ bool lowMotion); - void ReleaseFrameBuffer(); - - bool Allocate(int fd, int width, int height, int nAlign); -@@ -146,7 +151,7 @@ class CDVDVideoCodecIPUBuffers - int m_ipuHandle; - int m_bufferNum; - CDVDVideoCodecIPUBuffer **m_buffers; -- CDVDVideoCodecBuffer *m_lastBuffer; -+ int m_currentFieldFmt; - }; - - -@@ -181,31 +186,30 @@ class CDVDVideoCodecIMX : public CDVDVideoCodec - 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; -- -- 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 -+ 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; -+ -+ 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 - CDVDVideoCodecIPUBuffers m_deinterlacer; - CDVDVideoCodecIMXBuffer **m_outputBuffers; -- VpuMemDesc *m_extraMem; // Table of allocated extra Memory --// VpuMemDesc *m_outputBuffers; // Table of buffers out of VPU (used to call properly VPU_DecOutFrameDisplayed) -- int m_frameCounter; // Decoded frames counter -- bool m_usePTS; // State whether pts out of decoding process should be used -- int m_modeDeinterlace; // Deinterlacer mode: 0=off, 1=high, 2..=low -- VpuDecOutFrameInfo m_frameInfo; -- CBitstreamConverter *m_converter; -- bool m_convert_bitstream; -- 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 -+ CDVDVideoCodecIMXBuffer *m_lastBuffer; -+ 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; -+ CBitstreamConverter *m_converter; -+ bool m_convert_bitstream; -+ 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 - }; --- -1.9.3 - - -From e376aa4d95b8d0a730cf04cefca417762e92c90b Mon Sep 17 00:00:00 2001 -From: Thomas Genty -Date: Sun, 6 Apr 2014 13:57:12 +0200 -Subject: [PATCH 48/50] detect imx device on all platform using file - /sys/class/graphics/fb0/fsl_disp_dev_property - ---- - xbmc/windowing/egl/EGLNativeTypeIMX.cpp | 12 +++++------- - 1 file changed, 5 insertions(+), 7 deletions(-) - -diff --git a/xbmc/windowing/egl/EGLNativeTypeIMX.cpp b/xbmc/windowing/egl/EGLNativeTypeIMX.cpp -index 4ffa708..404bd3c 100644 ---- a/xbmc/windowing/egl/EGLNativeTypeIMX.cpp -+++ b/xbmc/windowing/egl/EGLNativeTypeIMX.cpp -@@ -33,6 +33,7 @@ - #include "guilib/gui3d.h" - #include "windowing/WindowingFactory.h" - #include "cores/AudioEngine/AEFactory.h" -+#include - - CEGLNativeTypeIMX::CEGLNativeTypeIMX() - : m_display(NULL) -@@ -46,14 +47,11 @@ CEGLNativeTypeIMX::~CEGLNativeTypeIMX() - - bool CEGLNativeTypeIMX::CheckCompatibility() - { -- std::string strName; -- std::string str2 ("mxc_sdc_fb"); -- get_sysfs_str("/sys/class/graphics/fb0/device/modalias", strName); -- StringUtils::Trim(strName); -- size_t found = strName.find(str2); -- if (found!=std::string::npos) -+ std::ifstream file("/sys/class/graphics/fb0/fsl_disp_dev_property"); -+ if (!file) -+ return false; -+ else - return true; -- return false; - } - - void CEGLNativeTypeIMX::Initialize() --- -1.9.3 - - -From f7c5f0ada67613994651ab24a987f2f1b147bc70 Mon Sep 17 00:00:00 2001 -From: Thomas Genty -Date: Tue, 8 Apr 2014 19:02:52 +0200 -Subject: [PATCH 49/50] detect imx device on all platforms (try2) - ---- - xbmc/windowing/egl/EGLNativeTypeIMX.cpp | 5 +---- - 1 file changed, 1 insertion(+), 4 deletions(-) - -diff --git a/xbmc/windowing/egl/EGLNativeTypeIMX.cpp b/xbmc/windowing/egl/EGLNativeTypeIMX.cpp -index 404bd3c..3dc64a3 100644 ---- a/xbmc/windowing/egl/EGLNativeTypeIMX.cpp -+++ b/xbmc/windowing/egl/EGLNativeTypeIMX.cpp -@@ -48,10 +48,7 @@ CEGLNativeTypeIMX::~CEGLNativeTypeIMX() - bool CEGLNativeTypeIMX::CheckCompatibility() - { - std::ifstream file("/sys/class/graphics/fb0/fsl_disp_dev_property"); -- if (!file) -- return false; -- else -- return true; -+ return file; - } - - void CEGLNativeTypeIMX::Initialize() --- -1.9.3 - - -From 23c32ef03be062e088fbd760fc1758c5726f0c44 Mon Sep 17 00:00:00 2001 -From: wolfgar -Date: Mon, 23 Jun 2014 23:17:34 +0200 -Subject: [PATCH 50/50] Reenable hotplug devices check - ---- - xbmc/input/linux/LinuxInputDevices.cpp | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/xbmc/input/linux/LinuxInputDevices.cpp b/xbmc/input/linux/LinuxInputDevices.cpp -index 1446a56..85dbb80 100644 ---- a/xbmc/input/linux/LinuxInputDevices.cpp -+++ b/xbmc/input/linux/LinuxInputDevices.cpp -@@ -1228,7 +1228,7 @@ XBMC_Event CLinuxInputDevices::ReadEvent() - if ((now - m_lastHotplugCheck) >= 10) - { - // Comment for now as it has visible issue on video decoding when USB devices are available -- //CheckHotplugged(); -+ CheckHotplugged(); - m_lastHotplugCheck = now; - } - } --- -1.9.3 - diff --git a/projects/Cuboxi/patches/xbmc/xbmc-002-buildfix_after-74f3f02.patch b/projects/Cuboxi/patches/xbmc/xbmc-002-buildfix_after-74f3f02.patch deleted file mode 100644 index 8f76fc4a35f..00000000000 --- a/projects/Cuboxi/patches/xbmc/xbmc-002-buildfix_after-74f3f02.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff -Naur xbmc-master-14-dae6f76/xbmc/windowing/egl/EGLNativeTypeIMX.cpp xbmc-master-14-dae6f76.patch/xbmc/windowing/egl/EGLNativeTypeIMX.cpp ---- xbmc-master-14-dae6f76/xbmc/windowing/egl/EGLNativeTypeIMX.cpp 2014-07-11 04:38:24.091279024 +0200 -+++ xbmc-master-14-dae6f76.patch/xbmc/windowing/egl/EGLNativeTypeIMX.cpp 2014-07-11 04:48:46.630581643 +0200 -@@ -211,8 +211,7 @@ - - std::string valstr; - get_sysfs_str("/sys/class/graphics/fb0/modes", valstr); -- std::vector probe_str; -- StringUtils::SplitString(valstr, "\n", probe_str); -+ std::vector probe_str = StringUtils::Split(valstr, "\n"); - - resolutions.clear(); - RESOLUTION_INFO res;