From 5426ba5e9ca67f938332f35b6c2126681e0e618d Mon Sep 17 00:00:00 2001 From: Stephan Raue Date: Tue, 25 Nov 2014 00:23:20 +0100 Subject: [PATCH] kodi: add PR5805 Signed-off-by: Stephan Raue --- .../kodi/patches/kodi-999.92-PR5805.patch | 2617 +++++++++++++++++ 1 file changed, 2617 insertions(+) create mode 100644 packages/mediacenter/kodi/patches/kodi-999.92-PR5805.patch diff --git a/packages/mediacenter/kodi/patches/kodi-999.92-PR5805.patch b/packages/mediacenter/kodi/patches/kodi-999.92-PR5805.patch new file mode 100644 index 0000000000..b91ae60c83 --- /dev/null +++ b/packages/mediacenter/kodi/patches/kodi-999.92-PR5805.patch @@ -0,0 +1,2617 @@ +From a4346e241e4266cbc752133524a5e772982935c2 Mon Sep 17 00:00:00 2001 +From: smallint +Date: Mon, 24 Nov 2014 16:22:47 +0100 +Subject: [PATCH 1/3] FIX: [imx] @wolfgar Reworked deinterlacing and moved it + into a dedicated mixer thread + +--- + xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp | 59 +- + xbmc/cores/VideoRenderers/LinuxRendererGLES.h | 4 +- + .../dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp | 965 ++++++++++++++++++--- + .../dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h | 170 +++- + 4 files changed, 1063 insertions(+), 135 deletions(-) + +diff --git a/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp b/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp +index 81fe19b..58ebceb 100644 +--- a/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp ++++ b/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp +@@ -89,7 +89,12 @@ static PFNEGLCLIENTWAITSYNCKHRPROC eglClientWaitSyncKHR; + #include "windowing/egl/EGLWrapper.h" + #include "DVDCodecs/Video/DVDVideoCodecIMX.h" + ++#define GL_VIV_YV12 0x8FC0 + #define GL_VIV_NV12 0x8FC1 ++#define GL_VIV_YUY2 0x8FC2 ++#define GL_VIV_UYVY 0x8FC3 ++#define GL_VIV_NV21 0x8FC4 ++#define GL_VIV_I420 0x8FC5 + 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; +@@ -1681,20 +1686,25 @@ void CLinuxRendererGLES::RenderIMXMAPTexture(int index, int field) + #endif + + YUVPLANE &plane = m_buffers[index].fields[field][0]; +- CDVDVideoCodecIMXBuffer *buffer = m_buffers[index].IMXBuffer; ++ CDVDVideoCodecBufferTs *buffer = m_buffers[index].IMXBuffer; + +- if(buffer == NULL) return; ++#ifdef IMX_PROFILE_BUFFERS ++ static unsigned long long last = 0; ++ unsigned long long current = XbmcThreads::SystemClockMillis(); ++ CLog::Log(LOGNOTICE, "+R %x %lld\n", (int)buffer, current-last); ++ last = current; ++#endif + +- CDVDVideoCodecIMX::Enter(); ++ if(buffer == NULL) return; + + if(!buffer->IsValid()) + { +- CDVDVideoCodecIMX::Leave(); + return; + } + + glDisable(GL_DEPTH_TEST); + ++ glEnable(m_textureTarget); + glActiveTexture(GL_TEXTURE0); + glBindTexture(m_textureTarget, plane.id); + +@@ -1742,10 +1752,9 @@ void CLinuxRendererGLES::RenderIMXMAPTexture(int index, int field) + VerifyGLState(); + + glBindTexture(m_textureTarget, 0); ++ glDisable(m_textureTarget); + VerifyGLState(); + +- CDVDVideoCodecIMX::Leave(); +- + #ifdef DEBUG_VERBOSE + CLog::Log(LOGDEBUG, "RenderIMXMAPTexture %d: tm:%d\n", index, XbmcThreads::SystemClockMillis() - time); + #endif +@@ -2715,29 +2724,33 @@ void CLinuxRendererGLES::UploadIMXMAPTexture(int index) + { + #ifdef HAS_IMXVPU + YUVBUFFER& buf = m_buffers[index]; +- CDVDVideoCodecIMXBuffer* IMXBuffer = buf.IMXBuffer; ++ CDVDVideoCodecBufferTs* IMXBuffer = buf.IMXBuffer; + + if(IMXBuffer) + { +- CDVDVideoCodecIMX::Enter(); +- + if(!IMXBuffer->IsValid()) + { +- CDVDVideoCodecIMX::Leave(); + return; + } + + YUVPLANE &plane = m_buffers[index].fields[0][0]; + ++ glEnable(m_textureTarget); + glActiveTexture(GL_TEXTURE0); ++ + glBindTexture(m_textureTarget, plane.id); + + GLuint physical = ~0U; +- GLvoid *virt = (GLvoid*)IMXBuffer->m_VirtAddr; +- glTexDirectVIVMap(m_textureTarget, IMXBuffer->m_iWidth, IMXBuffer->m_iHeight, GL_VIV_NV12, +- (GLvoid **)&virt, &physical); +- glTexDirectInvalidateVIV(m_textureTarget); ++ GLvoid *virt = (GLvoid*)IMXBuffer->data[0]; + ++ if (IMXBuffer->data[3] == 0) ++ glTexDirectVIVMap(m_textureTarget, IMXBuffer->iWidth, IMXBuffer->iHeight, GL_VIV_I420, ++ (GLvoid **)&virt, &physical); ++ else ++ glTexDirectVIVMap(m_textureTarget, IMXBuffer->iWidth, IMXBuffer->iHeight, GL_VIV_NV12, ++ (GLvoid **)&virt, &physical); ++ ++ glTexDirectInvalidateVIV(m_textureTarget); + glBindTexture(m_textureTarget, 0); + + plane.flipindex = m_buffers[index].flipindex; +@@ -2746,7 +2759,7 @@ void CLinuxRendererGLES::UploadIMXMAPTexture(int index) + + CalculateTextureSourceRects(index, 1); + +- CDVDVideoCodecIMX::Leave(); ++ glDisable(m_textureTarget); + } + #endif + } +@@ -2864,9 +2877,6 @@ bool CLinuxRendererGLES::Supports(EDEINTERLACEMODE mode) + if(m_renderMethod & RENDER_CVREF) + return false; + +- if(m_renderMethod & RENDER_IMXMAP) +- return false; +- + if(mode == VS_DEINTERLACEMODE_AUTO + || mode == VS_DEINTERLACEMODE_FORCE) + return true; +@@ -2901,6 +2911,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 +@@ -2966,6 +2985,8 @@ unsigned int CLinuxRendererGLES::GetOptimalBufferSize() + m_format == RENDER_FMT_EGLIMG || + m_format == RENDER_FMT_MEDIACODEC) + return 2; ++ else if(m_format == RENDER_FMT_IMXMAP) ++ return 1; + else + return 3; + } +@@ -3043,7 +3064,7 @@ void CLinuxRendererGLES::AddProcessor(CDVDMediaCodecInfo *mediacodec, int index) + #endif + + #ifdef HAS_IMXVPU +-void CLinuxRendererGLES::AddProcessor(CDVDVideoCodecIMXBuffer *buffer, int index) ++void CLinuxRendererGLES::AddProcessor(CDVDVideoCodecBufferTs *buffer, int index) + { + YUVBUFFER &buf = m_buffers[index]; + +diff --git a/xbmc/cores/VideoRenderers/LinuxRendererGLES.h b/xbmc/cores/VideoRenderers/LinuxRendererGLES.h +index d8bf35d..105e820 100644 +--- a/xbmc/cores/VideoRenderers/LinuxRendererGLES.h ++++ b/xbmc/cores/VideoRenderers/LinuxRendererGLES.h +@@ -172,7 +172,7 @@ class CLinuxRendererGLES : public CBaseRenderer + virtual void AddProcessor(CDVDMediaCodecInfo *mediacodec, int index); + #endif + #ifdef HAS_IMXVPU +- virtual void AddProcessor(CDVDVideoCodecIMXBuffer *codecinfo, int index); ++ virtual void AddProcessor(CDVDVideoCodecBufferTs *codecinfo, int index); + #endif + + protected: +@@ -299,7 +299,7 @@ class CLinuxRendererGLES : public CBaseRenderer + CDVDMediaCodecInfo *mediacodec; + #endif + #ifdef HAS_IMXVPU +- CDVDVideoCodecIMXBuffer *IMXBuffer; ++ CDVDVideoCodecBufferTs *IMXBuffer; + #endif + }; + +diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp +index e8ccc67..39fb70c 100644 +--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp ++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp +@@ -26,21 +26,30 @@ + #include + #include + #include ++#include ++#include ++#include "settings/MediaSettings.h" ++#include "settings/VideoSettings.h" ++#include "settings/AdvancedSettings.h" + #include "threads/SingleLock.h" ++#include "threads/Atomics.h" + #include "utils/log.h" + #include "DVDClock.h" +-#include "settings/AdvancedSettings.h" +-#include "threads/Atomics.h" + + #define FRAME_ALIGN 16 + #define MEDIAINFO 1 + #define _4CC(c1,c2,c3,c4) (((uint32_t)(c4)<<24)|((uint32_t)(c3)<<16)|((uint32_t)(c2)<<8)|(uint32_t)(c1)) + #define Align(ptr,align) (((unsigned int)ptr + (align) - 1)/(align)*(align)) + ++// Helpers to extract physical and virtual addresses from CDVDVideoCodecBuffer pointers ++#define GET_VIRT_ADDR(buf) (buf)->data[0] ++#define GET_PHYS_ADDR(buf) (buf)->data[1] ++#define GET_FIELDTYPE(buf) (buf)->data[2] ++#define GET_FORMAT(buf) (buf)->data[3] // 0 = I420, 1 = NV12 ++ + // Experiments show that we need at least one more (+1) VPU buffer than the min value returned by the VPU + const int CDVDVideoCodecIMX::m_extraVpuBuffers = 6; + const int CDVDVideoCodecIMX::m_maxVpuDecodeLoops = 5; +-CCriticalSection CDVDVideoCodecIMX::m_codecBufferLock; + + bool CDVDVideoCodecIMX::VpuAllocBuffers(VpuMemInfo *pMemBlock) + { +@@ -90,8 +99,8 @@ bool CDVDVideoCodecIMX::VpuAllocBuffers(VpuMemInfo *pMemBlock) + return true; + + AllocFailure: +- VpuFreeBuffers(); +- return false; ++ VpuFreeBuffers(); ++ return false; + } + + int CDVDVideoCodecIMX::VpuFindBuffer(void *frameAddr) +@@ -185,7 +194,11 @@ bool CDVDVideoCodecIMX::VpuOpen(void) + VpuAllocBuffers(&memInfo); + + m_decOpenParam.nReorderEnable = 1; ++#ifdef IMX_INPUT_FORMAT_I420 ++ m_decOpenParam.nChromaInterleave = 0; ++#else + m_decOpenParam.nChromaInterleave = 1; ++#endif + m_decOpenParam.nMapType = 0; + m_decOpenParam.nTiled2LinearEnable = 0; + m_decOpenParam.nEnableFileMode = 0; +@@ -206,6 +219,24 @@ bool CDVDVideoCodecIMX::VpuOpen(void) + goto VpuOpenError; + } + ++ config = VPU_DEC_CONF_BUFDELAY; ++ param = 0; ++ ret = VPU_DecConfig(m_vpuHandle, config, ¶m); ++ if (ret != VPU_DEC_RET_SUCCESS) ++ { ++ CLog::Log(LOGERROR, "%s - iMX VPU set buffer delay failed (%d).\n", __FUNCTION__, ret); ++ goto VpuOpenError; ++ } ++ ++ config = VPU_DEC_CONF_INPUTTYPE; ++ param = VPU_DEC_IN_NORMAL; ++ ret = VPU_DecConfig(m_vpuHandle, config, ¶m); ++ if (ret != VPU_DEC_RET_SUCCESS) ++ { ++ CLog::Log(LOGERROR, "%s - iMX VPU configure input type failed (%d).\n", __FUNCTION__, ret); ++ 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 +@@ -227,14 +258,16 @@ bool CDVDVideoCodecIMX::VpuOpen(void) + + bool CDVDVideoCodecIMX::VpuAllocFrameBuffers(void) + { ++ int totalSize = 0; ++ int ySize = 0; ++ int uSize = 0; ++ int vSize = 0; ++ int mvSize = 0; ++ int yStride = 0; ++ int uvStride = 0; ++ + VpuDecRetCode ret; + VpuMemDesc vpuMem; +- int totalSize=0; +- int mvSize=0; +- int ySize=0; +- int uvSize=0; +- int yStride=0; +- int uvStride=0; + unsigned char* ptr; + unsigned char* ptrVirt; + int nAlign; +@@ -242,35 +275,59 @@ bool CDVDVideoCodecIMX::VpuAllocFrameBuffers(void) + m_vpuFrameBufferNum = m_initInfo.nMinFrameBufferCount + m_extraVpuBuffers; + m_vpuFrameBuffers = new VpuFrameBuffer[m_vpuFrameBufferNum]; + +- yStride=Align(m_initInfo.nPicWidth,FRAME_ALIGN); ++ 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)); ++ ySize = Align(m_initInfo.nPicWidth,FRAME_ALIGN)*Align(m_initInfo.nPicHeight,(2*FRAME_ALIGN)); + } + else + { +- ySize=Align(m_initInfo.nPicWidth,FRAME_ALIGN)*Align(m_initInfo.nPicHeight,FRAME_ALIGN); ++ ySize = Align(m_initInfo.nPicWidth,FRAME_ALIGN)*Align(m_initInfo.nPicHeight,FRAME_ALIGN); + } + +- //NV12 for all video +- uvStride=yStride; +- uvSize=ySize/2; +- mvSize=uvSize/2; ++#ifdef IMX_INPUT_FORMAT_I420 ++ switch (m_initInfo.nMjpgSourceFormat) ++ { ++ case 0: // I420 (4:2:0) ++ uvStride = yStride / 2; ++ uSize = vSize = mvSize = ySize / 4; ++ break; ++ case 1: // Y42B (4:2:2 horizontal) ++ uvStride = yStride / 2; ++ uSize = vSize = mvSize = ySize / 2; ++ break; ++ case 3: // Y444 (4:4:4) ++ uvStride = yStride; ++ uSize = vSize = mvSize = ySize; ++ break; ++ default: ++ CLog::Log(LOGERROR, "%s: invalid source format in init info\n",__FUNCTION__,ret); ++ return false; ++ } + +- nAlign=m_initInfo.nAddressAlignment; ++#else ++ // NV12 ++ uvStride = yStride; ++ uSize = ySize/2; ++ mvSize = uSize/2; ++#endif ++ ++ nAlign = m_initInfo.nAddressAlignment; + if(nAlign>1) + { +- ySize=Align(ySize,nAlign); +- uvSize=Align(uvSize,nAlign); ++ ySize = Align(ySize, nAlign); ++ uSize = Align(uSize, nAlign); ++ vSize = Align(vSize, nAlign); ++ mvSize = Align(mvSize, nAlign); + } + + m_outputBuffers = new CDVDVideoCodecIMXBuffer*[m_vpuFrameBufferNum]; + + for (int i=0 ; i < m_vpuFrameBufferNum; i++) + { +- totalSize=(ySize+uvSize+mvSize+nAlign)*1; ++ totalSize = ySize + uSize + vSize + mvSize + nAlign; + +- vpuMem.nSize=totalSize; ++ vpuMem.nSize = totalSize; + ret = VPU_DecGetMem(&vpuMem); + if(ret != VPU_DEC_RET_SUCCESS) + { +@@ -287,36 +344,44 @@ bool CDVDVideoCodecIMX::VpuAllocFrameBuffers(void) + m_decMemInfo.phyMem[m_decMemInfo.nPhyNum-1].nSize = vpuMem.nSize; + + //fill frameBuf +- ptr=(unsigned char*)vpuMem.nPhyAddr; +- ptrVirt=(unsigned char*)vpuMem.nVirtAddr; ++ 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); ++ 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; ++ 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; ++ m_vpuFrameBuffers[i].pbufY = ptr; ++ m_vpuFrameBuffers[i].pbufCb = ptr + ySize; ++#ifdef IMX_INPUT_FORMAT_I420 ++ m_vpuFrameBuffers[i].pbufCr = ptr + ySize + uSize; ++#else ++ m_vpuFrameBuffers[i].pbufCr = 0; ++#endif ++ m_vpuFrameBuffers[i].pbufMvCol = ptr + ySize + uSize + vSize; + + // fill virt addr +- m_vpuFrameBuffers[i].pbufVirtY=ptrVirt; +- m_vpuFrameBuffers[i].pbufVirtCb=ptrVirt+ySize; +- m_vpuFrameBuffers[i].pbufVirtCr=0; +- m_vpuFrameBuffers[i].pbufVirtMvCol=ptrVirt+ySize+uvSize; ++ m_vpuFrameBuffers[i].pbufVirtY = ptrVirt; ++ m_vpuFrameBuffers[i].pbufVirtCb = ptrVirt + ySize; ++#ifdef IMX_INPUT_FORMAT_I420 ++ m_vpuFrameBuffers[i].pbufVirtCr = ptrVirt + ySize + uSize; ++#else ++ m_vpuFrameBuffers[i].pbufVirtCr = 0; ++#endif ++ m_vpuFrameBuffers[i].pbufVirtMvCol = ptrVirt + ySize + uSize + vSize; + +- 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_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); +@@ -325,16 +390,25 @@ bool CDVDVideoCodecIMX::VpuAllocFrameBuffers(void) + #endif + } + ++ CLog::Log(LOGNOTICE, "IMX: Initialize hardware deinterlacing\n"); ++ if (!m_deinterlacer.Init(m_initInfo.nPicWidth, m_initInfo.nPicHeight, GetAllowedReferences()+5, nAlign)) ++ { ++ CLog::Log(LOGWARNING, "IMX: Failed to initialize IPU buffers: deinterlacing disabled\n"); ++ } ++ ++ m_deinterlacer.SetAutoMode(m_initInfo.nInterlace); ++ + return true; + } + +-CDVDVideoCodecIMX::CDVDVideoCodecIMX() ++CDVDVideoCodecIMX::CDVDVideoCodecIMX() : m_mixer(&m_deinterlacer) + { + m_pFormatName = "iMX-xxx"; + m_vpuHandle = 0; + m_vpuFrameBuffers = NULL; + m_outputBuffers = NULL; + m_lastBuffer = NULL; ++ m_currentBuffer = NULL; + m_extraMem = NULL; + m_vpuFrameBufferNum = 0; + m_dropState = false; +@@ -349,6 +423,7 @@ CDVDVideoCodecIMX::CDVDVideoCodecIMX() + m_convert_bitstream = false; + m_bytesToBeConsumed = 0; + m_previousPts = DVD_NOPTS_VALUE; ++ m_mixer.SetCapacity(3,3); + } + + CDVDVideoCodecIMX::~CDVDVideoCodecIMX() +@@ -487,6 +562,8 @@ bool CDVDVideoCodecIMX::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options) + return false; + } + ++ m_mixer.Start(); ++ + return true; + } + +@@ -495,12 +572,12 @@ void CDVDVideoCodecIMX::Dispose(void) + VpuDecRetCode ret; + bool VPU_loaded = m_vpuHandle; + +- // Prevent rendering thread from using frame buffers +- Enter(); ++ // Dispose the mixer thread ++ m_mixer.Dispose(); + + // Release last buffer +- if(m_lastBuffer) +- SAFE_RELEASE(m_lastBuffer); ++ SAFE_RELEASE(m_lastBuffer); ++ SAFE_RELEASE(m_currentBuffer); + + // Invalidate output buffers to prevent the renderer from mapping this memory + for (int i=0; inFrmWidth = (((m_frameInfo.pExtInfo->nFrmWidth) + 15) & ~15); + m_frameInfo.pExtInfo->nFrmHeight = (((m_frameInfo.pExtInfo->nFrmHeight) + 15) & ~15); + +- retStatus |= VC_PICTURE; ++ idx = VpuFindBuffer(m_frameInfo.pDisplayFrameBuf->pbufY); ++ if (idx != -1) ++ { ++ CDVDVideoCodecIMXBuffer *buffer = m_outputBuffers[idx]; ++ buffer->Lock(); ++ buffer->SetDts(dts); ++ buffer->Queue(&m_frameInfo, m_lastBuffer); ++ ++#ifdef IMX_PROFILE_BUFFERS ++ CLog::Log(LOGNOTICE, "+D %x %lld\n", buffer, dec_time); ++ dec_time = 0; ++#endif ++ ++#ifdef TRACE_FRAMES ++ CLog::Log(LOGDEBUG, "+ %02d dts %f pts %f (VPU)\n", idx, pDvdVideoPicture->dts, pDvdVideoPicture->pts); ++#endif ++ ++ if (!m_usePTS) ++ { ++ buffer->SetPts(DVD_NOPTS_VALUE); ++ buffer->SetDts(DVD_NOPTS_VALUE); ++ } ++ ++ // Save last buffer ++ SAFE_RELEASE(m_lastBuffer); ++ m_lastBuffer = buffer; ++ m_lastBuffer->Lock(); ++ ++#ifdef IMX_PROFILE_BUFFERS ++ static unsigned long long lastD = 0; ++ unsigned long long current = XbmcThreads::SystemClockMillis(), tmp; ++ CLog::Log(LOGNOTICE, "+V %x %lld\n", buffer, current-lastD); ++ lastD = current; ++#endif ++ ++ //m_currentBuffer = buffer; ++ if (m_dropState) ++ { ++ m_currentBuffer = m_mixer.Process(NULL); ++ if (!m_currentBuffer) ++ m_currentBuffer = buffer; ++ else ++ buffer->Release(); ++ } ++ else ++ m_currentBuffer = m_mixer.Process(buffer); ++ ++ if (m_currentBuffer) ++ { ++ retStatus |= VC_PICTURE; ++ //m_currentBuffer->Release(); ++ //m_currentBuffer = NULL; ++ } ++ } + } //VPU_DEC_OUTPUT_DIS + + // According to libfslvpuwrap: If this flag is set then the frame should +@@ -813,7 +956,18 @@ int CDVDVideoCodecIMX::Decode(BYTE *pData, int iSize, double dts, double pts) + + if (retStatus == 0) + { +- retStatus |= VC_BUFFER; ++ /* We do not flush currently ++ m_currentBuffer = m_mixer.Process(NULL); ++ if (m_currentBuffer) ++ { ++ retStatus |= VC_PICTURE; ++ //m_currentBuffer->Release(); ++ //m_currentBuffer = NULL; ++ } ++ else*/ ++ { ++ retStatus |= VC_BUFFER; ++ } + } + + if (m_bytesToBeConsumed > 0) +@@ -824,8 +978,8 @@ int CDVDVideoCodecIMX::Decode(BYTE *pData, int iSize, double dts, double pts) + // at next call... + m_previousPts = pts; + } +- // Store current dts (will be used only if VC_PICTURE is set) +- m_dts = dts; ++ ++ /*lastEnter = XbmcThreads::SystemClockMillis();*/ + + #ifdef IMX_PROFILE + CLog::Log(LOGDEBUG, "%s - returns %x - duration %lld\n", __FUNCTION__, retStatus, XbmcThreads::SystemClockMillis() - previous); +@@ -843,9 +997,13 @@ void CDVDVideoCodecIMX::Reset() + if (g_advancedSettings.CanLogComponent(LOGVIDEO)) + CLog::Log(LOGDEBUG, "%s - called\n", __FUNCTION__); + ++ // Restart mixer ++ m_mixer.Dispose(); ++ m_mixer.Start(); ++ + // Release last buffer +- if(m_lastBuffer) +- SAFE_RELEASE(m_lastBuffer); ++ SAFE_RELEASE(m_lastBuffer); ++ SAFE_RELEASE(m_currentBuffer); + + // Invalidate all buffers + for(int i=0; i < m_vpuFrameBufferNum; i++) +@@ -906,38 +1064,12 @@ bool CDVDVideoCodecIMX::GetPicture(DVDVideoPicture* pDvdVideoPicture) + 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; +- } ++ // Current buffer is locked already -> hot potato ++ pDvdVideoPicture->pts = m_currentBuffer->GetPts(); ++ pDvdVideoPicture->dts = m_currentBuffer->GetDts(); + +- buffer->Queue(&m_frameInfo, m_lastBuffer); +- +-#ifdef TRACE_FRAMES +- CLog::Log(LOGDEBUG, "+ %02d dts %f pts %f (VPU)\n", idx, pDvdVideoPicture->dts, pDvdVideoPicture->pts); +-#endif +- +- pDvdVideoPicture->IMXBuffer = buffer; +- pDvdVideoPicture->IMXBuffer->Lock(); +- +- // Save last buffer +- if (m_lastBuffer) +- SAFE_RELEASE(m_lastBuffer); +- m_lastBuffer = buffer; +- m_lastBuffer->Lock(); +- } +- else +- { +- CLog::Log(LOGERROR, "%s - could not find frame buffer\n", __FUNCTION__); +- } ++ pDvdVideoPicture->codecinfo = m_currentBuffer; ++ m_currentBuffer = NULL; + + return true; + } +@@ -958,17 +1090,33 @@ void CDVDVideoCodecIMX::SetDropState(bool bDrop) + } + } + +-void CDVDVideoCodecIMX::Enter() ++/*******************************************/ ++ ++CDVDVideoCodecBufferTs::CDVDVideoCodecBufferTs() ++ : m_pts(DVD_NOPTS_VALUE) ++ , m_dts(DVD_NOPTS_VALUE) + { +- m_codecBufferLock.lock(); + } + +-void CDVDVideoCodecIMX::Leave() ++void CDVDVideoCodecBufferTs::SetPts(double pts) + { +- m_codecBufferLock.unlock(); ++ m_pts = pts; + } + +-/*******************************************/ ++double CDVDVideoCodecBufferTs::GetPts(void) const ++{ ++ return m_pts; ++} ++ ++void CDVDVideoCodecBufferTs::SetDts(double dts) ++{ ++ m_dts = dts; ++} ++ ++double CDVDVideoCodecBufferTs::GetDts(void) const ++{ ++ return m_dts; ++} + + #ifdef TRACE_FRAMES + CDVDVideoCodecIMXBuffer::CDVDVideoCodecIMXBuffer(int idx) +@@ -980,7 +1128,6 @@ CDVDVideoCodecIMXBuffer::CDVDVideoCodecIMXBuffer() + #endif + , m_frameBuffer(NULL) + , m_rendered(false) +- , m_pts(DVD_NOPTS_VALUE) + , m_previousBuffer(NULL) + { + } +@@ -1048,10 +1195,17 @@ void CDVDVideoCodecIMXBuffer::Queue(VpuDecOutFrameInfo *frameInfo, + if (m_previousBuffer) + m_previousBuffer->Lock(); + +- m_iWidth = frameInfo->pExtInfo->nFrmWidth; +- m_iHeight = frameInfo->pExtInfo->nFrmHeight; +- m_VirtAddr = m_frameBuffer->pbufVirtY; +- m_phyAddr = m_frameBuffer->pbufY; ++ 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; ++ // We decode to I420 ++#ifdef IMX_INPUT_FORMAT_I420 ++ GET_FORMAT(this) = (uint8_t*)0; ++#else ++ GET_FORMAT(this) = (uint8_t*)1; ++#endif + } + + VpuDecRetCode CDVDVideoCodecIMXBuffer::ReleaseFramebuffer(VpuDecHandle *handle) +@@ -1071,31 +1225,632 @@ VpuDecRetCode CDVDVideoCodecIMXBuffer::ReleaseFramebuffer(VpuDecHandle *handle) + #endif + m_rendered = false; + m_frameBuffer = NULL; +- m_pts = DVD_NOPTS_VALUE; ++ SetPts(DVD_NOPTS_VALUE); + SAFE_RELEASE(m_previousBuffer); + + return ret; + } + +-void CDVDVideoCodecIMXBuffer::SetPts(double pts) ++CDVDVideoCodecIMXBuffer *CDVDVideoCodecIMXBuffer::GetPreviousBuffer() const + { +- m_pts = pts; ++ return m_previousBuffer; + } + +-double CDVDVideoCodecIMXBuffer::GetPts(void) const ++CDVDVideoCodecIMXBuffer::~CDVDVideoCodecIMXBuffer() + { +- return m_pts; ++ assert(m_refs == 0); ++#ifdef TRACE_FRAMES ++ CLog::Log(LOGDEBUG, "~ %02d (VPU)\n", m_idx); ++#endif + } + +-CDVDVideoCodecIMXBuffer *CDVDVideoCodecIMXBuffer::GetPreviousBuffer() const ++#ifdef TRACE_FRAMES ++CDVDVideoCodecIPUBuffer::CDVDVideoCodecIPUBuffer(int idx) ++ : m_refs(1) ++ , m_idx(idx) ++#else ++CDVDVideoCodecIPUBuffer::CDVDVideoCodecIPUBuffer() ++ : m_refs(1) ++#endif ++ , m_bFree(true) ++ , m_pPhyAddr(0) ++ , m_pVirtAddr(NULL) ++ , m_nSize(0) + { +- return m_previousBuffer; + } + +-CDVDVideoCodecIMXBuffer::~CDVDVideoCodecIMXBuffer() ++CDVDVideoCodecIPUBuffer::~CDVDVideoCodecIPUBuffer() + { + assert(m_refs == 0); + #ifdef TRACE_FRAMES +- CLog::Log(LOGDEBUG, "~ %02d (VPU)\n", m_idx); ++ 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; ++ ++ m_bFree = true; ++ iWidth = buffer->iWidth; ++ iHeight = buffer->iHeight; ++ ++ // Input is the VPU decoded frame ++ task.input.width = iWidth; ++ task.input.height = iHeight; ++#ifdef IMX_INPUT_FORMAT_I420 ++ task.input.format = IPU_PIX_FMT_YUV420P; ++#else ++ task.input.format = IPU_PIX_FMT_NV12; ++#endif ++ ++ // Output is our IPU buffer ++ task.output.width = iWidth; ++ task.output.height = iHeight; ++#ifdef IMX_OUTPUT_FORMAT_I420 ++ task.output.format = IPU_PIX_FMT_YUV420P; ++ GET_FORMAT(this) = (uint8_t*)0; ++#else ++ task.output.format = IPU_PIX_FMT_NV12; ++ GET_FORMAT(this) = (uint8_t*)1; ++#endif ++ 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; ++ } ++ ++ m_bFree = false; ++ buffer->Lock(); ++ ++ // Copy PTS ++ SetPts(buffer->GetPts()); ++ SetDts(buffer->GetDts()); ++ ++ buffer->Release(); ++ ++ return true; ++} ++ ++void CDVDVideoCodecIPUBuffer::ReleaseFrameBuffer() ++{ ++#ifdef TRACE_FRAMES ++ CLog::Log(LOGDEBUG, "- %02d (IPU)\n", m_idx); ++#endif ++ m_bFree = true; ++} ++ ++bool CDVDVideoCodecIPUBuffer::Allocate(int fd, int width, int height, int nAlign) ++{ ++ m_iWidth = Align(width,FRAME_ALIGN); ++ m_iHeight = Align(height,(2*FRAME_ALIGN)); ++ // I420 == 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) ++{ ++ 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; ++ m_bFree = true; ++ ++ 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; ++ ++ if (!m_bufferNum) ++ 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, ++ 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"); ++ } ++ ++ return target; ++} ++ ++ ++CDVDVideoMixerIMX::CDVDVideoMixerIMX(CDVDVideoCodecIPUBuffers *proc) ++ : CThread("IMX6 Mixer") ++ , m_beginInput(0), m_endInput(0), m_bufferedInput(0) ++ , m_beginOutput(0), m_endOutput(0), m_bufferedOutput(0) ++ , m_proc(proc) ++{ ++} ++ ++CDVDVideoMixerIMX::~CDVDVideoMixerIMX() ++{ ++ Dispose(); ++} ++ ++void CDVDVideoMixerIMX::SetCapacity(int nInput, int nOutput) ++{ ++ Reset(); ++ m_input.resize(nInput); ++ m_output.resize(nOutput); ++} ++ ++void CDVDVideoMixerIMX::Start() ++{ ++ Create(); ++} ++ ++void CDVDVideoMixerIMX::Reset() ++{ ++ CSingleLock lk(m_monitor); ++ ++ // Release all still referenced buffers ++ for (size_t i = 0; i < m_input.size(); ++i) ++ { ++ SAFE_RELEASE(m_input[i]); ++ m_input[i] = NULL; ++ } ++ ++ for (size_t i = 0; i < m_output.size(); ++i) ++ { ++ SAFE_RELEASE(m_output[i]); ++ m_output[i] = NULL; ++ } ++ ++ // Reset ring buffer ++ m_beginInput = m_endInput = m_bufferedInput = 0; ++ m_beginOutput = m_endOutput = m_bufferedOutput = 0; ++ ++ m_inputNotFull.notifyAll(); ++ m_outputNotFull.notifyAll(); ++} ++ ++void CDVDVideoMixerIMX::Dispose() ++{ ++ StopThread(); ++ Reset(); ++} ++ ++bool CDVDVideoMixerIMX::IsActive() { ++ return IsRunning(); ++} ++ ++CDVDVideoCodecBufferTs *CDVDVideoMixerIMX::Process(CDVDVideoCodecIMXBuffer *buffer) ++{ ++ CSingleLock lk(m_monitor); ++ CDVDVideoCodecBufferTs *r; ++ ++ if (m_bStop) ++ { ++ m_inputNotEmpty.notifyAll(); ++ m_outputNotFull.notifyAll(); ++ SAFE_RELEASE(buffer); ++ return NULL; ++ } ++ ++ if (m_bufferedOutput) ++ { ++ // Pop the output ++ r = m_output[m_beginOutput]; ++ m_output[m_beginOutput] = NULL; ++ m_beginOutput = (m_beginOutput+1) % m_output.size(); ++ --m_bufferedOutput; ++ m_outputNotFull.notifyAll(); ++ } ++ else ++ r = NULL; ++ ++ // Flush call? ++ if (!buffer) ++ return r; ++ ++ // If the input queue is full, wait for a free slot ++ while ((m_bufferedInput == m_input.size()) && !m_bStop) ++ m_inputNotFull.wait(lk); ++ ++ if (m_bStop) ++ { ++ m_inputNotEmpty.notifyAll(); ++ m_outputNotFull.notifyAll(); ++ buffer->Release(); ++ return r; ++ } ++ ++ // Store the value ++ m_input[m_endInput] = buffer; ++ m_endInput = (m_endInput+1) % m_input.size(); ++ ++m_bufferedInput; ++ m_inputNotEmpty.notifyAll(); ++ ++ //CLog::Log(LOGNOTICE, "Pushed input frame %x\n", (int)buffer); ++ ++ return r; ++} ++ ++void CDVDVideoMixerIMX::OnStartup() ++{ ++ CLog::Log(LOGNOTICE, "CDVDVideoMixerIMX::OnStartup: Mixer Thread created"); ++} ++ ++void CDVDVideoMixerIMX::OnExit() ++{ ++ CLog::Log(LOGNOTICE, "CDVDVideoMixerIMX::OnExit: Mixer Thread terminated"); ++} ++ ++void CDVDVideoMixerIMX::StopThread(bool bWait /*= true*/) ++{ ++ CThread::StopThread(false); ++ m_inputNotFull.notifyAll(); ++ m_inputNotEmpty.notifyAll(); ++ m_outputNotFull.notifyAll(); ++ if (bWait) ++ CThread::StopThread(true); ++} ++ ++void CDVDVideoMixerIMX::Process() ++{ ++ while (!m_bStop) ++ { ++ // Blocking until an input is available ++ CDVDVideoCodecIMXBuffer *inputBuffer = GetNextInput(); ++ if (inputBuffer) ++ { ++ // Wait for free slot ++ WaitForFreeOutput(); ++ ++ CDVDVideoCodecBufferTs *outputBuffer = ProcessFrame(inputBuffer); ++ ++ // Queue the output if any ++ if (outputBuffer) ++ { ++ // Blocking until a free output slot is available. The buffer is ++ // reference counted in PushOutput ++ PushOutput(outputBuffer); ++ } ++ ++ SAFE_RELEASE(inputBuffer); ++ } ++ } ++} ++ ++CDVDVideoCodecIMXBuffer *CDVDVideoMixerIMX::GetNextInput() { ++ CSingleLock lk(m_monitor); ++ while (!m_bufferedInput && !m_bStop) ++ m_inputNotEmpty.wait(lk); ++ ++ if (m_bStop) ++ return NULL; ++ ++ CDVDVideoCodecIMXBuffer *v = m_input[m_beginInput]; ++ m_input[m_beginInput] = NULL; ++ m_beginInput = (m_beginInput+1) % m_input.size(); ++ --m_bufferedInput; ++ m_inputNotFull.notifyAll(); ++ ++ //CLog::Log(LOGNOTICE, "Popped input frame %x\n", (int)v); ++ ++ return v; ++} ++ ++void CDVDVideoMixerIMX::WaitForFreeOutput() { ++ CSingleLock lk(m_monitor); ++ ++ // Output queue is full, wait for a free slot ++ while (m_bufferedOutput == m_output.size() && !m_bStop) ++ m_outputNotFull.wait(lk); ++} ++ ++bool CDVDVideoMixerIMX::PushOutput(CDVDVideoCodecBufferTs *v) { ++ CSingleLock lk(m_monitor); ++ ++ v->Lock(); ++ ++ // If closed return false ++ if (m_bStop) ++ { ++ v->Release(); ++ return false; ++ } ++ ++ // Store the value ++ m_output[m_endOutput] = v; ++ m_endOutput = (m_endOutput+1) % m_output.size(); ++ ++m_bufferedOutput; ++ ++ return true; ++} ++ ++CDVDVideoCodecBufferTs *CDVDVideoMixerIMX::ProcessFrame(CDVDVideoCodecIMXBuffer *inputBuffer) ++{ ++ CDVDVideoCodecBufferTs *outputBuffer; ++ EDEINTERLACEMODE mDeintMode = CMediaSettings::Get().GetCurrentVideoSettings().m_DeinterlaceMode; ++ //EINTERLACEMETHOD mInt = CMediaSettings::Get().GetCurrentVideoSettings().m_InterlaceMethod; ++ ++ if ((mDeintMode == VS_DEINTERLACEMODE_OFF) ++ || ((mDeintMode == VS_DEINTERLACEMODE_AUTO) && !m_proc->AutoMode())) ++ { ++ outputBuffer = inputBuffer; ++ } ++ else ++ { ++#ifdef IMX_PROFILE_BUFFERS ++ unsigned long long current = XbmcThreads::SystemClockMillis(); ++#endif ++//#define DUMMY_DEINTERLACER ++#ifdef DUMMY_DEINTERLACER ++ Sleep(35); ++ outputBuffer = inputBuffer; ++#else ++ outputBuffer = m_proc->Process(inputBuffer, ++ (VpuFieldType)(int)GET_FIELDTYPE(inputBuffer), ++ false); ++#endif ++#ifdef IMX_PROFILE_BUFFERS ++ CLog::Log(LOGNOTICE, "+P %x %lld\n", (int)outputBuffer, ++ XbmcThreads::SystemClockMillis()-current); ++#endif ++ } ++ ++ return outputBuffer; ++} +diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h +index 6533683..186a4fd 100644 +--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h ++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h +@@ -19,13 +19,34 @@ + * + */ + #include ++#include + #include + #include "DVDVideoCodec.h" + #include "DVDStreamInfo.h" + #include "threads/CriticalSection.h" ++#include "threads/Condition.h" ++#include "threads/Event.h" ++#include "threads/Thread.h" + #include "utils/BitstreamConverter.h" + + ++// The decoding format of the VPU buffer. Comment this to decode ++// as NV12. The VPU works faster with I420. ++#define IMX_INPUT_FORMAT_I420 ++ ++// The deinterlacer output and render format. Uncomment to use I420. ++// The IPU works faster when outputting to NV12. ++//#define IMX_OUTPUT_FORMAT_I420 ++ ++// This enables logging of times for Decode->Decode, Render->Render, ++// Deinterlace->Deinterlace. It helps to profile several stages of ++// processing with respect to changed kernels or other configurations. ++// Since we utilize VPU, IPU and GPU at the same time different kernel ++// priorities to those subsystems can result in a very different user ++// experience. With that setting enabled we can build some statistics, ++// as numbers are always better than "feelings" ++//#define IMX_PROFILE_BUFFERS ++ + //#define IMX_PROFILE + //#define TRACE_FRAMES + +@@ -48,7 +69,25 @@ class CDecMemInfo + VpuMemDesc* phyMem; + }; + +-class CDVDVideoCodecIMXBuffer ++ ++class CDVDVideoCodecBufferTs : public CDVDVideoCodecBuffer { ++public: ++ CDVDVideoCodecBufferTs(); ++ ++ void SetPts(double pts); ++ double GetPts(void) const; ++ ++ void SetDts(double dts); ++ double GetDts(void) const; ++ ++private: ++ double m_pts; ++ double m_dts; ++}; ++ ++class CDVDVideoCodecIPUBuffer; ++ ++class CDVDVideoCodecIMXBuffer : public CDVDVideoCodecBufferTs + { + public: + #ifdef TRACE_FRAMES +@@ -66,8 +105,6 @@ class CDVDVideoCodecIMXBuffer + void Queue(VpuDecOutFrameInfo *frameInfo, + CDVDVideoCodecIMXBuffer *previous); + VpuDecRetCode ReleaseFramebuffer(VpuDecHandle *handle); +- void SetPts(double pts); +- double GetPts(void) const; + CDVDVideoCodecIMXBuffer *GetPreviousBuffer() const; + + uint32_t m_iWidth; +@@ -86,11 +123,128 @@ class CDVDVideoCodecIMXBuffer + 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 CDVDVideoCodecBufferTs ++{ ++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_bFree; } ++ 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; ++ bool m_bFree; ++ 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); ++ // Sets the mode to be used if deinterlacing is set to AUTO ++ void SetAutoMode(bool mode) { m_autoMode = mode; } ++ bool AutoMode() const { return m_autoMode; } ++ bool Reset(); ++ bool Close(); ++ ++ CDVDVideoCodecIPUBuffer *Process(CDVDVideoCodecBuffer *sourceBuffer, ++ VpuFieldType fieldType, bool lowMotion); ++ ++ private: ++ int m_ipuHandle; ++ bool m_autoMode; ++ int m_bufferNum; ++ CDVDVideoCodecIPUBuffer **m_buffers; ++ int m_currentFieldFmt; ++}; ++ ++ ++class CDVDVideoMixerIMX : private CThread { ++public: ++ CDVDVideoMixerIMX(CDVDVideoCodecIPUBuffers *proc); ++ virtual ~CDVDVideoMixerIMX(); ++ ++ void SetCapacity(int intput, int output); ++ ++ void Start(); ++ void Reset(); ++ void Dispose(); ++ bool IsActive(); ++ ++ // This function blocks until an input slot is available. ++ // It returns if an output is available. ++ CDVDVideoCodecBufferTs *Process(CDVDVideoCodecIMXBuffer *input); ++ ++private: ++ CDVDVideoCodecIMXBuffer *GetNextInput(); ++ void WaitForFreeOutput(); ++ bool PushOutput(CDVDVideoCodecBufferTs *v); ++ CDVDVideoCodecBufferTs *ProcessFrame(CDVDVideoCodecIMXBuffer *input); ++ ++ virtual void OnStartup(); ++ virtual void OnExit(); ++ virtual void StopThread(bool bWait = true); ++ virtual void Process(); ++ ++private: ++ typedef std::vector InputBuffers; ++ typedef std::vector OutputBuffers; ++ ++ CDVDVideoCodecIPUBuffers *m_proc; ++ InputBuffers m_input; ++ volatile int m_beginInput, m_endInput; ++ volatile size_t m_bufferedInput; ++ XbmcThreads::ConditionVariable m_inputNotEmpty; ++ XbmcThreads::ConditionVariable m_inputNotFull; ++ ++ OutputBuffers m_output; ++ volatile int m_beginOutput, m_endOutput; ++ volatile size_t m_bufferedOutput; ++ XbmcThreads::ConditionVariable m_outputNotFull; ++ ++ mutable CCriticalSection m_monitor; ++ CDVDVideoCodecBufferTs *m_lastFrame; // Last input frame ++}; ++ ++ + class CDVDVideoCodecIMX : public CDVDVideoCodec + { + friend class CDVDVideoCodecIMXBuffer; +@@ -111,9 +265,6 @@ 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(); +@@ -124,7 +275,6 @@ class CDVDVideoCodecIMX : public CDVDVideoCodec + + static const int m_extraVpuBuffers; // Number of additional buffers for VPU + static const int m_maxVpuDecodeLoops; // Maximum iterations in VPU decoding loop +- static CCriticalSection m_codecBufferLock; // Lock to protect buffers handled + // by both decoding and rendering threads + + CDVDStreamInfo m_hints; // Hints from demuxer at stream opening +@@ -136,8 +286,11 @@ class CDVDVideoCodecIMX : public CDVDVideoCodec + 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; // Pool of buffers used for deinterlacing ++ CDVDVideoMixerIMX m_mixer; + CDVDVideoCodecIMXBuffer **m_outputBuffers; // Table of VPU output buffers + CDVDVideoCodecIMXBuffer *m_lastBuffer; // Keep track of previous VPU output buffer (needed by deinterlacing motion engin) ++ CDVDVideoCodecBufferTs *m_currentBuffer; + 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 +@@ -147,5 +300,4 @@ 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 + }; + +From 01affb951b56866335e59089fe44dc51d64de816 Mon Sep 17 00:00:00 2001 +From: smallint +Date: Mon, 24 Nov 2014 20:22:32 +0100 +Subject: [PATCH 2/3] FIX: [imx] @wolfgar Made deinterlacing rework patch + compile with Kodi + +--- + xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp | 16 +- + xbmc/cores/VideoRenderers/LinuxRendererGLES.h | 7 +- + .../dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp | 183 ++++++++++---------- + .../dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h | 190 +++++++++++---------- + 4 files changed, 201 insertions(+), 195 deletions(-) + +diff --git a/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp b/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp +index 58ebceb..037a57b 100644 +--- a/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp ++++ b/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp +@@ -1242,7 +1242,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); +@@ -1686,7 +1686,7 @@ void CLinuxRendererGLES::RenderIMXMAPTexture(int index, int field) + #endif + + YUVPLANE &plane = m_buffers[index].fields[field][0]; +- CDVDVideoCodecBufferTs *buffer = m_buffers[index].IMXBuffer; ++ CDVDVideoCodecIMXBuffer *buffer = m_buffers[index].IMXBuffer; + + #ifdef IMX_PROFILE_BUFFERS + static unsigned long long last = 0; +@@ -2724,7 +2724,7 @@ void CLinuxRendererGLES::UploadIMXMAPTexture(int index) + { + #ifdef HAS_IMXVPU + YUVBUFFER& buf = m_buffers[index]; +- CDVDVideoCodecBufferTs* IMXBuffer = buf.IMXBuffer; ++ CDVDVideoCodecIMXBuffer* IMXBuffer = buf.IMXBuffer; + + if(IMXBuffer) + { +@@ -2741,9 +2741,9 @@ void CLinuxRendererGLES::UploadIMXMAPTexture(int index) + glBindTexture(m_textureTarget, plane.id); + + GLuint physical = ~0U; +- GLvoid *virt = (GLvoid*)IMXBuffer->data[0]; ++ GLvoid *virt = (GLvoid*)IMXBuffer->pVirtAddr; + +- if (IMXBuffer->data[3] == 0) ++ if (IMXBuffer->iFormat == 0) + glTexDirectVIVMap(m_textureTarget, IMXBuffer->iWidth, IMXBuffer->iHeight, GL_VIV_I420, + (GLvoid **)&virt, &physical); + else +@@ -2754,8 +2754,8 @@ void CLinuxRendererGLES::UploadIMXMAPTexture(int index) + glBindTexture(m_textureTarget, 0); + + plane.flipindex = m_buffers[index].flipindex; +- plane.texwidth = IMXBuffer->m_iWidth; +- plane.texheight = IMXBuffer->m_iHeight; ++ plane.texwidth = IMXBuffer->iWidth; ++ plane.texheight = IMXBuffer->iHeight; + + CalculateTextureSourceRects(index, 1); + +@@ -3064,7 +3064,7 @@ void CLinuxRendererGLES::AddProcessor(CDVDMediaCodecInfo *mediacodec, int index) + #endif + + #ifdef HAS_IMXVPU +-void CLinuxRendererGLES::AddProcessor(CDVDVideoCodecBufferTs *buffer, int index) ++void CLinuxRendererGLES::AddProcessor(CDVDVideoCodecIMXBuffer *buffer, int index) + { + YUVBUFFER &buf = m_buffers[index]; + +diff --git a/xbmc/cores/VideoRenderers/LinuxRendererGLES.h b/xbmc/cores/VideoRenderers/LinuxRendererGLES.h +index 105e820..0532c19 100644 +--- a/xbmc/cores/VideoRenderers/LinuxRendererGLES.h ++++ b/xbmc/cores/VideoRenderers/LinuxRendererGLES.h +@@ -42,6 +42,9 @@ namespace Shaders { class BaseVideoFilterShader; } + class COpenMaxVideo; + class CDVDVideoCodecStageFright; + class CDVDMediaCodecInfo; ++#ifdef HAS_IMXVPU ++class CDVDVideoCodecIMXBuffer; ++#endif + typedef std::vector Features; + + +@@ -172,7 +175,7 @@ class CLinuxRendererGLES : public CBaseRenderer + virtual void AddProcessor(CDVDMediaCodecInfo *mediacodec, int index); + #endif + #ifdef HAS_IMXVPU +- virtual void AddProcessor(CDVDVideoCodecBufferTs *codecinfo, int index); ++ virtual void AddProcessor(CDVDVideoCodecIMXBuffer *codecinfo, int index); + #endif + + protected: +@@ -299,7 +302,7 @@ class CLinuxRendererGLES : public CBaseRenderer + CDVDMediaCodecInfo *mediacodec; + #endif + #ifdef HAS_IMXVPU +- CDVDVideoCodecBufferTs *IMXBuffer; ++ CDVDVideoCodecIMXBuffer *IMXBuffer; + #endif + }; + +diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp +index 39fb70c..17c87d5 100644 +--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp ++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp +@@ -41,12 +41,6 @@ + #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)) + +-// Helpers to extract physical and virtual addresses from CDVDVideoCodecBuffer pointers +-#define GET_VIRT_ADDR(buf) (buf)->data[0] +-#define GET_PHYS_ADDR(buf) (buf)->data[1] +-#define GET_FIELDTYPE(buf) (buf)->data[2] +-#define GET_FORMAT(buf) (buf)->data[3] // 0 = I420, 1 = NV12 +- + // Experiments show that we need at least one more (+1) VPU buffer than the min value returned by the VPU + const int CDVDVideoCodecIMX::m_extraVpuBuffers = 6; + const int CDVDVideoCodecIMX::m_maxVpuDecodeLoops = 5; +@@ -321,7 +315,7 @@ bool CDVDVideoCodecIMX::VpuAllocFrameBuffers(void) + mvSize = Align(mvSize, nAlign); + } + +- m_outputBuffers = new CDVDVideoCodecIMXBuffer*[m_vpuFrameBufferNum]; ++ m_outputBuffers = new CDVDVideoCodecIMXVPUBuffer*[m_vpuFrameBufferNum]; + + for (int i=0 ; i < m_vpuFrameBufferNum; i++) + { +@@ -384,9 +378,9 @@ bool CDVDVideoCodecIMX::VpuAllocFrameBuffers(void) + m_vpuFrameBuffers[i].pbufVirtCb_tilebot = 0; + + #ifdef TRACE_FRAMES +- m_outputBuffers[i] = new CDVDVideoCodecIMXBuffer(i); ++ m_outputBuffers[i] = new CDVDVideoCodecIMXVPUBuffer(i); + #else +- m_outputBuffers[i] = new CDVDVideoCodecIMXBuffer(); ++ m_outputBuffers[i] = new CDVDVideoCodecIMXVPUBuffer(); + #endif + } + +@@ -825,7 +819,7 @@ int CDVDVideoCodecIMX::Decode(BYTE *pData, int iSize, double dts, double pts) + idx = VpuFindBuffer(m_frameInfo.pDisplayFrameBuf->pbufY); + if (idx != -1) + { +- CDVDVideoCodecIMXBuffer *buffer = m_outputBuffers[idx]; ++ CDVDVideoCodecIMXVPUBuffer *buffer = m_outputBuffers[idx]; + buffer->Lock(); + buffer->SetDts(dts); + buffer->Queue(&m_frameInfo, m_lastBuffer); +@@ -1068,7 +1062,7 @@ bool CDVDVideoCodecIMX::GetPicture(DVDVideoPicture* pDvdVideoPicture) + pDvdVideoPicture->pts = m_currentBuffer->GetPts(); + pDvdVideoPicture->dts = m_currentBuffer->GetDts(); + +- pDvdVideoPicture->codecinfo = m_currentBuffer; ++ pDvdVideoPicture->IMXBuffer = m_currentBuffer; + m_currentBuffer = NULL; + + return true; +@@ -1091,40 +1085,35 @@ void CDVDVideoCodecIMX::SetDropState(bool bDrop) + } + + /*******************************************/ +- +-CDVDVideoCodecBufferTs::CDVDVideoCodecBufferTs() +- : m_pts(DVD_NOPTS_VALUE) ++#ifdef TRACE_FRAMES ++CDVDVideoCodecIMXBuffer::CDVDVideoCodecIMXBuffer(int idx) ++ : m_idx(idx) ++ , m_refs(1) ++#else ++CDVDVideoCodecIMXBuffer::CDVDVideoCodecIMXBuffer() ++ : m_refs(1) ++#endif ++ , m_pts(DVD_NOPTS_VALUE) + , m_dts(DVD_NOPTS_VALUE) + { + } + +-void CDVDVideoCodecBufferTs::SetPts(double pts) ++void CDVDVideoCodecIMXBuffer::SetPts(double pts) + { + m_pts = pts; + } + +-double CDVDVideoCodecBufferTs::GetPts(void) const +-{ +- return m_pts; +-} +- +-void CDVDVideoCodecBufferTs::SetDts(double dts) ++void CDVDVideoCodecIMXBuffer::SetDts(double dts) + { + m_dts = dts; + } + +-double CDVDVideoCodecBufferTs::GetDts(void) const +-{ +- return m_dts; +-} +- + #ifdef TRACE_FRAMES +-CDVDVideoCodecIMXBuffer::CDVDVideoCodecIMXBuffer(int idx) +- : m_refs(1) +- , m_idx(idx) ++CDVDVideoCodecIMXVPUBuffer::CDVDVideoCodecIMXVPUBuffer(int idx) ++ : CDVDVideoCodecIMXBuffer(idx) + #else +-CDVDVideoCodecIMXBuffer::CDVDVideoCodecIMXBuffer() +- : m_refs(1) ++CDVDVideoCodecIMXVPUBuffer::CDVDVideoCodecIMXVPUBuffer() ++ : CDVDVideoCodecIMXBuffer() + #endif + , m_frameBuffer(NULL) + , m_rendered(false) +@@ -1132,7 +1121,7 @@ CDVDVideoCodecIMXBuffer::CDVDVideoCodecIMXBuffer() + { + } + +-void CDVDVideoCodecIMXBuffer::Lock() ++void CDVDVideoCodecIMXVPUBuffer::Lock() + { + #ifdef TRACE_FRAMES + long count = AtomicIncrement(&m_refs); +@@ -1142,7 +1131,7 @@ void CDVDVideoCodecIMXBuffer::Lock() + #endif + } + +-long CDVDVideoCodecIMXBuffer::Release() ++long CDVDVideoCodecIMXVPUBuffer::Release() + { + long count = AtomicDecrement(&m_refs); + #ifdef TRACE_FRAMES +@@ -1174,18 +1163,18 @@ long CDVDVideoCodecIMXBuffer::Release() + return count; + } + +-bool CDVDVideoCodecIMXBuffer::IsValid() ++bool CDVDVideoCodecIMXVPUBuffer::IsValid() + { + return m_frameBuffer != NULL; + } + +-bool CDVDVideoCodecIMXBuffer::Rendered() const ++bool CDVDVideoCodecIMXVPUBuffer::Rendered() const + { + return m_rendered; + } + +-void CDVDVideoCodecIMXBuffer::Queue(VpuDecOutFrameInfo *frameInfo, +- CDVDVideoCodecIMXBuffer *previous) ++void CDVDVideoCodecIMXVPUBuffer::Queue(VpuDecOutFrameInfo *frameInfo, ++ CDVDVideoCodecIMXVPUBuffer *previous) + { + // No lock necessary because at this time there is definitely no + // thread still holding a reference +@@ -1195,20 +1184,21 @@ void CDVDVideoCodecIMXBuffer::Queue(VpuDecOutFrameInfo *frameInfo, + 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; ++ iWidth = frameInfo->pExtInfo->nFrmWidth; ++ iHeight = frameInfo->pExtInfo->nFrmHeight; ++ pVirtAddr = m_frameBuffer->pbufVirtY; ++ pPhysAddr = m_frameBuffer->pbufY; ++ ++ m_fieldType = frameInfo->eFieldType; + // We decode to I420 + #ifdef IMX_INPUT_FORMAT_I420 +- GET_FORMAT(this) = (uint8_t*)0; ++ iFormat = 0; + #else +- GET_FORMAT(this) = (uint8_t*)1; ++ iFormat = 1; + #endif + } + +-VpuDecRetCode CDVDVideoCodecIMXBuffer::ReleaseFramebuffer(VpuDecHandle *handle) ++VpuDecRetCode CDVDVideoCodecIMXVPUBuffer::ReleaseFramebuffer(VpuDecHandle *handle) + { + // Again no lock required because this is only issued after the last + // external reference was released +@@ -1231,12 +1221,12 @@ VpuDecRetCode CDVDVideoCodecIMXBuffer::ReleaseFramebuffer(VpuDecHandle *handle) + return ret; + } + +-CDVDVideoCodecIMXBuffer *CDVDVideoCodecIMXBuffer::GetPreviousBuffer() const ++CDVDVideoCodecIMXVPUBuffer *CDVDVideoCodecIMXVPUBuffer::GetPreviousBuffer() const + { + return m_previousBuffer; + } + +-CDVDVideoCodecIMXBuffer::~CDVDVideoCodecIMXBuffer() ++CDVDVideoCodecIMXVPUBuffer::~CDVDVideoCodecIMXVPUBuffer() + { + assert(m_refs == 0); + #ifdef TRACE_FRAMES +@@ -1245,12 +1235,11 @@ CDVDVideoCodecIMXBuffer::~CDVDVideoCodecIMXBuffer() + } + + #ifdef TRACE_FRAMES +-CDVDVideoCodecIPUBuffer::CDVDVideoCodecIPUBuffer(int idx) +- : m_refs(1) +- , m_idx(idx) ++CDVDVideoCodecIMXIPUBuffer::CDVDVideoCodecIMXIPUBuffer(int idx) ++ : CDVDVideoCodecIMXBuffer(idx) + #else +-CDVDVideoCodecIPUBuffer::CDVDVideoCodecIPUBuffer() +- : m_refs(1) ++CDVDVideoCodecIMXIPUBuffer::CDVDVideoCodecIMXIPUBuffer() ++ : CDVDVideoCodecIMXBuffer() + #endif + , m_bFree(true) + , m_pPhyAddr(0) +@@ -1259,7 +1248,7 @@ CDVDVideoCodecIPUBuffer::CDVDVideoCodecIPUBuffer() + { + } + +-CDVDVideoCodecIPUBuffer::~CDVDVideoCodecIPUBuffer() ++CDVDVideoCodecIMXIPUBuffer::~CDVDVideoCodecIMXIPUBuffer() + { + assert(m_refs == 0); + #ifdef TRACE_FRAMES +@@ -1267,7 +1256,7 @@ CDVDVideoCodecIPUBuffer::~CDVDVideoCodecIPUBuffer() + #endif + } + +-void CDVDVideoCodecIPUBuffer::Lock() ++void CDVDVideoCodecIMXIPUBuffer::Lock() + { + #ifdef TRACE_FRAMES + long count = AtomicIncrement(&m_refs); +@@ -1278,7 +1267,7 @@ void CDVDVideoCodecIPUBuffer::Lock() + + } + +-long CDVDVideoCodecIPUBuffer::Release() ++long CDVDVideoCodecIMXIPUBuffer::Release() + { + long count = AtomicDecrement(&m_refs); + #ifdef TRACE_FRAMES +@@ -1296,16 +1285,16 @@ long CDVDVideoCodecIPUBuffer::Release() + return count; + } + +-bool CDVDVideoCodecIPUBuffer::IsValid() ++bool CDVDVideoCodecIMXIPUBuffer::IsValid() + { + return /*m_source && m_source->IsValid() && */m_pPhyAddr; + } + +-bool CDVDVideoCodecIPUBuffer::Process(int fd, CDVDVideoCodecIMXBuffer *buffer, ++bool CDVDVideoCodecIMXIPUBuffer::Process(int fd, CDVDVideoCodecIMXVPUBuffer *buffer, + VpuFieldType fieldType, int fieldFmt, + bool lowMotion) + { +- CDVDVideoCodecIMXBuffer *previousBuffer; ++ CDVDVideoCodecIMXVPUBuffer *previousBuffer; + struct ipu_task task; + memset(&task, 0, sizeof(task)); + task.priority = IPU_TASK_PRIORITY_HIGH; +@@ -1333,23 +1322,23 @@ bool CDVDVideoCodecIPUBuffer::Process(int fd, CDVDVideoCodecIMXBuffer *buffer, + task.output.height = iHeight; + #ifdef IMX_OUTPUT_FORMAT_I420 + task.output.format = IPU_PIX_FMT_YUV420P; +- GET_FORMAT(this) = (uint8_t*)0; ++ format = 0; + #else + task.output.format = IPU_PIX_FMT_NV12; +- GET_FORMAT(this) = (uint8_t*)1; ++ iFormat = 1; + #endif +- task.output.paddr = (int)GET_PHYS_ADDR(this); ++ task.output.paddr = (int)pPhysAddr; + + // 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.paddr = (int)previousBuffer->pPhysAddr; ++ task.input.paddr_n = (int)buffer->pPhysAddr; + task.input.deinterlace.motion = LOW_MOTION; + } + else + { +- task.input.paddr = (int)GET_PHYS_ADDR(buffer); ++ task.input.paddr = (int)buffer->pPhysAddr; + task.input.deinterlace.motion = HIGH_MOTION; + } + +@@ -1395,7 +1384,7 @@ bool CDVDVideoCodecIPUBuffer::Process(int fd, CDVDVideoCodecIMXBuffer *buffer, + return true; + } + +-void CDVDVideoCodecIPUBuffer::ReleaseFrameBuffer() ++void CDVDVideoCodecIMXIPUBuffer::ReleaseFrameBuffer() + { + #ifdef TRACE_FRAMES + CLog::Log(LOGDEBUG, "- %02d (IPU)\n", m_idx); +@@ -1403,7 +1392,7 @@ void CDVDVideoCodecIPUBuffer::ReleaseFrameBuffer() + m_bFree = true; + } + +-bool CDVDVideoCodecIPUBuffer::Allocate(int fd, int width, int height, int nAlign) ++bool CDVDVideoCodecIMXIPUBuffer::Allocate(int fd, int width, int height, int nAlign) + { + m_iWidth = Align(width,FRAME_ALIGN); + m_iHeight = Align(height,(2*FRAME_ALIGN)); +@@ -1411,7 +1400,7 @@ bool CDVDVideoCodecIPUBuffer::Allocate(int fd, int width, int height, int nAlign + m_nSize = m_iWidth*m_iHeight*12/8; + m_pPhyAddr = m_nSize; + +- GET_PHYS_ADDR(this) = GET_VIRT_ADDR(this) = NULL; ++ pPhysAddr = pVirtAddr = NULL; + + int r = ioctl(fd, IPU_ALLOC, &m_pPhyAddr); + if (r < 0) +@@ -1434,19 +1423,19 @@ bool CDVDVideoCodecIPUBuffer::Allocate(int fd, int width, int height, int nAlign + + if (nAlign>1) + { +- GET_PHYS_ADDR(this) = (uint8_t*)Align(m_pPhyAddr, nAlign); +- GET_VIRT_ADDR(this) = (uint8_t*)Align(m_pVirtAddr, nAlign); ++ pPhysAddr = (uint8_t*)Align(m_pPhyAddr, nAlign); ++ pVirtAddr = (uint8_t*)Align(m_pVirtAddr, nAlign); + } + else + { +- GET_PHYS_ADDR(this) = (uint8_t*)m_pPhyAddr; +- GET_VIRT_ADDR(this) = (uint8_t*)m_pVirtAddr; ++ pPhysAddr = (uint8_t*)m_pPhyAddr; ++ pVirtAddr = (uint8_t*)m_pVirtAddr; + } + + return true; + } + +-bool CDVDVideoCodecIPUBuffer::Free(int fd) ++bool CDVDVideoCodecIMXIPUBuffer::Free(int fd) + { + bool ret = true; + +@@ -1475,13 +1464,13 @@ bool CDVDVideoCodecIPUBuffer::Free(int fd) + m_pPhyAddr = 0; + } + +- GET_PHYS_ADDR(this) = GET_VIRT_ADDR(this) = NULL; ++ pPhysAddr = pVirtAddr = NULL; + m_bFree = true; + + return ret; + } + +-CDVDVideoCodecIPUBuffers::CDVDVideoCodecIPUBuffers() ++CDVDVideoCodecIMXIPUBuffers::CDVDVideoCodecIMXIPUBuffers() + : m_ipuHandle(0) + , m_bufferNum(0) + , m_buffers(NULL) +@@ -1489,12 +1478,12 @@ CDVDVideoCodecIPUBuffers::CDVDVideoCodecIPUBuffers() + { + } + +-CDVDVideoCodecIPUBuffers::~CDVDVideoCodecIPUBuffers() ++CDVDVideoCodecIMXIPUBuffers::~CDVDVideoCodecIMXIPUBuffers() + { + Close(); + } + +-bool CDVDVideoCodecIPUBuffers::Init(int width, int height, int numBuffers, int nAlign) ++bool CDVDVideoCodecIMXIPUBuffers::Init(int width, int height, int numBuffers, int nAlign) + { + if (numBuffers<=0) + { +@@ -1512,15 +1501,15 @@ bool CDVDVideoCodecIPUBuffers::Init(int width, int height, int numBuffers, int n + } + + m_bufferNum = numBuffers; +- m_buffers = new CDVDVideoCodecIPUBuffer*[m_bufferNum]; ++ m_buffers = new CDVDVideoCodecIMXIPUBuffer*[m_bufferNum]; + m_currentFieldFmt = 0; + + for (int i=0; i < m_bufferNum; i++) + { + #ifdef TRACE_FRAMES +- m_buffers[i] = new CDVDVideoCodecIPUBuffer(i); ++ m_buffers[i] = new CDVDVideoCodecIMXIPUBuffer(i); + #else +- m_buffers[i] = new CDVDVideoCodecIPUBuffer; ++ m_buffers[i] = new CDVDVideoCodecIMXIPUBuffer; + #endif + if (!m_buffers[i]->Allocate(m_ipuHandle, width, height, nAlign)) + { +@@ -1532,14 +1521,14 @@ bool CDVDVideoCodecIPUBuffers::Init(int width, int height, int numBuffers, int n + return true; + } + +-bool CDVDVideoCodecIPUBuffers::Reset() ++bool CDVDVideoCodecIMXIPUBuffers::Reset() + { + for (int i=0; i < m_bufferNum; i++) + m_buffers[i]->ReleaseFrameBuffer(); + m_currentFieldFmt = 0; + } + +-bool CDVDVideoCodecIPUBuffers::Close() ++bool CDVDVideoCodecIMXIPUBuffers::Close() + { + bool ret = true; + +@@ -1575,11 +1564,11 @@ bool CDVDVideoCodecIPUBuffers::Close() + return true; + } + +-CDVDVideoCodecIPUBuffer * +-CDVDVideoCodecIPUBuffers::Process(CDVDVideoCodecBuffer *sourceBuffer, +- VpuFieldType fieldType, bool lowMotion) ++CDVDVideoCodecIMXIPUBuffer * ++CDVDVideoCodecIMXIPUBuffers::Process(CDVDVideoCodecIMXBuffer *sourceBuffer, ++ VpuFieldType fieldType, bool lowMotion) + { +- CDVDVideoCodecIPUBuffer *target = NULL; ++ CDVDVideoCodecIMXIPUBuffer *target = NULL; + bool ret = true; + + if (!m_bufferNum) +@@ -1592,7 +1581,7 @@ CDVDVideoCodecIPUBuffers::Process(CDVDVideoCodecBuffer *sourceBuffer, + // 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, ++ ret = m_buffers[i]->Process(m_ipuHandle, (CDVDVideoCodecIMXVPUBuffer*)sourceBuffer, + fieldType, m_currentFieldFmt, + lowMotion); + if (ret) +@@ -1616,7 +1605,7 @@ CDVDVideoCodecIPUBuffers::Process(CDVDVideoCodecBuffer *sourceBuffer, + } + + +-CDVDVideoMixerIMX::CDVDVideoMixerIMX(CDVDVideoCodecIPUBuffers *proc) ++CDVDVideoMixerIMX::CDVDVideoMixerIMX(CDVDVideoCodecIMXIPUBuffers *proc) + : CThread("IMX6 Mixer") + , m_beginInput(0), m_endInput(0), m_bufferedInput(0) + , m_beginOutput(0), m_endOutput(0), m_bufferedOutput(0) +@@ -1676,10 +1665,10 @@ bool CDVDVideoMixerIMX::IsActive() { + return IsRunning(); + } + +-CDVDVideoCodecBufferTs *CDVDVideoMixerIMX::Process(CDVDVideoCodecIMXBuffer *buffer) ++CDVDVideoCodecIMXBuffer *CDVDVideoMixerIMX::Process(CDVDVideoCodecIMXVPUBuffer *buffer) + { + CSingleLock lk(m_monitor); +- CDVDVideoCodecBufferTs *r; ++ CDVDVideoCodecIMXBuffer *r; + + if (m_bStop) + { +@@ -1753,13 +1742,13 @@ void CDVDVideoMixerIMX::Process() + while (!m_bStop) + { + // Blocking until an input is available +- CDVDVideoCodecIMXBuffer *inputBuffer = GetNextInput(); ++ CDVDVideoCodecIMXVPUBuffer *inputBuffer = GetNextInput(); + if (inputBuffer) + { + // Wait for free slot + WaitForFreeOutput(); + +- CDVDVideoCodecBufferTs *outputBuffer = ProcessFrame(inputBuffer); ++ CDVDVideoCodecIMXBuffer *outputBuffer = ProcessFrame(inputBuffer); + + // Queue the output if any + if (outputBuffer) +@@ -1774,7 +1763,7 @@ void CDVDVideoMixerIMX::Process() + } + } + +-CDVDVideoCodecIMXBuffer *CDVDVideoMixerIMX::GetNextInput() { ++CDVDVideoCodecIMXVPUBuffer *CDVDVideoMixerIMX::GetNextInput() { + CSingleLock lk(m_monitor); + while (!m_bufferedInput && !m_bStop) + m_inputNotEmpty.wait(lk); +@@ -1782,7 +1771,7 @@ CDVDVideoCodecIMXBuffer *CDVDVideoMixerIMX::GetNextInput() { + if (m_bStop) + return NULL; + +- CDVDVideoCodecIMXBuffer *v = m_input[m_beginInput]; ++ CDVDVideoCodecIMXVPUBuffer *v = m_input[m_beginInput]; + m_input[m_beginInput] = NULL; + m_beginInput = (m_beginInput+1) % m_input.size(); + --m_bufferedInput; +@@ -1801,7 +1790,7 @@ void CDVDVideoMixerIMX::WaitForFreeOutput() { + m_outputNotFull.wait(lk); + } + +-bool CDVDVideoMixerIMX::PushOutput(CDVDVideoCodecBufferTs *v) { ++bool CDVDVideoMixerIMX::PushOutput(CDVDVideoCodecIMXBuffer *v) { + CSingleLock lk(m_monitor); + + v->Lock(); +@@ -1821,9 +1810,9 @@ bool CDVDVideoMixerIMX::PushOutput(CDVDVideoCodecBufferTs *v) { + return true; + } + +-CDVDVideoCodecBufferTs *CDVDVideoMixerIMX::ProcessFrame(CDVDVideoCodecIMXBuffer *inputBuffer) ++CDVDVideoCodecIMXBuffer *CDVDVideoMixerIMX::ProcessFrame(CDVDVideoCodecIMXVPUBuffer *inputBuffer) + { +- CDVDVideoCodecBufferTs *outputBuffer; ++ CDVDVideoCodecIMXBuffer *outputBuffer; + EDEINTERLACEMODE mDeintMode = CMediaSettings::Get().GetCurrentVideoSettings().m_DeinterlaceMode; + //EINTERLACEMETHOD mInt = CMediaSettings::Get().GetCurrentVideoSettings().m_InterlaceMethod; + +@@ -1843,7 +1832,7 @@ CDVDVideoCodecBufferTs *CDVDVideoMixerIMX::ProcessFrame(CDVDVideoCodecIMXBuffer + outputBuffer = inputBuffer; + #else + outputBuffer = m_proc->Process(inputBuffer, +- (VpuFieldType)(int)GET_FIELDTYPE(inputBuffer), ++ inputBuffer->GetFieldType(), + false); + #endif + #ifdef IMX_PROFILE_BUFFERS +diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h +index 186a4fd..d8eb72b 100644 +--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h ++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h +@@ -70,72 +70,89 @@ class CDecMemInfo + }; + + +-class CDVDVideoCodecBufferTs : public CDVDVideoCodecBuffer { ++// Base class of IMXVPU and IMXIPU buffer ++class CDVDVideoCodecIMXBuffer { + public: +- CDVDVideoCodecBufferTs(); ++#ifdef TRACE_FRAMES ++ CDVDVideoCodecIMXBuffer(int idx); ++#else ++ CDVDVideoCodecIMXBuffer(); ++#endif ++ ++ // reference counting ++ virtual void Lock() = 0; ++ virtual long Release() = 0; ++ virtual bool IsValid() = 0; ++ ++ void SetPts(double pts); ++ double GetPts(void) const { return m_pts; } ++ ++ void SetDts(double dts); ++ double GetDts(void) const { return m_dts; } + +- void SetPts(double pts); +- double GetPts(void) const; ++ uint32_t iWidth; ++ uint32_t iHeight; ++ uint8_t *pPhysAddr; ++ uint8_t *pVirtAddr; ++ uint8_t iFormat; + +- void SetDts(double dts); +- double GetDts(void) const; ++protected: ++#ifdef TRACE_FRAMES ++ int m_idx; ++#endif ++ long m_refs; + + private: +- double m_pts; +- double m_dts; ++ double m_pts; ++ double m_dts; + }; + +-class CDVDVideoCodecIPUBuffer; + +-class CDVDVideoCodecIMXBuffer : public CDVDVideoCodecBufferTs ++class CDVDVideoCodecIMXIPUBuffer; ++ ++class CDVDVideoCodecIMXVPUBuffer : public CDVDVideoCodecIMXBuffer + { + public: + #ifdef TRACE_FRAMES +- CDVDVideoCodecIMXBuffer(int idx); ++ CDVDVideoCodecIMXVPUBuffer(int idx); + #else +- CDVDVideoCodecIMXBuffer(); ++ CDVDVideoCodecIMXVPUBuffer(); + #endif + + // reference counting +- virtual void Lock(); +- virtual long Release(); +- virtual bool IsValid(); ++ virtual void Lock(); ++ virtual long Release(); ++ virtual bool IsValid(); + +- bool Rendered() const; +- void Queue(VpuDecOutFrameInfo *frameInfo, +- CDVDVideoCodecIMXBuffer *previous); +- VpuDecRetCode ReleaseFramebuffer(VpuDecHandle *handle); +- CDVDVideoCodecIMXBuffer *GetPreviousBuffer() const; +- +- uint32_t m_iWidth; +- uint32_t m_iHeight; +- uint8_t *m_phyAddr; +- uint8_t *m_VirtAddr; ++ bool Rendered() const; ++ void Queue(VpuDecOutFrameInfo *frameInfo, ++ CDVDVideoCodecIMXVPUBuffer *previous); ++ VpuDecRetCode ReleaseFramebuffer(VpuDecHandle *handle); ++ CDVDVideoCodecIMXVPUBuffer *GetPreviousBuffer() const; ++ VpuFieldType GetFieldType() const { return m_fieldType; } + + private: + // private because we are reference counted +- virtual ~CDVDVideoCodecIMXBuffer(); ++ virtual ~CDVDVideoCodecIMXVPUBuffer(); + + private: +-#ifdef TRACE_FRAMES +- int m_idx; +-#endif +- long m_refs; +- VpuFrameBuffer *m_frameBuffer; +- bool m_rendered; +- CDVDVideoCodecIMXBuffer *m_previousBuffer; // Holds a the reference counted ++ VpuFrameBuffer *m_frameBuffer; ++ VpuFieldType m_fieldType; ++ ++ bool m_rendered; ++ CDVDVideoCodecIMXVPUBuffer *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 CDVDVideoCodecBufferTs ++class CDVDVideoCodecIMXIPUBuffer : public CDVDVideoCodecIMXBuffer + { + public: + #ifdef TRACE_FRAMES +- CDVDVideoCodecIPUBuffer(int idx); ++ CDVDVideoCodecIMXIPUBuffer(int idx); + #else +- CDVDVideoCodecIPUBuffer(); ++ CDVDVideoCodecIMXIPUBuffer(); + #endif + + // reference counting +@@ -145,7 +162,7 @@ class CDVDVideoCodecIPUBuffer : public CDVDVideoCodecBufferTs + + // Returns whether the buffer is ready to be used + bool Rendered() const { return m_bFree; } +- bool Process(int fd, CDVDVideoCodecIMXBuffer *buffer, ++ bool Process(int fd, CDVDVideoCodecIMXVPUBuffer *buffer, + VpuFieldType fieldType, int fieldFmt, + bool lowMotion); + void ReleaseFrameBuffer(); +@@ -154,29 +171,25 @@ class CDVDVideoCodecIPUBuffer : public CDVDVideoCodecBufferTs + bool Free(int fd); + + private: +- virtual ~CDVDVideoCodecIPUBuffer(); ++ virtual ~CDVDVideoCodecIMXIPUBuffer(); + + private: +-#ifdef TRACE_FRAMES +- int m_idx; +-#endif +- long m_refs; + bool m_bFree; + int m_pPhyAddr; + uint8_t *m_pVirtAddr; +- int m_iWidth; +- int m_iHeight; ++ uint32_t m_iWidth; ++ uint32_t 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 ++class CDVDVideoCodecIMXIPUBuffers + { + public: +- CDVDVideoCodecIPUBuffers(); +- ~CDVDVideoCodecIPUBuffers(); ++ CDVDVideoCodecIMXIPUBuffers(); ++ ~CDVDVideoCodecIMXIPUBuffers(); + + bool Init(int width, int height, int numBuffers, int nAlign); + // Sets the mode to be used if deinterlacing is set to AUTO +@@ -185,21 +198,22 @@ class CDVDVideoCodecIPUBuffers + bool Reset(); + bool Close(); + +- CDVDVideoCodecIPUBuffer *Process(CDVDVideoCodecBuffer *sourceBuffer, +- VpuFieldType fieldType, bool lowMotion); ++ CDVDVideoCodecIMXIPUBuffer * ++ Process(CDVDVideoCodecIMXBuffer *sourceBuffer, ++ VpuFieldType fieldType, bool lowMotion); + + private: +- int m_ipuHandle; +- bool m_autoMode; +- int m_bufferNum; +- CDVDVideoCodecIPUBuffer **m_buffers; +- int m_currentFieldFmt; ++ int m_ipuHandle; ++ bool m_autoMode; ++ int m_bufferNum; ++ CDVDVideoCodecIMXIPUBuffer **m_buffers; ++ int m_currentFieldFmt; + }; + + + class CDVDVideoMixerIMX : private CThread { + public: +- CDVDVideoMixerIMX(CDVDVideoCodecIPUBuffers *proc); ++ CDVDVideoMixerIMX(CDVDVideoCodecIMXIPUBuffers *proc); + virtual ~CDVDVideoMixerIMX(); + + void SetCapacity(int intput, int output); +@@ -211,13 +225,13 @@ class CDVDVideoMixerIMX : private CThread { + + // This function blocks until an input slot is available. + // It returns if an output is available. +- CDVDVideoCodecBufferTs *Process(CDVDVideoCodecIMXBuffer *input); ++ CDVDVideoCodecIMXBuffer *Process(CDVDVideoCodecIMXVPUBuffer *input); + + private: +- CDVDVideoCodecIMXBuffer *GetNextInput(); ++ CDVDVideoCodecIMXVPUBuffer *GetNextInput(); + void WaitForFreeOutput(); +- bool PushOutput(CDVDVideoCodecBufferTs *v); +- CDVDVideoCodecBufferTs *ProcessFrame(CDVDVideoCodecIMXBuffer *input); ++ bool PushOutput(CDVDVideoCodecIMXBuffer *v); ++ CDVDVideoCodecIMXBuffer *ProcessFrame(CDVDVideoCodecIMXVPUBuffer *input); + + virtual void OnStartup(); + virtual void OnExit(); +@@ -225,10 +239,10 @@ class CDVDVideoMixerIMX : private CThread { + virtual void Process(); + + private: +- typedef std::vector InputBuffers; +- typedef std::vector OutputBuffers; ++ typedef std::vector InputBuffers; ++ typedef std::vector OutputBuffers; + +- CDVDVideoCodecIPUBuffers *m_proc; ++ CDVDVideoCodecIMXIPUBuffers *m_proc; + InputBuffers m_input; + volatile int m_beginInput, m_endInput; + volatile size_t m_bufferedInput; +@@ -241,7 +255,7 @@ class CDVDVideoMixerIMX : private CThread { + XbmcThreads::ConditionVariable m_outputNotFull; + + mutable CCriticalSection m_monitor; +- CDVDVideoCodecBufferTs *m_lastFrame; // Last input frame ++ CDVDVideoCodecIMXBuffer *m_lastFrame; // Last input frame + }; + + +@@ -273,31 +287,31 @@ 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 const int m_extraVpuBuffers; // Number of additional buffers for VPU ++ static const int m_maxVpuDecodeLoops; // Maximum iterations in VPU decoding loop + // by both decoding and rendering threads + +- CDVDStreamInfo m_hints; // Hints from demuxer at stream opening +- const char *m_pFormatName; // Current decoder format name +- VpuDecOpenParam m_decOpenParam; // Parameters required to call VPU_DecOpen +- CDecMemInfo m_decMemInfo; // VPU dedicated memory description +- VpuDecHandle m_vpuHandle; // Handle for VPU library calls +- VpuDecInitInfo m_initInfo; // Initial info returned from VPU at decoding start +- bool m_dropState; // Current drop state +- int m_vpuFrameBufferNum; // Total number of allocated frame buffers +- VpuFrameBuffer *m_vpuFrameBuffers; // Table of VPU frame buffers description +- CDVDVideoCodecIPUBuffers m_deinterlacer; // Pool of buffers used for deinterlacing +- CDVDVideoMixerIMX m_mixer; +- CDVDVideoCodecIMXBuffer **m_outputBuffers; // Table of VPU output buffers +- CDVDVideoCodecIMXBuffer *m_lastBuffer; // Keep track of previous VPU output buffer (needed by deinterlacing motion engin) +- CDVDVideoCodecBufferTs *m_currentBuffer; +- VpuMemDesc *m_extraMem; // Table of allocated extra Memory +- int m_frameCounter; // Decoded frames counter +- bool m_usePTS; // State whether pts out of decoding process should be used +- VpuDecOutFrameInfo m_frameInfo; // Store last VPU output frame info +- CBitstreamConverter *m_converter; // H264 annex B converter +- bool m_convert_bitstream; // State whether bitstream conversion is required +- int m_bytesToBeConsumed; // Remaining bytes in VPU +- double m_previousPts; // Enable to keep pts when needed +- bool m_frameReported; // State whether the frame consumed event will be reported by libfslvpu ++ 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 ++ CDVDVideoCodecIMXIPUBuffers m_deinterlacer; // Pool of buffers used for deinterlacing ++ CDVDVideoMixerIMX m_mixer; ++ CDVDVideoCodecIMXVPUBuffer **m_outputBuffers; // Table of VPU output buffers ++ CDVDVideoCodecIMXVPUBuffer *m_lastBuffer; // Keep track of previous VPU output buffer (needed by deinterlacing motion engin) ++ CDVDVideoCodecIMXBuffer *m_currentBuffer; ++ VpuMemDesc *m_extraMem; // Table of allocated extra Memory ++ int m_frameCounter; // Decoded frames counter ++ bool m_usePTS; // State whether pts out of decoding process should be used ++ VpuDecOutFrameInfo m_frameInfo; // Store last VPU output frame info ++ CBitstreamConverter *m_converter; // H264 annex B converter ++ bool m_convert_bitstream; // State whether bitstream conversion is required ++ int m_bytesToBeConsumed; // Remaining bytes in VPU ++ double m_previousPts; // Enable to keep pts when needed ++ bool m_frameReported; // State whether the frame consumed event will be reported by libfslvpu + }; + +From 66ba72713451ede05da22bc9a5a2f0ea14f4d4d7 Mon Sep 17 00:00:00 2001 +From: smallint +Date: Mon, 24 Nov 2014 22:48:47 +0100 +Subject: [PATCH 3/3] FIX: [imx] @wolfgar Indentation + +--- + xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp +index 17c87d5..0394e63 100644 +--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp ++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp +@@ -1174,7 +1174,7 @@ bool CDVDVideoCodecIMXVPUBuffer::Rendered() const + } + + void CDVDVideoCodecIMXVPUBuffer::Queue(VpuDecOutFrameInfo *frameInfo, +- CDVDVideoCodecIMXVPUBuffer *previous) ++ CDVDVideoCodecIMXVPUBuffer *previous) + { + // No lock necessary because at this time there is definitely no + // thread still holding a reference +@@ -1291,8 +1291,8 @@ bool CDVDVideoCodecIMXIPUBuffer::IsValid() + } + + bool CDVDVideoCodecIMXIPUBuffer::Process(int fd, CDVDVideoCodecIMXVPUBuffer *buffer, +- VpuFieldType fieldType, int fieldFmt, +- bool lowMotion) ++ VpuFieldType fieldType, int fieldFmt, ++ bool lowMotion) + { + CDVDVideoCodecIMXVPUBuffer *previousBuffer; + struct ipu_task task;