Files
LibreELEC.tv/packages/mediacenter/kodi/patches/kodi-999.92-PR5805-v2.patch
Stephan Raue 521df499e1 kodi: add PR5805
Signed-off-by: Stephan Raue <stephan@openelec.tv>
2014-12-09 20:58:07 +01:00

2743 lines
91 KiB
Diff

From d1d19f8d0a69f751b03a97ef0f546564527a7caa Mon Sep 17 00:00:00 2001
From: smallint <tahoma@gmx.de>
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 <tahoma@gmx.de>
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 <tahoma@gmx.de>
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 <tahoma@gmx.de>
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 <tahoma@gmx.de>
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 <tahoma@gmx.de>
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 <sys/ioctl.h>
#include <unistd.h>
#include <sys/mman.h>
+#include <linux/mxcfb.h>
+#include <linux/ipu.h>
+#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 <queue>
+#include <vector>
#include <imx-mm/vpu/vpu_wrapper.h>
#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<CDVDVideoCodecIMXVPUBuffer*> InputBuffers;
+ typedef std::vector<CDVDVideoCodecIMXBuffer*> 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 <tahoma@gmx.de>
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 <tahoma@gmx.de>
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 <tahoma@gmx.de>
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, &param);
+ 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, &param);
+ 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 <tahoma@gmx.de>
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 <tahoma@gmx.de>
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 <tahoma@gmx.de>
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<int> 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; i<m_vpuFrameBufferNum; i++)
@@ -579,8 +580,6 @@ void CDVDVideoCodecIMX::Dispose(void)
SAFE_RELEASE(m_outputBuffers[i]);
}
- Leave();
-
if (m_vpuHandle)
{
ret = VPU_DecFlushAll(m_vpuHandle);
@@ -648,6 +647,8 @@ int CDVDVideoCodecIMX::Decode(BYTE *pData, int iSize, double dts, double pts)
unsigned long long before_dec;
#endif
+ SAFE_RELEASE(m_currentBuffer);
+
if (!m_vpuHandle)
{
VpuOpen();
@@ -704,6 +705,10 @@ 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
@@ -711,7 +716,11 @@ int CDVDVideoCodecIMX::Decode(BYTE *pData, int iSize, double dts, double pts)
#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;
+#endif
#ifdef IMX_PROFILE
CLog::Log(LOGDEBUG, "%s - VPU dec 0x%x decode takes : %lld\n\n", __FUNCTION__, decRet, XbmcThreads::SystemClockMillis() - before_dec);
#endif
@@ -802,14 +811,64 @@ 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);
- 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 <tahoma@gmx.de>
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 <tahoma@gmx.de>
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 <tahoma@gmx.de>
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 <tahoma@gmx.de>
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 <tahoma@gmx.de>
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 <tahoma@gmx.de>
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();