diff --git a/packages/mediacenter/kodi/patches/kodi-999.92-PR5805-v2.patch b/packages/mediacenter/kodi/patches/kodi-999.92-PR5805-v2.patch new file mode 100644 index 0000000000..09bd995e17 --- /dev/null +++ b/packages/mediacenter/kodi/patches/kodi-999.92-PR5805-v2.patch @@ -0,0 +1,2742 @@ +From d1d19f8d0a69f751b03a97ef0f546564527a7caa Mon Sep 17 00:00:00 2001 +From: smallint +Date: Tue, 25 Nov 2014 18:53:25 +0100 +Subject: [PATCH 01/18] [imx] @wolfgar Renamed CDVDVideoCodecIMXBuffer to + CDVDVideoCodecIMXVPUBuffer and added typedef for Renderer + +--- + .../dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp | 34 +++++------ + .../dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h | 70 +++++++++++----------- + 2 files changed, 53 insertions(+), 51 deletions(-) + +diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp +index 34db863..17d2f15 100644 +--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp ++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp +@@ -264,7 +264,7 @@ bool CDVDVideoCodecIMX::VpuAllocFrameBuffers(void) + uvSize=Align(uvSize,nAlign); + } + +- m_outputBuffers = new CDVDVideoCodecIMXBuffer*[m_vpuFrameBufferNum]; ++ m_outputBuffers = new CDVDVideoCodecIMXVPUBuffer*[m_vpuFrameBufferNum]; + + for (int i=0 ; i < m_vpuFrameBufferNum; i++) + { +@@ -319,9 +319,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 + } + +@@ -916,7 +916,7 @@ bool CDVDVideoCodecIMX::GetPicture(DVDVideoPicture* pDvdVideoPicture) + int idx = VpuFindBuffer(m_frameInfo.pDisplayFrameBuf->pbufY); + if (idx != -1) + { +- CDVDVideoCodecIMXBuffer *buffer = m_outputBuffers[idx]; ++ CDVDVideoCodecIMXVPUBuffer *buffer = m_outputBuffers[idx]; + + pDvdVideoPicture->pts = buffer->GetPts(); + pDvdVideoPicture->dts = m_dts; +@@ -978,11 +978,11 @@ void CDVDVideoCodecIMX::Leave() + /*******************************************/ + + #ifdef TRACE_FRAMES +-CDVDVideoCodecIMXBuffer::CDVDVideoCodecIMXBuffer(int idx) ++CDVDVideoCodecIMXVPUBuffer::CDVDVideoCodecIMXVPUBuffer(int idx) + : m_refs(1) + , m_idx(idx) + #else +-CDVDVideoCodecIMXBuffer::CDVDVideoCodecIMXBuffer() ++CDVDVideoCodecIMXVPUBuffer::CDVDVideoCodecIMXVPUBuffer() + : m_refs(1) + #endif + , m_frameBuffer(NULL) +@@ -992,7 +992,7 @@ CDVDVideoCodecIMXBuffer::CDVDVideoCodecIMXBuffer() + { + } + +-void CDVDVideoCodecIMXBuffer::Lock() ++void CDVDVideoCodecIMXVPUBuffer::Lock() + { + #ifdef TRACE_FRAMES + long count = AtomicIncrement(&m_refs); +@@ -1002,7 +1002,7 @@ void CDVDVideoCodecIMXBuffer::Lock() + #endif + } + +-long CDVDVideoCodecIMXBuffer::Release() ++long CDVDVideoCodecIMXVPUBuffer::Release() + { + long count = AtomicDecrement(&m_refs); + #ifdef TRACE_FRAMES +@@ -1034,18 +1034,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 +@@ -1061,7 +1061,7 @@ void CDVDVideoCodecIMXBuffer::Queue(VpuDecOutFrameInfo *frameInfo, + m_phyAddr = m_frameBuffer->pbufY; + } + +-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 +@@ -1084,22 +1084,22 @@ VpuDecRetCode CDVDVideoCodecIMXBuffer::ReleaseFramebuffer(VpuDecHandle *handle) + return ret; + } + +-void CDVDVideoCodecIMXBuffer::SetPts(double pts) ++void CDVDVideoCodecIMXVPUBuffer::SetPts(double pts) + { + m_pts = pts; + } + +-double CDVDVideoCodecIMXBuffer::GetPts(void) const ++double CDVDVideoCodecIMXVPUBuffer::GetPts(void) const + { + return m_pts; + } + +-CDVDVideoCodecIMXBuffer *CDVDVideoCodecIMXBuffer::GetPreviousBuffer() const ++CDVDVideoCodecIMXVPUBuffer *CDVDVideoCodecIMXVPUBuffer::GetPreviousBuffer() const + { + return m_previousBuffer; + } + +-CDVDVideoCodecIMXBuffer::~CDVDVideoCodecIMXBuffer() ++CDVDVideoCodecIMXVPUBuffer::~CDVDVideoCodecIMXVPUBuffer() + { + assert(m_refs == 0); + #ifdef TRACE_FRAMES +diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h +index 6533683..eb88ecd 100644 +--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h ++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h +@@ -48,13 +48,13 @@ class CDecMemInfo + VpuMemDesc* phyMem; + }; + +-class CDVDVideoCodecIMXBuffer ++class CDVDVideoCodecIMXVPUBuffer + { + public: + #ifdef TRACE_FRAMES +- CDVDVideoCodecIMXBuffer(int idx); ++ CDVDVideoCodecIMXVPUBuffer(int idx); + #else +- CDVDVideoCodecIMXBuffer(); ++ CDVDVideoCodecIMXVPUBuffer(); + #endif + + // reference counting +@@ -64,11 +64,11 @@ class CDVDVideoCodecIMXBuffer + + bool Rendered() const; + void Queue(VpuDecOutFrameInfo *frameInfo, +- CDVDVideoCodecIMXBuffer *previous); ++ CDVDVideoCodecIMXVPUBuffer *previous); + VpuDecRetCode ReleaseFramebuffer(VpuDecHandle *handle); + void SetPts(double pts); + double GetPts(void) const; +- CDVDVideoCodecIMXBuffer *GetPreviousBuffer() const; ++ CDVDVideoCodecIMXVPUBuffer *GetPreviousBuffer() const; + + uint32_t m_iWidth; + uint32_t m_iHeight; +@@ -77,7 +77,7 @@ class CDVDVideoCodecIMXBuffer + + private: + // private because we are reference counted +- virtual ~CDVDVideoCodecIMXBuffer(); ++ virtual ~CDVDVideoCodecIMXVPUBuffer(); + + private: + #ifdef TRACE_FRAMES +@@ -87,13 +87,15 @@ class CDVDVideoCodecIMXBuffer + VpuFrameBuffer *m_frameBuffer; + bool m_rendered; + double m_pts; +- CDVDVideoCodecIMXBuffer *m_previousBuffer; // Holds a the reference counted ++ CDVDVideoCodecIMXVPUBuffer *m_previousBuffer; // Holds a the reference counted + // previous buffer + }; + ++typedef CDVDVideoCodecIMXVPUBuffer CDVDVideoCodecIMXBuffer; ++ + class CDVDVideoCodecIMX : public CDVDVideoCodec + { +- friend class CDVDVideoCodecIMXBuffer; ++ friend class CDVDVideoCodecIMXVPUBuffer; + friend class CDVDVideoCodecIPUBuffer; + + public: +@@ -122,30 +124,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; // Lock to protect buffers handled +- // by both decoding and rendering threads +- +- CDVDStreamInfo m_hints; // Hints from demuxer at stream opening +- const char *m_pFormatName; // Current decoder format name +- VpuDecOpenParam m_decOpenParam; // Parameters required to call VPU_DecOpen +- CDecMemInfo m_decMemInfo; // VPU dedicated memory description +- VpuDecHandle m_vpuHandle; // Handle for VPU library calls +- VpuDecInitInfo m_initInfo; // Initial info returned from VPU at decoding start +- bool m_dropState; // Current drop state +- int m_vpuFrameBufferNum; // Total number of allocated frame buffers +- VpuFrameBuffer *m_vpuFrameBuffers; // Table of VPU frame buffers description +- CDVDVideoCodecIMXBuffer **m_outputBuffers; // Table of VPU output buffers +- CDVDVideoCodecIMXBuffer *m_lastBuffer; // Keep track of previous VPU output buffer (needed by deinterlacing motion engin) +- VpuMemDesc *m_extraMem; // Table of allocated extra Memory +- int m_frameCounter; // Decoded frames counter +- bool m_usePTS; // State whether pts out of decoding process should be used +- VpuDecOutFrameInfo m_frameInfo; // Store last VPU output frame info +- CBitstreamConverter *m_converter; // H264 annex B converter +- bool m_convert_bitstream; // State whether bitstream conversion is required +- int m_bytesToBeConsumed; // Remaining bytes in VPU +- double m_previousPts; // Enable to keep pts when needed +- bool m_frameReported; // State whether the frame consumed event will be reported by libfslvpu +- double m_dts; // Current dts ++ static const int m_extraVpuBuffers; // Number of additional buffers for VPU ++ static const int m_maxVpuDecodeLoops; // Maximum iterations in VPU decoding loop ++ static CCriticalSection m_codecBufferLock; // Lock to protect buffers handled ++ // by both decoding and rendering threads ++ ++ CDVDStreamInfo m_hints; // Hints from demuxer at stream opening ++ const char *m_pFormatName; // Current decoder format name ++ VpuDecOpenParam m_decOpenParam; // Parameters required to call VPU_DecOpen ++ CDecMemInfo m_decMemInfo; // VPU dedicated memory description ++ VpuDecHandle m_vpuHandle; // Handle for VPU library calls ++ VpuDecInitInfo m_initInfo; // Initial info returned from VPU at decoding start ++ bool m_dropState; // Current drop state ++ int m_vpuFrameBufferNum; // Total number of allocated frame buffers ++ VpuFrameBuffer *m_vpuFrameBuffers; // Table of VPU frame buffers description ++ CDVDVideoCodecIMXVPUBuffer **m_outputBuffers; // Table of VPU output buffers ++ CDVDVideoCodecIMXVPUBuffer *m_lastBuffer; // Keep track of previous VPU output buffer (needed by deinterlacing motion engin) ++ VpuMemDesc *m_extraMem; // Table of allocated extra Memory ++ int m_frameCounter; // Decoded frames counter ++ bool m_usePTS; // State whether pts out of decoding process should be used ++ VpuDecOutFrameInfo m_frameInfo; // Store last VPU output frame info ++ CBitstreamConverter *m_converter; // H264 annex B converter ++ bool m_convert_bitstream; // State whether bitstream conversion is required ++ int m_bytesToBeConsumed; // Remaining bytes in VPU ++ double m_previousPts; // Enable to keep pts when needed ++ bool m_frameReported; // State whether the frame consumed event will be reported by libfslvpu ++ double m_dts; // Current dts + }; + +From f62a4dab8e084dffa74fddfbc5cdc16a2b49f721 Mon Sep 17 00:00:00 2001 +From: smallint +Date: Tue, 25 Nov 2014 18:58:33 +0100 +Subject: [PATCH 02/18] [imx] @wolfgar Indentation + +--- + .../dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h | 34 +++++++++++----------- + 1 file changed, 17 insertions(+), 17 deletions(-) + +diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h +index eb88ecd..88b555c 100644 +--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h ++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h +@@ -58,16 +58,16 @@ class CDVDVideoCodecIMXVPUBuffer + #endif + + // reference counting +- virtual void Lock(); +- virtual long Release(); +- virtual bool IsValid(); +- +- bool Rendered() const; +- void Queue(VpuDecOutFrameInfo *frameInfo, +- CDVDVideoCodecIMXVPUBuffer *previous); +- VpuDecRetCode ReleaseFramebuffer(VpuDecHandle *handle); +- void SetPts(double pts); +- double GetPts(void) const; ++ virtual void Lock(); ++ virtual long Release(); ++ virtual bool IsValid(); ++ ++ bool Rendered() const; ++ void Queue(VpuDecOutFrameInfo *frameInfo, ++ CDVDVideoCodecIMXVPUBuffer *previous); ++ VpuDecRetCode ReleaseFramebuffer(VpuDecHandle *handle); ++ void SetPts(double pts); ++ double GetPts(void) const; + CDVDVideoCodecIMXVPUBuffer *GetPreviousBuffer() const; + + uint32_t m_iWidth; +@@ -77,18 +77,18 @@ class CDVDVideoCodecIMXVPUBuffer + + private: + // private because we are reference counted +- virtual ~CDVDVideoCodecIMXVPUBuffer(); ++ virtual ~CDVDVideoCodecIMXVPUBuffer(); + + 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; ++ VpuFrameBuffer *m_frameBuffer; ++ bool m_rendered; ++ double m_pts; + CDVDVideoCodecIMXVPUBuffer *m_previousBuffer; // Holds a the reference counted +- // previous buffer ++ // previous buffer + }; + + typedef CDVDVideoCodecIMXVPUBuffer CDVDVideoCodecIMXBuffer; + +From 7190879c7e4038e26edec13d50f026fed1d95728 Mon Sep 17 00:00:00 2001 +From: smallint +Date: Tue, 25 Nov 2014 19:04:49 +0100 +Subject: [PATCH 03/18] [imx] @wolfgar Added base class CDVDVideoCodecIMXBuffer + that CDVDVideoCodecIMXVPUBuffer derives from + +--- + xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp | 8 ++-- + .../dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp | 40 ++++++++++------ + .../dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h | 53 ++++++++++++++++------ + 3 files changed, 67 insertions(+), 34 deletions(-) + +diff --git a/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp b/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp +index 81fe19b..b0229ef 100644 +--- a/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp ++++ b/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp +@@ -2733,16 +2733,16 @@ void CLinuxRendererGLES::UploadIMXMAPTexture(int index) + 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 = (GLvoid*)IMXBuffer->pVirtAddr; ++ 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; +- plane.texwidth = IMXBuffer->m_iWidth; +- plane.texheight = IMXBuffer->m_iHeight; ++ plane.texwidth = IMXBuffer->iWidth; ++ plane.texheight = IMXBuffer->iHeight; + + CalculateTextureSourceRects(index, 1); + +diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp +index 17d2f15..9782a2c 100644 +--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp ++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp +@@ -976,18 +976,38 @@ void CDVDVideoCodecIMX::Leave() + } + + /*******************************************/ ++#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 CDVDVideoCodecIMXBuffer::SetPts(double pts) ++{ ++ m_pts = pts; ++} ++ ++void CDVDVideoCodecIMXBuffer::SetDts(double dts) ++{ ++ m_dts = dts; ++} + + #ifdef TRACE_FRAMES + CDVDVideoCodecIMXVPUBuffer::CDVDVideoCodecIMXVPUBuffer(int idx) +- : m_refs(1) +- , m_idx(idx) ++ : CDVDVideoCodecIMXBuffer(idx) + #else + CDVDVideoCodecIMXVPUBuffer::CDVDVideoCodecIMXVPUBuffer() +- : m_refs(1) ++ : CDVDVideoCodecIMXBuffer() + #endif + , m_frameBuffer(NULL) + , m_rendered(false) +- , m_pts(DVD_NOPTS_VALUE) + , m_previousBuffer(NULL) + { + } +@@ -1078,22 +1098,12 @@ VpuDecRetCode CDVDVideoCodecIMXVPUBuffer::ReleaseFramebuffer(VpuDecHandle *handl + #endif + m_rendered = false; + m_frameBuffer = NULL; +- m_pts = DVD_NOPTS_VALUE; ++ SetPts(DVD_NOPTS_VALUE); + SAFE_RELEASE(m_previousBuffer); + + return ret; + } + +-void CDVDVideoCodecIMXVPUBuffer::SetPts(double pts) +-{ +- m_pts = pts; +-} +- +-double CDVDVideoCodecIMXVPUBuffer::GetPts(void) const +-{ +- return m_pts; +-} +- + CDVDVideoCodecIMXVPUBuffer *CDVDVideoCodecIMXVPUBuffer::GetPreviousBuffer() const + { + return m_previousBuffer; +diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h +index 88b555c..c4452ca 100644 +--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h ++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h +@@ -48,7 +48,44 @@ class CDecMemInfo + VpuMemDesc* phyMem; + }; + +-class CDVDVideoCodecIMXVPUBuffer ++// Base class of IMXVPU buffer ++class CDVDVideoCodecIMXBuffer { ++public: ++#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; } ++ ++ uint32_t iWidth; ++ uint32_t iHeight; ++ uint8_t *pPhysAddr; ++ uint8_t *pVirtAddr; ++ uint8_t iFormat; ++ ++protected: ++#ifdef TRACE_FRAMES ++ int m_idx; ++#endif ++ long m_refs; ++ ++private: ++ double m_pts; ++ double m_dts; ++}; ++ ++class CDVDVideoCodecIMXVPUBuffer : public CDVDVideoCodecIMXBuffer + { + public: + #ifdef TRACE_FRAMES +@@ -66,33 +103,19 @@ class CDVDVideoCodecIMXVPUBuffer + void Queue(VpuDecOutFrameInfo *frameInfo, + CDVDVideoCodecIMXVPUBuffer *previous); + VpuDecRetCode ReleaseFramebuffer(VpuDecHandle *handle); +- void SetPts(double pts); +- double GetPts(void) const; + CDVDVideoCodecIMXVPUBuffer *GetPreviousBuffer() const; + +- uint32_t m_iWidth; +- uint32_t m_iHeight; +- uint8_t *m_phyAddr; +- uint8_t *m_VirtAddr; +- + private: + // private because we are reference counted + virtual ~CDVDVideoCodecIMXVPUBuffer(); + + private: +-#ifdef TRACE_FRAMES +- int m_idx; +-#endif +- long m_refs; + VpuFrameBuffer *m_frameBuffer; + bool m_rendered; +- double m_pts; + CDVDVideoCodecIMXVPUBuffer *m_previousBuffer; // Holds a the reference counted + // previous buffer + }; + +-typedef CDVDVideoCodecIMXVPUBuffer CDVDVideoCodecIMXBuffer; +- + class CDVDVideoCodecIMX : public CDVDVideoCodec + { + friend class CDVDVideoCodecIMXVPUBuffer; + +From fd94f1fcad232f4b8df20616ef2b4fe4fe84cd2c Mon Sep 17 00:00:00 2001 +From: smallint +Date: Tue, 25 Nov 2014 19:15:04 +0100 +Subject: [PATCH 04/18] [imx] @wolfgar Added CDVDVideoCodecIMXIPUBuffer class + that wraps IPU allocated picture buffers + +--- + .../dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp | 236 +++++++++++++++++++++ + .../dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h | 44 +++- + 2 files changed, 279 insertions(+), 1 deletion(-) + +diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp +index 9782a2c..e812b60 100644 +--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp ++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp +@@ -1116,3 +1116,239 @@ CDVDVideoCodecIMXVPUBuffer::~CDVDVideoCodecIMXVPUBuffer() + CLog::Log(LOGDEBUG, "~ %02d (VPU)\n", m_idx); + #endif + } ++ ++#ifdef TRACE_FRAMES ++CDVDVideoCodecIMXIPUBuffer::CDVDVideoCodecIMXIPUBuffer(int idx) ++ : CDVDVideoCodecIMXBuffer(idx) ++#else ++CDVDVideoCodecIMXIPUBuffer::CDVDVideoCodecIMXIPUBuffer() ++ : CDVDVideoCodecIMXBuffer() ++#endif ++ , m_bFree(true) ++ , m_pPhyAddr(0) ++ , m_pVirtAddr(NULL) ++ , m_nSize(0) ++{ ++} ++ ++CDVDVideoCodecIMXIPUBuffer::~CDVDVideoCodecIMXIPUBuffer() ++{ ++ assert(m_refs == 0); ++#ifdef TRACE_FRAMES ++ CLog::Log(LOGDEBUG, "~ %02d (IPU)\n", m_idx); ++#endif ++} ++ ++void CDVDVideoCodecIMXIPUBuffer::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 CDVDVideoCodecIMXIPUBuffer::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 CDVDVideoCodecIMXIPUBuffer::IsValid() ++{ ++ return /*m_source && m_source->IsValid() && */m_pPhyAddr; ++} ++ ++bool CDVDVideoCodecIMXIPUBuffer::Process(int fd, CDVDVideoCodecIMXVPUBuffer *buffer, ++ VpuFieldType fieldType, int fieldFmt, ++ bool lowMotion) ++{ ++ CDVDVideoCodecIMXVPUBuffer *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; ++ format = 0; ++#else ++ task.output.format = IPU_PIX_FMT_NV12; ++ iFormat = 1; ++#endif ++ task.output.paddr = (int)pPhysAddr; ++ ++ // Fill current and next buffer address ++ if (lowMotion && previousBuffer && previousBuffer->IsValid()) ++ { ++ task.input.paddr = (int)previousBuffer->pPhysAddr; ++ task.input.paddr_n = (int)buffer->pPhysAddr; ++ task.input.deinterlace.motion = LOW_MOTION; ++ } ++ else ++ { ++ task.input.paddr = (int)buffer->pPhysAddr; ++ 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 CDVDVideoCodecIMXIPUBuffer::ReleaseFrameBuffer() ++{ ++#ifdef TRACE_FRAMES ++ CLog::Log(LOGDEBUG, "- %02d (IPU)\n", m_idx); ++#endif ++ m_bFree = true; ++} ++ ++bool CDVDVideoCodecIMXIPUBuffer::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; ++ ++ pPhysAddr = pVirtAddr = 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) ++ { ++ pPhysAddr = (uint8_t*)Align(m_pPhyAddr, nAlign); ++ pVirtAddr = (uint8_t*)Align(m_pVirtAddr, nAlign); ++ } ++ else ++ { ++ pPhysAddr = (uint8_t*)m_pPhyAddr; ++ pVirtAddr = (uint8_t*)m_pVirtAddr; ++ } ++ ++ return true; ++} ++ ++bool CDVDVideoCodecIMXIPUBuffer::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; ++ } ++ ++ pPhysAddr = pVirtAddr = NULL; ++ m_bFree = true; ++ ++ return ret; ++} +diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h +index c4452ca..86edaa2 100644 +--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h ++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h +@@ -48,7 +48,8 @@ class CDecMemInfo + VpuMemDesc* phyMem; + }; + +-// Base class of IMXVPU buffer ++ ++// Base class of IMXVPU and IMXIPU buffer + class CDVDVideoCodecIMXBuffer { + public: + #ifdef TRACE_FRAMES +@@ -85,6 +86,7 @@ class CDVDVideoCodecIMXBuffer { + double m_dts; + }; + ++ + class CDVDVideoCodecIMXVPUBuffer : public CDVDVideoCodecIMXBuffer + { + public: +@@ -116,6 +118,46 @@ class CDVDVideoCodecIMXVPUBuffer : public CDVDVideoCodecIMXBuffer + // 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 CDVDVideoCodecIMXIPUBuffer : public CDVDVideoCodecIMXBuffer ++{ ++public: ++#ifdef TRACE_FRAMES ++ CDVDVideoCodecIMXIPUBuffer(int idx); ++#else ++ CDVDVideoCodecIMXIPUBuffer(); ++#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, CDVDVideoCodecIMXVPUBuffer *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 ~CDVDVideoCodecIMXIPUBuffer(); ++ ++private: ++ bool m_bFree; ++ int m_pPhyAddr; ++ uint8_t *m_pVirtAddr; ++ uint32_t m_iWidth; ++ uint32_t m_iHeight; ++ int m_nSize; ++}; ++ ++ + class CDVDVideoCodecIMX : public CDVDVideoCodec + { + friend class CDVDVideoCodecIMXVPUBuffer; + +From 8c4eb96c7c82b66bad008dd521429f8cc1039d2d Mon Sep 17 00:00:00 2001 +From: smallint +Date: Tue, 25 Nov 2014 19:16:49 +0100 +Subject: [PATCH 05/18] [imx] @wolfgar Added CDVDVideoCodecIMXIPUBuffers that + manages a pool of IPU buffers and implements deinterlacing of VPU buffers to + IPU buffers + +--- + .../dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp | 134 +++++++++++++++++++++ + .../dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h | 37 ++++++ + 2 files changed, 171 insertions(+) + +diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp +index e812b60..5dfa4f8 100644 +--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp ++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp +@@ -1352,3 +1352,137 @@ bool CDVDVideoCodecIMXIPUBuffer::Free(int fd) + + return ret; + } ++ ++CDVDVideoCodecIMXIPUBuffers::CDVDVideoCodecIMXIPUBuffers() ++ : m_ipuHandle(0) ++ , m_bufferNum(0) ++ , m_buffers(NULL) ++ , m_currentFieldFmt(0) ++{ ++} ++ ++CDVDVideoCodecIMXIPUBuffers::~CDVDVideoCodecIMXIPUBuffers() ++{ ++ Close(); ++} ++ ++bool CDVDVideoCodecIMXIPUBuffers::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 CDVDVideoCodecIMXIPUBuffer*[m_bufferNum]; ++ m_currentFieldFmt = 0; ++ ++ for (int i=0; i < m_bufferNum; i++) ++ { ++#ifdef TRACE_FRAMES ++ m_buffers[i] = new CDVDVideoCodecIMXIPUBuffer(i); ++#else ++ m_buffers[i] = new CDVDVideoCodecIMXIPUBuffer; ++#endif ++ if (!m_buffers[i]->Allocate(m_ipuHandle, width, height, nAlign)) ++ { ++ Close(); ++ return false; ++ } ++ } ++ ++ return true; ++} ++ ++bool CDVDVideoCodecIMXIPUBuffers::Reset() ++{ ++ for (int i=0; i < m_bufferNum; i++) ++ m_buffers[i]->ReleaseFrameBuffer(); ++ m_currentFieldFmt = 0; ++} ++ ++bool CDVDVideoCodecIMXIPUBuffers::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; ++} ++ ++CDVDVideoCodecIMXIPUBuffer * ++CDVDVideoCodecIMXIPUBuffers::Process(CDVDVideoCodecIMXBuffer *sourceBuffer, ++ VpuFieldType fieldType, bool lowMotion) ++{ ++ CDVDVideoCodecIMXIPUBuffer *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, (CDVDVideoCodecIMXVPUBuffer*)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; ++} +diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h +index 86edaa2..bb2f7d1 100644 +--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h ++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h +@@ -26,6 +26,14 @@ + #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 ++ + //#define IMX_PROFILE + //#define TRACE_FRAMES + +@@ -158,6 +166,35 @@ class CDVDVideoCodecIMXIPUBuffer : public CDVDVideoCodecIMXBuffer + }; + + ++// 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 CDVDVideoCodecIMXIPUBuffers ++{ ++ public: ++ CDVDVideoCodecIMXIPUBuffers(); ++ ~CDVDVideoCodecIMXIPUBuffers(); ++ ++ 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(); ++ ++ CDVDVideoCodecIMXIPUBuffer * ++ Process(CDVDVideoCodecIMXBuffer *sourceBuffer, ++ VpuFieldType fieldType, bool lowMotion); ++ ++ private: ++ int m_ipuHandle; ++ bool m_autoMode; ++ int m_bufferNum; ++ CDVDVideoCodecIMXIPUBuffer **m_buffers; ++ int m_currentFieldFmt; ++}; ++ ++ + class CDVDVideoCodecIMX : public CDVDVideoCodec + { + friend class CDVDVideoCodecIMXVPUBuffer; + +From 4b14e49ad629c7fe22b438aee2065dafd426c97f Mon Sep 17 00:00:00 2001 +From: smallint +Date: Tue, 25 Nov 2014 19:22:28 +0100 +Subject: [PATCH 06/18] [imx] @wolfgar Added mixer thread implementation with + capacity limited input/output queue + +--- + .../dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp | 248 ++++++++++++++++++++- + .../dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h | 90 ++++++++ + 2 files changed, 336 insertions(+), 2 deletions(-) + +diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp +index 5dfa4f8..6da91eb 100644 +--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp ++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp +@@ -26,11 +26,15 @@ + #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 +@@ -1486,3 +1490,243 @@ CDVDVideoCodecIMXIPUBuffers::Process(CDVDVideoCodecIMXBuffer *sourceBuffer, + + return target; + } ++ ++ ++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) ++ , 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(); ++} ++ ++CDVDVideoCodecIMXBuffer *CDVDVideoMixerIMX::Process(CDVDVideoCodecIMXVPUBuffer *buffer) ++{ ++ CSingleLock lk(m_monitor); ++ CDVDVideoCodecIMXBuffer *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 ++ CDVDVideoCodecIMXVPUBuffer *inputBuffer = GetNextInput(); ++ if (inputBuffer) ++ { ++ // Wait for free slot ++ WaitForFreeOutput(); ++ ++ CDVDVideoCodecIMXBuffer *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); ++ } ++ } ++} ++ ++CDVDVideoCodecIMXVPUBuffer *CDVDVideoMixerIMX::GetNextInput() { ++ CSingleLock lk(m_monitor); ++ while (!m_bufferedInput && !m_bStop) ++ m_inputNotEmpty.wait(lk); ++ ++ if (m_bStop) ++ return NULL; ++ ++ CDVDVideoCodecIMXVPUBuffer *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(CDVDVideoCodecIMXBuffer *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; ++} ++ ++CDVDVideoCodecIMXBuffer *CDVDVideoMixerIMX::ProcessFrame(CDVDVideoCodecIMXVPUBuffer *inputBuffer) ++{ ++ CDVDVideoCodecIMXBuffer *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, ++ inputBuffer->GetFieldType(), ++ 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 bb2f7d1..5b4d835 100644 +--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h ++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h +@@ -19,10 +19,14 @@ + * + */ + #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" + + +@@ -34,6 +38,15 @@ + // 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 + +@@ -195,6 +208,83 @@ class CDVDVideoCodecIMXIPUBuffers + }; + + ++// 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 CDVDVideoCodecIMXIPUBuffers ++{ ++ public: ++ CDVDVideoCodecIMXIPUBuffers(); ++ ~CDVDVideoCodecIMXIPUBuffers(); ++ ++ 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(); ++ ++ CDVDVideoCodecIMXIPUBuffer * ++ Process(CDVDVideoCodecIMXBuffer *sourceBuffer, ++ VpuFieldType fieldType, bool lowMotion); ++ ++ private: ++ int m_ipuHandle; ++ bool m_autoMode; ++ int m_bufferNum; ++ CDVDVideoCodecIMXIPUBuffer **m_buffers; ++ int m_currentFieldFmt; ++}; ++ ++ ++class CDVDVideoMixerIMX : private CThread { ++public: ++ CDVDVideoMixerIMX(CDVDVideoCodecIMXIPUBuffers *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. ++ CDVDVideoCodecIMXBuffer *Process(CDVDVideoCodecIMXVPUBuffer *input); ++ ++private: ++ CDVDVideoCodecIMXVPUBuffer *GetNextInput(); ++ void WaitForFreeOutput(); ++ bool PushOutput(CDVDVideoCodecIMXBuffer *v); ++ CDVDVideoCodecIMXBuffer *ProcessFrame(CDVDVideoCodecIMXVPUBuffer *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; ++ ++ CDVDVideoCodecIMXIPUBuffers *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; ++ CDVDVideoCodecIMXBuffer *m_lastFrame; // Last input frame ++}; ++ ++ + class CDVDVideoCodecIMX : public CDVDVideoCodec + { + friend class CDVDVideoCodecIMXVPUBuffer; + +From 657ea2836b26cc70c3ed4cee881b876080ab228b Mon Sep 17 00:00:00 2001 +From: smallint +Date: Tue, 25 Nov 2014 19:30:30 +0100 +Subject: [PATCH 07/18] [imx] @wolfgar Removed friend declaration + +--- + xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h | 3 --- + 1 file changed, 3 deletions(-) + +diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h +index 5b4d835..33e449f 100644 +--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h ++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h +@@ -287,9 +287,6 @@ class CDVDVideoMixerIMX : private CThread { + + class CDVDVideoCodecIMX : public CDVDVideoCodec + { +- friend class CDVDVideoCodecIMXVPUBuffer; +- friend class CDVDVideoCodecIPUBuffer; +- + public: + CDVDVideoCodecIMX(); + virtual ~CDVDVideoCodecIMX(); + +From 288033e49346e9f2710d1a145abadf2308553d54 Mon Sep 17 00:00:00 2001 +From: smallint +Date: Tue, 25 Nov 2014 19:42:49 +0100 +Subject: [PATCH 08/18] [imx] @wolfgar Added missing attribute to + CDVDVideoCodecIMXVPUBuffer, cosmetics (indentation) and allocate buffer + according to input format at compile time + +--- + .../dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp | 130 ++++++++++++++------- + .../dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h | 7 +- + 2 files changed, 91 insertions(+), 46 deletions(-) + +diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp +index 6da91eb..87a6c48 100644 +--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp ++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp +@@ -94,8 +94,8 @@ bool CDVDVideoCodecIMX::VpuAllocBuffers(VpuMemInfo *pMemBlock) + return true; + + AllocFailure: +- VpuFreeBuffers(); +- return false; ++ VpuFreeBuffers(); ++ return false; + } + + int CDVDVideoCodecIMX::VpuFindBuffer(void *frameAddr) +@@ -231,50 +231,76 @@ 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; + +- m_vpuFrameBufferNum = m_initInfo.nMinFrameBufferCount + m_extraVpuBuffers; ++ 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); ++ } ++ ++#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; + } + +- //NV12 for all video +- uvStride=yStride; +- uvSize=ySize/2; +- mvSize=uvSize/2; ++#else ++ // NV12 ++ uvStride = yStride; ++ uSize = ySize/2; ++ mvSize = uSize/2; ++#endif + +- nAlign=m_initInfo.nAddressAlignment; ++ 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 CDVDVideoCodecIMXVPUBuffer*[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) + { +@@ -291,36 +317,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 CDVDVideoCodecIMXVPUBuffer(i); +@@ -647,7 +681,7 @@ int CDVDVideoCodecIMX::Decode(BYTE *pData, int iSize, double dts, double pts) + 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); ++ 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) +@@ -1079,10 +1113,18 @@ void CDVDVideoCodecIMXVPUBuffer::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; ++ pVirtAddr = m_frameBuffer->pbufVirtY; ++ pPhysAddr = m_frameBuffer->pbufY; ++ ++ m_fieldType = frameInfo->eFieldType; ++ // We decode to I420 ++#ifdef IMX_INPUT_FORMAT_I420 ++ iFormat = 0; ++#else ++ iFormat = 1; ++#endif + } + + VpuDecRetCode CDVDVideoCodecIMXVPUBuffer::ReleaseFramebuffer(VpuDecHandle *handle) +diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h +index 33e449f..c8b807d 100644 +--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h ++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h +@@ -127,16 +127,19 @@ class CDVDVideoCodecIMXVPUBuffer : public CDVDVideoCodecIMXBuffer + CDVDVideoCodecIMXVPUBuffer *previous); + VpuDecRetCode ReleaseFramebuffer(VpuDecHandle *handle); + CDVDVideoCodecIMXVPUBuffer *GetPreviousBuffer() const; ++ VpuFieldType GetFieldType() const { return m_fieldType; } + + private: + // private because we are reference counted +- virtual ~CDVDVideoCodecIMXVPUBuffer(); ++ virtual ~CDVDVideoCodecIMXVPUBuffer(); + + private: + VpuFrameBuffer *m_frameBuffer; ++ VpuFieldType m_fieldType; ++ + bool m_rendered; + CDVDVideoCodecIMXVPUBuffer *m_previousBuffer; // Holds a the reference counted +- // previous buffer ++ // previous buffer + }; + + + +From 9cb00a6922b74690e7502cd72dba98071297700e Mon Sep 17 00:00:00 2001 +From: smallint +Date: Tue, 25 Nov 2014 19:46:32 +0100 +Subject: [PATCH 09/18] [imx] @wolfgar Added more VPU decoder configuration and + fixed nChromaInterleave depending on input format + +--- + .../dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp | 22 ++++++++++++++++++++++ + 1 file changed, 22 insertions(+) + +diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp +index 87a6c48..c09b4e6 100644 +--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp ++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp +@@ -189,7 +189,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; +@@ -210,6 +214,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 + +From abe29f2acc6291d5807f34ed0fd9fd7ba83f8274 Mon Sep 17 00:00:00 2001 +From: smallint +Date: Tue, 25 Nov 2014 19:50:47 +0100 +Subject: [PATCH 10/18] [imx] @wolfgar Added deinterlacer initialization and + mixer thread but still unused + +--- + xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp | 12 +++++++++++- + xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h | 3 +++ + 2 files changed, 14 insertions(+), 1 deletion(-) + +diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp +index c09b4e6..59187e8 100644 +--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp ++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp +@@ -385,16 +385,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; +@@ -409,6 +418,7 @@ CDVDVideoCodecIMX::CDVDVideoCodecIMX() + m_convert_bitstream = false; + m_bytesToBeConsumed = 0; + m_previousPts = DVD_NOPTS_VALUE; ++ m_mixer.SetCapacity(3,3); + } + + CDVDVideoCodecIMX::~CDVDVideoCodecIMX() +diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h +index c8b807d..69e27f7 100644 +--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h ++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h +@@ -330,8 +330,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 ++ 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 + +From f54fdf922228a37fb7d4f89177f4bd5c766a8026 Mon Sep 17 00:00:00 2001 +From: smallint +Date: Tue, 25 Nov 2014 19:56:14 +0100 +Subject: [PATCH 11/18] [imx] @wolfgar Cosmetics and removed duplicate class + declaration + +--- + .../dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h | 71 +++++++--------------- + 1 file changed, 21 insertions(+), 50 deletions(-) + +diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h +index 69e27f7..7c0e7da 100644 +--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h ++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h +@@ -187,60 +187,32 @@ class CDVDVideoCodecIMXIPUBuffer : public CDVDVideoCodecIMXBuffer + // buffers. + class CDVDVideoCodecIMXIPUBuffers + { +- public: +- CDVDVideoCodecIMXIPUBuffers(); +- ~CDVDVideoCodecIMXIPUBuffers(); +- +- 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(); +- +- CDVDVideoCodecIMXIPUBuffer * +- Process(CDVDVideoCodecIMXBuffer *sourceBuffer, +- VpuFieldType fieldType, bool lowMotion); +- +- private: +- int m_ipuHandle; +- bool m_autoMode; +- int m_bufferNum; +- CDVDVideoCodecIMXIPUBuffer **m_buffers; +- int m_currentFieldFmt; +-}; ++public: ++ CDVDVideoCodecIMXIPUBuffers(); ++ ~CDVDVideoCodecIMXIPUBuffers(); + ++ 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(); + +-// 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 CDVDVideoCodecIMXIPUBuffers +-{ +- public: +- CDVDVideoCodecIMXIPUBuffers(); +- ~CDVDVideoCodecIMXIPUBuffers(); +- +- 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(); +- +- CDVDVideoCodecIMXIPUBuffer * +- Process(CDVDVideoCodecIMXBuffer *sourceBuffer, +- VpuFieldType fieldType, bool lowMotion); +- +- private: +- int m_ipuHandle; +- bool m_autoMode; +- int m_bufferNum; +- CDVDVideoCodecIMXIPUBuffer **m_buffers; +- int m_currentFieldFmt; ++ CDVDVideoCodecIMXIPUBuffer * ++ Process(CDVDVideoCodecIMXBuffer *sourceBuffer, ++ VpuFieldType fieldType, bool lowMotion); ++ ++private: ++ int m_ipuHandle; ++ bool m_autoMode; ++ int m_bufferNum; ++ CDVDVideoCodecIMXIPUBuffer **m_buffers; ++ int m_currentFieldFmt; + }; + + +-class CDVDVideoMixerIMX : private CThread { ++class CDVDVideoMixerIMX : private CThread ++{ + public: + CDVDVideoMixerIMX(CDVDVideoCodecIMXIPUBuffers *proc); + virtual ~CDVDVideoMixerIMX(); +@@ -309,7 +281,6 @@ class CDVDVideoCodecIMX : public CDVDVideoCodec + static void Leave(); + + protected: +- + bool VpuOpen(); + bool VpuAllocBuffers(VpuMemInfo *); + bool VpuFreeBuffers(); + +From 5c8168ca2a215c52b7d2fba81de6b300df87586a Mon Sep 17 00:00:00 2001 +From: smallint +Date: Tue, 25 Nov 2014 20:00:17 +0100 +Subject: [PATCH 12/18] [imx6] @wolfgar Activated deinterlacer and mixer thread + +--- + xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp | 53 +++++--- + xbmc/cores/VideoRenderers/LinuxRendererGLES.h | 3 + + .../dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp | 141 ++++++++++++--------- + .../dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h | 6 - + 4 files changed, 123 insertions(+), 80 deletions(-) + +diff --git a/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp b/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp +index b0229ef..037a57b 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; +@@ -1237,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); +@@ -1683,18 +1688,23 @@ void CLinuxRendererGLES::RenderIMXMAPTexture(int index, int field) + YUVPLANE &plane = m_buffers[index].fields[field][0]; + CDVDVideoCodecIMXBuffer *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 +@@ -2719,25 +2728,29 @@ void CLinuxRendererGLES::UploadIMXMAPTexture(int index) + + 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->pVirtAddr; +- glTexDirectVIVMap(m_textureTarget, IMXBuffer->iWidth, IMXBuffer->iHeight, GL_VIV_NV12, +- (GLvoid **)&virt, &physical); +- glTexDirectInvalidateVIV(m_textureTarget); + ++ if (IMXBuffer->iFormat == 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; + } +diff --git a/xbmc/cores/VideoRenderers/LinuxRendererGLES.h b/xbmc/cores/VideoRenderers/LinuxRendererGLES.h +index d8bf35d..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; + + +diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp +index 59187e8..f841380 100644 +--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp ++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp +@@ -44,7 +44,6 @@ + // 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) + { +@@ -557,6 +556,8 @@ bool CDVDVideoCodecIMX::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options) + return false; + } + ++ m_mixer.Start(); ++ + return true; + } + +@@ -565,12 +566,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); + +- /* quick & dirty fix to get proper timestamping for VP8 codec */ +- if (m_decOpenParam.CodecFormat == VPU_V_VP8) ++ idx = VpuFindBuffer(m_frameInfo.pDisplayFrameBuf->pbufY); ++ if (idx != -1) + { +- idx = VpuFindBuffer(m_frameInfo.pDisplayFrameBuf->pbufY); +- m_outputBuffers[idx]->SetPts(pts); +- } ++ CDVDVideoCodecIMXVPUBuffer *buffer = m_outputBuffers[idx]; ++ /* quick & dirty fix to get proper timestamping for VP8 codec */ ++ if (m_decOpenParam.CodecFormat == VPU_V_VP8) ++ buffer->SetPts(pts); + +- retStatus |= VC_PICTURE; ++ 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 +@@ -901,8 +960,6 @@ 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; + + #ifdef IMX_PROFILE + CLog::Log(LOGDEBUG, "%s - returns %x - duration %lld\n", __FUNCTION__, retStatus, XbmcThreads::SystemClockMillis() - previous); +@@ -920,9 +977,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++) +@@ -983,38 +1044,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) +- { +- CDVDVideoCodecIMXVPUBuffer *buffer = m_outputBuffers[idx]; +- +- pDvdVideoPicture->pts = buffer->GetPts(); +- pDvdVideoPicture->dts = m_dts; +- if (!m_usePTS) +- { +- pDvdVideoPicture->pts = DVD_NOPTS_VALUE; +- pDvdVideoPicture->dts = DVD_NOPTS_VALUE; +- } +- +- buffer->Queue(&m_frameInfo, m_lastBuffer); +- +-#ifdef TRACE_FRAMES +- CLog::Log(LOGDEBUG, "+ %02d dts %f pts %f (VPU)\n", idx, pDvdVideoPicture->dts, pDvdVideoPicture->pts); +-#endif +- +- pDvdVideoPicture->IMXBuffer = buffer; +- pDvdVideoPicture->IMXBuffer->Lock(); ++ // Current buffer is locked already -> hot potato ++ pDvdVideoPicture->pts = m_currentBuffer->GetPts(); ++ pDvdVideoPicture->dts = m_currentBuffer->GetDts(); + +- // 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->IMXBuffer = m_currentBuffer; ++ m_currentBuffer = NULL; + + return true; + } +@@ -1035,16 +1070,6 @@ void CDVDVideoCodecIMX::SetDropState(bool bDrop) + } + } + +-void CDVDVideoCodecIMX::Enter() +-{ +- m_codecBufferLock.lock(); +-} +- +-void CDVDVideoCodecIMX::Leave() +-{ +- m_codecBufferLock.unlock(); +-} +- + /*******************************************/ + #ifdef TRACE_FRAMES + CDVDVideoCodecIMXBuffer::CDVDVideoCodecIMXBuffer(int idx) +diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h +index 7c0e7da..6af8130 100644 +--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h ++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h +@@ -277,9 +277,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(); + bool VpuAllocBuffers(VpuMemInfo *); +@@ -289,8 +286,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 + const char *m_pFormatName; // Current decoder format name +@@ -315,5 +310,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 a9f1458a4b43f722db4d115e1b5e0a1c4d81f72f Mon Sep 17 00:00:00 2001 +From: smallint +Date: Wed, 26 Nov 2014 01:11:54 +0100 +Subject: [PATCH 13/18] [imx] @wolfgar return 3 in + LinuxRendererGLES::GetOptimalBufferSize for IMX render path + +--- + xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp b/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp +index 037a57b..35c905b 100644 +--- a/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp ++++ b/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp +@@ -2986,7 +2986,7 @@ unsigned int CLinuxRendererGLES::GetOptimalBufferSize() + m_format == RENDER_FMT_MEDIACODEC) + return 2; + else if(m_format == RENDER_FMT_IMXMAP) +- return 1; ++ return 3; + else + return 3; + } + +From b3c24108ad8f61989f9fbbeab605c021782889f4 Mon Sep 17 00:00:00 2001 +From: smallint +Date: Thu, 27 Nov 2014 22:39:10 +0100 +Subject: [PATCH 14/18] [imx] @wolfgar Corrected some comments, fixed iFormat + along with IMX_OUTPUT_FORMAT_I420 + +--- + xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp | 9 +++++---- + xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h | 4 ++-- + 2 files changed, 7 insertions(+), 6 deletions(-) + +diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp +index f841380..511956d 100644 +--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp ++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp +@@ -644,6 +644,8 @@ int CDVDVideoCodecIMX::Decode(BYTE *pData, int iSize, double dts, double pts) + + #ifdef IMX_PROFILE + static unsigned long long previous, current; ++#endif ++#if defined(IMX_PROFILE) || defined(IMX_PROFILE_BUFFERS) + unsigned long long before_dec; + #endif + +@@ -711,12 +713,11 @@ int CDVDVideoCodecIMX::Decode(BYTE *pData, int iSize, double dts, double pts) + + while (true) // Decode as long as the VPU consumes data + { +-#ifdef IMX_PROFILE ++#if defined(IMX_PROFILE) || defined(IMX_PROFILE_BUFFERS) + before_dec = XbmcThreads::SystemClockMillis(); + #endif + if (m_frameReported) + m_bytesToBeConsumed += inData.nSize; +- unsigned long long before_dec = XbmcThreads::SystemClockMillis(); + ret = VPU_DecDecodeBuf(m_vpuHandle, &inData, &decRet); + #ifdef IMX_PROFILE_BUFFERS + dec_time += XbmcThreads::SystemClockMillis()-before_dec; +@@ -1125,7 +1126,7 @@ long CDVDVideoCodecIMXVPUBuffer::Release() + #endif + if (count == 2) + { +- // Only referenced by the coded and its next frame, release the previous ++ // Only referenced by the codec and its next frame, release the previous + SAFE_RELEASE(m_previousBuffer); + } + if (count == 1) +@@ -1308,7 +1309,7 @@ bool CDVDVideoCodecIMXIPUBuffer::Process(int fd, CDVDVideoCodecIMXVPUBuffer *buf + task.output.height = iHeight; + #ifdef IMX_OUTPUT_FORMAT_I420 + task.output.format = IPU_PIX_FMT_YUV420P; +- format = 0; ++ iFormat = 0; + #else + task.output.format = IPU_PIX_FMT_NV12; + iFormat = 1; +diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h +index 6af8130..d9aadc9 100644 +--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h ++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h +@@ -38,8 +38,8 @@ + // 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 ++// This enables logging of times for Decode, Render->Render, ++// 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 + +From 4eff53acf4e0dfe892a484ec7355bc60aafda6c0 Mon Sep 17 00:00:00 2001 +From: smallint +Date: Thu, 27 Nov 2014 22:42:36 +0100 +Subject: [PATCH 15/18] [imx] @wolfgar Enable LOW_MOTION for SD content + +--- + 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 511956d..51ec5d8 100644 +--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp ++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp +@@ -1818,9 +1818,11 @@ CDVDVideoCodecIMXBuffer *CDVDVideoMixerIMX::ProcessFrame(CDVDVideoCodecIMXVPUBuf + Sleep(35); + outputBuffer = inputBuffer; + #else ++ // Enable low motion for buffers that are not split up by the VDIC ++ bool lowMotion = (inputBuffer->iWidth < 1024) && (inputBuffer->iHeight < 1024); + outputBuffer = m_proc->Process(inputBuffer, + inputBuffer->GetFieldType(), +- false); ++ lowMotion); + #endif + #ifdef IMX_PROFILE_BUFFERS + CLog::Log(LOGNOTICE, "+P %x %lld\n", (int)outputBuffer, + +From 021f9599d77a0579f278c3f8d4a9ea474f71c177 Mon Sep 17 00:00:00 2001 +From: smallint +Date: Fri, 28 Nov 2014 23:42:09 +0100 +Subject: [PATCH 16/18] [imx] @wolfgar Removed commented lines and removed + WRITE flag for read only mapped buffers + +--- + 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 51ec5d8..d20028f 100644 +--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp ++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp +@@ -864,11 +864,7 @@ int CDVDVideoCodecIMX::Decode(BYTE *pData, int iSize, double dts, double pts) + m_currentBuffer = m_mixer.Process(buffer); + + if (m_currentBuffer) +- { + retStatus |= VC_PICTURE; +- //m_currentBuffer->Release(); +- //m_currentBuffer = NULL; +- } + } + } //VPU_DEC_OUTPUT_DIS + +@@ -1400,7 +1396,7 @@ bool CDVDVideoCodecIMXIPUBuffer::Allocate(int fd, int width, int height, int nAl + 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, ++ m_pVirtAddr = (uint8_t*)mmap(0, m_nSize, PROT_READ, MAP_SHARED, + fd, m_pPhyAddr); + if (!m_pVirtAddr) + { + +From ea72d307c53eb417c6d2bb898cae438e34b62c89 Mon Sep 17 00:00:00 2001 +From: smallint +Date: Fri, 5 Dec 2014 17:02:36 +0000 +Subject: [PATCH 17/18] [imx] @wolfgar Added VDI buffer splitting to bypass + kernel splitting algorithms which introduces some DMA memory burst penalties + +--- + xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp | 8 ++- + .../dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp | 62 +++++++++++++++++++--- + .../dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h | 17 ++++-- + 3 files changed, 76 insertions(+), 11 deletions(-) + +diff --git a/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp b/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp +index 35c905b..0364a6c 100644 +--- a/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp ++++ b/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp +@@ -2746,9 +2746,15 @@ void CLinuxRendererGLES::UploadIMXMAPTexture(int index) + if (IMXBuffer->iFormat == 0) + glTexDirectVIVMap(m_textureTarget, IMXBuffer->iWidth, IMXBuffer->iHeight, GL_VIV_I420, + (GLvoid **)&virt, &physical); +- else ++ else if (IMXBuffer->iFormat == 1) + glTexDirectVIVMap(m_textureTarget, IMXBuffer->iWidth, IMXBuffer->iHeight, GL_VIV_NV12, + (GLvoid **)&virt, &physical); ++ else if (IMXBuffer->iFormat == 2) ++ glTexDirectVIVMap(m_textureTarget, IMXBuffer->iWidth, IMXBuffer->iHeight, GL_RGB565, ++ (GLvoid **)&virt, &physical); ++ else if (IMXBuffer->iFormat == 3) ++ glTexDirectVIVMap(m_textureTarget, IMXBuffer->iWidth, IMXBuffer->iHeight, GL_RGBA, ++ (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 d20028f..f556223 100644 +--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp ++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp +@@ -36,6 +36,7 @@ + #include "utils/log.h" + #include "DVDClock.h" + ++#define IMX_MDI_MAX_WIDTH 968 + #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)) +@@ -1294,6 +1295,8 @@ bool CDVDVideoCodecIMXIPUBuffer::Process(int fd, CDVDVideoCodecIMXVPUBuffer *buf + // Input is the VPU decoded frame + task.input.width = iWidth; + task.input.height = iHeight; ++ task.input.crop.h = iHeight; ++ + #ifdef IMX_INPUT_FORMAT_I420 + task.input.format = IPU_PIX_FMT_YUV420P; + #else +@@ -1303,6 +1306,7 @@ bool CDVDVideoCodecIMXIPUBuffer::Process(int fd, CDVDVideoCodecIMXVPUBuffer *buf + // Output is our IPU buffer + task.output.width = iWidth; + task.output.height = iHeight; ++ task.output.crop.h = iHeight; + #ifdef IMX_OUTPUT_FORMAT_I420 + task.output.format = IPU_PIX_FMT_YUV420P; + iFormat = 0; +@@ -1310,6 +1314,14 @@ bool CDVDVideoCodecIMXIPUBuffer::Process(int fd, CDVDVideoCodecIMXVPUBuffer *buf + task.output.format = IPU_PIX_FMT_NV12; + iFormat = 1; + #endif ++#ifdef IMX_OUTPUT_FORMAT_RGB565 ++ task.output.format = IPU_PIX_FMT_RGB565; ++ iFormat = 2; ++#endif ++#ifdef IMX_OUTPUT_FORMAT_RGB32 ++ task.output.format = IPU_PIX_FMT_RGB32; ++ iFormat = 3; ++#endif + task.output.paddr = (int)pPhysAddr; + + // Fill current and next buffer address +@@ -1345,15 +1357,42 @@ bool CDVDVideoCodecIMXIPUBuffer::Process(int fd, CDVDVideoCodecIMXVPUBuffer *buf + #ifdef IMX_PROFILE + unsigned int time = XbmcThreads::SystemClockMillis(); + #endif +- int ret = ioctl(fd, IPU_QUEUE_TASK, &task); ++ ++ /* We do the VDI buffer splitting ourselves since the kernel ++ * driver (IPU) is either buggy or it is a feature that it does ++ * not split widths to multiple of 16 to get maximum burst on ++ * on DMA. Since we know that the input and output dimensions are the ++ * same we can implement an easier algorithm that takes care of ++ * that. ++ */ ++ unsigned int nRequiredStripes = (iWidth+IMX_MDI_MAX_WIDTH-1) / IMX_MDI_MAX_WIDTH; ++ unsigned int iProcWidth = iWidth; ++ unsigned int iStripeOffset = 0; ++ ++ while (iStripeOffset < iWidth) ++ { ++ unsigned int iStripeWidth = Align(iWidth/nRequiredStripes, FRAME_ALIGN); ++ if (iStripeWidth > iProcWidth) ++ iStripeWidth = iProcWidth; ++ ++ task.input.crop.pos.x = iStripeOffset; ++ task.input.crop.w = iStripeWidth; ++ task.output.crop.pos.x = task.input.crop.pos.x; ++ task.output.crop.w = task.input.crop.w; ++ ++ if (ioctl(fd, IPU_QUEUE_TASK, &task) < 0) ++ { ++ CLog::Log(LOGERROR, "IPU task failed: %s\n", strerror(errno)); ++ return false; ++ } ++ ++ iStripeOffset += iStripeWidth; ++ iProcWidth -= iStripeWidth; ++ } ++ + #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(); +@@ -1379,8 +1418,19 @@ bool CDVDVideoCodecIMXIPUBuffer::Allocate(int fd, int width, int height, int nAl + { + m_iWidth = Align(width,FRAME_ALIGN); + m_iHeight = Align(height,(2*FRAME_ALIGN)); ++#if defined(IMX_OUTPUT_FORMAT_NV12) || defined(IMX_OUTPUT_FORMAT_I420) + // I420 == 12 bpp + m_nSize = m_iWidth*m_iHeight*12/8; ++#endif ++#ifdef IMX_OUTPUT_FORMAT_RGB565 ++ // RGB565 = 16 bpp ++ m_nSize = m_iWidth*m_iHeight*16/8; ++#endif ++#ifdef IMX_OUTPUT_FORMAT_RGB32 ++ // RGB32 = 32 bpp ++ m_nSize = m_iWidth*m_iHeight*32/8; ++#endif ++ + m_pPhyAddr = m_nSize; + + pPhysAddr = pVirtAddr = NULL; +diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h +index d9aadc9..f44168b 100644 +--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h ++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h +@@ -31,12 +31,16 @@ + + + // The decoding format of the VPU buffer. Comment this to decode +-// as NV12. The VPU works faster with I420. +-#define IMX_INPUT_FORMAT_I420 ++// as NV12. The VPU works faster with NV12 in combination with ++// deinterlacing. ++//#define IMX_INPUT_FORMAT_I420 + +-// The deinterlacer output and render format. Uncomment to use I420. +-// The IPU works faster when outputting to NV12. ++// The deinterlacer output and render format. Only one format must be active ++// at a time ++#define IMX_OUTPUT_FORMAT_NV12 + //#define IMX_OUTPUT_FORMAT_I420 ++//#define IMX_OUTPUT_FORMAT_RGB565 ++//#define IMX_OUTPUT_FORMAT_RGB32 + + // This enables logging of times for Decode, Render->Render, + // Deinterlace. It helps to profile several stages of +@@ -50,6 +54,11 @@ + //#define IMX_PROFILE + //#define TRACE_FRAMES + ++// If uncommented a file "stream.dump" will be created in the current ++// directory whenever a new stream is started. This is only for debugging ++// and performance tests. This define must never be active in distributions. ++//#define DUMP_STREAM ++ + class CDecMemInfo + { + public: + +From 3c6b55e684e821c0ddedcd8fbb86b19363ce8f39 Mon Sep 17 00:00:00 2001 +From: smallint +Date: Fri, 5 Dec 2014 17:58:36 +0000 +Subject: [PATCH 18/18] [imx] @wolfgar Removed IPU task priority setting + +--- + xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp +index f556223..5c2b021 100644 +--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp ++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp +@@ -1281,7 +1281,6 @@ bool CDVDVideoCodecIMXIPUBuffer::Process(int fd, CDVDVideoCodecIMXVPUBuffer *buf + CDVDVideoCodecIMXVPUBuffer *previousBuffer; + struct ipu_task task; + memset(&task, 0, sizeof(task)); +- task.priority = IPU_TASK_PRIORITY_HIGH; + + if (lowMotion) + previousBuffer = buffer->GetPreviousBuffer(); diff --git a/projects/imx6/patches/kodi/kodi-01-renderer-drop-old-tempfix-firstflippage-did-not-work.patch b/projects/imx6/patches/kodi/kodi-01-renderer-drop-old-tempfix-firstflippage-did-not-work.patch deleted file mode 100644 index b1305576d7..0000000000 --- a/projects/imx6/patches/kodi/kodi-01-renderer-drop-old-tempfix-firstflippage-did-not-work.patch +++ /dev/null @@ -1,99 +0,0 @@ -From 5aed65d63d71073340a4b4c7da814a67a8e814a7 Mon Sep 17 00:00:00 2001 -From: Rainer Hochecker -Date: Fri, 2 Jan 2015 10:02:09 +0100 -Subject: [PATCH 1/6] renderer: drop old tempfix firstflippage, did not work - anyway because RendererHandlesPresent returned always true - ---- - xbmc/Application.cpp | 2 +- - xbmc/cores/VideoRenderers/RenderManager.cpp | 9 --------- - xbmc/cores/VideoRenderers/RenderManager.h | 5 ----- - xbmc/guilib/GUIVideoControl.cpp | 3 +-- - 4 files changed, 2 insertions(+), 17 deletions(-) - -diff --git a/xbmc/Application.cpp b/xbmc/Application.cpp -index 7ee0a34..1c717c2 100644 ---- a/xbmc/Application.cpp -+++ b/xbmc/Application.cpp -@@ -2222,7 +2222,7 @@ void CApplication::Render() - bool extPlayerActive = m_pPlayer->GetCurrentPlayer() == EPC_EXTPLAYER && m_pPlayer->IsPlaying() && !m_AppFocused; - - m_bPresentFrame = false; -- if (!extPlayerActive && g_graphicsContext.IsFullScreenVideo() && !m_pPlayer->IsPausedPlayback() && g_renderManager.RendererHandlesPresent()) -+ if (!extPlayerActive && g_graphicsContext.IsFullScreenVideo() && !m_pPlayer->IsPausedPlayback()) - { - m_bPresentFrame = g_renderManager.FrameWait(100); - hasRendered = true; -diff --git a/xbmc/cores/VideoRenderers/RenderManager.cpp b/xbmc/cores/VideoRenderers/RenderManager.cpp -index b31f3c9..ab894ba 100644 ---- a/xbmc/cores/VideoRenderers/RenderManager.cpp -+++ b/xbmc/cores/VideoRenderers/RenderManager.cpp -@@ -293,19 +293,12 @@ bool CXBMCRenderManager::Configure(unsigned int width, unsigned int height, unsi - m_sleeptime = 1.0; - m_presentevent.notifyAll(); - -- m_firstFlipPage = false; // tempfix -- - CLog::Log(LOGDEBUG, "CXBMCRenderManager::Configure - %d", m_QueueSize); - } - - return result; - } - --bool CXBMCRenderManager::RendererHandlesPresent() const --{ -- return IsConfigured() && (m_firstFlipPage || m_format != RENDER_FMT_BYPASS); --} -- - bool CXBMCRenderManager::IsConfigured() const - { - if (!m_pRenderer) -@@ -661,8 +654,6 @@ void CXBMCRenderManager::FlipPage(volatile bool& bStop, double timestamp /* = 0L - - if(!m_pRenderer) return; - -- m_firstFlipPage = true; // tempfix -- - EPRESENTMETHOD presentmethod; - - EDEINTERLACEMODE deinterlacemode = CMediaSettings::Get().GetCurrentVideoSettings().m_DeinterlaceMode; -diff --git a/xbmc/cores/VideoRenderers/RenderManager.h b/xbmc/cores/VideoRenderers/RenderManager.h -index d3c2f1d..1086066 100644 ---- a/xbmc/cores/VideoRenderers/RenderManager.h -+++ b/xbmc/cores/VideoRenderers/RenderManager.h -@@ -143,8 +143,6 @@ public: - - void UpdateResolution(); - -- bool RendererHandlesPresent() const; -- - #ifdef HAS_GL - CLinuxRendererGL *m_pRenderer; - #elif defined(HAS_MMAL) -@@ -267,9 +265,6 @@ protected: - //set to true when adding something to m_captures, set to false when m_captures is made empty - //std::list::empty() isn't thread safe, using an extra bool will save a lock per render when no captures are requested - bool m_hasCaptures; -- -- // temporary fix for RendererHandlesPresent after #2811 -- bool m_firstFlipPage; - }; - - extern CXBMCRenderManager g_renderManager; -diff --git a/xbmc/guilib/GUIVideoControl.cpp b/xbmc/guilib/GUIVideoControl.cpp -index 22d0fc8..c47a6d5 100644 ---- a/xbmc/guilib/GUIVideoControl.cpp -+++ b/xbmc/guilib/GUIVideoControl.cpp -@@ -43,8 +43,7 @@ CGUIVideoControl::~CGUIVideoControl(void) - void CGUIVideoControl::Process(unsigned int currentTime, CDirtyRegionList &dirtyregions) - { - // TODO Proper processing which marks when its actually changed. Just mark always for now. -- if (g_renderManager.RendererHandlesPresent()) -- MarkDirtyRegion(); -+ MarkDirtyRegion(); - - CGUIControl::Process(currentTime, dirtyregions); - } --- -1.9.1 - diff --git a/projects/imx6/patches/kodi/kodi-02-Set-dirty-flag-in-teletext-dialog-if-required.patch b/projects/imx6/patches/kodi/kodi-02-Set-dirty-flag-in-teletext-dialog-if-required.patch deleted file mode 100644 index 0795f6c093..0000000000 --- a/projects/imx6/patches/kodi/kodi-02-Set-dirty-flag-in-teletext-dialog-if-required.patch +++ /dev/null @@ -1,95 +0,0 @@ -From a14f5348c5ce76ca074630c8bf0bfc3b6bf3f767 Mon Sep 17 00:00:00 2001 -From: smallint -Date: Fri, 2 Jan 2015 15:35:33 +0000 -Subject: [PATCH 2/6] Set dirty flag in teletext dialog if required - ---- - xbmc/video/dialogs/GUIDialogTeletext.cpp | 19 +++++++++++++++++++ - xbmc/video/dialogs/GUIDialogTeletext.h | 1 + - 2 files changed, 20 insertions(+) - -diff --git a/xbmc/video/dialogs/GUIDialogTeletext.cpp b/xbmc/video/dialogs/GUIDialogTeletext.cpp -index c552ae6..9be4548 100644 ---- a/xbmc/video/dialogs/GUIDialogTeletext.cpp -+++ b/xbmc/video/dialogs/GUIDialogTeletext.cpp -@@ -46,7 +46,10 @@ CGUIDialogTeletext::~CGUIDialogTeletext() - bool CGUIDialogTeletext::OnAction(const CAction& action) - { - if (m_TextDecoder.HandleAction(action)) -+ { -+ MarkDirtyRegion(); - return true; -+ } - - return CGUIDialog::OnAction(action); - } -@@ -54,6 +57,7 @@ bool CGUIDialogTeletext::OnAction(const CAction& action) - bool CGUIDialogTeletext::OnBack(int actionID) - { - m_bClose = true; -+ MarkDirtyRegion(); - return true; - } - -@@ -79,6 +83,12 @@ bool CGUIDialogTeletext::OnMessage(CGUIMessage& message) - return CGUIDialog::OnMessage(message); - } - -+void CGUIDialogTeletext::Process(unsigned int currentTime, CDirtyRegionList &dirtyregions) -+{ -+ CGUIDialog::Process(currentTime, dirtyregions); -+ m_renderRegion = m_vertCoords; -+} -+ - void CGUIDialogTeletext::Render() - { - // Do not render if we have no texture -@@ -93,12 +103,18 @@ void CGUIDialogTeletext::Render() - if (!m_bClose) - { - if (teletextFadeAmount < 100) -+ { - teletextFadeAmount = std::min(100, teletextFadeAmount + 5); -+ MarkDirtyRegion(); -+ } - } - else - { - if (teletextFadeAmount > 0) -+ { - teletextFadeAmount = std::max(0, teletextFadeAmount - 10); -+ MarkDirtyRegion(); -+ } - - if (teletextFadeAmount == 0) - Close(); -@@ -109,6 +125,7 @@ void CGUIDialogTeletext::Render() - { - m_pTxtTexture->Update(m_TextDecoder.GetWidth(), m_TextDecoder.GetHeight(), m_TextDecoder.GetWidth()*4, XB_FMT_A8R8G8B8, textureBuffer, false); - m_TextDecoder.RenderingDone(); -+ MarkDirtyRegion(); - } - - color_t color = ((color_t)(teletextFadeAmount * 2.55f) & 0xff) << 24 | 0xFFFFFF; -@@ -184,4 +201,6 @@ void CGUIDialogTeletext::SetCoordinates() - top, - right, - bottom); -+ -+ MarkDirtyRegion(); - } -diff --git a/xbmc/video/dialogs/GUIDialogTeletext.h b/xbmc/video/dialogs/GUIDialogTeletext.h -index 51aced5..e8e11f8 100644 ---- a/xbmc/video/dialogs/GUIDialogTeletext.h -+++ b/xbmc/video/dialogs/GUIDialogTeletext.h -@@ -32,6 +32,7 @@ public: - virtual bool OnMessage(CGUIMessage& message); - virtual bool OnAction(const CAction& action); - virtual bool OnBack(int actionID); -+ virtual void Process(unsigned int currentTime, CDirtyRegionList &dirtyregions); - virtual void Render(); - virtual void OnInitWindow(); - virtual void OnDeinitWindow(int nextWindowID); --- -1.9.1 - diff --git a/projects/imx6/patches/kodi/kodi-03-renderer-improve-rendering-to-gui-and-separate-video.patch b/projects/imx6/patches/kodi/kodi-03-renderer-improve-rendering-to-gui-and-separate-video.patch deleted file mode 100644 index d90cb18964..0000000000 --- a/projects/imx6/patches/kodi/kodi-03-renderer-improve-rendering-to-gui-and-separate-video.patch +++ /dev/null @@ -1,659 +0,0 @@ -From 12021a04a6662400ed2bfffd0f2a752af89a6643 Mon Sep 17 00:00:00 2001 -From: smallint -Date: Sat, 16 Aug 2014 17:29:15 +0200 -Subject: [PATCH 3/6] renderer: improve rendering to gui and separate video - layer - ---- - xbmc/Application.cpp | 10 +--- - xbmc/cores/VideoRenderers/BaseRenderer.h | 1 + - xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp | 52 +++++++++++++-------- - xbmc/cores/VideoRenderers/LinuxRendererGLES.h | 2 + - xbmc/cores/VideoRenderers/MMALRenderer.cpp | 15 ------ - xbmc/cores/VideoRenderers/MMALRenderer.h | 1 + - xbmc/cores/VideoRenderers/OverlayRenderer.cpp | 18 +++++++ - xbmc/cores/VideoRenderers/OverlayRenderer.h | 1 + - xbmc/cores/VideoRenderers/RenderManager.cpp | 62 ++++++++++++++++++++----- - xbmc/cores/VideoRenderers/RenderManager.h | 5 +- - xbmc/guilib/GUIControl.h | 3 ++ - xbmc/guilib/GUIControlGroup.cpp | 7 +++ - xbmc/guilib/GUIControlGroup.h | 1 + - xbmc/guilib/GUIVideoControl.cpp | 31 ++++++++++++- - xbmc/guilib/GUIVideoControl.h | 1 + - xbmc/guilib/GUIWindowManager.cpp | 22 ++++++++- - xbmc/guilib/GUIWindowManager.h | 1 + - xbmc/video/windows/GUIWindowFullScreen.cpp | 31 ++++++++++++- - xbmc/video/windows/GUIWindowFullScreen.h | 2 + - 19 files changed, 204 insertions(+), 62 deletions(-) - -diff --git a/xbmc/Application.cpp b/xbmc/Application.cpp -index 1c717c2..137872c 100644 ---- a/xbmc/Application.cpp -+++ b/xbmc/Application.cpp -@@ -2170,9 +2170,6 @@ bool CApplication::RenderNoPresent() - // dont show GUI when playing full screen video - if (g_graphicsContext.IsFullScreenVideo()) - { -- g_graphicsContext.SetRenderingResolution(g_graphicsContext.GetVideoResolution(), false); -- g_renderManager.Render(true, 0, 255); -- - // close window overlays - CGUIDialog *overlay = (CGUIDialog *)g_windowManager.GetWindow(WINDOW_DIALOG_VIDEO_OVERLAY); - if (overlay) overlay->Close(true); -@@ -2225,7 +2222,6 @@ void CApplication::Render() - if (!extPlayerActive && g_graphicsContext.IsFullScreenVideo() && !m_pPlayer->IsPausedPlayback()) - { - m_bPresentFrame = g_renderManager.FrameWait(100); -- hasRendered = true; - } - else - { -@@ -2268,8 +2264,6 @@ void CApplication::Render() - if(!g_Windowing.BeginRender()) - return; - -- g_renderManager.FrameMove(); -- - CDirtyRegionList dirtyRegions = g_windowManager.GetDirty(); - if(g_graphicsContext.GetStereoMode()) - { -@@ -2291,8 +2285,6 @@ void CApplication::Render() - hasRendered = true; - } - -- g_renderManager.FrameFinish(); -- - g_Windowing.EndRender(); - - // execute post rendering actions (finalize window closing) -@@ -2317,7 +2309,7 @@ void CApplication::Render() - flip = true; - - //fps limiter, make sure each frame lasts at least singleFrameTime milliseconds -- if (limitFrames || !flip) -+ if (limitFrames || !(flip || m_bPresentFrame)) - { - if (!limitFrames) - singleFrameTime = 40; //if not flipping, loop at 25 fps -diff --git a/xbmc/cores/VideoRenderers/BaseRenderer.h b/xbmc/cores/VideoRenderers/BaseRenderer.h -index 850aa6f..8988e35 100644 ---- a/xbmc/cores/VideoRenderers/BaseRenderer.h -+++ b/xbmc/cores/VideoRenderers/BaseRenderer.h -@@ -94,6 +94,7 @@ public: - virtual void SetBufferSize(int numBuffers) { } - virtual void ReleaseBuffer(int idx) { } - virtual bool NeedBufferForRef(int idx) { return false; } -+ virtual bool IsGuiLayer() { return true; } - - virtual bool Supports(ERENDERFEATURE feature) { return false; } - -diff --git a/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp b/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp -index 81fe19b..a765461 100644 ---- a/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp -+++ b/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp -@@ -526,32 +526,16 @@ void CLinuxRendererGLES::Update() - - void CLinuxRendererGLES::RenderUpdate(bool clear, DWORD flags, DWORD alpha) - { -- if (!m_bConfigured) return; -+ if (!m_bConfigured) -+ return; - - // if its first pass, just init textures and return - if (ValidateRenderTarget()) - return; - -- if (m_renderMethod & RENDER_BYPASS) -+ if (!IsGuiLayer()) - { -- ManageDisplay(); -- // if running bypass, then the player might need the src/dst rects -- // for sizing video playback on a layer other than the gles layer. -- if (m_RenderUpdateCallBackFn) -- (*m_RenderUpdateCallBackFn)(m_RenderUpdateCallBackCtx, m_sourceRect, m_destRect); -- -- CRect old = g_graphicsContext.GetScissors(); -- -- g_graphicsContext.BeginPaint(); -- g_graphicsContext.SetScissors(m_destRect); -- -- 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(); -+ RenderUpdateVideo(clear, flags, alpha); - return; - } - -@@ -606,6 +590,26 @@ void CLinuxRendererGLES::RenderUpdate(bool clear, DWORD flags, DWORD alpha) - g_graphicsContext.EndPaint(); - } - -+void CLinuxRendererGLES::RenderUpdateVideo(bool clear, DWORD flags, DWORD alpha) -+{ -+ if (!m_bConfigured) -+ return; -+ -+ if (IsGuiLayer()) -+ return; -+ -+ if (m_renderMethod & RENDER_BYPASS) -+ { -+ ManageDisplay(); -+ // if running bypass, then the player might need the src/dst rects -+ // for sizing video playback on a layer other than the gles layer. -+ if (m_RenderUpdateCallBackFn) -+ (*m_RenderUpdateCallBackFn)(m_RenderUpdateCallBackCtx, m_sourceRect, m_destRect); -+ -+ return; -+ } -+} -+ - void CLinuxRendererGLES::FlipPage(int source) - { - if( source >= 0 && source < m_NumYV12Buffers ) -@@ -3055,5 +3059,13 @@ void CLinuxRendererGLES::AddProcessor(CDVDVideoCodecIMXBuffer *buffer, int index - } - #endif - -+bool CLinuxRendererGLES::IsGuiLayer() -+{ -+ if (m_format == RENDER_FMT_BYPASS) -+ return false; -+ else -+ return true; -+} -+ - #endif - -diff --git a/xbmc/cores/VideoRenderers/LinuxRendererGLES.h b/xbmc/cores/VideoRenderers/LinuxRendererGLES.h -index d8bf35d..b865033 100644 ---- a/xbmc/cores/VideoRenderers/LinuxRendererGLES.h -+++ b/xbmc/cores/VideoRenderers/LinuxRendererGLES.h -@@ -144,6 +144,7 @@ public: - virtual void SetBufferSize(int numBuffers) { m_NumYV12Buffers = numBuffers; } - virtual unsigned int GetMaxBufferSize() { return NUM_BUFFERS; } - virtual unsigned int GetOptimalBufferSize(); -+ virtual bool IsGuiLayer(); - - virtual void RenderUpdate(bool clear, DWORD flags = 0, DWORD alpha = 255); - -@@ -177,6 +178,7 @@ public: - - protected: - virtual void Render(DWORD flags, int index); -+ void RenderUpdateVideo(bool clear, DWORD flags = 0, DWORD alpha = 255); - - int NextYV12Texture(); - virtual bool ValidateRenderTarget(); -diff --git a/xbmc/cores/VideoRenderers/MMALRenderer.cpp b/xbmc/cores/VideoRenderers/MMALRenderer.cpp -index 03a05de..69ff30a 100644 ---- a/xbmc/cores/VideoRenderers/MMALRenderer.cpp -+++ b/xbmc/cores/VideoRenderers/MMALRenderer.cpp -@@ -347,21 +347,6 @@ void CMMALRenderer::RenderUpdate(bool clear, DWORD flags, DWORD alpha) - // for sizing video playback on a layer other than the gles layer. - if (m_RenderUpdateCallBackFn) - (*m_RenderUpdateCallBackFn)(m_RenderUpdateCallBackCtx, m_sourceRect, m_destRect); -- -- SetVideoRect(m_sourceRect, m_destRect); -- -- CRect old = g_graphicsContext.GetScissors(); -- -- g_graphicsContext.BeginPaint(); -- g_graphicsContext.SetScissors(m_destRect); -- -- 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(); - } - - void CMMALRenderer::FlipPage(int source) -diff --git a/xbmc/cores/VideoRenderers/MMALRenderer.h b/xbmc/cores/VideoRenderers/MMALRenderer.h -index 8ca0b94..62d513e 100644 ---- a/xbmc/cores/VideoRenderers/MMALRenderer.h -+++ b/xbmc/cores/VideoRenderers/MMALRenderer.h -@@ -90,6 +90,7 @@ public: - virtual unsigned int GetMaxBufferSize() { return NUM_BUFFERS; } - virtual unsigned int GetOptimalBufferSize() { return NUM_BUFFERS; } - virtual void SetVideoRect(const CRect& SrcRect, const CRect& DestRect); -+ virtual bool IsGuiLayer() { return false; } - - void vout_input_port_cb(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer); - protected: -diff --git a/xbmc/cores/VideoRenderers/OverlayRenderer.cpp b/xbmc/cores/VideoRenderers/OverlayRenderer.cpp -index ea07d9f..e8c4bec 100644 ---- a/xbmc/cores/VideoRenderers/OverlayRenderer.cpp -+++ b/xbmc/cores/VideoRenderers/OverlayRenderer.cpp -@@ -306,6 +306,24 @@ void CRenderer::Render(COverlay* o, float adjust_height) - o->Render(state); - } - -+bool CRenderer::HasOverlay(int idx) -+{ -+ bool hasOverlay = false; -+ -+ CSingleLock lock(m_section); -+ -+ SElementV& list = m_buffers[idx]; -+ for(SElementV::iterator it = list.begin(); it != list.end(); ++it) -+ { -+ if (it->overlay || it->overlay_dvd) -+ { -+ hasOverlay = true; -+ break; -+ } -+ } -+ return hasOverlay; -+} -+ - COverlay* CRenderer::Convert(CDVDOverlaySSA* o, double pts) - { - CRect src, dst; -diff --git a/xbmc/cores/VideoRenderers/OverlayRenderer.h b/xbmc/cores/VideoRenderers/OverlayRenderer.h -index 9b8e9da..ca02644 100644 ---- a/xbmc/cores/VideoRenderers/OverlayRenderer.h -+++ b/xbmc/cores/VideoRenderers/OverlayRenderer.h -@@ -100,6 +100,7 @@ namespace OVERLAY { - void Render(int idx); - void Flush(); - void Release(int idx); -+ bool HasOverlay(int idx); - - protected: - -diff --git a/xbmc/cores/VideoRenderers/RenderManager.cpp b/xbmc/cores/VideoRenderers/RenderManager.cpp -index ab894ba..63bbdcc 100644 ---- a/xbmc/cores/VideoRenderers/RenderManager.cpp -+++ b/xbmc/cores/VideoRenderers/RenderManager.cpp -@@ -120,6 +120,7 @@ CXBMCRenderManager::CXBMCRenderManager() - m_QueueSize = 2; - m_QueueSkip = 0; - m_format = RENDER_FMT_NONE; -+ m_renderedOverlay = false; - } - - CXBMCRenderManager::~CXBMCRenderManager() -@@ -233,7 +234,7 @@ bool CXBMCRenderManager::Configure(unsigned int width, unsigned int height, unsi - - /* make sure any queued frame was fully presented */ - XbmcThreads::EndTime endtime(5000); -- while(m_presentstep != PRESENT_IDLE) -+ while(m_presentstep != PRESENT_IDLE && m_presentstep != PRESENT_READY) - { - if(endtime.IsTimePast()) - { -@@ -292,6 +293,7 @@ bool CXBMCRenderManager::Configure(unsigned int width, unsigned int height, unsi - m_presentpts = DVD_NOPTS_VALUE; - m_sleeptime = 1.0; - m_presentevent.notifyAll(); -+ m_renderedOverlay = false; - - CLog::Log(LOGDEBUG, "CXBMCRenderManager::Configure - %d", m_QueueSize); - } -@@ -766,22 +768,58 @@ void CXBMCRenderManager::RegisterRenderFeaturesCallBack(const void *ctx, RenderF - m_pRenderer->RegisterRenderFeaturesCallBack(ctx, fn); - } - --void CXBMCRenderManager::Render(bool clear, DWORD flags, DWORD alpha) -+void CXBMCRenderManager::Render(bool clear, DWORD flags, DWORD alpha, bool gui) - { - CSharedLock lock(m_sharedSection); - -- SPresent& m = m_Queue[m_presentsource]; -+ if (!gui && m_pRenderer->IsGuiLayer()) -+ return; - -- if( m.presentmethod == PRESENT_METHOD_BOB ) -- PresentFields(clear, flags, alpha); -- else if( m.presentmethod == PRESENT_METHOD_WEAVE ) -- PresentFields(clear, flags | RENDER_FLAG_WEAVE, alpha); -- else if( m.presentmethod == PRESENT_METHOD_BLEND ) -- PresentBlend(clear, flags, alpha); -- else -- PresentSingle(clear, flags, alpha); -+ if (!gui || m_pRenderer->IsGuiLayer()) -+ { -+ SPresent& m = m_Queue[m_presentsource]; -+ -+ if( m.presentmethod == PRESENT_METHOD_BOB ) -+ PresentFields(clear, flags, alpha); -+ else if( m.presentmethod == PRESENT_METHOD_WEAVE ) -+ PresentFields(clear, flags | RENDER_FLAG_WEAVE, alpha); -+ else if( m.presentmethod == PRESENT_METHOD_BLEND ) -+ PresentBlend(clear, flags, alpha); -+ else -+ PresentSingle(clear, flags, alpha); -+ } -+ -+ if (gui) -+ { -+ m_renderedOverlay = m_overlays.HasOverlay(m_presentsource); -+ m_overlays.Render(m_presentsource); -+ } -+} -+ -+bool CXBMCRenderManager::IsGuiLayer() -+{ -+ { CSingleLock lock(m_presentlock); -+ -+ if (!m_pRenderer) -+ return false; -+ -+ if (m_pRenderer->IsGuiLayer() || m_renderedOverlay || m_overlays.HasOverlay(m_presentsource)) -+ return true; -+ } -+ return false; -+} -+ -+bool CXBMCRenderManager::IsVideoLayer() -+{ -+ { CSingleLock lock(m_presentlock); - -- m_overlays.Render(m_presentsource); -+ if (!m_pRenderer) -+ return false; -+ -+ if (!m_pRenderer->IsGuiLayer()) -+ return true; -+ } -+ return false; - } - - /* simple present method */ -diff --git a/xbmc/cores/VideoRenderers/RenderManager.h b/xbmc/cores/VideoRenderers/RenderManager.h -index 1086066..7280423 100644 ---- a/xbmc/cores/VideoRenderers/RenderManager.h -+++ b/xbmc/cores/VideoRenderers/RenderManager.h -@@ -60,7 +60,9 @@ public: - void FrameMove(); - void FrameFinish(); - bool FrameWait(int ms); -- void Render(bool clear, DWORD flags = 0, DWORD alpha = 255); -+ void Render(bool clear, DWORD flags = 0, DWORD alpha = 255, bool gui = true); -+ bool IsGuiLayer(); -+ bool IsVideoLayer(); - void SetupScreenshot(); - - CRenderCapture* AllocRenderCapture(); -@@ -257,6 +259,7 @@ protected: - - - OVERLAY::CRenderer m_overlays; -+ bool m_renderedOverlay; - - void RenderCapture(CRenderCapture* capture); - void RemoveCapture(CRenderCapture* capture); -diff --git a/xbmc/guilib/GUIControl.h b/xbmc/guilib/GUIControl.h -index b303ccc..6e0b92e 100644 ---- a/xbmc/guilib/GUIControl.h -+++ b/xbmc/guilib/GUIControl.h -@@ -83,6 +83,9 @@ public: - virtual void Process(unsigned int currentTime, CDirtyRegionList &dirtyregions); - virtual void DoRender(); - virtual void Render() {}; -+ // Called after the actual rendering is completed to trigger additional -+ // non GUI rendering operations -+ virtual void RenderEx() {}; - - /*! \brief Returns whether or not we have processed */ - bool HasProcessed() const { return m_hasProcessed; }; -diff --git a/xbmc/guilib/GUIControlGroup.cpp b/xbmc/guilib/GUIControlGroup.cpp -index 7858e42..bdd7f54 100644 ---- a/xbmc/guilib/GUIControlGroup.cpp -+++ b/xbmc/guilib/GUIControlGroup.cpp -@@ -133,6 +133,13 @@ void CGUIControlGroup::Render() - g_graphicsContext.RestoreOrigin(); - } - -+void CGUIControlGroup::RenderEx() -+{ -+ for (iControls it = m_children.begin(); it != m_children.end(); ++it) -+ (*it)->RenderEx(); -+ CGUIControl::RenderEx(); -+} -+ - bool CGUIControlGroup::OnAction(const CAction &action) - { - ASSERT(false); // unimplemented -diff --git a/xbmc/guilib/GUIControlGroup.h b/xbmc/guilib/GUIControlGroup.h -index 054757f..0b38a56 100644 ---- a/xbmc/guilib/GUIControlGroup.h -+++ b/xbmc/guilib/GUIControlGroup.h -@@ -42,6 +42,7 @@ public: - - virtual void Process(unsigned int currentTime, CDirtyRegionList &dirtyregions); - virtual void Render(); -+ virtual void RenderEx(); - virtual bool OnAction(const CAction &action); - virtual bool OnMessage(CGUIMessage& message); - virtual bool SendControlMessage(CGUIMessage& message); -diff --git a/xbmc/guilib/GUIVideoControl.cpp b/xbmc/guilib/GUIVideoControl.cpp -index c47a6d5..126e95f 100644 ---- a/xbmc/guilib/GUIVideoControl.cpp -+++ b/xbmc/guilib/GUIVideoControl.cpp -@@ -42,8 +42,11 @@ CGUIVideoControl::~CGUIVideoControl(void) - - void CGUIVideoControl::Process(unsigned int currentTime, CDirtyRegionList &dirtyregions) - { -+ g_renderManager.FrameMove(); -+ - // TODO Proper processing which marks when its actually changed. Just mark always for now. -- MarkDirtyRegion(); -+ if (g_renderManager.IsGuiLayer()) -+ MarkDirtyRegion(); - - CGUIControl::Process(currentTime, dirtyregions); - } -@@ -67,14 +70,38 @@ void CGUIVideoControl::Render() - - #ifdef HAS_VIDEO_PLAYBACK - color_t alpha = g_graphicsContext.MergeAlpha(0xFF000000) >> 24; -- g_renderManager.Render(false, 0, alpha); -+ if (g_renderManager.IsVideoLayer()) -+ { -+ CRect old = g_graphicsContext.GetScissors(); -+ CRect region = GetRenderRegion(); -+ region.Intersect(old); -+ g_graphicsContext.BeginPaint(); -+ g_graphicsContext.SetScissors(region); -+ g_graphicsContext.Clear(0); -+ g_graphicsContext.SetScissors(old); -+ g_graphicsContext.EndPaint(); -+ } -+ else -+ g_renderManager.Render(false, 0, alpha); - #else - ((CDummyVideoPlayer *)g_application.m_pPlayer->GetInternal())->Render(); - #endif - } -+ // TODO: remove this crap: HAS_VIDEO_PLAYBACK -+ // instantiateing a vidio control having no playback is complete nonsense - CGUIControl::Render(); - } - -+void CGUIVideoControl::RenderEx() -+{ -+#ifdef HAS_VIDEO_PLAYBACK -+ if (g_application.m_pPlayer->IsPlayingVideo() && g_renderManager.IsStarted()) -+ g_renderManager.Render(false, 0, 255, false); -+ g_renderManager.FrameFinish(); -+#endif -+ CGUIControl::RenderEx(); -+} -+ - EVENT_RESULT CGUIVideoControl::OnMouseEvent(const CPoint &point, const CMouseEvent &event) - { - if (!g_application.m_pPlayer->IsPlayingVideo()) return EVENT_RESULT_UNHANDLED; -diff --git a/xbmc/guilib/GUIVideoControl.h b/xbmc/guilib/GUIVideoControl.h -index a692d01..0f89a9a 100644 ---- a/xbmc/guilib/GUIVideoControl.h -+++ b/xbmc/guilib/GUIVideoControl.h -@@ -44,6 +44,7 @@ public: - - virtual void Process(unsigned int currentTime, CDirtyRegionList &dirtyregions); - virtual void Render(); -+ virtual void RenderEx(); - virtual EVENT_RESULT OnMouseEvent(const CPoint &point, const CMouseEvent &event); - virtual bool CanFocus() const; - virtual bool CanFocusFromPoint(const CPoint &point) const; -diff --git a/xbmc/guilib/GUIWindowManager.cpp b/xbmc/guilib/GUIWindowManager.cpp -index 788bbe9..ef97251 100644 ---- a/xbmc/guilib/GUIWindowManager.cpp -+++ b/xbmc/guilib/GUIWindowManager.cpp -@@ -547,6 +547,24 @@ void CGUIWindowManager::RenderPass() const - } - } - -+void CGUIWindowManager::RenderEx() const -+{ -+ CGUIWindow* pWindow = GetWindow(GetActiveWindow()); -+ if (pWindow) -+ pWindow->RenderEx(); -+ -+ // We don't call RenderEx for now on dialogs since it is used -+ // to trigger non gui video rendering. We can activate it later at any time. -+ /* -+ vector &activeDialogs = m_activeDialogs; -+ for (iDialog it = activeDialogs.begin(); it != activeDialogs.end(); ++it) -+ { -+ if ((*it)->IsDialogRunning()) -+ (*it)->RenderEx(); -+ } -+ */ -+} -+ - bool CGUIWindowManager::Render() - { - assert(g_application.IsCurrentThread()); -@@ -586,13 +604,15 @@ bool CGUIWindowManager::Render() - if (g_advancedSettings.m_guiVisualizeDirtyRegions) - { - g_graphicsContext.SetRenderingResolution(g_graphicsContext.GetResInfo(), false); -- const CDirtyRegionList &markedRegions = m_tracker.GetMarkedRegions(); -+ const CDirtyRegionList &markedRegions = m_tracker.GetMarkedRegions(); - for (CDirtyRegionList::const_iterator i = markedRegions.begin(); i != markedRegions.end(); ++i) - CGUITexture::DrawQuad(*i, 0x0fff0000); - for (CDirtyRegionList::const_iterator i = dirtyRegions.begin(); i != dirtyRegions.end(); ++i) - CGUITexture::DrawQuad(*i, 0x4c00ff00); - } - -+ RenderEx(); -+ - return hasRendered; - } - -diff --git a/xbmc/guilib/GUIWindowManager.h b/xbmc/guilib/GUIWindowManager.h -index 4f1f96f..ea7239a 100644 ---- a/xbmc/guilib/GUIWindowManager.h -+++ b/xbmc/guilib/GUIWindowManager.h -@@ -144,6 +144,7 @@ public: - #endif - private: - void RenderPass() const; -+ void RenderEx() const; - - void LoadNotOnDemandWindows(); - void UnloadNotOnDemandWindows(); -diff --git a/xbmc/video/windows/GUIWindowFullScreen.cpp b/xbmc/video/windows/GUIWindowFullScreen.cpp -index dfbf773..ed7c090 100644 ---- a/xbmc/video/windows/GUIWindowFullScreen.cpp -+++ b/xbmc/video/windows/GUIWindowFullScreen.cpp -@@ -353,6 +353,12 @@ bool CGUIWindowFullScreen::OnAction(const CAction &action) - return CGUIWindow::OnAction(action); - } - -+void CGUIWindowFullScreen::ClearBackground() -+{ -+ if (g_renderManager.IsVideoLayer()) -+ g_graphicsContext.Clear(0); -+} -+ - void CGUIWindowFullScreen::OnWindowLoaded() - { - CGUIWindow::OnWindowLoaded(); -@@ -455,6 +461,7 @@ bool CGUIWindowFullScreen::OnMessage(CGUIMessage& message) - #ifdef HAS_VIDEO_PLAYBACK - // make sure renderer is uptospeed - g_renderManager.Update(); -+ g_renderManager.FrameFinish(); - #endif - return true; - } -@@ -730,22 +737,40 @@ void CGUIWindowFullScreen::FrameMove() - SET_CONTROL_HIDDEN(BLUE_BAR); - SET_CONTROL_HIDDEN(CONTROL_GROUP_CHOOSER); - } -+ -+ g_renderManager.FrameMove(); - } - - void CGUIWindowFullScreen::Process(unsigned int currentTime, CDirtyRegionList &dirtyregion) - { -+ if (g_renderManager.IsGuiLayer()) -+ MarkDirtyRegion(); -+ -+ CGUIWindow::Process(currentTime, dirtyregion); -+ - // TODO: This isn't quite optimal - ideally we'd only be dirtying up the actual video render rect - // which is probably the job of the renderer as it can more easily track resizing etc. -- MarkDirtyRegion(); -- CGUIWindow::Process(currentTime, dirtyregion); - m_renderRegion.SetRect(0, 0, (float)g_graphicsContext.GetWidth(), (float)g_graphicsContext.GetHeight()); - } - - void CGUIWindowFullScreen::Render() - { -+ g_graphicsContext.SetRenderingResolution(g_graphicsContext.GetVideoResolution(), false); -+ g_renderManager.Render(true, 0, 255); -+ g_graphicsContext.SetRenderingResolution(m_coordsRes, m_needsScaling); - CGUIWindow::Render(); - } - -+void CGUIWindowFullScreen::RenderEx() -+{ -+ CGUIWindow::RenderEx(); -+ g_graphicsContext.SetRenderingResolution(g_graphicsContext.GetVideoResolution(), false); -+#ifdef HAS_VIDEO_PLAYBACK -+ g_renderManager.Render(false, 0, 255, false); -+ g_renderManager.FrameFinish(); -+#endif -+} -+ - void CGUIWindowFullScreen::ChangetheTimeCode(int remote) - { - if (remote >= REMOTE_0 && remote <= REMOTE_9) -@@ -851,6 +876,8 @@ void CGUIWindowFullScreen::ToggleOSD() - else - pOSD->DoModal(); - } -+ -+ MarkDirtyRegion(); - } - - void CGUIWindowFullScreen::TriggerOSD() -diff --git a/xbmc/video/windows/GUIWindowFullScreen.h b/xbmc/video/windows/GUIWindowFullScreen.h -index 03608af..5a9b101 100644 ---- a/xbmc/video/windows/GUIWindowFullScreen.h -+++ b/xbmc/video/windows/GUIWindowFullScreen.h -@@ -30,9 +30,11 @@ public: - virtual ~CGUIWindowFullScreen(void); - virtual bool OnMessage(CGUIMessage& message); - virtual bool OnAction(const CAction &action); -+ virtual void ClearBackground(); - virtual void FrameMove(); - virtual void Process(unsigned int currentTime, CDirtyRegionList &dirtyregion); - virtual void Render(); -+ virtual void RenderEx(); - virtual void OnWindowLoaded(); - void ChangetheTimeCode(int remote); - void ChangetheTVGroup(bool next); --- -1.9.1 - diff --git a/projects/imx6/patches/kodi/kodi-04-guilib-mark-control-dirty-when-setting-to-invisible.patch b/projects/imx6/patches/kodi/kodi-04-guilib-mark-control-dirty-when-setting-to-invisible.patch deleted file mode 100644 index dfaa34a512..0000000000 --- a/projects/imx6/patches/kodi/kodi-04-guilib-mark-control-dirty-when-setting-to-invisible.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 23ef73e82745569bcd95ce1fdbcc698318388b0f Mon Sep 17 00:00:00 2001 -From: Rainer Hochecker -Date: Mon, 5 Jan 2015 11:29:15 +0100 -Subject: [PATCH 4/6] guilib: mark control dirty when setting to invisible - ---- - xbmc/guilib/GUIControl.cpp | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/xbmc/guilib/GUIControl.cpp b/xbmc/guilib/GUIControl.cpp -index e3d04db..ff2086b 100644 ---- a/xbmc/guilib/GUIControl.cpp -+++ b/xbmc/guilib/GUIControl.cpp -@@ -511,6 +511,8 @@ void CGUIControl::SetVisible(bool bVisible, bool setVisState) - { - m_forceHidden = !bVisible; - SetInvalid(); -+ if (m_forceHidden) -+ MarkDirtyRegion(); - } - if (m_forceHidden) - { // reset any visible animations that are in process --- -1.9.1 - diff --git a/projects/imx6/patches/kodi/kodi-05-renderer-exit-gfx-lock-when-waiting-for-present-time.patch b/projects/imx6/patches/kodi/kodi-05-renderer-exit-gfx-lock-when-waiting-for-present-time.patch deleted file mode 100644 index c528ad3ca3..0000000000 --- a/projects/imx6/patches/kodi/kodi-05-renderer-exit-gfx-lock-when-waiting-for-present-time.patch +++ /dev/null @@ -1,27 +0,0 @@ -From ef6230c3d3106f045719cdebf3ca33cc5cedf88d Mon Sep 17 00:00:00 2001 -From: Rainer Hochecker -Date: Tue, 6 Jan 2015 13:13:27 +0100 -Subject: [PATCH 5/6] renderer: exit gfx lock when waiting for present time - ---- - xbmc/cores/VideoRenderers/RenderManager.cpp | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git a/xbmc/cores/VideoRenderers/RenderManager.cpp b/xbmc/cores/VideoRenderers/RenderManager.cpp -index 63bbdcc..b394d7b 100644 ---- a/xbmc/cores/VideoRenderers/RenderManager.cpp -+++ b/xbmc/cores/VideoRenderers/RenderManager.cpp -@@ -381,7 +381,10 @@ void CXBMCRenderManager::FrameFinish() - SPresent& m = m_Queue[m_presentsource]; - - if(g_graphicsContext.IsFullScreenVideo()) -+ { -+ CSingleExit lock(g_graphicsContext); - WaitPresentTime(m.timestamp); -+ } - - m_clock_framefinish = GetPresentTime(); - --- -1.9.1 - diff --git a/projects/imx6/patches/kodi/kodi-05-rfix-sequence-from-WaitFrame-Render-FrameMov.patch b/projects/imx6/patches/kodi/kodi-05-rfix-sequence-from-WaitFrame-Render-FrameMov.patch deleted file mode 100644 index 0cd656b49e..0000000000 --- a/projects/imx6/patches/kodi/kodi-05-rfix-sequence-from-WaitFrame-Render-FrameMov.patch +++ /dev/null @@ -1,94 +0,0 @@ -From ecf0df3917462187b6def084bb7e3adf797effcd Mon Sep 17 00:00:00 2001 -From: Rainer Hochecker -Date: Fri, 23 Jan 2015 07:41:46 +0100 -Subject: [PATCH] renderer: fix sequence from WaitFrame, Render, FrameMove to - WaitFrame, FrameMove, Render - ---- - xbmc/Application.cpp | 12 +++++++++--- - xbmc/cores/VideoRenderers/RenderManager.cpp | 12 ++++++++++-- - xbmc/cores/VideoRenderers/RenderManager.h | 3 ++- - 3 files changed, 21 insertions(+), 6 deletions(-) - -diff --git a/xbmc/Application.cpp b/xbmc/Application.cpp -index fe44706..3410209 100644 ---- a/xbmc/Application.cpp -+++ b/xbmc/Application.cpp -@@ -2212,16 +2212,17 @@ void CApplication::Render() - bool limitFrames = false; - unsigned int singleFrameTime = 10; // default limit 100 fps - -+ // Whether externalplayer is playing and we're unfocused -+ bool extPlayerActive = m_pPlayer->GetCurrentPlayer() == EPC_EXTPLAYER && m_pPlayer->IsPlaying() && !m_AppFocused; -+ - { - // Less fps in DPMS - bool lowfps = m_dpmsIsActive || g_Windowing.EnableFrameLimiter(); -- // Whether externalplayer is playing and we're unfocused -- bool extPlayerActive = m_pPlayer->GetCurrentPlayer() == EPC_EXTPLAYER && m_pPlayer->IsPlaying() && !m_AppFocused; - - m_bPresentFrame = false; - if (!extPlayerActive && g_graphicsContext.IsFullScreenVideo() && !m_pPlayer->IsPausedPlayback()) - { -- m_bPresentFrame = g_renderManager.FrameWait(100); -+ m_bPresentFrame = g_renderManager.HasFrame(); - } - else - { -@@ -2322,6 +2323,11 @@ void CApplication::Render() - if (flip) - g_graphicsContext.Flip(dirtyRegions); - -+ if (!extPlayerActive && g_graphicsContext.IsFullScreenVideo() && !m_pPlayer->IsPausedPlayback()) -+ { -+ g_renderManager.FrameWait(100); -+ } -+ - m_lastFrameTime = XbmcThreads::SystemClockMillis(); - CTimeUtils::UpdateFrameTime(flip); - -diff --git a/xbmc/cores/VideoRenderers/RenderManager.cpp b/xbmc/cores/VideoRenderers/RenderManager.cpp -index 72ad819..85c3565 100644 ---- a/xbmc/cores/VideoRenderers/RenderManager.cpp -+++ b/xbmc/cores/VideoRenderers/RenderManager.cpp -@@ -316,13 +316,21 @@ void CXBMCRenderManager::Update() - m_pRenderer->Update(); - } - --bool CXBMCRenderManager::FrameWait(int ms) -+void CXBMCRenderManager::FrameWait(int ms) - { - XbmcThreads::EndTime timeout(ms); - CSingleLock lock(m_presentlock); - while(m_presentstep == PRESENT_IDLE && !timeout.IsTimePast()) - m_presentevent.wait(lock, timeout.MillisLeft()); -- return m_presentstep != PRESENT_IDLE; -+} -+ -+bool CXBMCRenderManager::HasFrame() -+{ -+ CSingleLock lock(m_presentlock); -+ if (m_presentstep == PRESENT_FRAME || m_presentstep == PRESENT_FRAME2) -+ return true; -+ else -+ return false; - } - - void CXBMCRenderManager::FrameMove() -diff --git a/xbmc/cores/VideoRenderers/RenderManager.h b/xbmc/cores/VideoRenderers/RenderManager.h -index 7280423..b80319a 100644 ---- a/xbmc/cores/VideoRenderers/RenderManager.h -+++ b/xbmc/cores/VideoRenderers/RenderManager.h -@@ -59,7 +59,8 @@ public: - void Update(); - void FrameMove(); - void FrameFinish(); -- bool FrameWait(int ms); -+ void FrameWait(int ms); -+ bool HasFrame(); - void Render(bool clear, DWORD flags = 0, DWORD alpha = 255, bool gui = true); - bool IsGuiLayer(); - bool IsVideoLayer(); --- -1.9.1 - diff --git a/projects/imx6/patches/kodi/kodi-06-imx-Rework-of-frame-processing-and-rendering-based-o.patch b/projects/imx6/patches/kodi/kodi-06-imx-Rework-of-frame-processing-and-rendering-based-o.patch deleted file mode 100644 index f36a721288..0000000000 --- a/projects/imx6/patches/kodi/kodi-06-imx-Rework-of-frame-processing-and-rendering-based-o.patch +++ /dev/null @@ -1,2593 +0,0 @@ -From b71b5abc387c6d3feda9c1a6dadb1f565dfb15e1 Mon Sep 17 00:00:00 2001 -From: smallint -Date: Thu, 22 Jan 2015 10:15:38 +0100 -Subject: [PATCH 6/6] [imx] Rework of frame processing and rendering based on - fullscreen PR - -Conflicts: - xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp ---- - language/English/strings.po | 14 +- - xbmc/Application.cpp | 34 +- - xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp | 144 ++- - xbmc/cores/VideoRenderers/LinuxRendererGLES.h | 3 + - xbmc/cores/VideoRenderers/RenderManager.cpp | 12 +- - .../dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp | 1102 +++++++++++++++++--- - .../dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h | 336 ++++-- - xbmc/guilib/GUIVideoControl.cpp | 4 + - xbmc/guilib/GUIWindow.h | 2 +- - xbmc/guilib/GUIWindowManager.cpp | 2 +- - xbmc/settings/VideoSettings.h | 3 + - xbmc/utils/Screenshot.cpp | 13 +- - xbmc/video/dialogs/GUIDialogVideoSettings.cpp | 2 + - xbmc/video/windows/GUIWindowFullScreen.cpp | 6 +- - xbmc/windowing/egl/EGLNativeTypeIMX.cpp | 70 +- - xbmc/windowing/egl/WinSystemEGL.cpp | 9 +- - 16 files changed, 1453 insertions(+), 303 deletions(-) - -diff --git a/language/English/strings.po b/language/English/strings.po -index 15090fc..d994570 100755 ---- a/language/English/strings.po -+++ b/language/English/strings.po -@@ -7548,7 +7548,19 @@ msgctxt "#16333" - msgid "MMAL - Bob (Half)" - msgstr "" - --#empty strings from id 16334 to 16399 -+#. Description of OSD video settings for deinterlace method with label #16334 -+#: xbmc/video/dialogs/GUIDialogVideoSettings.cpp -+msgctxt "#16334" -+msgid "IMX - Fast motion" -+msgstr "" -+ -+#. Description of OSD video settings for deinterlace method with label #16335 -+#: xbmc/video/dialogs/GUIDialogVideoSettings.cpp -+msgctxt "#16335" -+msgid "IMX - Fast motion (Double)" -+msgstr "" -+ -+#empty strings from id 16336 to 16399 - - #: xbmc/video/dialogs/GUIDialogVideoSettings.cpp - msgctxt "#16400" -diff --git a/xbmc/Application.cpp b/xbmc/Application.cpp -index 137872c..fe44706 100644 ---- a/xbmc/Application.cpp -+++ b/xbmc/Application.cpp -@@ -706,7 +706,7 @@ bool CApplication::Create() - CLog::Log(LOGNOTICE, "WARNING: unsupported ffmpeg version detected"); - } - #endif -- -+ - std::string cpuModel(g_cpuInfo.getCPUModel()); - if (!cpuModel.empty()) - CLog::Log(LOGNOTICE, "Host CPU: %s, %d core%s available", cpuModel.c_str(), g_cpuInfo.getCPUCount(), (g_cpuInfo.getCPUCount() == 1) ? "" : "s"); -@@ -1407,7 +1407,7 @@ bool CApplication::Initialize() - - g_windowManager.Add(new CGUIDialogPeripheralManager); - g_windowManager.Add(new CGUIDialogPeripheralSettings); -- -+ - g_windowManager.Add(new CGUIDialogMediaFilter); - g_windowManager.Add(new CGUIDialogSubtitles); - -@@ -1811,7 +1811,7 @@ bool CApplication::OnSettingUpdate(CSetting* &setting, const char *oldSettingId, - CSettingString *audioDevice = (CSettingString*)setting; - // Gotham and older didn't enumerate audio devices per stream on osx - // add stream0 per default which should be ok for all old settings. -- if (!StringUtils::EqualsNoCase(audioDevice->GetValue(), "DARWINOSX:default") && -+ if (!StringUtils::EqualsNoCase(audioDevice->GetValue(), "DARWINOSX:default") && - StringUtils::FindWords(audioDevice->GetValue().c_str(), ":stream") == std::string::npos) - { - std::string newSetting = audioDevice->GetValue(); -@@ -2538,8 +2538,8 @@ bool CApplication::OnAction(const CAction &action) - if (action.IsMouse()) - g_Mouse.SetActive(true); - -- -- if (action.GetID() == ACTION_CREATE_EPISODE_BOOKMARK) -+ -+ if (action.GetID() == ACTION_CREATE_EPISODE_BOOKMARK) - { - CGUIDialogVideoBookmarks::OnAddEpisodeBookmark(); - } -@@ -2547,7 +2547,7 @@ bool CApplication::OnAction(const CAction &action) - { - CGUIDialogVideoBookmarks::OnAddBookmark(); - } -- -+ - // The action PLAYPAUSE behaves as ACTION_PAUSE if we are currently - // playing or ACTION_PLAYER_PLAY if we are seeking (FF/RW) or not playing. - if (action.GetID() == ACTION_PLAYER_PLAYPAUSE) -@@ -3447,7 +3447,7 @@ bool CApplication::Cleanup() - #ifdef HAS_DVD_DRIVE - CLibcdio::ReleaseInstance(); - #endif --#endif -+#endif - #if defined(TARGET_ANDROID) - // enable for all platforms once it's safe - g_sectionLoader.UnloadAll(); -@@ -3729,7 +3729,7 @@ PlayBackRet CApplication::PlayStack(const CFileItem& item, bool bRestart) - else - { - LoadVideoSettings(item.GetPath()); -- -+ - // see if we have the info in the database - // TODO: If user changes the time speed (FPS via framerate conversion stuff) - // then these times will be wrong. -@@ -4034,7 +4034,7 @@ PlayBackRet CApplication::PlayFile(const CFileItem& item, bool bRestart) - CSingleLock lock(m_playStateMutex); - // tell system we are starting a file - m_bPlaybackStarting = true; -- -+ - // for playing a new item, previous playing item's callback may already - // pushed some delay message into the threadmessage list, they are not - // expected be processed after or during the new item playback starting. -@@ -4344,7 +4344,7 @@ void CApplication::SaveFileState(bool bForeground /* = false */) - m_progressTrackingVideoResumeBookmark, - m_progressTrackingPlayCountUpdate, - CMediaSettings::Get().GetCurrentVideoSettings()); -- -+ - if (bForeground) - { - // Run job in the foreground to make sure it finishes -@@ -4437,11 +4437,11 @@ void CApplication::LoadVideoSettings(const std::string &path) - if (dbs.Open()) - { - CLog::Log(LOGDEBUG, "Loading settings for %s", path.c_str()); -- -+ - // Load stored settings if they exist, otherwise use default - if (!dbs.GetVideoSettings(path, CMediaSettings::Get().GetCurrentVideoSettings())) - CMediaSettings::Get().GetCurrentVideoSettings() = CMediaSettings::Get().GetDefaultVideoSettings(); -- -+ - dbs.Close(); - } - } -@@ -4762,7 +4762,7 @@ bool CApplication::OnMessage(CGUIMessage& message) - - // Update our infoManager with the new details etc. - if (m_nextPlaylistItem >= 0) -- { -+ { - // playing an item which is not in the list - player might be stopped already - // so do nothing - if (playList.size() <= m_nextPlaylistItem) -@@ -5364,7 +5364,7 @@ float CApplication::GetVolume(bool percentage /* = true */) const - // converts the hardware volume to a percentage - return m_volumeLevel * 100.0f; - } -- -+ - return m_volumeLevel; - } - -@@ -5839,15 +5839,15 @@ void CApplication::CloseNetworkShares() - #if defined(HAS_FILESYSTEM_SMB) && !defined(TARGET_WINDOWS) - smb.Deinit(); - #endif -- -+ - #ifdef HAS_FILESYSTEM_NFS - gNfsConnection.Deinit(); - #endif -- -+ - #ifdef HAS_FILESYSTEM_AFP - gAfpConnection.Deinit(); - #endif -- -+ - #ifdef HAS_FILESYSTEM_SFTP - CSFTPSessionManager::DisconnectAllSessions(); - #endif -diff --git a/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp b/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp -index a765461..74e950c 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; -@@ -608,6 +613,69 @@ void CLinuxRendererGLES::RenderUpdateVideo(bool clear, DWORD flags, DWORD alpha) - - return; - } -+#ifdef HAS_IMXVPU -+ else if (m_renderMethod & RENDER_IMXMAP) -+ { -+ ManageDisplay(); -+ -+ CDVDVideoCodecIMXBuffer *buffer = m_buffers[m_iYV12RenderBuffer].IMXBuffer; -+ if (buffer != NULL && buffer->IsValid()) -+ { -+ g_IMXContext.SetBlitRects(m_sourceRect, m_destRect); -+ -+ bool topFieldFirst = true; -+ bool done = true; -+ -+ // Deinterlacing requested -+ if (flags & RENDER_FLAG_FIELDMASK) -+ { -+ if (flags & RENDER_FLAG_FIELD0) -+ { -+ // Double rate first frame -+ topFieldFirst = flags & RENDER_FLAG_TOP; -+ g_IMXContext.SetDeInterlacing(true); -+ g_IMXContext.SetDoubleRate(true); -+ g_IMXContext.SetInterpolatedFrame(true); -+ done = false; -+ } -+ else if (flags & RENDER_FLAG_FIELD1) -+ { -+ // Double rate second frame -+ // FIELD1 swaps the render field order, we need to -+ // swap it back for the IPU -+ topFieldFirst = flags & RENDER_FLAG_BOT; -+ g_IMXContext.SetDeInterlacing(true); -+ g_IMXContext.SetDoubleRate(true); -+ g_IMXContext.SetInterpolatedFrame(false); -+ } -+ else -+ { -+ // Fast motion -+ topFieldFirst = flags & RENDER_FLAG_TOP; -+ g_IMXContext.SetDeInterlacing(true); -+ g_IMXContext.SetDoubleRate(false); -+ } -+ } -+ // Progressive -+ else -+ g_IMXContext.SetDeInterlacing(false); -+ -+#if 0 -+ int page = g_IMXContext.GetCurrentPage(); -+ page = 1-page; -+ -+ g_IMXContext.Blit(page, NULL, buffer, topFieldFirst); -+ g_IMXContext.ShowPage(page); -+#else -+ g_IMXContext.BlitAsync(NULL, buffer, topFieldFirst); -+#endif -+ -+ // Prevent rendering again -+ if (done) -+ SAFE_RELEASE(m_buffers[m_iYV12RenderBuffer].IMXBuffer); -+ } -+ } -+#endif - } - - void CLinuxRendererGLES::FlipPage(int source) -@@ -618,7 +686,6 @@ void CLinuxRendererGLES::FlipPage(int source) - m_iYV12RenderBuffer = NextYV12Texture(); - - m_buffers[m_iYV12RenderBuffer].flipindex = ++m_flipindex; -- - return; - } - -@@ -963,13 +1030,7 @@ void CLinuxRendererGLES::ReleaseBuffer(int idx) - #endif - #ifdef HAS_IMXVPU - if (m_renderMethod & RENDER_IMXMAP) -- { -- if (buf.IMXBuffer) -- { -- SAFE_RELEASE(buf.IMXBuffer); -- buf.IMXBuffer = NULL; -- } -- } -+ SAFE_RELEASE(buf.IMXBuffer); - #endif - } - -@@ -1241,7 +1302,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); -@@ -1679,6 +1740,7 @@ void CLinuxRendererGLES::RenderCoreVideoRef(int index, int field) - - void CLinuxRendererGLES::RenderIMXMAPTexture(int index, int field) - { -+#if 0 - #if defined(HAS_IMXVPU) - #ifdef DEBUG_VERBOSE - unsigned int time = XbmcThreads::SystemClockMillis(); -@@ -1754,6 +1816,7 @@ void CLinuxRendererGLES::RenderIMXMAPTexture(int index, int field) - CLog::Log(LOGDEBUG, "RenderIMXMAPTexture %d: tm:%d\n", index, XbmcThreads::SystemClockMillis() - time); - #endif - #endif -+#endif - } - - bool CLinuxRendererGLES::RenderCapture(CRenderCapture* capture) -@@ -2717,42 +2780,6 @@ void CLinuxRendererGLES::SetTextureFilter(GLenum method) - //******************************************************************************************************** - void CLinuxRendererGLES::UploadIMXMAPTexture(int index) - { --#ifdef HAS_IMXVPU -- YUVBUFFER& buf = m_buffers[index]; -- CDVDVideoCodecIMXBuffer* IMXBuffer = buf.IMXBuffer; -- -- if(IMXBuffer) -- { -- CDVDVideoCodecIMX::Enter(); -- -- if(!IMXBuffer->IsValid()) -- { -- CDVDVideoCodecIMX::Leave(); -- return; -- } -- -- YUVPLANE &plane = m_buffers[index].fields[0][0]; -- -- glActiveTexture(GL_TEXTURE0); -- glBindTexture(m_textureTarget, plane.id); -- -- GLuint physical = ~0U; -- GLvoid *virt = (GLvoid*)IMXBuffer->m_VirtAddr; -- glTexDirectVIVMap(m_textureTarget, IMXBuffer->m_iWidth, IMXBuffer->m_iHeight, GL_VIV_NV12, -- (GLvoid **)&virt, &physical); -- glTexDirectInvalidateVIV(m_textureTarget); -- -- glBindTexture(m_textureTarget, 0); -- -- plane.flipindex = m_buffers[index].flipindex; -- plane.texwidth = IMXBuffer->m_iWidth; -- plane.texheight = IMXBuffer->m_iHeight; -- -- CalculateTextureSourceRects(index, 1); -- -- CDVDVideoCodecIMX::Leave(); -- } --#endif - } - - void CLinuxRendererGLES::DeleteIMXMAPTexture(int index) -@@ -2868,9 +2895,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; -@@ -2899,13 +2923,19 @@ bool CLinuxRendererGLES::Supports(EINTERLACEMETHOD method) - if(m_renderMethod & RENDER_CVREF) - return false; - -- if(m_renderMethod & RENDER_IMXMAP) -- return false; -- - if(method == VS_INTERLACEMETHOD_AUTO) - return true; - --#if defined(__i386__) || defined(__x86_64__) -+ if(m_renderMethod & RENDER_IMXMAP) -+ { -+ if(method == VS_INTERLACEMETHOD_IMX_FASTMOTION -+ || method == VS_INTERLACEMETHOD_IMX_FASTMOTION_DOUBLE) -+ return true; -+ else -+ return false; -+ } -+ -+#if !defined(TARGET_ANDROID) && (defined(__i386__) || defined(__x86_64__)) - if(method == VS_INTERLACEMETHOD_DEINTERLACE - || method == VS_INTERLACEMETHOD_DEINTERLACE_HALF - || method == VS_INTERLACEMETHOD_SW_BLEND) -@@ -2926,6 +2956,9 @@ bool CLinuxRendererGLES::Supports(ESCALINGMETHOD method) - return itr != m_scalingMethods.end(); - } - -+ if(m_renderMethod & RENDER_IMXMAP) -+ return false; -+ - if(method == VS_SCALINGMETHOD_NEAREST - || method == VS_SCALINGMETHOD_LINEAR) - return true; -@@ -2954,7 +2987,7 @@ EINTERLACEMETHOD CLinuxRendererGLES::AutoInterlaceMethod() - return VS_INTERLACEMETHOD_NONE; - - if(m_renderMethod & RENDER_IMXMAP) -- return VS_INTERLACEMETHOD_NONE; -+ return VS_INTERLACEMETHOD_IMX_FASTMOTION; - - #if defined(__i386__) || defined(__x86_64__) - return VS_INTERLACEMETHOD_DEINTERLACE_HALF; -@@ -2970,6 +3003,9 @@ unsigned int CLinuxRendererGLES::GetOptimalBufferSize() - m_format == RENDER_FMT_EGLIMG || - m_format == RENDER_FMT_MEDIACODEC) - return 2; -+ else if(m_format == RENDER_FMT_IMXMAP) -+ // Let the codec control the buffer size -+ return GetMaxBufferSize(); - else - return 3; - } -@@ -3061,7 +3097,7 @@ void CLinuxRendererGLES::AddProcessor(CDVDVideoCodecIMXBuffer *buffer, int index - - bool CLinuxRendererGLES::IsGuiLayer() - { -- if (m_format == RENDER_FMT_BYPASS) -+ if (m_format == RENDER_FMT_BYPASS || m_format == RENDER_FMT_IMXMAP) - return false; - else - return true; -diff --git a/xbmc/cores/VideoRenderers/LinuxRendererGLES.h b/xbmc/cores/VideoRenderers/LinuxRendererGLES.h -index b865033..ce5356d 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; - - -diff --git a/xbmc/cores/VideoRenderers/RenderManager.cpp b/xbmc/cores/VideoRenderers/RenderManager.cpp -index b394d7b..72ad819 100644 ---- a/xbmc/cores/VideoRenderers/RenderManager.cpp -+++ b/xbmc/cores/VideoRenderers/RenderManager.cpp -@@ -668,7 +668,10 @@ void CXBMCRenderManager::FlipPage(volatile bool& bStop, double timestamp /* = 0L - deinterlacemode = VS_DEINTERLACEMODE_OFF; - - if (deinterlacemode == VS_DEINTERLACEMODE_OFF) -+ { - presentmethod = PRESENT_METHOD_SINGLE; -+ sync = FS_NONE; -+ } - else - { - if (deinterlacemode == VS_DEINTERLACEMODE_AUTO && sync == FS_NONE) -@@ -683,6 +686,7 @@ void CXBMCRenderManager::FlipPage(volatile bool& bStop, double timestamp /* = 0L - else if (interlacemethod == VS_INTERLACEMETHOD_RENDER_BOB_INVERTED) { presentmethod = PRESENT_METHOD_BOB; invert = true; } - else if (interlacemethod == VS_INTERLACEMETHOD_DXVA_BOB) presentmethod = PRESENT_METHOD_BOB; - else if (interlacemethod == VS_INTERLACEMETHOD_DXVA_BEST) presentmethod = PRESENT_METHOD_BOB; -+ else if (interlacemethod == VS_INTERLACEMETHOD_IMX_FASTMOTION_DOUBLE) presentmethod = PRESENT_METHOD_BOB; - else presentmethod = PRESENT_METHOD_SINGLE; - - /* default to odd field if we want to deinterlace and don't know better */ -@@ -829,8 +833,14 @@ bool CXBMCRenderManager::IsVideoLayer() - void CXBMCRenderManager::PresentSingle(bool clear, DWORD flags, DWORD alpha) - { - CSingleLock lock(g_graphicsContext); -+ SPresent& m = m_Queue[m_presentsource]; - -- m_pRenderer->RenderUpdate(clear, flags, alpha); -+ if (m.presentfield == FS_BOT) -+ m_pRenderer->RenderUpdate(clear, flags | RENDER_FLAG_BOT, alpha); -+ else if (m.presentfield == FS_TOP) -+ m_pRenderer->RenderUpdate(clear, flags | RENDER_FLAG_TOP, alpha); -+ else -+ m_pRenderer->RenderUpdate(clear, flags, alpha); - } - - /* new simpler method of handling interlaced material, * -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp -index ca0abcc..a4d3c7e 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp -@@ -20,25 +20,34 @@ - - #include "DVDVideoCodecIMX.h" - --#include --#include --#include --#include --#include --#include -+#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" - -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define IMX_VDI_MAX_WIDTH 968 - #define FRAME_ALIGN 16 - #define MEDIAINFO 1 -+#define RENDER_QUEUE_SIZE 3 - #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 Align2(ptr,align) (((unsigned int)ptr)/(align)*(align)) -+ -+ -+// Global instance -+CIMXContext g_IMXContext; -+ - - // 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_extraVpuBuffers = 1+RENDER_QUEUE_SIZE+2; - const int CDVDVideoCodecIMX::m_maxVpuDecodeLoops = 5; - CCriticalSection CDVDVideoCodecIMX::m_codecBufferLock; - -@@ -90,8 +99,8 @@ bool CDVDVideoCodecIMX::VpuAllocBuffers(VpuMemInfo *pMemBlock) - return true; - - AllocFailure: -- VpuFreeBuffers(); -- return false; -+ VpuFreeBuffers(); -+ return false; - } - - int CDVDVideoCodecIMX::VpuFindBuffer(void *frameAddr) -@@ -104,7 +113,7 @@ int CDVDVideoCodecIMX::VpuFindBuffer(void *frameAddr) - return -1; - } - --bool CDVDVideoCodecIMX::VpuFreeBuffers(void) -+bool CDVDVideoCodecIMX::VpuFreeBuffers() - { - VpuMemDesc vpuMem; - VpuDecRetCode vpuRet; -@@ -135,7 +144,7 @@ bool CDVDVideoCodecIMX::VpuFreeBuffers(void) - vpuRet = VPU_DecFreeMem(&vpuMem); - if(vpuRet != VPU_DEC_RET_SUCCESS) - { -- CLog::Log(LOGERROR, "%s - Errror while trying to free physical memory (%d).\n", __FUNCTION__, ret); -+ CLog::Log(LOGERROR, "%s - Error while trying to free physical memory (%d).\n", __FUNCTION__, ret); - ret = false; - } - } -@@ -148,7 +157,7 @@ bool CDVDVideoCodecIMX::VpuFreeBuffers(void) - } - - --bool CDVDVideoCodecIMX::VpuOpen(void) -+bool CDVDVideoCodecIMX::VpuOpen() - { - VpuDecRetCode ret; - VpuVersionInfo vpuVersion; -@@ -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 -@@ -225,52 +256,78 @@ VpuOpenError: - return false; - } - --bool CDVDVideoCodecIMX::VpuAllocFrameBuffers(void) -+bool CDVDVideoCodecIMX::VpuAllocFrameBuffers() - { -+ 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; - -- m_vpuFrameBufferNum = m_initInfo.nMinFrameBufferCount + m_extraVpuBuffers; -+ 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; -+ } -+ -+#else -+ // NV12 -+ uvStride = yStride; -+ uSize = ySize/2; -+ mvSize = uSize/2; -+#endif - -- nAlign=m_initInfo.nAddressAlignment; -+ 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]; -+ m_outputBuffers = new CDVDVideoCodecIMXVPUBuffer*[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,42 +344,52 @@ 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); -+ m_outputBuffers[i] = new CDVDVideoCodecIMXVPUBuffer(i); - #else -- m_outputBuffers[i] = new CDVDVideoCodecIMXBuffer(); -+ m_outputBuffers[i] = new CDVDVideoCodecIMXVPUBuffer; - #endif -+ // Those buffers are ours so lock them to prevent destruction -+ m_outputBuffers[i]->Lock(); - } - - return true; -@@ -335,6 +402,7 @@ CDVDVideoCodecIMX::CDVDVideoCodecIMX() - m_vpuFrameBuffers = NULL; - m_outputBuffers = NULL; - m_lastBuffer = NULL; -+ m_currentBuffer = NULL; - m_extraMem = NULL; - m_vpuFrameBufferNum = 0; - m_dropState = false; -@@ -349,6 +417,9 @@ CDVDVideoCodecIMX::CDVDVideoCodecIMX() - m_convert_bitstream = false; - m_bytesToBeConsumed = 0; - m_previousPts = DVD_NOPTS_VALUE; -+#ifdef DUMP_STREAM -+ m_dump = NULL; -+#endif - } - - CDVDVideoCodecIMX::~CDVDVideoCodecIMX() -@@ -364,6 +435,26 @@ bool CDVDVideoCodecIMX::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options) - return false; - } - -+ if (!g_IMXContext.Configure()) -+ return false; -+ -+#ifdef DUMP_STREAM -+ m_dump = fopen("stream.dump", "wb"); -+ if (m_dump != NULL) -+ { -+ fwrite(&hints.software, sizeof(hints.software), 1, m_dump); -+ fwrite(&hints.codec, sizeof(hints.codec), 1, m_dump); -+ fwrite(&hints.profile, sizeof(hints.profile), 1, m_dump); -+ fwrite(&hints.codec_tag, sizeof(hints.codec_tag), 1, m_dump); -+ fwrite(&hints.extrasize, sizeof(hints.extrasize), 1, m_dump); -+ CLog::Log(LOGNOTICE, "Dump: HEADER: %d %d %d %d %d\n", -+ hints.software, hints.codec, hints.profile, -+ hints.codec_tag, hints.extrasize); -+ if (hints.extrasize > 0) -+ fwrite(hints.extradata, 1, hints.extrasize, m_dump); -+ } -+#endif -+ - m_hints = hints; - if (g_advancedSettings.CanLogComponent(LOGVIDEO)) - CLog::Log(LOGDEBUG, "Let's decode with iMX VPU\n"); -@@ -494,17 +585,26 @@ bool CDVDVideoCodecIMX::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options) - return true; - } - --void CDVDVideoCodecIMX::Dispose(void) -+void CDVDVideoCodecIMX::Dispose() - { -+#ifdef DUMP_STREAM -+ if (m_dump) -+ { -+ fclose(m_dump); -+ m_dump = NULL; -+ } -+#endif -+ -+ g_IMXContext.Clear(); -+ - VpuDecRetCode ret; - bool VPU_loaded = m_vpuHandle; - -- // Prevent rendering thread from using frame buffers -- Enter(); -- - // Release last buffer -- if(m_lastBuffer) -- SAFE_RELEASE(m_lastBuffer); -+ SAFE_RELEASE(m_lastBuffer); -+ SAFE_RELEASE(m_currentBuffer); -+ -+ Enter(); - - // Invalidate output buffers to prevent the renderer from mapping this memory - for (int i=0; iClose(); - SAFE_DELETE(m_converter); - } -+ - return; - } - -@@ -579,9 +680,26 @@ int CDVDVideoCodecIMX::Decode(BYTE *pData, int iSize, double dts, double pts) - - #ifdef IMX_PROFILE - static unsigned long long previous, current; -+#endif -+#if defined(IMX_PROFILE) || defined(IMX_PROFILE_BUFFERS) - unsigned long long before_dec; - #endif - -+#ifdef DUMP_STREAM -+ if (m_dump != NULL) -+ { -+ if (pData) -+ { -+ fwrite(&dts, sizeof(double), 1, m_dump); -+ fwrite(&pts, sizeof(double), 1, m_dump); -+ fwrite(&iSize, sizeof(int), 1, m_dump); -+ fwrite(pData, 1, iSize, m_dump); -+ } -+ } -+#endif -+ -+ SAFE_RELEASE(m_currentBuffer); -+ - if (!m_vpuHandle) - { - VpuOpen(); -@@ -610,6 +728,7 @@ int CDVDVideoCodecIMX::Decode(BYTE *pData, int iSize, double dts, double pts) - if ((pData && iSize) || - (m_bytesToBeConsumed)) - { -+ //printf("D %f %d\n", pts, iSize); - if ((m_convert_bitstream) && (iSize)) - { - // convert demuxer packet from bitstream to bytestream (AnnexB) -@@ -638,16 +757,24 @@ int CDVDVideoCodecIMX::Decode(BYTE *pData, int iSize, double dts, double pts) - inData.sCodecData.nSize = 0; - } - -+#ifdef IMX_PROFILE_BUFFERS -+ static unsigned long long dec_time = 0; -+#endif -+ - while (true) // Decode as long as the VPU consumes data - { --#ifdef IMX_PROFILE -+#if defined(IMX_PROFILE) || defined(IMX_PROFILE_BUFFERS) - before_dec = XbmcThreads::SystemClockMillis(); - #endif - if (m_frameReported) - m_bytesToBeConsumed += inData.nSize; - ret = VPU_DecDecodeBuf(m_vpuHandle, &inData, &decRet); -+#ifdef IMX_PROFILE_BUFFERS -+ unsigned long long dec_single_call = XbmcThreads::SystemClockMillis()-before_dec; -+ dec_time += dec_single_call; -+#endif - #ifdef IMX_PROFILE -- CLog::Log(LOGDEBUG, "%s - VPU dec 0x%x decode takes : %lld\n\n", __FUNCTION__, decRet, XbmcThreads::SystemClockMillis() - before_dec); -+ 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) -@@ -736,14 +863,53 @@ int CDVDVideoCodecIMX::Decode(BYTE *pData, int iSize, double dts, double pts) - m_frameInfo.pExtInfo->nFrmWidth = (((m_frameInfo.pExtInfo->nFrmWidth) + 15) & ~15); - m_frameInfo.pExtInfo->nFrmHeight = (((m_frameInfo.pExtInfo->nFrmHeight) + 15) & ~15); - -- /* quick & dirty fix to get proper timestamping for VP8 codec */ -- if (m_decOpenParam.CodecFormat == VPU_V_VP8) -+ idx = VpuFindBuffer(m_frameInfo.pDisplayFrameBuf->pbufY); -+ if (idx != -1) - { -- idx = VpuFindBuffer(m_frameInfo.pDisplayFrameBuf->pbufY); -- m_outputBuffers[idx]->SetPts(pts); -- } -+ CDVDVideoCodecIMXVPUBuffer *buffer = m_outputBuffers[idx]; -+ -+ /* quick & dirty fix to get proper timestamping for VP8 codec */ -+ if (m_decOpenParam.CodecFormat == VPU_V_VP8) -+ buffer->SetPts(pts); -+ -+ buffer->Lock(); -+ buffer->SetDts(dts); -+ buffer->Queue(&m_frameInfo, m_lastBuffer); -+ -+#ifdef IMX_PROFILE_BUFFERS -+ CLog::Log(LOGNOTICE, "+D %f %lld\n", buffer->GetPts(), 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(); - -- retStatus |= VC_PICTURE; -+#ifdef IMX_PROFILE_BUFFERS -+ static unsigned long long lastD = 0; -+ unsigned long long current = XbmcThreads::SystemClockMillis(), tmp; -+ CLog::Log(LOGNOTICE, "+V %f %lld\n", buffer->GetPts(), current-lastD); -+ lastD = current; -+#endif -+ -+ m_currentBuffer = buffer; -+ -+ if (m_currentBuffer) -+ { -+ retStatus |= VC_PICTURE; -+ } -+ } - } //VPU_DEC_OUTPUT_DIS - - // According to libfslvpuwrap: If this flag is set then the frame should -@@ -822,10 +988,8 @@ int CDVDVideoCodecIMX::Decode(BYTE *pData, int iSize, double dts, double pts) - } // Decode loop - } //(pData && iSize) - -- if (retStatus == 0) -- { -+ if (!retStatus) - retStatus |= VC_BUFFER; -- } - - if (m_bytesToBeConsumed > 0) - { -@@ -835,8 +999,6 @@ 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; - - #ifdef IMX_PROFILE - CLog::Log(LOGDEBUG, "%s - returns %x - duration %lld\n", __FUNCTION__, retStatus, XbmcThreads::SystemClockMillis() - previous); -@@ -855,8 +1017,8 @@ void CDVDVideoCodecIMX::Reset() - CLog::Log(LOGDEBUG, "%s - called\n", __FUNCTION__); - - // 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++) -@@ -872,12 +1034,11 @@ void CDVDVideoCodecIMX::Reset() - { - CLog::Log(LOGERROR, "%s - VPU flush failed with error code %d.\n", __FUNCTION__, ret); - } -- - } - - unsigned CDVDVideoCodecIMX::GetAllowedReferences() - { -- return 3; -+ return RENDER_QUEUE_SIZE; - } - - bool CDVDVideoCodecIMX::ClearPicture(DVDVideoPicture* pDvdVideoPicture) -@@ -909,46 +1070,29 @@ bool CDVDVideoCodecIMX::GetPicture(DVDVideoPicture* pDvdVideoPicture) - else - pDvdVideoPicture->iFlags &= ~DVP_FLAG_DROPPED; - -+ if (m_initInfo.nInterlace) -+ pDvdVideoPicture->iFlags |= DVP_FLAG_INTERLACED; -+ else -+ pDvdVideoPicture->iFlags &= ~DVP_FLAG_INTERLACED; -+ -+ if (m_currentBuffer->GetFieldType() != VPU_FIELD_BOTTOM && m_currentBuffer->GetFieldType() != VPU_FIELD_BT) -+ pDvdVideoPicture->iFlags |= DVP_FLAG_TOP_FIELD_FIRST; -+ else -+ pDvdVideoPicture->iFlags &= ~DVP_FLAG_TOP_FIELD_FIRST; -+ - 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; -- } -+ // 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->IMXBuffer = m_currentBuffer; -+ m_currentBuffer = NULL; - - return true; - } -@@ -980,44 +1124,64 @@ void CDVDVideoCodecIMX::Leave() - } - - /*******************************************/ -- - #ifdef TRACE_FRAMES - CDVDVideoCodecIMXBuffer::CDVDVideoCodecIMXBuffer(int idx) -- : m_refs(1) -- , m_idx(idx) -+ : m_idx(idx) -+ , - #else - CDVDVideoCodecIMXBuffer::CDVDVideoCodecIMXBuffer() -- : m_refs(1) -+ : -+#endif -+ m_pts(DVD_NOPTS_VALUE) -+ , m_dts(DVD_NOPTS_VALUE) -+{ -+} -+ -+void CDVDVideoCodecIMXBuffer::SetPts(double pts) -+{ -+ m_pts = pts; -+} -+ -+void CDVDVideoCodecIMXBuffer::SetDts(double dts) -+{ -+ m_dts = dts; -+} -+ -+#ifdef TRACE_FRAMES -+CDVDVideoCodecIMXVPUBuffer::CDVDVideoCodecIMXVPUBuffer(int idx) -+ : CDVDVideoCodecIMXBuffer(idx) -+#else -+CDVDVideoCodecIMXVPUBuffer::CDVDVideoCodecIMXVPUBuffer() -+ : CDVDVideoCodecIMXBuffer() - #endif - , m_frameBuffer(NULL) - , m_rendered(false) -- , m_pts(DVD_NOPTS_VALUE) - , m_previousBuffer(NULL) - { - } - --void CDVDVideoCodecIMXBuffer::Lock() -+void CDVDVideoCodecIMXVPUBuffer::Lock() - { - #ifdef TRACE_FRAMES -- long count = AtomicIncrement(&m_refs); -+ long count = AtomicIncrement(&m_iRefs); - CLog::Log(LOGDEBUG, "R+ %02d - ref : %d (VPU)\n", m_idx, count); - #else -- AtomicIncrement(&m_refs); -+ AtomicIncrement(&m_iRefs); - #endif - } - --long CDVDVideoCodecIMXBuffer::Release() -+long CDVDVideoCodecIMXVPUBuffer::Release() - { -- long count = AtomicDecrement(&m_refs); -+ long count = AtomicDecrement(&m_iRefs); - #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 -+ // Only referenced by the codec and its next frame, release the previous - SAFE_RELEASE(m_previousBuffer); - } -- if (count == 1) -+ else 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. -@@ -1038,18 +1202,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 -@@ -1059,13 +1223,19 @@ 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; -+#ifdef IMX_INPUT_FORMAT_I420 -+ iFormat = _4CC('I', '4', '2', '0'); -+#else -+ iFormat = _4CC('N', 'V', '1', '2'); -+#endif -+ iWidth = frameInfo->pExtInfo->nFrmWidth; -+ iHeight = frameInfo->pExtInfo->nFrmHeight; -+ pVirtAddr = m_frameBuffer->pbufVirtY; -+ pPhysAddr = (int)m_frameBuffer->pbufY; -+ m_fieldType = frameInfo->eFieldType; - } - --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 -@@ -1082,31 +1252,679 @@ 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) -+CDVDVideoCodecIMXVPUBuffer::~CDVDVideoCodecIMXVPUBuffer() - { -- m_pts = pts; -+ assert(m_iRefs == 0); -+#ifdef TRACE_FRAMES -+ CLog::Log(LOGDEBUG, "~ %02d (VPU)\n", m_idx); -+#endif - } - --double CDVDVideoCodecIMXBuffer::GetPts(void) const -+CIMXContext::CIMXContext() -+ : CThread("iMX IPU") -+ , m_fbHandle(0) -+ , m_fbPages(0) -+ , m_fbPhysAddr(0) -+ , m_fbVirtAddr(NULL) -+ , m_ipuHandle(0) -+ , m_vsync(true) -+ , m_pageCrops(NULL) - { -- return m_pts; -+ // Limit queue to 2 -+ m_input.resize(2); -+ m_beginInput = m_endInput = m_bufferedInput = 0; - } - --CDVDVideoCodecIMXBuffer *CDVDVideoCodecIMXBuffer::GetPreviousBuffer() const -+CIMXContext::~CIMXContext() - { -- return m_previousBuffer; -+ Close(); - } - --CDVDVideoCodecIMXBuffer::~CDVDVideoCodecIMXBuffer() -+bool CIMXContext::Configure(int pages) - { -- assert(m_refs == 0); --#ifdef TRACE_FRAMES -- CLog::Log(LOGDEBUG, "~ %02d (VPU)\n", m_idx); -+ SetBlitRects(CRectInt(), CRectInt()); -+ m_fbCurrentPage = 0; -+ -+ int fb0 = open("/dev/fb0", O_RDWR, 0); -+ -+ if (fb0 < 0) -+ { -+ CLog::Log(LOGWARNING, "iMX : Failed to open /dev/fb0\n"); -+ return false; -+ } -+ -+ struct fb_var_screeninfo fbVar; -+ if (ioctl(fb0, FBIOGET_VSCREENINFO, &fbVar) < 0) -+ { -+ CLog::Log(LOGWARNING, "iMX : Failed to read primary screen resolution\n"); -+ close(fb0); -+ return false; -+ } -+ -+ close(fb0); -+ -+ if (m_fbHandle) -+ { -+ // Check for updated screen resolution -+ if ((m_fbWidth != fbVar.xres) || (m_fbHeight != fbVar.yres) || (pages != m_fbPages)) -+ Close(); -+ else -+ { -+ Clear(); -+ Unblank(); -+ return true; -+ } -+ } -+ -+ CLog::Log(LOGNOTICE, "iMX : Initialize render buffers\n"); -+ -+ memcpy(&m_fbVar, &fbVar, sizeof(fbVar)); -+ -+ const char *deviceName = "/dev/fb1"; -+ -+ m_fbHandle = open(deviceName, O_RDWR | O_NONBLOCK, 0); -+ if (m_fbHandle < 0) -+ { -+ CLog::Log(LOGWARNING, "iMX : Failed to open framebuffer: %s\n", deviceName); -+ return false; -+ } -+ -+ m_fbWidth = m_fbVar.xres; -+ m_fbHeight = m_fbVar.yres; -+ -+ if (ioctl(m_fbHandle, FBIOGET_VSCREENINFO, &m_fbVar) < 0) -+ { -+ CLog::Log(LOGWARNING, "iMX : Failed to query variable screen info at %s\n", deviceName); -+ return false; -+ } -+ -+ // We want n fb pages -+ m_fbPages = pages; -+ m_pageCrops = new CRectInt[m_fbPages]; -+ -+ m_fbVar.xoffset = 0; -+ m_fbVar.yoffset = 0; -+ m_fbVar.bits_per_pixel = 16; -+ m_fbVar.nonstd = _4CC('U', 'Y', 'V', 'Y'); -+ m_fbVar.activate = FB_ACTIVATE_NOW; -+ m_fbVar.xres = m_fbWidth; -+ m_fbVar.yres = m_fbHeight; -+ // One additional line that is required for deinterlacing -+ m_fbVar.yres_virtual = (m_fbVar.yres+1) * m_fbPages; -+ m_fbVar.xres_virtual = m_fbVar.xres; -+ -+ if (ioctl(m_fbHandle, FBIOPUT_VSCREENINFO, &m_fbVar) < 0) -+ { -+ CLog::Log(LOGWARNING, "iMX : Failed to setup %s\n", deviceName); -+ close(m_fbHandle); -+ m_fbHandle = 0; -+ m_fbPages = 0; -+ return false; -+ } -+ -+ struct fb_fix_screeninfo fb_fix; -+ if (ioctl(m_fbHandle, FBIOGET_FSCREENINFO, &fb_fix) < 0) -+ { -+ CLog::Log(LOGWARNING, "iMX : Failed to query fixed screen info at %s\n", deviceName); -+ close(m_fbHandle); -+ m_fbHandle = 0; -+ m_fbPages = 0; -+ return false; -+ } -+ -+ // Final setup -+ m_fbLineLength = fb_fix.line_length; -+ m_fbPhysSize = fb_fix.smem_len; -+ m_fbPageSize = m_fbLineLength * m_fbVar.yres_virtual / m_fbPages; -+ m_fbPhysAddr = fb_fix.smem_start; -+ m_fbVirtAddr = (uint8_t*)mmap(0, m_fbPhysSize, PROT_READ | PROT_WRITE, MAP_SHARED, m_fbHandle, 0); -+ -+ CLog::Log(LOGDEBUG, "iMX : Allocated %d render buffers\n", m_fbPages); -+ -+ m_ipuHandle = open("/dev/mxc_ipu", O_RDWR, 0); -+ if (m_ipuHandle < 0) -+ { -+ CLog::Log(LOGWARNING, "iMX : Failed to initialize IPU: %s\n", strerror(errno)); -+ m_ipuHandle = 0; -+ Close(); -+ return false; -+ } -+ -+ Clear(); -+ Unblank(); -+ -+ // Start the ipu thread -+ Create(); -+ return true; -+} -+ -+bool CIMXContext::Close() -+{ -+ CLog::Log(LOGINFO, "iMX : Closing context\n"); -+ -+ // Stop the ipu thread -+ StopThread(); -+ -+ if (m_pageCrops) -+ { -+ delete[] m_pageCrops; -+ m_pageCrops = NULL; -+ } -+ -+ if (m_fbVirtAddr) -+ { -+ Clear(); -+ munmap(m_fbVirtAddr, m_fbPhysSize); -+ m_fbVirtAddr = NULL; -+ } -+ -+ if (m_fbHandle) -+ { -+ Blank(); -+ close(m_fbHandle); -+ m_fbPages = 0; -+ m_fbHandle = 0; -+ m_fbPhysAddr = 0; -+ } -+ -+ if (m_ipuHandle) -+ { -+ // Close IPU device -+ if (close(m_ipuHandle)) -+ CLog::Log(LOGERROR, "iMX : Failed to close IPU: %s\n", strerror(errno)); -+ -+ m_ipuHandle = 0; -+ } -+ -+ CLog::Log(LOGNOTICE, "iMX : Deinitialized render context\n", m_fbPages); -+ -+ return true; -+} -+ -+bool CIMXContext::GetPageInfo(CIMXBuffer *info, int page) -+{ -+ if (page < 0 || page >= m_fbPages) -+ return false; -+ -+ info->iWidth = m_fbWidth; -+ info->iHeight = m_fbHeight; -+ info->iFormat = m_fbVar.nonstd; -+ info->pPhysAddr = m_fbPhysAddr + page*m_fbPageSize; -+ info->pVirtAddr = m_fbVirtAddr + page*m_fbPageSize; -+ -+ return true; -+} -+ -+bool CIMXContext::Blank() -+{ -+ if (!m_fbHandle) return false; -+ return ioctl(m_fbHandle, FBIOBLANK, 1) == 0; -+} -+ -+bool CIMXContext::Unblank() -+{ -+ if (!m_fbHandle) return false; -+ return ioctl(m_fbHandle, FBIOBLANK, FB_BLANK_UNBLANK) == 0; -+} -+ -+bool CIMXContext::SetVSync(bool enable) -+{ -+ m_vsync = enable; -+} -+ -+void CIMXContext::SetDoubleRate(bool flag) -+{ -+ if (flag) -+ m_currentFieldFmt |= IPU_DEINTERLACE_RATE_EN; -+ else -+ m_currentFieldFmt &= ~IPU_DEINTERLACE_RATE_EN; -+ -+ m_currentFieldFmt &= ~IPU_DEINTERLACE_RATE_FRAME1; -+} -+ -+bool CIMXContext::DoubleRate() const -+{ -+ return m_currentFieldFmt & IPU_DEINTERLACE_RATE_EN; -+} -+ -+void CIMXContext::SetInterpolatedFrame(bool flag) -+{ -+ if (flag) -+ m_currentFieldFmt &= ~IPU_DEINTERLACE_RATE_FRAME1; -+ else -+ m_currentFieldFmt |= IPU_DEINTERLACE_RATE_FRAME1; -+} -+ -+void CIMXContext::SetDeInterlacing(bool flag) -+{ -+ m_deInterlacing = flag; -+} -+ -+void CIMXContext::SetBlitRects(const CRect &srcRect, const CRect &dstRect) -+{ -+ m_srcRect = srcRect; -+ m_dstRect = dstRect; -+} -+ -+bool CIMXContext::Blit(int page, CIMXBuffer *source_p, CIMXBuffer *source, bool topBottomFields) -+{ -+ if (page < 0 || page >= m_fbPages) -+ return false; -+ -+ IPUTask ipu; -+ PrepareTask(ipu, source_p, source, topBottomFields); -+ return DoTask(ipu, page); -+} -+ -+bool CIMXContext::BlitAsync(CIMXBuffer *source_p, CIMXBuffer *source, bool topBottomFields) -+{ -+ IPUTask ipu; -+ PrepareTask(ipu, source_p, source, topBottomFields); -+ return PushTask(ipu); -+} -+ -+bool CIMXContext::ShowPage(int page) -+{ -+ int ret; -+ -+ if (!m_fbHandle) return false; -+ if (page < 0 || page >= m_fbPages) return false; -+ -+ // Protect page swapping from screen capturing that does read the current -+ // front buffer. This is actually not done very frequently so the lock -+ // does not hurt. -+ CSingleLock lk(m_pageSwapLock); -+ -+ m_fbCurrentPage = page; -+ m_fbVar.activate = FB_ACTIVATE_VBL; -+ m_fbVar.yoffset = (m_fbVar.yres+1)*page; -+ if ((ret = ioctl(m_fbHandle, FBIOPAN_DISPLAY, &m_fbVar)) < 0) -+ CLog::Log(LOGWARNING, "Panning failed: %s\n", strerror(errno)); -+ -+ // Wait for sync -+ if (m_vsync) -+ { -+ if (ioctl(m_fbHandle, FBIO_WAITFORVSYNC, 0) < 0) -+ CLog::Log(LOGWARNING, "Vsync failed: %s\n", strerror(errno)); -+ } -+ -+ return true; -+} -+ -+void CIMXContext::Clear(int page) -+{ -+ if (!m_fbVirtAddr) return; -+ -+ uint8_t *tmp_buf; -+ int pixels; -+ -+ if (page < 0) -+ { -+ tmp_buf = m_fbVirtAddr; -+ pixels = m_fbPageSize*m_fbPages/2; -+ } -+ else if (page < m_fbPages) -+ { -+ tmp_buf = m_fbVirtAddr + page*m_fbPageSize; -+ pixels = m_fbPageSize/2; -+ } -+ else -+ // out of range -+ return; -+ -+ for (int i = 0; i < pixels; ++i, tmp_buf += 2) -+ { -+ tmp_buf[0] = 128; -+ tmp_buf[1] = 16; -+ } -+} -+ -+#define clamp_byte(x) (x<0?0:(x>255?255:x)) -+ -+void CIMXContext::CapureDisplay(unsigned char *buffer, int iWidth, int iHeight) -+{ -+ if (m_fbVar.nonstd != _4CC('U', 'Y', 'V', 'Y')) -+ { -+ CLog::Log(LOGWARNING, "iMX : Unknown screen capture format\n"); -+ return; -+ } -+ -+ // Prevent page swaps -+ CSingleLock lk(m_pageSwapLock); -+ if (m_fbCurrentPage < 0 || m_fbCurrentPage >= m_fbPages) -+ { -+ CLog::Log(LOGWARNING, "iMX : Invalid page to capture\n"); -+ return; -+ } -+ -+ int r,g,b,a; -+ int u, y0, v, y1; -+ -+ unsigned char *display = m_fbVirtAddr + m_fbCurrentPage*m_fbPageSize; -+ int iStride = m_fbWidth*2; -+ int oStride = iWidth*4; -+ -+ int cy = 1*(1 << 16); -+ int cr1 = 1.40200*(1 << 16); -+ int cr2 = -0.71414*(1 << 16); -+ int cr3 = 0*(1 << 16); -+ int cb1 = 0*(1 << 16); -+ int cb2 = -0.34414*(1 << 16); -+ int cb3 = 1.77200*(1 << 16); -+ -+ iWidth = std::min(iWidth/2, m_fbWidth/2); -+ iHeight = std::min(iHeight, m_fbHeight); -+ -+ for (int y = 0; y < iHeight; ++y, display += iStride, buffer += oStride) -+ { -+ unsigned char *iLine = display; -+ unsigned char *oLine = buffer; -+ -+ for (int x = 0; x < iWidth; ++x, iLine += 4, oLine += 8 ) -+ { -+ u = iLine[0]-128; -+ y0 = iLine[1]-16; -+ v = iLine[2]-128; -+ y1 = iLine[3]-16; -+ -+ a = 255-oLine[3]; -+ r = (cy*y0 + cb1*u + cr1*v) >> 16; -+ g = (cy*y0 + cb2*u + cr2*v) >> 16; -+ b = (cy*y0 + cb3*u + cr3*v) >> 16; -+ -+ oLine[0] = (clamp_byte(b)*a + oLine[0]*oLine[3])/255; -+ oLine[1] = (clamp_byte(g)*a + oLine[1]*oLine[3])/255; -+ oLine[2] = (clamp_byte(r)*a + oLine[2]*oLine[3])/255; -+ oLine[3] = 255; -+ -+ a = 255-oLine[7]; -+ r = (cy*y0 + cb1*u + cr1*v) >> 16; -+ g = (cy*y0 + cb2*u + cr2*v) >> 16; -+ b = (cy*y0 + cb3*u + cr3*v) >> 16; -+ -+ oLine[4] = (clamp_byte(b)*a + oLine[4]*oLine[7])/255; -+ oLine[5] = (clamp_byte(g)*a + oLine[5]*oLine[7])/255; -+ oLine[6] = (clamp_byte(r)*a + oLine[6]*oLine[7])/255; -+ oLine[7] = 255; -+ } -+ } -+} -+ -+bool CIMXContext::PushTask(const IPUTask &task) -+{ -+ if (!task.current) -+ return false; -+ -+ CSingleLock lk(m_monitor); -+ -+ if (m_bStop) -+ { -+ m_inputNotEmpty.notifyAll(); -+ return false; -+ } -+ -+ // 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(); -+ return false; -+ } -+ -+ // Store the value -+ if (task.previous) task.previous->Lock(); -+ task.current->Lock(); -+ -+ memcpy(&m_input[m_endInput], &task, sizeof(IPUTask)); -+ m_endInput = (m_endInput+1) % m_input.size(); -+ ++m_bufferedInput; -+ m_inputNotEmpty.notifyAll(); -+ -+ return true; -+} -+ -+void CIMXContext::PrepareTask(IPUTask &ipu, CIMXBuffer *source_p, CIMXBuffer *source, -+ bool topBottomFields) -+{ -+ // Fill with zeros -+ ipu.Zero(); -+ ipu.previous = source_p; -+ ipu.current = source; -+ -+ CRect srcRect = m_srcRect; -+ CRect dstRect = m_dstRect; -+ CRectInt iSrcRect, iDstRect; -+ -+ float srcWidth = srcRect.Width(); -+ float srcHeight = srcRect.Height(); -+ float dstWidth = dstRect.Width(); -+ float dstHeight = dstRect.Height(); -+ -+ // Project coordinates outside the target buffer rect to -+ // the source rect otherwise the IPU task will fail -+ // This is under the assumption that the srcRect is always -+ // inside the input buffer rect. If that is not the case -+ // it needs to be projected to the ouput buffer rect as well -+ if (dstRect.x1 < 0) -+ { -+ srcRect.x1 -= dstRect.x1*srcWidth / dstWidth; -+ dstRect.x1 = 0; -+ } -+ if (dstRect.x2 > m_fbWidth) -+ { -+ srcRect.x2 -= (dstRect.x2-m_fbWidth)*srcWidth / dstWidth; -+ dstRect.x2 = m_fbWidth; -+ } -+ if (dstRect.y1 < 0) -+ { -+ srcRect.y1 -= dstRect.y1*srcHeight / dstHeight; -+ dstRect.y1 = 0; -+ } -+ if (dstRect.y2 > m_fbHeight) -+ { -+ srcRect.y2 -= (dstRect.y2-m_fbHeight)*srcHeight / dstHeight; -+ dstRect.y2 = m_fbHeight; -+ } -+ -+ iSrcRect.x1 = Align((int)srcRect.x1,8); -+ iSrcRect.y1 = Align((int)srcRect.y1,8); -+ iSrcRect.x2 = Align((int)srcRect.x2,8); -+ iSrcRect.y2 = Align((int)srcRect.y2,8); -+ -+ iDstRect.x1 = Align((int)dstRect.x1,8); -+ iDstRect.y1 = Align((int)dstRect.y1,8); -+ iDstRect.x2 = Align((int)dstRect.x2,8); -+ iDstRect.y2 = Align((int)dstRect.y2,8); -+ -+ ipu.task.input.crop.pos.x = iSrcRect.x1; -+ ipu.task.input.crop.pos.y = iSrcRect.y1; -+ ipu.task.input.crop.w = iSrcRect.Width(); -+ ipu.task.input.crop.h = iSrcRect.Height(); -+ -+ ipu.task.output.crop.pos.x = iDstRect.x1; -+ ipu.task.output.crop.pos.y = iDstRect.y1; -+ ipu.task.output.crop.w = iDstRect.Width(); -+ ipu.task.output.crop.h = iDstRect.Height(); -+ -+ // Setup deinterlacing if enabled -+ if (m_deInterlacing) -+ { -+ ipu.task.input.deinterlace.enable = 1; -+ /* -+ if (source_p) -+ { -+ task.input.deinterlace.motion = MED_MOTION; -+ task.input.paddr = source_p->pPhysAddr; -+ task.input.paddr_n = source->pPhysAddr; -+ } -+ else -+ */ -+ ipu.task.input.deinterlace.motion = HIGH_MOTION; -+ ipu.task.input.deinterlace.field_fmt = m_currentFieldFmt; -+ -+ if (topBottomFields) -+ ipu.task.input.deinterlace.field_fmt |= IPU_DEINTERLACE_FIELD_TOP; -+ else -+ ipu.task.input.deinterlace.field_fmt |= IPU_DEINTERLACE_FIELD_BOTTOM; -+ } -+} -+ -+bool CIMXContext::DoTask(IPUTask &ipu, int targetPage) -+{ -+ // Clear page if cropping changes -+ CRectInt dstRect(ipu.task.output.crop.pos.x, ipu.task.output.crop.pos.y, -+ ipu.task.output.crop.pos.x + ipu.task.output.crop.w, -+ ipu.task.output.crop.pos.y + ipu.task.output.crop.h); -+ -+ // Populate input block -+ ipu.task.input.width = ipu.current->iWidth; -+ ipu.task.input.height = ipu.current->iHeight; -+ ipu.task.input.format = ipu.current->iFormat; -+ ipu.task.input.paddr = ipu.current->pPhysAddr; -+ -+ // Populate output block -+ ipu.task.output.width = m_fbWidth; -+ ipu.task.output.height = m_fbHeight; -+ ipu.task.output.format = m_fbVar.nonstd; -+ ipu.task.output.paddr = m_fbPhysAddr + targetPage*m_fbPageSize; -+ -+ if (m_pageCrops[targetPage] != dstRect) -+ { -+ m_pageCrops[targetPage] = dstRect; -+ Clear(targetPage); -+ } -+ -+ if ((ipu.task.input.crop.w <= 0) || (ipu.task.input.crop.h <= 0) -+ || (ipu.task.output.crop.w <= 0) || (ipu.task.output.crop.h <= 0)) -+ return false; -+ -+#ifdef IMX_PROFILE_BUFFERS -+ unsigned long long before = XbmcThreads::SystemClockMillis(); - #endif -+ -+ int ret = IPU_CHECK_ERR_INPUT_CROP; -+ while (ret != IPU_CHECK_OK && ret > IPU_CHECK_ERR_MIN) -+ { -+ ret = ioctl(m_ipuHandle, IPU_CHECK_TASK, &ipu.task); -+ switch (ret) -+ { -+ case IPU_CHECK_OK: -+ break; -+ case IPU_CHECK_ERR_SPLIT_INPUTW_OVER: -+ ipu.task.input.crop.w -= 8; -+ break; -+ case IPU_CHECK_ERR_SPLIT_INPUTH_OVER: -+ ipu.task.input.crop.h -= 8; -+ break; -+ case IPU_CHECK_ERR_SPLIT_OUTPUTW_OVER: -+ ipu.task.output.crop.w -= 8; -+ break; -+ case IPU_CHECK_ERR_SPLIT_OUTPUTH_OVER: -+ ipu.task.output.crop.h -= 8; -+ break; -+ default: -+ CLog::Log(LOGWARNING, "iMX : unhandled IPU check error: %d\n", ret); -+ return false; -+ } -+ } -+ -+ // Need to find another interface to protect ipu.current from disposing -+ // in CDVDVideoCodecIMX::Dispose. CIMXContext must not have knowledge -+ // about CDVDVideoCodecIMX. -+ CDVDVideoCodecIMX::Enter(); -+ if (ipu.current->IsValid()) -+ ret = ioctl(m_ipuHandle, IPU_QUEUE_TASK, &ipu.task); -+ else -+ ret = 0; -+ CDVDVideoCodecIMX::Leave(); -+ -+ if (ret < 0) -+ { -+ CLog::Log(LOGERROR, "IPU task failed: %s\n", strerror(errno)); -+ return false; -+ } -+ -+ // Duplicate 2nd scandline if double rate is active -+ if (ipu.task.input.deinterlace.field_fmt & IPU_DEINTERLACE_RATE_EN) -+ { -+ uint8_t *pageAddr = m_fbVirtAddr + targetPage*m_fbPageSize; -+ memcpy(pageAddr, pageAddr+m_fbLineLength, m_fbLineLength); -+ } -+ -+#ifdef IMX_PROFILE_BUFFERS -+ unsigned long long after = XbmcThreads::SystemClockMillis(); -+ printf("+P %f %d\n", ((CDVDVideoCodecIMXBuffer*)ipu.current)->GetPts(), (int)(after-before)); -+#endif -+ -+ return true; -+} -+ -+void CIMXContext::OnStartup() -+{ -+ CLog::Log(LOGNOTICE, "iMX : IPU thread started"); -+} -+ -+void CIMXContext::OnExit() -+{ -+ CLog::Log(LOGNOTICE, "iMX : IPU thread terminated"); -+} -+ -+void CIMXContext::StopThread(bool bWait /*= true*/) -+{ -+ CThread::StopThread(false); -+ m_inputNotFull.notifyAll(); -+ m_inputNotEmpty.notifyAll(); -+ if (bWait) -+ CThread::StopThread(true); -+} -+ -+void CIMXContext::Process() -+{ -+ bool ret, useBackBuffer; -+ int backBuffer; -+ -+ while (!m_bStop) -+ { -+ { -+ CSingleLock lk(m_monitor); -+ while (!m_bufferedInput && !m_bStop) -+ m_inputNotEmpty.wait(lk); -+ -+ if (m_bStop) break; -+ -+ useBackBuffer = m_vsync; -+ IPUTask &task = m_input[m_beginInput]; -+ backBuffer = useBackBuffer?1-m_fbCurrentPage:m_fbCurrentPage; -+ ret = DoTask(task, backBuffer); -+ -+ // Free resources -+ task.Done(); -+ -+ m_beginInput = (m_beginInput+1) % m_input.size(); -+ --m_bufferedInput; -+ m_inputNotFull.notifyAll(); -+ } -+ -+ // Show back buffer -+ if (useBackBuffer && ret) ShowPage(backBuffer); -+ } -+ -+ // Mark all pending jobs as done -+ CSingleLock lk(m_monitor); -+ while (m_bufferedInput > 0) -+ { -+ m_input[m_beginInput].Done(); -+ m_beginInput = (m_beginInput+1) % m_input.size(); -+ --m_bufferedInput; -+ } -+ -+ return; - } -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h -index 6533683..50d9efa 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h -@@ -18,17 +18,198 @@ - * . - * - */ --#include --#include --#include "DVDVideoCodec.h" --#include "DVDStreamInfo.h" -+ - #include "threads/CriticalSection.h" -+#include "threads/Condition.h" -+#include "threads/Thread.h" - #include "utils/BitstreamConverter.h" -+#include "guilib/Geometry.h" -+#include "DVDVideoCodec.h" -+#include "DVDStreamInfo.h" -+ -+#include -+#include -+#include -+#include -+ -+ -+// The decoding format of the VPU buffer. Comment this to decode -+// as NV12. The VPU works faster with NV12 in combination with -+// deinterlacing. -+// Progressive content seems to be handled faster with I420 whereas -+// interlaced content is processed faster with NV12 as output format. -+//#define IMX_INPUT_FORMAT_I420 - -+// This enables logging of times for Decode, Render->Render, -+// 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 - -+// If uncommented a file "stream.dump" will be created in the current -+// directory whenever a new stream is started. This is only for debugging -+// and performance tests. This define must never be active in distributions. -+//#define DUMP_STREAM -+ -+ -+/*>> TO BE MOVED TO A MORE CENTRAL PLACE IN THE SOURCE DIR >>>>>>>>>>>>>>>>>>>*/ -+// Generell description of a buffer used by -+// the IMX context, e.g. for blitting -+class CIMXBuffer { -+public: -+ CIMXBuffer() : m_iRefs(0) {} -+ -+ // Shared pointer interface -+ virtual void Lock() = 0; -+ virtual long Release() = 0; -+ virtual bool IsValid() = 0; -+ -+public: -+ uint32_t iWidth; -+ uint32_t iHeight; -+ int pPhysAddr; -+ uint8_t *pVirtAddr; -+ int iFormat; -+ -+protected: -+ long m_iRefs; -+}; -+ -+ -+// iMX context class that handles all iMX hardware -+// related stuff -+class CIMXContext : private CThread -+{ -+public: -+ CIMXContext(); -+ ~CIMXContext(); -+ -+ bool Configure(int pages = 2); -+ bool Close(); -+ -+ bool Blank(); -+ bool Unblank(); -+ bool SetVSync(bool enable); -+ -+ bool IsValid() const { return m_fbPages > 0; } -+ -+ // Returns the number of available pages -+ int PageCount() const { return m_fbPages; } -+ -+ // Populates a CIMXBuffer with attributes of a page -+ bool GetPageInfo(CIMXBuffer *info, int page); -+ -+ // Blitter configuration -+ void SetDeInterlacing(bool flag); -+ void SetDoubleRate(bool flag); -+ bool DoubleRate() const; -+ void SetInterpolatedFrame(bool flag); -+ -+ void SetBlitRects(const CRect &srcRect, const CRect &dstRect); -+ -+ // Blits a buffer to a particular page. -+ // source_p (previous buffer) is required for de-interlacing -+ // modes LOW_MOTION and MED_MOTION. -+ bool Blit(int targetPage, CIMXBuffer *source_p, -+ CIMXBuffer *source, -+ bool topBottomFields = true); -+ -+ // Same as blit but runs in another thread and returns after the task has -+ // been queued. BlitAsync renders always to the current backbuffer and -+ // swaps the pages. -+ bool BlitAsync(CIMXBuffer *source_p, CIMXBuffer *source, -+ bool topBottomFields = true); -+ -+ // Shows a page vsynced -+ bool ShowPage(int page); -+ -+ // Returns the visible page -+ int GetCurrentPage() const { return m_fbCurrentPage; } -+ -+ // Clears the pages or a single page with 'black' -+ void Clear(int page = -1); -+ -+ // Captures the current visible frame buffer page and blends it into -+ // the passed overlay. The buffer format is BGRA (4 byte) -+ void CapureDisplay(unsigned char *buffer, int iWidth, int iHeight); -+ -+private: -+ struct IPUTask -+ { -+ void Zero() -+ { -+ current = previous = NULL; -+ memset(&task, 0, sizeof(task)); -+ } -+ -+ void Done() -+ { -+ SAFE_RELEASE(previous); -+ SAFE_RELEASE(current); -+ } -+ -+ // Kept for reference -+ CIMXBuffer *previous; -+ CIMXBuffer *current; -+ -+ // The actual task -+ struct ipu_task task; -+ }; -+ -+ bool PushTask(const IPUTask &); -+ void PrepareTask(IPUTask &ipu, CIMXBuffer *source_p, CIMXBuffer *source, -+ bool topBottomFields); -+ bool DoTask(IPUTask &ipu, int targetPage); -+ -+ virtual void OnStartup(); -+ virtual void OnExit(); -+ virtual void StopThread(bool bWait = true); -+ virtual void Process(); -+ -+private: -+ typedef std::vector TaskQueue; -+ -+ int m_fbHandle; -+ int m_fbPages; -+ int m_fbCurrentPage; -+ int m_fbWidth; -+ int m_fbHeight; -+ int m_fbLineLength; -+ int m_fbPageSize; -+ int m_fbPhysSize; -+ int m_fbPhysAddr; -+ uint8_t *m_fbVirtAddr; -+ struct fb_var_screeninfo m_fbVar; -+ int m_ipuHandle; -+ int m_currentFieldFmt; -+ bool m_vsync; -+ bool m_deInterlacing; -+ CRect m_srcRect; -+ CRect m_dstRect; -+ CRectInt m_inputRect; -+ CRectInt m_outputRect; -+ CRectInt *m_pageCrops; -+ -+ CCriticalSection m_pageSwapLock; -+ TaskQueue m_input; -+ volatile int m_beginInput, m_endInput; -+ volatile size_t m_bufferedInput; -+ XbmcThreads::ConditionVariable m_inputNotEmpty; -+ XbmcThreads::ConditionVariable m_inputNotFull; -+ mutable CCriticalSection m_monitor; -+}; -+ -+ -+extern CIMXContext g_IMXContext; -+/*<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ -+ -+ - class CDecMemInfo - { - public: -@@ -40,16 +221,17 @@ public: - {} - - //virtual mem info -- int nVirtNum; -- void** virtMem; -+ int nVirtNum; -+ void **virtMem; - - //phy mem info -- int nPhyNum; -- VpuMemDesc* phyMem; -+ int nPhyNum; -+ VpuMemDesc *phyMem; - }; - --class CDVDVideoCodecIMXBuffer --{ -+ -+// Base class of IMXVPU and IMXIPU buffer -+class CDVDVideoCodecIMXBuffer : public CIMXBuffer { - public: - #ifdef TRACE_FRAMES - CDVDVideoCodecIMXBuffer(int idx); -@@ -57,95 +239,111 @@ public: - CDVDVideoCodecIMXBuffer(); - #endif - -+ void SetPts(double pts); -+ double GetPts() const { return m_pts; } -+ -+ void SetDts(double dts); -+ double GetDts() const { return m_dts; } -+ -+protected: -+#ifdef TRACE_FRAMES -+ int m_idx; -+#endif -+ -+private: -+ double m_pts; -+ double m_dts; -+}; -+ -+ -+class CDVDVideoCodecIMXVPUBuffer : public CDVDVideoCodecIMXBuffer -+{ -+public: -+#ifdef TRACE_FRAMES -+ CDVDVideoCodecIMXVPUBuffer(int idx); -+#else -+ CDVDVideoCodecIMXVPUBuffer(); -+#endif -+ - // reference counting -- virtual void Lock(); -- virtual long Release(); -- virtual bool IsValid(); -- -- bool Rendered() const; -- void Queue(VpuDecOutFrameInfo *frameInfo, -- CDVDVideoCodecIMXBuffer *previous); -- VpuDecRetCode ReleaseFramebuffer(VpuDecHandle *handle); -- void SetPts(double pts); -- double GetPts(void) const; -- CDVDVideoCodecIMXBuffer *GetPreviousBuffer() const; -- -- uint32_t m_iWidth; -- uint32_t m_iHeight; -- uint8_t *m_phyAddr; -- uint8_t *m_VirtAddr; -+ virtual void Lock(); -+ virtual long Release(); -+ virtual bool IsValid(); -+ -+ bool Rendered() const; -+ void Queue(VpuDecOutFrameInfo *frameInfo, -+ CDVDVideoCodecIMXVPUBuffer *previous); -+ VpuDecRetCode ReleaseFramebuffer(VpuDecHandle *handle); -+ CDVDVideoCodecIMXVPUBuffer *GetPreviousBuffer() const { return m_previousBuffer; } -+ VpuFieldType GetFieldType() const { return m_fieldType; } -+ bool IsInterlaced() const { return m_fieldType != VPU_FIELD_NONE; } - - 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; -- double m_pts; -- CDVDVideoCodecIMXBuffer *m_previousBuffer; // Holds a the reference counted -- // previous buffer -+ VpuFieldType m_fieldType; -+ VpuFrameBuffer *m_frameBuffer; -+ bool m_rendered; -+ CDVDVideoCodecIMXVPUBuffer *m_previousBuffer; // Holds a the reference counted -+ // previous buffer - }; - -+ - class CDVDVideoCodecIMX : public CDVDVideoCodec - { -- friend class CDVDVideoCodecIMXBuffer; -- friend class CDVDVideoCodecIPUBuffer; -- - public: - CDVDVideoCodecIMX(); - virtual ~CDVDVideoCodecIMX(); - - // Methods from CDVDVideoCodec which require overrides - virtual bool Open(CDVDStreamInfo &hints, CDVDCodecOptions &options); -- virtual void Dispose(void); -+ virtual void Dispose(); - virtual int Decode(BYTE *pData, int iSize, double dts, double pts); -- virtual void Reset(void); -+ virtual void Reset(); - 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 const char* GetName() { return (const char*)m_pFormatName; } - virtual unsigned GetAllowedReferences(); - - static void Enter(); - static void Leave(); - - protected: -- - bool VpuOpen(); - bool VpuAllocBuffers(VpuMemInfo *); - bool VpuFreeBuffers(); - bool VpuAllocFrameBuffers(); - int VpuFindBuffer(void *frameAddr); - -- static const int m_extraVpuBuffers; // Number of additional buffers for VPU -- static const int m_maxVpuDecodeLoops; // Maximum iterations in VPU decoding loop -- static CCriticalSection m_codecBufferLock; // Lock to protect buffers handled -- // by both decoding and rendering threads -- -- CDVDStreamInfo m_hints; // Hints from demuxer at stream opening -- const char *m_pFormatName; // Current decoder format name -- VpuDecOpenParam m_decOpenParam; // Parameters required to call VPU_DecOpen -- CDecMemInfo m_decMemInfo; // VPU dedicated memory description -- VpuDecHandle m_vpuHandle; // Handle for VPU library calls -- VpuDecInitInfo m_initInfo; // Initial info returned from VPU at decoding start -- bool m_dropState; // Current drop state -- int m_vpuFrameBufferNum; // Total number of allocated frame buffers -- VpuFrameBuffer *m_vpuFrameBuffers; // Table of VPU frame buffers description -- CDVDVideoCodecIMXBuffer **m_outputBuffers; // Table of VPU output buffers -- CDVDVideoCodecIMXBuffer *m_lastBuffer; // Keep track of previous VPU output buffer (needed by deinterlacing motion engin) -- VpuMemDesc *m_extraMem; // Table of allocated extra Memory -- int m_frameCounter; // Decoded frames counter -- bool m_usePTS; // State whether pts out of decoding process should be used -- VpuDecOutFrameInfo m_frameInfo; // Store last VPU output frame info -- CBitstreamConverter *m_converter; // H264 annex B converter -- bool m_convert_bitstream; // State whether bitstream conversion is required -- int m_bytesToBeConsumed; // Remaining bytes in VPU -- double m_previousPts; // Enable to keep pts when needed -- bool m_frameReported; // State whether the frame consumed event will be reported by libfslvpu -- double m_dts; // Current dts -+ 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 -+ static CCriticalSection m_codecBufferLock; // Lock to protect buffers handled -+ 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 -+ CDVDVideoCodecIMXVPUBuffer **m_outputBuffers; // Table of VPU output buffers -+ CDVDVideoCodecIMXVPUBuffer *m_lastBuffer; // Keep track of previous VPU output buffer (needed by deinterlacing motion engin) -+ CDVDVideoCodecIMXVPUBuffer *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 -+#ifdef DUMP_STREAM -+ FILE *m_dump; -+#endif - }; -diff --git a/xbmc/guilib/GUIVideoControl.cpp b/xbmc/guilib/GUIVideoControl.cpp -index 126e95f..2b8c2cf 100644 ---- a/xbmc/guilib/GUIVideoControl.cpp -+++ b/xbmc/guilib/GUIVideoControl.cpp -@@ -77,7 +77,11 @@ void CGUIVideoControl::Render() - region.Intersect(old); - g_graphicsContext.BeginPaint(); - g_graphicsContext.SetScissors(region); -+#ifdef HAS_IMXVPU -+ g_graphicsContext.Clear((16 << 16)|(8 << 8)|16); -+#else - g_graphicsContext.Clear(0); -+#endif - g_graphicsContext.SetScissors(old); - g_graphicsContext.EndPaint(); - } -diff --git a/xbmc/guilib/GUIWindow.h b/xbmc/guilib/GUIWindow.h -index af82934..0e05493 100644 ---- a/xbmc/guilib/GUIWindow.h -+++ b/xbmc/guilib/GUIWindow.h -@@ -101,7 +101,7 @@ public: - /*! \brief Do any post render activities. - Check if window closing animation is finished and finalize window closing. - */ -- void AfterRender(); -+ virtual void AfterRender(); - - /*! \brief Main update function, called every frame prior to rendering - Any window that requires updating on a frame by frame basis (such as to maintain -diff --git a/xbmc/guilib/GUIWindowManager.cpp b/xbmc/guilib/GUIWindowManager.cpp -index ef97251..fe2080e 100644 ---- a/xbmc/guilib/GUIWindowManager.cpp -+++ b/xbmc/guilib/GUIWindowManager.cpp -@@ -539,7 +539,7 @@ void CGUIWindowManager::RenderPass() const - // we render the dialogs based on their render order. - vector renderList = m_activeDialogs; - stable_sort(renderList.begin(), renderList.end(), RenderOrderSortFunction); -- -+ - for (iDialog it = renderList.begin(); it != renderList.end(); ++it) - { - if ((*it)->IsDialogRunning()) -diff --git a/xbmc/settings/VideoSettings.h b/xbmc/settings/VideoSettings.h -index 6eaef1d..8644250 100644 ---- a/xbmc/settings/VideoSettings.h -+++ b/xbmc/settings/VideoSettings.h -@@ -72,6 +72,9 @@ enum EINTERLACEMETHOD - VS_INTERLACEMETHOD_MMAL_BOB = 27, - VS_INTERLACEMETHOD_MMAL_BOB_HALF = 28, - -+ VS_INTERLACEMETHOD_IMX_FASTMOTION = 29, -+ VS_INTERLACEMETHOD_IMX_FASTMOTION_DOUBLE = 30, -+ - VS_INTERLACEMETHOD_MAX // do not use and keep as last enum value. - }; - -diff --git a/xbmc/utils/Screenshot.cpp b/xbmc/utils/Screenshot.cpp -index db73d4a..35a586e 100644 ---- a/xbmc/utils/Screenshot.cpp -+++ b/xbmc/utils/Screenshot.cpp -@@ -37,6 +37,11 @@ - #include "cores/VideoRenderers/RenderManager.h" - #endif - -+#ifdef HAS_IMXVPU -+// This has to go into another header file -+#include "cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h" -+#endif -+ - #include "filesystem/File.h" - #include "guilib/GraphicContext.h" - -@@ -156,13 +161,19 @@ bool CScreenshotSurface::capture() - for (int x = 0; x < m_width; x++, swap_pixels+=4) - { - std::swap(swap_pixels[0], swap_pixels[2]); -- } -+ } - #endif - memcpy(m_buffer + y * m_stride, surface + (m_height - y - 1) *m_stride, m_stride); - } - - delete [] surface; - -+#ifdef HAS_IMXVPU -+ // Captures the current visible framebuffer page and blends it into the -+ // captured GL overlay -+ g_IMXContext.CapureDisplay(m_buffer, m_width, m_height); -+#endif -+ - #else - //nothing to take a screenshot from - return false; -diff --git a/xbmc/video/dialogs/GUIDialogVideoSettings.cpp b/xbmc/video/dialogs/GUIDialogVideoSettings.cpp -index ca65fdc..d350a02 100644 ---- a/xbmc/video/dialogs/GUIDialogVideoSettings.cpp -+++ b/xbmc/video/dialogs/GUIDialogVideoSettings.cpp -@@ -266,6 +266,8 @@ void CGUIDialogVideoSettings::InitializeSettings() - entries.push_back(make_pair(16331, VS_INTERLACEMETHOD_MMAL_ADVANCED_HALF)); - entries.push_back(make_pair(16332, VS_INTERLACEMETHOD_MMAL_BOB)); - entries.push_back(make_pair(16333, VS_INTERLACEMETHOD_MMAL_BOB_HALF)); -+ entries.push_back(make_pair(16334, VS_INTERLACEMETHOD_IMX_FASTMOTION)); -+ entries.push_back(make_pair(16335, VS_INTERLACEMETHOD_IMX_FASTMOTION_DOUBLE)); - - /* remove unsupported methods */ - for (StaticIntegerSettingOptions::iterator it = entries.begin(); it != entries.end(); ) -diff --git a/xbmc/video/windows/GUIWindowFullScreen.cpp b/xbmc/video/windows/GUIWindowFullScreen.cpp -index ed7c090..e9beff7 100644 ---- a/xbmc/video/windows/GUIWindowFullScreen.cpp -+++ b/xbmc/video/windows/GUIWindowFullScreen.cpp -@@ -284,7 +284,7 @@ bool CGUIWindowFullScreen::OnAction(const CAction &action) - CStdString strChannel = StringUtils::Format("%i", action.GetID() - REMOTE_0); - if (CGUIDialogNumeric::ShowAndGetNumber(strChannel, g_localizeStrings.Get(19000))) - iChannelNumber = atoi(strChannel.c_str()); -- -+ - if (iChannelNumber > 0) - g_application.OnAction(CAction(ACTION_CHANNEL_SWITCH, (float)iChannelNumber)); - } -@@ -356,7 +356,11 @@ bool CGUIWindowFullScreen::OnAction(const CAction &action) - void CGUIWindowFullScreen::ClearBackground() - { - if (g_renderManager.IsVideoLayer()) -+#ifdef HAS_IMXVPU -+ g_graphicsContext.Clear((16 << 16)|(8 << 8)|16); -+#else - g_graphicsContext.Clear(0); -+#endif - } - - void CGUIWindowFullScreen::OnWindowLoaded() -diff --git a/xbmc/windowing/egl/EGLNativeTypeIMX.cpp b/xbmc/windowing/egl/EGLNativeTypeIMX.cpp -index 04cadc8..2b8180b 100644 ---- a/xbmc/windowing/egl/EGLNativeTypeIMX.cpp -+++ b/xbmc/windowing/egl/EGLNativeTypeIMX.cpp -@@ -25,6 +25,7 @@ - #include - #include - #include -+#include - #include "utils/log.h" - #include "utils/RegExp.h" - #include "utils/StringUtils.h" -@@ -54,6 +55,40 @@ void CEGLNativeTypeIMX::Initialize() - { - int 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\n", __FUNCTION__); -+ m_readonly = false; -+ } -+ else -+ { -+ CLog::Log(LOGNOTICE, "%s - graphics sysfs is read-only\n", __FUNCTION__); -+ m_readonly = true; -+ } -+ close(fd); -+ -+ bool alphaBlending = false; -+ std::string bpp; -+ if (SysfsUtils::GetString("/sys/class/graphics/fb0/bits_per_pixel", bpp)) -+ { -+ CLog::Log(LOGWARNING, "%s - determining current bits per pixel failed, assuming 16bpp\n", __FUNCTION__); -+ } -+ else -+ { -+ StringUtils::Trim(bpp); -+ if (bpp == "32") -+ { -+ CLog::Log(LOGNOTICE, "%s - 32bpp: configure alpha blending\n", __FUNCTION__); -+ alphaBlending = true; -+ } -+ else -+ { -+ CLog::Log(LOGNOTICE, "%s - %sbpp: configure color keying\n", __FUNCTION__, bpp.c_str()); -+ } -+ } -+ - fd = open("/dev/fb0",O_RDWR); - if (fd < 0) - { -@@ -61,6 +96,27 @@ void CEGLNativeTypeIMX::Initialize() - return; - } - -+ struct mxcfb_color_key colorKey; -+ struct mxcfb_gbl_alpha gbl_alpha; -+ struct mxcfb_loc_alpha lalpha; -+ memset(&lalpha, 0, sizeof(lalpha)); -+ -+ // Configure local alpha -+ lalpha.enable = alphaBlending?1:0; -+ lalpha.alpha_in_pixel = 1; -+ if (ioctl(fd, MXCFB_SET_LOC_ALPHA, &lalpha) < 0) -+ CLog::Log(LOGERROR, "%s - Failed to setup alpha blending\n", __FUNCTION__); -+ -+ gbl_alpha.alpha = 255; -+ gbl_alpha.enable = alphaBlending?0:1; -+ if (ioctl(fd, MXCFB_SET_GBL_ALPHA, &gbl_alpha) < 0) -+ CLog::Log(LOGERROR, "%s - Failed to setup global alpha\n", __FUNCTION__); -+ -+ colorKey.enable = alphaBlending?0:1; -+ colorKey.color_key = (16 << 16)|(8 << 8)|16; -+ if (ioctl(fd, MXCFB_SET_CLR_KEY, &colorKey) < 0) -+ CLog::Log(LOGERROR, "%s - Failed to setup color keying\n", __FUNCTION__); -+ - // Unblank the fb - if (ioctl(fd, FBIOBLANK, 0) < 0) - { -@@ -69,20 +125,6 @@ void CEGLNativeTypeIMX::Initialize() - - 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; - } - -diff --git a/xbmc/windowing/egl/WinSystemEGL.cpp b/xbmc/windowing/egl/WinSystemEGL.cpp -index 2bdd4fa..dec2ba9 100644 ---- a/xbmc/windowing/egl/WinSystemEGL.cpp -+++ b/xbmc/windowing/egl/WinSystemEGL.cpp -@@ -31,6 +31,10 @@ - #include "settings/DisplaySettings.h" - #include "guilib/DispResource.h" - #include "threads/SingleLock.h" -+#ifdef HAS_IMXVPU -+// This has to go into another header file -+#include "cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h" -+#endif - #include "utils/log.h" - #include "EGLWrapper.h" - #include "EGLQuirks.h" -@@ -266,7 +270,7 @@ bool CWinSystemEGL::CreateNewWindow(const CStdString& name, bool fullScreen, RES - RESOLUTION_INFO current_resolution; - current_resolution.iWidth = current_resolution.iHeight = 0; - -- m_nWidth = res.iWidth; -+ m_nWidth = res.iWidth; - m_nHeight = res.iHeight; - m_displayWidth = res.iScreenWidth; - m_displayHeight = res.iScreenHeight; -@@ -450,6 +454,9 @@ void CWinSystemEGL::SetVSyncImpl(bool enable) - m_iVSyncMode = 0; - CLog::Log(LOGERROR, "%s,Could not set egl vsync", __FUNCTION__); - } -+#ifdef HAS_IMXVPU -+ g_IMXContext.SetVSync(enable); -+#endif - } - - void CWinSystemEGL::ShowOSMouse(bool show) --- -1.9.1 - diff --git a/projects/imx6/patches/kodi/kodi-999.96-iMX6-disable-deinterlace-by-default.patch b/projects/imx6/patches/kodi/kodi-999.96-iMX6-disable-deinterlace-by-default.patch new file mode 100644 index 0000000000..806079144f --- /dev/null +++ b/projects/imx6/patches/kodi/kodi-999.96-iMX6-disable-deinterlace-by-default.patch @@ -0,0 +1,26 @@ +From 467c583ca00c3512d93745ae6bee7ae26ebcb13e Mon Sep 17 00:00:00 2001 +From: fritsch +Date: Sun, 21 Dec 2014 12:58:30 +0100 +Subject: [PATCH] IMX: Disable deinterlacing by default (user can enable it if + he wants) + +--- + xbmc/settings/VideoSettings.cpp | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/xbmc/settings/VideoSettings.cpp b/xbmc/settings/VideoSettings.cpp +index 65105e8..e61f49a 100644 +--- a/xbmc/settings/VideoSettings.cpp ++++ b/xbmc/settings/VideoSettings.cpp +@@ -29,7 +29,7 @@ + + CVideoSettings::CVideoSettings() + { +- m_DeinterlaceMode = VS_DEINTERLACEMODE_AUTO; ++ m_DeinterlaceMode = VS_DEINTERLACEMODE_OFF; + m_InterlaceMethod = VS_INTERLACEMETHOD_AUTO; + m_ScalingMethod = VS_SCALINGMETHOD_LINEAR; + m_ViewMode = ViewModeNormal; +-- +1.9.1 +