From 900434a9b5f7262191e342f2537b23a039b636a9 Mon Sep 17 00:00:00 2001 From: Stephan Raue Date: Wed, 19 Feb 2014 23:02:57 +0100 Subject: [PATCH] projects/Cuboxi/patches/xbmc: update IMX6 patch Signed-off-by: Stephan Raue --- .../patches/xbmc/xbmc-001-imx6_support.patch | 3473 +++++------------ 1 file changed, 979 insertions(+), 2494 deletions(-) diff --git a/projects/Cuboxi/patches/xbmc/xbmc-001-imx6_support.patch b/projects/Cuboxi/patches/xbmc/xbmc-001-imx6_support.patch index 3573cd652c..4e7f6c9b7f 100644 --- a/projects/Cuboxi/patches/xbmc/xbmc-001-imx6_support.patch +++ b/projects/Cuboxi/patches/xbmc/xbmc-001-imx6_support.patch @@ -1,7 +1,7 @@ -diff -Naur xbmc-gotham-latest.test/configure.in xbmc-wolfgar-imx-wip.test/configure.in ---- xbmc-gotham-latest.test/configure.in 2014-02-09 01:41:42.290169158 +0100 -+++ xbmc-wolfgar-imx-wip.test/configure.in 2014-02-09 01:40:43.539103171 +0100 -@@ -555,7 +555,7 @@ +diff -Naur xbmc-gotham-latest.test/configure.in xbmc-imx6.test/configure.in +--- xbmc-gotham-latest.test/configure.in 2014-02-19 22:25:08.062516204 +0100 ++++ xbmc-imx6.test/configure.in 2014-02-19 22:25:22.740529992 +0100 +@@ -558,7 +558,7 @@ AC_ARG_ENABLE([codec], [AS_HELP_STRING([--enable-codec], @@ -10,7 +10,7 @@ diff -Naur xbmc-gotham-latest.test/configure.in xbmc-wolfgar-imx-wip.test/config [add_codecs=$enableval], [add_codecs=no]) -@@ -1985,6 +1985,17 @@ +@@ -1993,6 +1993,17 @@ *libstagefright*) XB_ADD_CODEC([LIBSTAGEFRIGHT], [libstagefright], [$codecs]) ;; @@ -28,17 +28,9 @@ diff -Naur xbmc-gotham-latest.test/configure.in xbmc-wolfgar-imx-wip.test/config *) esac done -@@ -2663,6 +2674,7 @@ - AC_SUBST(GNUTLS_ALL_LIBS) - AC_SUBST(VORBISENC_ALL_LIBS) - -+ - # pushd and popd are not available in other shells besides bash, so implement - # our own pushd/popd functions - XB_DIRSTACK="$PWD" -diff -Naur xbmc-gotham-latest.test/lib/ffmpeg/libavcodec/arm/dca.h xbmc-wolfgar-imx-wip.test/lib/ffmpeg/libavcodec/arm/dca.h ---- xbmc-gotham-latest.test/lib/ffmpeg/libavcodec/arm/dca.h 2014-02-09 01:41:27.311152362 +0100 -+++ xbmc-wolfgar-imx-wip.test/lib/ffmpeg/libavcodec/arm/dca.h 2014-02-09 01:40:36.140094843 +0100 +diff -Naur xbmc-gotham-latest.test/lib/ffmpeg/libavcodec/arm/dca.h xbmc-imx6.test/lib/ffmpeg/libavcodec/arm/dca.h +--- xbmc-gotham-latest.test/lib/ffmpeg/libavcodec/arm/dca.h 2014-02-19 22:24:57.603506380 +0100 ++++ xbmc-imx6.test/lib/ffmpeg/libavcodec/arm/dca.h 2014-02-19 22:25:22.019529315 +0100 @@ -30,9 +30,9 @@ #define decode_blockcodes decode_blockcodes @@ -56,9 +48,9 @@ diff -Naur xbmc-gotham-latest.test/lib/ffmpeg/libavcodec/arm/dca.h xbmc-wolfgar- #endif /* AVCODEC_ARM_DCA_H */ + -diff -Naur xbmc-gotham-latest.test/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp xbmc-wolfgar-imx-wip.test/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp ---- xbmc-gotham-latest.test/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp 2014-02-09 01:41:15.200138764 +0100 -+++ xbmc-wolfgar-imx-wip.test/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp 2014-02-09 01:40:26.161083601 +0100 +diff -Naur xbmc-gotham-latest.test/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp xbmc-imx6.test/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp +--- xbmc-gotham-latest.test/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp 2014-02-19 22:24:45.699495198 +0100 ++++ xbmc-imx6.test/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp 2014-02-19 22:25:21.467528797 +0100 @@ -714,7 +714,10 @@ * will automatically add "@" instead to enable surroundXX mangling. * We don't want to do that if "default" can handle multichannel @@ -104,9 +96,9 @@ diff -Naur xbmc-gotham-latest.test/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp x if (name.substr(0, 4) == "hdmi") return AE_DEVTYPE_HDMI; else if (name.substr(0, 6) == "iec958" || name.substr(0, 5) == "spdif") -diff -Naur xbmc-gotham-latest.test/xbmc/cores/AudioEngine/Utils/AEConvert.cpp xbmc-wolfgar-imx-wip.test/xbmc/cores/AudioEngine/Utils/AEConvert.cpp ---- xbmc-gotham-latest.test/xbmc/cores/AudioEngine/Utils/AEConvert.cpp 2014-02-09 01:41:15.237138806 +0100 -+++ xbmc-wolfgar-imx-wip.test/xbmc/cores/AudioEngine/Utils/AEConvert.cpp 2014-02-09 01:40:26.223083671 +0100 +diff -Naur xbmc-gotham-latest.test/xbmc/cores/AudioEngine/Utils/AEConvert.cpp xbmc-imx6.test/xbmc/cores/AudioEngine/Utils/AEConvert.cpp +--- xbmc-gotham-latest.test/xbmc/cores/AudioEngine/Utils/AEConvert.cpp 2014-02-19 22:24:45.727495224 +0100 ++++ xbmc-imx6.test/xbmc/cores/AudioEngine/Utils/AEConvert.cpp 2014-02-19 22:25:21.467528797 +0100 @@ -841,7 +841,7 @@ _mm_empty(); #else /* no SSE2 */ @@ -116,9 +108,9 @@ diff -Naur xbmc-gotham-latest.test/xbmc/cores/AudioEngine/Utils/AEConvert.cpp xb #endif return samples << 2; -diff -Naur xbmc-gotham-latest.test/xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.cpp xbmc-wolfgar-imx-wip.test/xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.cpp ---- xbmc-gotham-latest.test/xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.cpp 2014-02-09 01:41:14.964138497 +0100 -+++ xbmc-wolfgar-imx-wip.test/xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.cpp 2014-02-09 01:40:25.777083169 +0100 +diff -Naur xbmc-gotham-latest.test/xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.cpp xbmc-imx6.test/xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.cpp +--- xbmc-gotham-latest.test/xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.cpp 2014-02-19 22:24:45.330494851 +0100 ++++ xbmc-imx6.test/xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.cpp 2014-02-19 22:25:21.443528774 +0100 @@ -35,6 +35,9 @@ #include "Video/DVDVideoCodecFFmpeg.h" #include "Video/DVDVideoCodecOpenMax.h" @@ -158,47 +150,36 @@ diff -Naur xbmc-gotham-latest.test/xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCode #if defined(TARGET_DARWIN_OSX) if (!hint.software && CSettings::Get().GetBool("videoplayer.usevda")) { -diff -Naur xbmc-gotham-latest.test/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h xbmc-wolfgar-imx-wip.test/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h ---- xbmc-gotham-latest.test/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h 2014-02-09 01:41:14.980138516 +0100 -+++ xbmc-wolfgar-imx-wip.test/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h 2014-02-09 01:40:25.834083233 +0100 -@@ -38,7 +38,9 @@ - class COpenMax; - class COpenMaxVideo; - struct OpenMaxVideoBuffer; -+class CIMXOutputFrame; - class CDVDVideoCodecStageFright; -+ - class CDVDMediaCodecInfo; - typedef void* EGLImageKHR; +diff -Naur xbmc-gotham-latest.test/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h xbmc-imx6.test/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h +--- xbmc-gotham-latest.test/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h 2014-02-19 22:24:45.337494858 +0100 ++++ xbmc-imx6.test/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h 2014-02-19 22:25:21.443528774 +0100 +@@ -27,6 +27,7 @@ + #include + #include + #include "cores/VideoRenderers/RenderFormats.h" ++#include "DVDVideoCodecInfo.h" -@@ -64,17 +66,19 @@ + struct DVDCodecAvailableType + { +@@ -91,6 +92,11 @@ struct { - VAAPI::CHolder* vaapi; + CDVDMediaCodecInfo *mediacodec; }; -- - struct { - COpenMax *openMax; - OpenMaxVideoBuffer *openMaxBuffer; - }; -- - struct { - struct __CVBuffer *cvBufferRef; - }; - - struct { -+ CIMXOutputFrame *imxOutputFrame; ++ ++ struct { ++ CDVDVideoCodecBuffer *codecinfo; + }; + -+ struct { - CDVDVideoCodecStageFright* stf; - EGLImageKHR eglimg; - }; -diff -Naur xbmc-gotham-latest.test/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp xbmc-wolfgar-imx-wip.test/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp + }; + + unsigned int iFlags; +diff -Naur xbmc-gotham-latest.test/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp xbmc-imx6.test/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp --- xbmc-gotham-latest.test/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp 1970-01-01 01:00:00.000000000 +0100 -+++ xbmc-wolfgar-imx-wip.test/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp 2014-02-09 01:40:25.852083253 +0100 -@@ -0,0 +1,1745 @@ -+/* -+ * Copyright (C) 2013 Stephan Rafin ++++ xbmc-imx6.test/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp 2014-02-19 22:25:21.444528775 +0100 +@@ -0,0 +1,979 @@ ++/* ++ * Copyright (C) 2010-2013 Team XBMC ++ * http://www.xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -228,487 +209,10 @@ diff -Naur xbmc-gotham-latest.test/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideo +#include "threads/SingleLock.h" +#include "utils/log.h" +#include "DVDClock.h" -+#include "mfw_gst_ts.h" +#include "threads/Atomics.h" + -+//#define NO_V4L_RENDERING + -+#ifdef IMX_PROFILE -+static unsigned long long render_ts[30]; -+static unsigned long long get_time() -+{ -+ struct timespec ts; -+ unsigned long long now; -+ -+ clock_gettime(CLOCK_MONOTONIC, &ts); -+ now = (((unsigned long long)ts.tv_sec) * 1000000000ULL) + -+ ((unsigned long long)ts.tv_nsec); -+ -+ return now; -+} -+#endif -+ -+void CIMXOutputFrame::Render(struct v4l2_crop &crop) -+{ -+ CIMXRenderingFrames& renderingFrames = CIMXRenderingFrames::GetInstance(); -+ renderingFrames.Queue(this, crop); -+} -+ -+/* video device on which the video will be rendered (/dev/video17 => /dev/fb1) */ -+const char *CIMXRenderingFrames::m_v4lDeviceName = "/dev/video17"; -+static long sg_singleton_lock_variable = 0; -+CIMXRenderingFrames* CIMXRenderingFrames::m_instance = 0; -+ -+CIMXRenderingFrames& -+CIMXRenderingFrames::GetInstance() -+{ -+ CAtomicSpinLock lock(sg_singleton_lock_variable); -+ if( ! m_instance ) -+ { -+ m_instance = new CIMXRenderingFrames(); -+ } -+ return *m_instance; -+} -+ -+CIMXRenderingFrames::CIMXRenderingFrames() -+{ -+ m_ready = false; -+ m_v4lfd = -1; -+ m_virtAddr = NULL; -+ m_v4lBuffers = NULL; -+ memset(&m_crop, 0, sizeof(m_crop)); -+ m_crop.type = V4L2_BUF_TYPE_VIDEO_OUTPUT; -+ m_motionCtrl = -1; -+} -+ -+bool CIMXRenderingFrames::AllocateBuffers(const struct v4l2_format *format, int nbBuffers) -+{ -+ int ret, i; -+ struct v4l2_requestbuffers bufReq; -+ struct v4l2_format fmt; -+ struct v4l2_buffer v4lBuf; -+ struct v4l2_control ctrl; -+ -+ CSingleLock lock(m_renderingFramesLock); -+ if (m_ready) -+ { -+ CLog::Log(LOGERROR, "%s - Try to re-allocate buffers while previous buffers were not freed.\n", __FUNCTION__); -+ return false; -+ } -+ -+ m_v4lfd = open(m_v4lDeviceName, O_RDWR|O_NONBLOCK, 0); -+ if (m_v4lfd < 0) -+ { -+ CLog::Log(LOGERROR, "%s - Error while trying to open %s.\n", __FUNCTION__, m_v4lDeviceName); -+ __ReleaseBuffers(); -+ return false; -+ } -+ -+ ret = ioctl(m_v4lfd, VIDIOC_S_FMT, format); -+ if (ret < 0) -+ { -+ CLog::Log(LOGERROR, "%s - Error while setting V4L format (ret %d : %s).\n", __FUNCTION__, ret, strerror(errno)); -+ __ReleaseBuffers(); -+ return false; -+ } -+ -+ if (format->fmt.pix.field != V4L2_FIELD_NONE) -+ { -+ char * motion_entry; -+ motion_entry = getenv("IMX_DEINT_MOTION"); -+ if (motion_entry != NULL) -+ { -+ errno = 0; -+ m_motionCtrl = strtol(motion_entry, NULL, 10); -+ if (errno != 0) -+ m_motionCtrl = -1; -+ } -+ if (m_motionCtrl == -1) -+ m_motionCtrl = 2; /* Default value : 2 stands for high motion */ -+ -+ if ((m_motionCtrl >= 0) && (m_motionCtrl <=2)) -+ { -+ ctrl.id = V4L2_CID_MXC_MOTION; -+ ctrl.value = m_motionCtrl; -+ ret = ioctl (m_v4lfd, VIDIOC_S_CTRL, &ctrl); -+ if (ret < 0) -+ { -+ CLog::Log(LOGERROR, "%s - Error while setting V4L motion (ret %d : %s).\n", __FUNCTION__, ret, strerror(errno)); -+ } -+ } -+ else -+ { -+ CLog::Log(LOGNOTICE, "%s - IMX_DEINT_MOTION set to %d. Disabling deinterlacing.\n", __FUNCTION__, m_motionCtrl); -+ m_motionCtrl = -2; -+ } -+ } -+ -+ fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT; -+ ret = ioctl(m_v4lfd, VIDIOC_G_FMT, &fmt); -+ if (ret < 0) -+ { -+ CLog::Log(LOGERROR, "%s - Error while getting V4L format (ret %d : %s).\n", __FUNCTION__, ret, strerror(errno)); -+ __ReleaseBuffers(); -+ return false; -+ } -+ -+ m_bufferNum = nbBuffers; -+ /* Alloc V4L2 buffers */ -+ memset(&bufReq, 0, sizeof(bufReq)); -+ bufReq.count = m_bufferNum; -+ bufReq.type = V4L2_BUF_TYPE_VIDEO_OUTPUT; -+ bufReq.memory = V4L2_MEMORY_MMAP; -+ ret = ioctl(m_v4lfd, VIDIOC_REQBUFS, &bufReq); -+ if (ret < 0) -+ { -+ CLog::Log(LOGERROR, "%s - %d Hw buffer allocation error (%d)\n", __FUNCTION__, bufReq.count, ret); -+ __ReleaseBuffers(); -+ return false; -+ } -+ CLog::Log(LOGDEBUG, "%s - %d Hw buffer of %d bytes allocated\n", __FUNCTION__, bufReq.count, fmt.fmt.pix.sizeimage); -+ -+ m_virtAddr = new void*[m_bufferNum]; -+ if (m_virtAddr == NULL) -+ { -+ CLog::Log(LOGERROR, "%s - Allocation failure (m_virtAddr table of %d elements)\n", __FUNCTION__, m_bufferNum); -+ __ReleaseBuffers(); -+ return false; -+ } -+ m_v4lBuffers = new v4l2_buffer[m_bufferNum]; -+ if (m_v4lBuffers == NULL) -+ { -+ CLog::Log(LOGERROR, "%s - Allocation failure (m_v4lBuffers table of %d elements)\n", __FUNCTION__, m_bufferNum); -+ __ReleaseBuffers(); -+ return false; -+ } -+ -+ for (i = 0 ; i < m_bufferNum; i++) -+ { -+ memset(&v4lBuf, 0, sizeof(v4lBuf)); -+ v4lBuf.index = i; -+ v4lBuf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT; -+ v4lBuf.memory = V4L2_MEMORY_MMAP; -+ ret = ioctl (m_v4lfd, VIDIOC_QUERYBUF, &v4lBuf); -+ if (ret < 0) -+ { -+ CLog::Log(LOGERROR, "%s - Error during 1st query of V4L buffer (ret %d : %s)\n", __FUNCTION__, ret, strerror(errno)); -+ return false; -+ } -+ m_v4lBuffers[i] = v4lBuf; -+ m_virtAddr[i] = NULL; -+ } -+ memset(&m_crop, 0, sizeof(m_crop)); -+ m_crop.type = V4L2_BUF_TYPE_VIDEO_OUTPUT; -+ m_pushedFrames = 0; -+ m_streamOn = false; -+ m_ready = true; -+ return true; -+} -+ -+void *CIMXRenderingFrames::GetVirtAddr(int idx) -+{ -+ struct v4l2_buffer v4lBuf; -+ int ret; -+ -+ CSingleLock lock(m_renderingFramesLock); -+ if (!m_ready) -+ return NULL; -+ if ((idx < 0) || (idx >= m_bufferNum)) -+ return NULL; -+ -+ if (m_virtAddr[idx] == NULL) -+ { -+ v4lBuf = m_v4lBuffers[idx]; -+ m_virtAddr[idx] = mmap(NULL, v4lBuf.length, PROT_READ | PROT_WRITE, MAP_SHARED, m_v4lfd, v4lBuf.m.offset); -+ -+ /* 2nd query to retrieve real Physical address after mmap (iMX6 bug) */ -+ ret = ioctl (m_v4lfd, VIDIOC_QUERYBUF, &v4lBuf); -+ if (ret < 0) -+ { -+ CLog::Log(LOGERROR, "%s - Error during 2nd query of V4L buffer (ret %d : %s)\n", __FUNCTION__, ret, strerror(errno)); -+ } -+ m_v4lBuffers[idx] = v4lBuf; -+ } -+ return m_virtAddr[idx]; -+} -+ -+void *CIMXRenderingFrames::GetPhyAddr(int idx) -+{ -+ -+ CSingleLock lock(m_renderingFramesLock); -+ if (!m_ready) -+ return NULL; -+ if ((idx < 0) || (idx >= m_bufferNum)) -+ return NULL; -+ -+ return (void *)m_v4lBuffers[idx].m.offset; -+} -+ -+int CIMXRenderingFrames::FindBuffer(void *phyAddr) -+{ -+ int i; -+ -+ CSingleLock lock(m_renderingFramesLock); -+ if (!m_ready) -+ return -1; -+ -+ for (i = 0; i < m_bufferNum; i++) -+ { -+ if (m_v4lBuffers[i].m.offset == (unsigned int)phyAddr) -+ { -+ // CLog::Log(LOGNOTICE, "%s - found buffer OK %d!\n", __FUNCTION__, i); -+ return i; -+ } -+ } -+ return -1; -+} -+ -+int CIMXRenderingFrames::DeQueue(bool wait) -+{ -+ int ret; -+ int status; -+ struct v4l2_buffer buf; -+ -+ CSingleLock lock(m_renderingFramesLock); -+ if (!m_ready) -+ { -+ CLog::Log(LOGNOTICE, "%s - Cannot dequeue frame as buffers were released !\n", -+ __FUNCTION__); -+ return -1; -+ } -+ if (!m_streamOn) -+ { -+ return -1; -+ } -+ -+ if (wait) -+ { -+ status = fcntl(m_v4lfd, F_GETFL); -+ fcntl(m_v4lfd, F_SETFL, status & (~O_NONBLOCK)); -+ } -+ buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT; -+ buf.memory = V4L2_MEMORY_MMAP; -+ ret = ioctl(m_v4lfd, VIDIOC_DQBUF, &buf); -+ if (wait) -+ { -+ fcntl(m_v4lfd, F_SETFL, status | O_NONBLOCK); -+ } -+ if (ret != 0) -+ { -+ if (errno != EAGAIN) -+ CLog::Log(LOGERROR, "%s - Dequeue buffer error (ret %d : %s)\n", -+ __FUNCTION__, ret, strerror(errno)); -+ return -1; -+ } -+ -+#ifdef IMX_PROFILE -+ CLog::Log(LOGDEBUG, "%s - Time render to dequeue (%d) %llu\n", -+ __FUNCTION__, buf.index, get_time() - render_ts[buf.index]); -+#endif -+// CLog::Log(LOGERROR, "%s dequeued retuns (%d)\n", __FUNCTION__, buf.index); -+ -+ return buf.index; -+} -+ -+void CIMXRenderingFrames::Queue(CIMXOutputFrame *picture, struct v4l2_crop &destRect) -+{ -+ /* Warning : called from renderer thread -+ * Especially do not call any VPU functions as they are not thread safe -+ */ -+ -+ int ret, type; -+ struct timeval queue_ts; -+ int stream_trigger; -+ bool crop_update = false; -+ -+ CSingleLock lock(m_renderingFramesLock); -+ if (!m_ready) -+ { -+ CLog::Log(LOGNOTICE, "%s - Cannot queue frame as buffers were released !\n", -+ __FUNCTION__); -+ return; -+ } -+ -+ /*CLog::Log(LOGDEBUG, "%s - queuing frame %d - picture adress : %p\n", -+ __FUNCTION__, picture->v4l2BufferIdx, picture);*/ -+ -+ if ((picture->v4l2BufferIdx < 0) || (picture->v4l2BufferIdx >= m_bufferNum)) -+ { -+ CLog::Log(LOGERROR, "%s - Invalid buffer index : %d - picture address : %p\n", -+ __FUNCTION__, picture->v4l2BufferIdx, picture); -+ return; -+ } -+ -+ /* Set field type for each buffer otherwise the mxc_vout driver reverts to progressive */ -+ switch (picture->field) -+ { -+ case VPU_FIELD_TB: -+ m_v4lBuffers[picture->v4l2BufferIdx].field = V4L2_FIELD_INTERLACED_TB; -+ break; -+ case VPU_FIELD_BT: -+ m_v4lBuffers[picture->v4l2BufferIdx].field= V4L2_FIELD_INTERLACED_BT; -+ break; -+ case VPU_FIELD_NONE: -+ default: -+ m_v4lBuffers[picture->v4l2BufferIdx].field = V4L2_FIELD_NONE; -+ break; -+ } -+ /* In case deinterlacing is forced to disabled */ -+ if (m_motionCtrl == -2) -+ m_v4lBuffers[picture->v4l2BufferIdx].field = V4L2_FIELD_NONE; -+ -+ /* mxc_vout driver does not display immediatly -+ * if timestamp is set to 0 -+ * (instead this driver expects a 30fps rate) -+ * So we explicitly set current time for immediate display -+ */ -+ gettimeofday (&queue_ts, NULL); -+ m_v4lBuffers[picture->v4l2BufferIdx].timestamp = queue_ts; -+ -+#ifndef NO_V4L_RENDERING -+ ret = ioctl(m_v4lfd, VIDIOC_QBUF, &m_v4lBuffers[picture->v4l2BufferIdx]); -+ if (ret < 0) -+ { -+ CLog::Log(LOGERROR, "%s - V4L Queue buffer failed (ret %d : %s)\n", -+ __FUNCTION__, ret, strerror(errno)); -+ /* If it fails odds are very high picture is invalid so just exit now */ -+ return; -+ } -+ else -+ { -+ m_pushedFrames++; -+ } -+ -+ /* Force cropping dimensions to be aligned */ -+ destRect.c.top &= 0xFFFFFFF8; -+ destRect.c.left &= 0xFFFFFFF8; -+ destRect.c.width &= 0xFFFFFFF8; -+ destRect.c.height &= 0xFFFFFFF8; -+ if ((m_crop.c.top != destRect.c.top) || -+ (m_crop.c.left != destRect.c.left) || -+ (m_crop.c.width != destRect.c.width) || -+ (m_crop.c.height != destRect.c.height)) -+ { -+ CLog::Log(LOGNOTICE, "%s - Newcrop : %d % d %d %d\n", -+ __FUNCTION__, destRect.c.top, destRect.c.left, destRect.c.width, destRect.c.height); -+ m_crop.c = destRect.c; -+ crop_update = true; -+ } -+ -+ if (!m_streamOn) -+ { -+ if (picture->field == VPU_FIELD_NONE) -+ stream_trigger = 1; -+ else { -+ if (m_motionCtrl < 2) -+ stream_trigger = 3; -+ else -+ stream_trigger = 2; -+ } -+ -+ if (m_pushedFrames >= stream_trigger) { -+ CLog::Log(LOGDEBUG, "%s - Motion control is : %d - Number of required frames before streaming : %d\n", -+ __FUNCTION__, m_motionCtrl, stream_trigger); -+ -+ type = V4L2_BUF_TYPE_VIDEO_OUTPUT; -+ ret = ioctl(m_v4lfd, VIDIOC_STREAMON, &type); -+ if (ret < 0) -+ { -+ CLog::Log(LOGERROR, "%s - V4L Stream ON failed (ret %d : %s)\n", -+ __FUNCTION__, ret, strerror(errno)); -+ } -+ else -+ { -+ CLog::Log(LOGDEBUG, "%s - V4L Stream ON OK\n", -+ __FUNCTION__); -+ m_streamOn = true; -+ } -+ /* We have to repeat crop command after streamon for some vids -+ * FIXME : Check why in drivers... -+ */ -+ ret = ioctl(m_v4lfd, VIDIOC_S_CROP, &m_crop); -+ if (ret < 0) -+ { -+ CLog::Log(LOGERROR, "%s - S_CROP failed (ret %d : %s)\n", -+ __FUNCTION__, ret, strerror(errno)); -+ } -+ } -+ } -+ else -+ { -+ if (crop_update) -+ { -+ ret = ioctl(m_v4lfd, VIDIOC_S_CROP, &m_crop); -+ if (ret < 0) -+ { -+ CLog::Log(LOGERROR, "%s - S_CROP failed (ret %d : %s)\n", -+ __FUNCTION__, ret, strerror(errno)); -+ } -+ } -+ } -+#endif -+ -+#ifdef IMX_PROFILE -+ render_ts[picture->v4l2BufferIdx] = get_time(); -+ CLog::Log(LOGDEBUG, "%s - Time push to render (%d) %llu\n", -+ __FUNCTION__, picture->v4l2BufferIdx, render_ts[picture->v4l2BufferIdx] - picture->pushTS); -+#endif -+} -+ -+void CIMXRenderingFrames::ReleaseBuffers() -+{ -+ CSingleLock lock(m_renderingFramesLock); -+ if (!m_ready) -+ { -+ CLog::Log(LOGERROR, "%s - AllocateBuffers was not previously called\n", __FUNCTION__); -+ return; -+ } -+ __ReleaseBuffers(); -+} -+ -+/* Note : Has to be called with m_renderingFramesLock held */ -+void CIMXRenderingFrames::__ReleaseBuffers() -+{ -+ int type, i; -+ -+ if (m_v4lfd >= 0) -+ { -+ /* stream off */ -+ type = V4L2_BUF_TYPE_VIDEO_OUTPUT; -+ ioctl (m_v4lfd, VIDIOC_STREAMOFF, &type); -+ m_streamOn = false; -+ } -+ -+ if (m_virtAddr != NULL) -+ { -+ for (i = 0; i < m_bufferNum; i++) -+ { -+ if (m_virtAddr[i] != NULL) -+ munmap (m_virtAddr[i], m_v4lBuffers[i].length); -+ } -+ delete m_virtAddr; -+ m_virtAddr = NULL; -+ } -+ -+ if (m_v4lfd >= 0) -+ { -+ /* Close V4L2 device */ -+ close(m_v4lfd); -+ m_v4lfd = -1; -+ } -+ -+ if (m_v4lBuffers != NULL) -+ { -+ delete m_v4lBuffers; -+ m_v4lBuffers = NULL; -+ } -+ m_bufferNum = 0; -+ m_pushedFrames = 0; -+ m_ready = false; -+ m_motionCtrl = -1; -+} -+ -+/* FIXME get rid of these defines properly */ ++// FIXME get rid of these defines properly +#define FRAME_ALIGN 16 +#define MEDIAINFO 1 +#define _4CC(c1,c2,c3,c4) (((uint32_t)(c4)<<24)|((uint32_t)(c3)<<16)|((uint32_t)(c2)<<8)|(uint32_t)(c1)) @@ -716,29 +220,9 @@ diff -Naur xbmc-gotham-latest.test/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideo +#define min(a, b) (aGetClock() / DVD_TIME_BASE; -+ -+ return clock_pts; -+} -+ -+void CDVDVideoCodecIMX::FlushDecodedFrames(void) -+{ -+ DVDVideoPicture DVDFrame; -+ while (m_decodedFrames.size() > 0) -+ { -+ DVDFrame = m_decodedFrames.front(); -+ VpuReleaseBufferV4L(DVDFrame.imxOutputFrame->v4l2BufferIdx); -+ m_decodedFrames.pop(); -+ } -+} ++CCriticalSection CDVDVideoCodecIMX::m_codecBufferLock; + +bool CDVDVideoCodecIMX::VpuAllocBuffers(VpuMemInfo *pMemBlock) +{ @@ -790,6 +274,17 @@ diff -Naur xbmc-gotham-latest.test/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideo + return false; +} + ++int CDVDVideoCodecIMX::VpuFindBuffer(void *frameAddr) ++{ ++ int i; ++ for (i=0; i1) ++ { ++ ySize=Align(ySize,nAlign); ++ uvSize=Align(uvSize,nAlign); ++ } ++ ++ m_outputBuffers = new CDVDVideoCodecIMXBuffer*[m_vpuFrameBufferNum]; ++ + for (i = 0 ; i < m_vpuFrameBufferNum; i++) + { -+ m_extraMem[i].nSize = cSize; -+ vpuRet = VPU_DecGetMem(&m_extraMem[i]); -+ if (vpuRet != VPU_DEC_RET_SUCCESS) ++ totalSize=(ySize+uvSize+mvSize+nAlign)*1; ++ ++ vpuMem.nSize=totalSize; ++ ret = VPU_DecGetMem(&vpuMem); ++ if(ret != VPU_DEC_RET_SUCCESS) + { -+ CLog::Log(LOGERROR, "%s - Extra memory (%d bytes) allocation failure (%d).\n", -+ __FUNCTION__, m_extraMem[i].nSize , vpuRet); -+ for (j=i ; jpDisplayFrameBuf; -+ CIMXOutputFrame *outputFrame; -+ int i; -+ double pts; -+ DVDVideoPicture DVDFrame; ++ //fill frameBuf ++ ptr=(unsigned char*)vpuMem.nPhyAddr; ++ ptrVirt=(unsigned char*)vpuMem.nVirtAddr; + -+ // FIXME pts = (double)TSManagerSend2(m_tsm, frameBuffer) / (double)1000.0; -+ pts = (double)TSManagerSend(m_tsm) / (double)1000.0; -+ /* Find Frame given physical address */ -+ i = m_renderingFrames.FindBuffer(frameBuffer->pbufY); -+ if (i == -1) -+ { -+ CLog::Log(LOGERROR, "%s - V4L buffer not found\n", __FUNCTION__); -+ return false; -+ } -+ if (m_outputBuffers[i].used()) -+ { -+ CLog::Log(LOGERROR, "%s - Try to reuse buffer which was not dequeued !\n", __FUNCTION__); -+ return false; -+ } ++ /*align the base address*/ ++ if(nAlign>1) ++ { ++ ptr=(unsigned char*)Align(ptr,nAlign); ++ ptrVirt=(unsigned char*)Align(ptrVirt,nAlign); ++ } + -+ /* Store the pointer to be able to invoke VPU_DecOutFrameDisplayed when the buffer will be dequeued */ -+ m_outputBuffers[i].store(frameBuffer, m_frameCounter++); ++ /* fill stride info */ ++ m_vpuFrameBuffers[i].nStrideY=yStride; ++ m_vpuFrameBuffers[i].nStrideC=uvStride; + -+ outputFrame = &m_outputBuffers[i].outputFrame; -+ outputFrame->v4l2BufferIdx = i; -+ outputFrame->field = frameInfo->eFieldType; -+ outputFrame->picCrop = frameInfo->pExtInfo->FrmCropRect; -+ outputFrame->nQ16ShiftWidthDivHeightRatio = frameInfo->pExtInfo->nQ16ShiftWidthDivHeightRatio; -+ DVDFrame.imxOutputFrame = outputFrame; ++ /* fill phy addr*/ ++ m_vpuFrameBuffers[i].pbufY=ptr; ++ m_vpuFrameBuffers[i].pbufCb=ptr+ySize; ++ m_vpuFrameBuffers[i].pbufCr=0; ++ m_vpuFrameBuffers[i].pbufMvCol=ptr+ySize+uvSize; ++ //ptr+=ySize+uSize+vSize+mvSize; ++ /* fill virt addr */ ++ m_vpuFrameBuffers[i].pbufVirtY=ptrVirt; ++ m_vpuFrameBuffers[i].pbufVirtCb=ptrVirt+ySize; ++ m_vpuFrameBuffers[i].pbufVirtCr=0; ++ m_vpuFrameBuffers[i].pbufVirtMvCol=ptrVirt+ySize+uvSize; ++ //ptrVirt+=ySize+uSize+vSize+mvSize; + -+ DVDFrame.pts = pts; -+ DVDFrame.dts = DVD_NOPTS_VALUE; -+ /* -+ m_outputFrame.iWidth = frameInfo->pExtInfo->nFrmWidth; -+ m_outputFrame.iHeight = frameInfo->pExtInfo->nFrmHeight; -+ */ -+ DVDFrame.iWidth = frameInfo->pExtInfo->FrmCropRect.nRight - frameInfo->pExtInfo->FrmCropRect.nLeft; -+ DVDFrame.iHeight = frameInfo->pExtInfo->FrmCropRect.nBottom - frameInfo->pExtInfo->FrmCropRect.nTop; -+ DVDFrame.format = RENDER_FMT_IMX; ++ m_vpuFrameBuffers[i].pbufY_tilebot=0; ++ m_vpuFrameBuffers[i].pbufCb_tilebot=0; ++ m_vpuFrameBuffers[i].pbufVirtY_tilebot=0; ++ m_vpuFrameBuffers[i].pbufVirtCb_tilebot=0; + -+ m_decodedFrames.push(DVDFrame); -+ if (m_decodedFrames.size() > IMX_MAX_QUEUE_SIZE) -+ { -+ CLog::Log(LOGERROR, "%s - Too many enqueued decoded frames : %d (Max %d)\n", __FUNCTION__, m_decodedFrames.size(), IMX_MAX_QUEUE_SIZE); -+ } -+ -+#ifdef IMX_PROFILE -+ DVDFrame.imxOutputFrame->pushTS = get_time(); -+ CLog::Log(LOGDEBUG, "%s - push (%i) Time between push %llu\n", -+ __FUNCTION__, i, DVDFrame.imxOutputFrame->pushTS - previous_ts); -+ previous_ts =DVDFrame.imxOutputFrame->pushTS; ++#ifdef TRACE_FRAMES ++ m_outputBuffers[i] = new CDVDVideoCodecIMXBuffer(i); ++#else ++ m_outputBuffers[i] = new CDVDVideoCodecIMXBuffer(); +#endif ++ } + + return true; +} + -+int CDVDVideoCodecIMX::GetAvailableBufferNb(void) -+{ -+ int i, nb; -+ -+ nb = 0; -+ for (i = 0; i < m_vpuFrameBufferNum; i++) -+ { -+ if (!m_outputBuffers[i].used()) -+ nb++; -+ } -+ return nb; -+} -+ -+bool CDVDVideoCodecIMX::VpuReleaseBufferV4L(int idx) -+{ -+ if (idx < 0 || idx >= m_vpuFrameBufferNum) -+ { -+ CLog::Log(LOGERROR, "%s - Invalid index - idx : %d\n", __FUNCTION__, idx); -+ return false; -+ } -+ -+ /*CLog::Log(LOGDEBUG, "%s - idx : %d - frame : %d\n", __FUNCTION__, -+ idx, m_outputBuffers[idx].frameNo);*/ -+ -+ VPU_DecOutFrameDisplayed(m_vpuHandle, m_outputBuffers[idx].buffer); -+ m_outputBuffers[idx].clear(); -+ return true; -+} -+ -+/* Dequeue queued frames and free the corresponding VPU buffers */ -+bool CDVDVideoCodecIMX::VpuDeQueueFrame(bool wait) -+{ -+ int idx, i, frameNo; -+ -+ idx = m_renderingFrames.DeQueue(wait); -+ if (idx != -1) -+ { -+ if (!m_outputBuffers[idx].used()) -+ { -+ CLog::Log(LOGERROR, "%s - WTF : associated buffer does not exist anymore\n", -+ __FUNCTION__); -+ return true; -+ } -+ else -+ { -+ frameNo = m_outputBuffers[idx].frameNo(); -+ VpuReleaseBufferV4L(idx); -+ if (frameNo > 0) -+ { -+ /* Release buffers which are not used anymore and were -+ * queued before the idx buffer that has just been dequeued*/ -+ for (i = 0; i < m_vpuFrameBufferNum; ++i) -+ { -+ if (m_outputBuffers[i].expired(frameNo)) -+ { -+ CLog::Log(LOGNOTICE, "%s - Release expired buffer - idx : %d\n", __FUNCTION__, i); -+ VpuReleaseBufferV4L(i); -+ } -+ } -+ } -+ return true; -+ } -+ } -+ else -+ { -+#ifdef NO_V4L_RENDERING -+ int i; -+ for (i = 0; i < m_vpuFrameBufferNum; i++) -+ { -+ if (m_outputBuffers[i].used()) -+ { -+ VpuReleaseBufferV4L(idx); -+ } -+ } -+#endif -+ return false; -+ } -+} -+ -+CDVDVideoCodecIMX::CDVDVideoCodecIMX() : m_renderingFrames(CIMXRenderingFrames::GetInstance()) ++CDVDVideoCodecIMX::CDVDVideoCodecIMX() +{ ++ m_vpuHandle = 0; + m_pFormatName = "iMX-xxx"; + memset(&m_decMemInfo, 0, sizeof(DecMemInfo)); + m_vpuHandle = 0; @@ -1160,7 +500,6 @@ diff -Naur xbmc-gotham-latest.test/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideo + m_vpuFrameBufferNum = 0; + m_tsSyncRequired = true; + m_dropState = false; -+ m_tsm = NULL; + m_convert_bitstream = false; + m_frameCounter = 0; + m_usePTS = true; @@ -1168,6 +507,8 @@ diff -Naur xbmc-gotham-latest.test/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideo + { + m_usePTS = false; + } ++ m_converter = NULL; ++ m_convert_bitstream = false; +} + +CDVDVideoCodecIMX::~CDVDVideoCodecIMX() @@ -1229,8 +570,11 @@ diff -Naur xbmc-gotham-latest.test/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideo + m_pFormatName = "iMX-h264"; + if (hints.extradata) + { -+ if ( *(char*)hints.extradata == 1 ) -+ m_convert_bitstream = bitstream_convert_init(hints.extradata,hints.extrasize); ++ if ( *(char*)hints.extradata == 1 ) ++ { ++ m_converter = new CBitstreamConverter(); ++ m_convert_bitstream = m_converter->Open(hints.codec, (uint8_t *)hints.extradata, hints.extrasize, true); ++ } + } + break; + case CODEC_ID_VC1: @@ -1302,10 +646,16 @@ diff -Naur xbmc-gotham-latest.test/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideo +void CDVDVideoCodecIMX::Dispose(void) +{ + VpuDecRetCode ret; -+ int i; + bool VPU_loaded = m_vpuHandle; ++ int i; ++ ++ // Invalidate output buffers to prevent the renderer from mapping this memory ++ for (i=0; iInvalidate(&m_vpuHandle); ++ SAFE_RELEASE(m_outputBuffers[i]); ++ } + -+ FlushDecodedFrames(); + if (m_vpuHandle) + { + ret = VPU_DecFlushAll(m_vpuHandle); @@ -1321,35 +671,14 @@ diff -Naur xbmc-gotham-latest.test/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideo + m_vpuHandle = 0; + } + -+ VpuFreeBuffers(); -+ ++ // Clear memory + if (m_outputBuffers != NULL) + { -+ while (VpuDeQueueFrame(false)); -+ m_renderingFrames.ReleaseBuffers(); -+ RestoreFB(); + delete m_outputBuffers; + m_outputBuffers = NULL; + } + -+ /* Free extramem */ -+ if (m_extraMem != NULL) -+ { -+ for (i = 0; i < m_vpuFrameBufferNum; i++) -+ { -+ if (m_extraMem[i].nSize > 0) -+ { -+ ret = VPU_DecFreeMem(&m_extraMem[i]); -+ if (ret != VPU_DEC_RET_SUCCESS) -+ { -+ CLog::Log(LOGERROR, "%s - Release extra mem failed with error code %d.\n", __FUNCTION__, ret); -+ } -+ m_extraMem[i].nSize = 0; -+ } -+ } -+ delete m_extraMem; -+ m_extraMem = NULL; -+ } ++ VpuFreeBuffers(); + m_vpuFrameBufferNum = 0; + + if (m_vpuFrameBuffers != NULL) @@ -1367,19 +696,10 @@ diff -Naur xbmc-gotham-latest.test/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideo + } + } + -+ if (m_tsm != NULL) ++ if (m_converter) + { -+ destroyTSManager(m_tsm); -+ m_tsm = NULL; -+ } -+ -+ if (m_convert_bitstream) -+ { -+ if (m_sps_pps_context.sps_pps_data) -+ { -+ free(m_sps_pps_context.sps_pps_data); -+ m_sps_pps_context.sps_pps_data = NULL; -+ } ++ m_converter->Close(); ++ SAFE_DELETE(m_converter); + } + return; +} @@ -1388,15 +708,13 @@ diff -Naur xbmc-gotham-latest.test/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideo +{ + VpuDecFrameLengthInfo frameLengthInfo; + VpuBufferNode inData; -+ VpuDecRetCode ret; -+ VpuDecOutFrameInfo frameInfo; -+ int decRet = 0; ++ VpuDecRetCode ret; ++ int decRet = 0, i; + int retStatus = 0; + int demuxer_bytes = iSize; + uint8_t *demuxer_content = pData; -+ bool bitstream_convered = false; + bool retry = false; -+ bool frameConsumed = false; ++ int idx; + +#ifdef IMX_PROFILE + static unsigned long long previous, current; @@ -1410,8 +728,20 @@ diff -Naur xbmc-gotham-latest.test/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideo + return VC_ERROR; + } + ++ for (i=0; i < m_vpuFrameBufferNum; i++) ++ { ++ if (m_outputBuffers[i]->Rendered()) ++ { ++ ret = m_outputBuffers[i]->ClearDisplay(&m_vpuHandle); ++ if(ret != VPU_DEC_RET_SUCCESS) ++ { ++ CLog::Log(LOGERROR, "%s: vpu clear frame display failure: ret=%d \r\n",__FUNCTION__,ret); ++ } ++ } ++ } ++ +#ifdef IMX_PROFILE -+ current = get_time(); ++ current = XbmcThreads::SystemClockMillis(); + CLog::Log(LOGDEBUG, "%s - delta time decode : %llu - demux size : %d dts : %f - pts : %f\n", __FUNCTION__, current - previous, iSize, dts, pts); + previous = current; +#endif @@ -1421,28 +751,18 @@ diff -Naur xbmc-gotham-latest.test/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideo + ((unsigned int *)pData)[0] = htonl(iSize-4); +*/ + -+ while (VpuDeQueueFrame(false)); -+ + if (pData && iSize) + { + if (m_convert_bitstream) + { + // convert demuxer packet from bitstream to bytestream (AnnexB) -+ int bytestream_size = 0; -+ uint8_t *bytestream_buff = NULL; -+ -+ if (!bitstream_convert(demuxer_content, demuxer_bytes, &bytestream_buff, &bytestream_size)) ++ if (m_converter->Convert(demuxer_content, demuxer_bytes)) + { -+ CLog::Log(LOGERROR, "%s - bitstream convert error...\n", __FUNCTION__); -+ return VC_ERROR; -+ } -+ -+ if (bytestream_buff && (bytestream_size > 0)) -+ { -+ bitstream_convered = true; -+ demuxer_bytes = bytestream_size; -+ demuxer_content = bytestream_buff; ++ demuxer_content = m_converter->GetConvertBuffer(); ++ demuxer_bytes = m_converter->GetConvertSize(); + } ++ else ++ CLog::Log(LOGERROR,"%s - bitstream_convert error", __FUNCTION__); + } + + inData.nSize = demuxer_bytes; @@ -1466,11 +786,11 @@ diff -Naur xbmc-gotham-latest.test/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideo + { + retry = false; +#ifdef IMX_PROFILE -+ before_dec = get_time(); ++ before_dec = XbmcThreads::SystemClockMillis(); +#endif + ret = VPU_DecDecodeBuf(m_vpuHandle, &inData, &decRet); +#ifdef IMX_PROFILE -+ CLog::Log(LOGDEBUG, "%s - VPU dec 0x%x decode takes : %lld\n\n", __FUNCTION__, decRet, get_time() - 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) @@ -1518,9 +838,25 @@ diff -Naur xbmc-gotham-latest.test/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideo + { + CLog::Log(LOGERROR, "%s - VPU error retireving info about consummed frame (%d).\n", __FUNCTION__, ret); + } -+ frameConsumed = true; -+ // FIXME TSManagerValid2(m_tsm, frameLengthInfo.nFrameLength + frameLengthInfo.nStuffLength, frameLengthInfo.pFrame); -+ //CLog::Log(LOGDEBUG, "%s - size : %d - key consummed : %x\n", __FUNCTION__, frameLengthInfo.nFrameLength + frameLengthInfo.nStuffLength, frameLengthInfo.pFrame); ++ if (frameLengthInfo.pFrame) ++ { ++ idx = VpuFindBuffer(frameLengthInfo.pFrame->pbufY); ++ if (idx != -1) ++ { ++ if (pts != DVD_NOPTS_VALUE) ++ { ++ m_outputBuffers[idx]->SetPts(pts); ++ } ++ else if (dts != DVD_NOPTS_VALUE) ++ { ++ m_outputBuffers[idx]->SetPts(dts); ++ } ++ } ++ else ++ { ++ CLog::Log(LOGERROR, "%s - could not find frame buffer\n", __FUNCTION__); ++ } ++ } + }//VPU_DEC_ONE_FRM_CONSUMED + + if ((decRet & VPU_DEC_OUTPUT_DIS) || @@ -1530,26 +866,21 @@ diff -Naur xbmc-gotham-latest.test/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideo + if (retStatus & VC_PICTURE) + CLog::Log(LOGERROR, "%s - Second picture in the same decode call !\n", __FUNCTION__); + -+ ret = VPU_DecGetOutputFrame(m_vpuHandle, &frameInfo); ++ ret = VPU_DecGetOutputFrame(m_vpuHandle, &m_frameInfo); + if(ret != VPU_DEC_RET_SUCCESS) + { + CLog::Log(LOGERROR, "%s - VPU Cannot get output frame(%d).\n", __FUNCTION__, ret); + goto out_error; + } -+ if (VpuPushFrame(&frameInfo)) -+ { -+ retStatus |= VC_PICTURE; -+ } ++ retStatus |= VC_PICTURE; + } //VPU_DEC_OUTPUT_DIS + + if (decRet & VPU_DEC_OUTPUT_REPEAT) + { -+ TSManagerSend(m_tsm); + CLog::Log(LOGDEBUG, "%s - Frame repeat.\n", __FUNCTION__); + } + if (decRet & VPU_DEC_OUTPUT_DROPPED) + { -+ TSManagerSend(m_tsm); + CLog::Log(LOGDEBUG, "%s - Frame dropped.\n", __FUNCTION__); + } + if (decRet & VPU_DEC_NO_ENOUGH_BUF) @@ -1558,7 +889,6 @@ diff -Naur xbmc-gotham-latest.test/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideo + } + if (decRet & VPU_DEC_SKIP) + { -+ TSManagerSend(m_tsm); + CLog::Log(LOGDEBUG, "%s - Frame skipped.\n", __FUNCTION__); + } + if (decRet & VPU_DEC_FLUSH) @@ -1583,10 +913,8 @@ diff -Naur xbmc-gotham-latest.test/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideo + if (!(decRet & VPU_DEC_INPUT_USED)) + { + CLog::Log(LOGERROR, "%s - input not used : addr %p size :%d!\n", __FUNCTION__, inData.pVirAddr, inData.nSize); -+ TSManagerSend(m_tsm); + } + -+ + if (!(decRet & VPU_DEC_OUTPUT_DIS) && + (inData.nSize != 0)) + { @@ -1599,82 +927,34 @@ diff -Naur xbmc-gotham-latest.test/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideo + } + + } while (retry == true); -+ -+ /* Push ts only if a frame was consumed by the VPU -+ * as it will produce an output in future for sure */ -+ if (frameConsumed) -+ { -+ if (pts != DVD_NOPTS_VALUE) -+ { -+ if (m_tsSyncRequired) -+ { -+ m_tsSyncRequired = false; -+ resyncTSManager(m_tsm, llrint(pts) * 1000, MODE_AI); -+ } -+ //TSManagerReceive2(m_tsm, llrint(pts) * 1000, iSize); -+ TSManagerReceive(m_tsm, llrint(pts) * 1000); -+ } -+ else -+ { -+ //If no pts but dts available (AVI container for instance) then use this one -+ if (dts != DVD_NOPTS_VALUE) -+ { -+ if (m_tsSyncRequired) -+ { -+ m_tsSyncRequired = false; -+ resyncTSManager(m_tsm, llrint(dts) * 1000, MODE_AI); -+ } -+ //TSManagerReceive2(m_tsm, llrint(dts) * 1000, iSize); -+ TSManagerReceive(m_tsm, llrint(dts) * 1000); -+ } -+ } -+ } -+ + } //(pData && iSize) + -+ if (GetAvailableBufferNb() > (m_vpuFrameBufferNum - m_extraVpuBuffers)) ++ if (retStatus == 0) + { + retStatus |= VC_BUFFER; + } -+ else -+ { -+ if (retStatus == 0) { -+ /* No Picture ready and Not enough VPU buffers. It should NOT happen so log dedicated error */ -+ CLog::Log(LOGERROR, "%s - Not hw buffer available. Waiting for 2ms\n", __FUNCTION__); -+ /* Lets wait for the IPU to free a buffer. Anyway we have several decoded frames ready */ -+ usleep(2000); -+ } -+ } -+ -+ if (bitstream_convered) -+ free(demuxer_content); -+ -+ retStatus &= (~VC_PICTURE); -+ if (m_decodedFrames.size() >= IMX_MAX_QUEUE_SIZE) -+ retStatus |= VC_PICTURE; + +#ifdef IMX_PROFILE -+ CLog::Log(LOGDEBUG, "%s - returns %x - duration %lld\n", __FUNCTION__, retStatus, get_time() - previous); ++ CLog::Log(LOGDEBUG, "%s - returns %x - duration %lld\n", __FUNCTION__, retStatus, XbmcThreads::SystemClockMillis() - previous); +#endif + return retStatus; + +out_error: -+ if (bitstream_convered) -+ free(demuxer_content); + return VC_ERROR; +} + +void CDVDVideoCodecIMX::Reset() +{ -+ int ret; ++ int ret, i; + + CLog::Log(LOGDEBUG, "%s - called\n", __FUNCTION__); + + /* We have to resync timestamp manager */ + m_tsSyncRequired = true; + -+ /* Flush decoded frames */ -+ FlushDecodedFrames(); ++ /* Invalidate all buffers */ ++ for(i = 0; i < m_vpuFrameBufferNum; i++) ++ m_outputBuffers[i]->Invalidate(&m_vpuHandle); + + /* Flush VPU */ + ret = VPU_DecFlushAll(m_vpuHandle); @@ -1687,80 +967,63 @@ diff -Naur xbmc-gotham-latest.test/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideo + +unsigned CDVDVideoCodecIMX::GetAllowedReferences() +{ -+ // Note : It is useless if CLinuxRendererGLES::GetProcessorSize returns 0 for RENDER_FMT_IMX -+ return min(3, m_extraVpuBuffers / 2); ++ return 3; +} + ++bool CDVDVideoCodecIMX::ClearPicture(DVDVideoPicture* pDvdVideoPicture) ++{ ++ if (pDvdVideoPicture) ++ { ++ SAFE_RELEASE(pDvdVideoPicture->codecinfo); ++ } ++ ++ return true; ++} + +bool CDVDVideoCodecIMX::GetPicture(DVDVideoPicture* pDvdVideoPicture) +{ -+ double currentPlayerPts; -+ double ts = DVD_NOPTS_VALUE; -+ DVDVideoPicture DVDFrame; -+ -+ if (m_decodedFrames.size() == 0) -+ { -+ CLog::Log(LOGERROR, "%s called while no picture ready\n", __FUNCTION__); -+ return false; -+ } -+ -+ /* Retrieve oldest decoded frame */ -+ DVDFrame = m_decodedFrames.front(); -+ m_decodedFrames.pop(); -+ //CLog::Log(LOGNOTICE, "%s - buffer(%d)\n", __FUNCTION__, DVDFrame.imxOutputFrame->v4l2BufferIdx); -+ -+ pDvdVideoPicture->iFlags &= DVP_FLAG_DROPPED; -+ if ((pDvdVideoPicture->iFlags != 0) || (m_dropState)) -+ { -+ CLog::Log(LOGNOTICE, "%s - Flushing video picture\n", __FUNCTION__); -+ pDvdVideoPicture->iFlags = DVP_FLAG_DROPPED; -+ VpuReleaseBufferV4L(DVDFrame.imxOutputFrame->v4l2BufferIdx); -+ DVDFrame.imxOutputFrame = NULL; -+ } -+ else -+ { -+ ts = DVDFrame.pts; -+ currentPlayerPts = GetPlayerPtsSeconds() * (double)DVD_TIME_BASE; -+ if (currentPlayerPts > ts) -+ { -+ CLog::Log(LOGERROR, "%s - player is ahead of time (%f)\n", __FUNCTION__, currentPlayerPts - ts); -+ } -+ //CLog::Log(LOGINFO, "%s - idx : %d - delta call %f - delta ts %f \n", __FUNCTION__, outputFrame.v4l2_buffer->index,ts - previous, ts - currentPlayerPts); -+ } -+ -+#ifdef NO_V4L_RENDERING -+ if (!m_dropState) -+ { -+ VpuReleaseBufferV4L(DVDFrame.imxOutputFrame->v4l2BufferIdx); -+ } -+#endif -+ -+ pDvdVideoPicture->pts = DVDFrame.pts; -+ if (!m_usePTS) -+ { -+ pDvdVideoPicture->pts = DVD_NOPTS_VALUE; -+ } -+ pDvdVideoPicture->dts = DVDFrame.dts; -+ pDvdVideoPicture->iWidth = DVDFrame.iWidth; -+ pDvdVideoPicture->iHeight = DVDFrame.iHeight; ++ pDvdVideoPicture->iFlags = DVP_FLAG_ALLOCATED; + if (m_dropState) ++ pDvdVideoPicture->iFlags |= DVP_FLAG_DROPPED; ++ else ++ pDvdVideoPicture->iFlags &= ~DVP_FLAG_DROPPED; ++ ++ pDvdVideoPicture->format = RENDER_FMT_IMXMAP; ++ pDvdVideoPicture->dts = DVD_NOPTS_VALUE; ++ pDvdVideoPicture->iWidth = m_frameInfo.pExtInfo->FrmCropRect.nRight - m_frameInfo.pExtInfo->FrmCropRect.nLeft; ++ pDvdVideoPicture->iHeight = m_frameInfo.pExtInfo->FrmCropRect.nBottom - m_frameInfo.pExtInfo->FrmCropRect.nTop; ++ ++ pDvdVideoPicture->iDisplayWidth = ((pDvdVideoPicture->iWidth * m_frameInfo.pExtInfo->nQ16ShiftWidthDivHeightRatio) + 32767) >> 16; ++ pDvdVideoPicture->iDisplayHeight = pDvdVideoPicture->iHeight; ++ ++ int idx = VpuFindBuffer(m_frameInfo.pDisplayFrameBuf->pbufY); ++ if (idx != -1) + { -+ pDvdVideoPicture->iDisplayWidth = DVDFrame.iWidth; -+ pDvdVideoPicture->iDisplayHeight = DVDFrame.iHeight; ++ CDVDVideoCodecIMXBuffer *buffer = m_outputBuffers[idx]; ++ pDvdVideoPicture->pts = buffer->GetPts(); ++ if (!m_usePTS) ++ { ++ pDvdVideoPicture->pts = DVD_NOPTS_VALUE; ++ } ++ buffer->Queue(m_frameInfo.pDisplayFrameBuf); ++ pDvdVideoPicture->codecinfo = buffer; ++ ++#ifdef TRACE_FRAMES ++ CLog::Log(LOGDEBUG, "+ %02d\n", idx); ++ CLog::Log(LOGDEBUG, "pts %f\n",pDvdVideoPicture->pts); ++#endif ++ ++ pDvdVideoPicture->codecinfo->Lock(); ++ pDvdVideoPicture->codecinfo->iWidth = m_frameInfo.pExtInfo->nFrmWidth; ++ pDvdVideoPicture->codecinfo->iHeight = m_frameInfo.pExtInfo->nFrmHeight; ++ pDvdVideoPicture->codecinfo->data[0] = m_frameInfo.pDisplayFrameBuf->pbufVirtY; ++ pDvdVideoPicture->codecinfo->data[1] = m_frameInfo.pDisplayFrameBuf->pbufY; + } + else + { -+ pDvdVideoPicture->iDisplayWidth = ((pDvdVideoPicture->iWidth * DVDFrame.imxOutputFrame->nQ16ShiftWidthDivHeightRatio) + 32767) >> 16; -+ pDvdVideoPicture->iDisplayHeight = pDvdVideoPicture->iHeight; ++ CLog::Log(LOGERROR, "%s - could not find frame buffer\n", __FUNCTION__); + } -+ pDvdVideoPicture->format = DVDFrame.format; -+ pDvdVideoPicture->imxOutputFrame = DVDFrame.imxOutputFrame; + -+#ifdef V4L_OUTPUT_PROFILE -+ CLog::Log(LOGDEBUG, "%s - QF : %d - HWfre : %d/%d/%d\n", -+ (int)m_decodedFrames.size(), GetAvailableBufferNb(), -+ m_extraVpuBuffers, m_vpuFrameBufferNum); -+#endif + return true; +} + @@ -1778,174 +1041,125 @@ diff -Naur xbmc-gotham-latest.test/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideo + } +} + -+/* bitstream convert : Shameless copy from openmax */ -+/* TODO : Have a look at it as the malloc/copy/free strategy is obviously not the most efficient one */ ++/*******************************************/ + -+bool CDVDVideoCodecIMX::bitstream_convert_init(void *in_extradata, int in_extrasize) ++#ifdef TRACE_FRAMES ++CDVDVideoCodecIMXBuffer::CDVDVideoCodecIMXBuffer(int idx) ++ : m_refs(1) ++ , m_idx(idx) ++#else ++CDVDVideoCodecIMXBuffer::CDVDVideoCodecIMXBuffer() ++ : m_refs(1) ++#endif ++ , m_frameBuffer(NULL) ++ , m_rendered(false) ++ , m_pts(DVD_NOPTS_VALUE) +{ -+ // based on h264_mp4toannexb_bsf.c (ffmpeg) -+ // which is Copyright (c) 2007 Benoit Fouet -+ // and Licensed GPL 2.1 or greater -+ -+ m_sps_pps_size = 0; -+ m_sps_pps_context.sps_pps_data = NULL; -+ -+ // nothing to filter -+ if (!in_extradata || in_extrasize < 6) -+ return false; -+ -+ uint16_t unit_size; -+ uint32_t total_size = 0; -+ uint8_t *out = NULL, unit_nb, sps_done = 0; -+ const uint8_t *extradata = (uint8_t*)in_extradata + 4; -+ static const uint8_t nalu_header[4] = {0, 0, 0, 1}; -+ -+ // retrieve length coded size -+ m_sps_pps_context.length_size = (*extradata++ & 0x3) + 1; -+ if (m_sps_pps_context.length_size == 3) -+ return false; -+ -+ // retrieve sps and pps unit(s) -+ unit_nb = *extradata++ & 0x1f; // number of sps unit(s) -+ if (!unit_nb) -+ { -+ unit_nb = *extradata++; // number of pps unit(s) -+ sps_done++; -+ } -+ while (unit_nb--) -+ { -+ unit_size = extradata[0] << 8 | extradata[1]; -+ total_size += unit_size + 4; -+ if ( (extradata + 2 + unit_size) > ((uint8_t*)in_extradata + in_extrasize) ) -+ { -+ free(out); -+ return false; -+ } -+ uint8_t* new_out = (uint8_t*)realloc(out, total_size); -+ if (new_out) -+ { -+ out = new_out; -+ } -+ else -+ { -+ CLog::Log(LOGERROR, "bitstream_convert_init failed - %s : could not realloc the buffer out", __FUNCTION__); -+ free(out); -+ return false; -+ } -+ -+ memcpy(out + total_size - unit_size - 4, nalu_header, 4); -+ memcpy(out + total_size - unit_size, extradata + 2, unit_size); -+ extradata += 2 + unit_size; -+ -+ if (!unit_nb && !sps_done++) -+ unit_nb = *extradata++; // number of pps unit(s) -+ } -+ -+ m_sps_pps_context.sps_pps_data = out; -+ m_sps_pps_context.size = total_size; -+ m_sps_pps_context.first_idr = 1; -+ -+ return true; +} + -+bool CDVDVideoCodecIMX::bitstream_convert(BYTE* pData, int iSize, uint8_t **poutbuf, int *poutbuf_size) ++void CDVDVideoCodecIMXBuffer::Lock() +{ -+ // based on h264_mp4toannexb_bsf.c (ffmpeg) -+ // which is Copyright (c) 2007 Benoit Fouet -+ // and Licensed GPL 2.1 or greater -+ -+ uint8_t *buf = pData; -+ uint32_t buf_size = iSize; -+ uint8_t unit_type; -+ int32_t nal_size; -+ uint32_t cumul_size = 0; -+ const uint8_t *buf_end = buf + buf_size; -+ -+ do -+ { -+ if (buf + m_sps_pps_context.length_size > buf_end) -+ goto fail; -+ -+ if (m_sps_pps_context.length_size == 1) -+ nal_size = buf[0]; -+ else if (m_sps_pps_context.length_size == 2) -+ nal_size = buf[0] << 8 | buf[1]; -+ else -+ nal_size = buf[0] << 24 | buf[1] << 16 | buf[2] << 8 | buf[3]; -+ -+ // FIXME CLog::Log(LOGERROR, "%s - nal_size : %d \n", __FUNCTION__, nal_size); -+ buf += m_sps_pps_context.length_size; -+ unit_type = *buf & 0x1f; -+ -+ if (buf + nal_size > buf_end || nal_size < 0) -+ goto fail; -+ -+ // prepend only to the first type 5 NAL unit of an IDR picture -+ if (m_sps_pps_context.first_idr && unit_type == 5) -+ { -+ bitstream_alloc_and_copy(poutbuf, poutbuf_size, -+ m_sps_pps_context.sps_pps_data, m_sps_pps_context.size, buf, nal_size); -+ m_sps_pps_context.first_idr = 0; -+ } -+ else -+ { -+ bitstream_alloc_and_copy(poutbuf, poutbuf_size, NULL, 0, buf, nal_size); -+ if (!m_sps_pps_context.first_idr && unit_type == 1) -+ m_sps_pps_context.first_idr = 1; -+ } -+ -+ buf += nal_size; -+ cumul_size += nal_size + m_sps_pps_context.length_size; -+ } while (cumul_size < buf_size); -+ -+ return true; -+ -+fail: -+ free(*poutbuf); -+ *poutbuf = NULL; -+ *poutbuf_size = 0; -+ return false; ++#ifdef TRACE_FRAMES ++ long count = AtomicIncrement(&m_refs); ++ CLog::Log(LOGDEBUG, "R+ %02d - ref : %d\n", m_idx, count); ++#else ++ AtomicIncrement(&m_refs); ++#endif +} + -+void CDVDVideoCodecIMX::bitstream_alloc_and_copy( -+ uint8_t **poutbuf, int *poutbuf_size, -+ const uint8_t *sps_pps, uint32_t sps_pps_size, -+ const uint8_t *in, uint32_t in_size) ++long CDVDVideoCodecIMXBuffer::Release() +{ -+ // based on h264_mp4toannexb_bsf.c (ffmpeg) -+ // which is Copyright (c) 2007 Benoit Fouet -+ // and Licensed GPL 2.1 or greater -+ -+ #define CHD_WB32(p, d) { \ -+ ((uint8_t*)(p))[3] = (d); \ -+ ((uint8_t*)(p))[2] = (d) >> 8; \ -+ ((uint8_t*)(p))[1] = (d) >> 16; \ -+ ((uint8_t*)(p))[0] = (d) >> 24; } -+ -+ uint32_t offset = *poutbuf_size; -+ uint8_t nal_header_size = offset ? 3 : 4; -+ -+ *poutbuf_size += sps_pps_size + in_size + nal_header_size; -+ *poutbuf = (uint8_t*)realloc(*poutbuf, *poutbuf_size); -+ if (sps_pps) -+ memcpy(*poutbuf + offset, sps_pps, sps_pps_size); -+ -+ memcpy(*poutbuf + sps_pps_size + nal_header_size + offset, in, in_size); -+ if (!offset) ++ long count = AtomicDecrement(&m_refs); ++#ifdef TRACE_FRAMES ++ CLog::Log(LOGDEBUG, "R- %02d - ref : %d\n", m_idx, count); ++#endif ++ if (count == 1) + { -+ CHD_WB32(*poutbuf + sps_pps_size, 1); ++ // If count drops to 1 then the only reference is being held by the codec ++ // that it can be released in the next Decode call. ++ if(m_frameBuffer != NULL) ++ m_rendered = true; ++#ifdef TRACE_FRAMES ++ CLog::Log(LOGDEBUG, "R %02d\n", m_idx); ++#endif + } -+ else ++ else if (count == 0) + { -+ (*poutbuf + offset + sps_pps_size)[0] = 0; -+ (*poutbuf + offset + sps_pps_size)[1] = 0; -+ (*poutbuf + offset + sps_pps_size)[2] = 1; ++#ifdef TRACE_FRAMES ++ CLog::Log(LOGDEBUG, "~ %02d\n", m_idx); ++#endif ++ ++ delete this; + } ++ ++ return count; +} -diff -Naur xbmc-gotham-latest.test/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h xbmc-wolfgar-imx-wip.test/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h ++ ++bool CDVDVideoCodecIMXBuffer::IsValid() ++{ ++ CSingleLock lock(CDVDVideoCodecIMX::m_codecBufferLock); ++ return m_frameBuffer != NULL; ++} ++ ++void CDVDVideoCodecIMXBuffer::Invalidate(VpuDecHandle *handle) ++{ ++ CSingleLock lock(CDVDVideoCodecIMX::m_codecBufferLock); ++#ifdef TRACE_FRAMES ++ CLog::Log(LOGDEBUG, "I %02d\n", m_idx); ++#endif ++ if((m_frameBuffer != NULL) && *handle) ++ { ++ VpuDecRetCode ret = VPU_DecOutFrameDisplayed(*handle, m_frameBuffer); ++ if(ret != VPU_DEC_RET_SUCCESS) ++ CLog::Log(LOGERROR, "%s: vpu clear frame display failure: ret=%d \r\n",__FUNCTION__,ret); ++ } ++ ++ m_frameBuffer = NULL; ++ m_rendered = false; ++ m_pts = DVD_NOPTS_VALUE; ++} ++ ++bool CDVDVideoCodecIMXBuffer::Rendered() ++{ ++ return m_rendered; ++} ++ ++void CDVDVideoCodecIMXBuffer::Queue(VpuFrameBuffer *buffer) ++{ ++ m_frameBuffer = buffer; ++ m_rendered = false; ++} ++ ++VpuDecRetCode CDVDVideoCodecIMXBuffer::ClearDisplay(VpuDecHandle *handle) ++{ ++ VpuDecRetCode ret = VPU_DecOutFrameDisplayed(*handle, m_frameBuffer); ++#ifdef TRACE_FRAMES ++ CLog::Log(LOGDEBUG, "- %02d\n", m_idx); ++#endif ++ m_rendered = false; ++ m_frameBuffer = NULL; ++ m_pts = DVD_NOPTS_VALUE; ++ return ret; ++} ++ ++void CDVDVideoCodecIMXBuffer::SetPts(double pts) ++{ ++ m_pts = pts; ++} ++ ++double CDVDVideoCodecIMXBuffer::GetPts(void) const ++{ ++ return m_pts; ++} ++ ++CDVDVideoCodecIMXBuffer::~CDVDVideoCodecIMXBuffer() ++{ ++ assert(m_refs == 0); ++} +diff -Naur xbmc-gotham-latest.test/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h xbmc-imx6.test/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h --- xbmc-gotham-latest.test/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h 1970-01-01 01:00:00.000000000 +0100 -+++ xbmc-wolfgar-imx-wip.test/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h 2014-02-09 01:40:25.878083282 +0100 -@@ -0,0 +1,191 @@ ++++ xbmc-imx6.test/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h 2014-02-19 22:25:21.444528775 +0100 +@@ -0,0 +1,132 @@ +#pragma once +/* + * Copyright (C) 2010-2013 Team XBMC @@ -1971,10 +1185,13 @@ diff -Naur xbmc-gotham-latest.test/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideo +#include +#include "DVDVideoCodec.h" +#include "DVDStreamInfo.h" ++#include "DVDVideoCodecInfo.h" +#include "threads/CriticalSection.h" ++#include "utils/BitstreamConverter.h" + + +//#define IMX_PROFILE ++//#define TRACE_FRAMES + +/* FIXME TODO Develop real proper CVPUBuffer class */ +#define VPU_DEC_MAX_NUM_MEM_NUM 20 @@ -1992,56 +1209,44 @@ diff -Naur xbmc-gotham-latest.test/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideo + unsigned int phyMem_size[VPU_DEC_MAX_NUM_MEM_NUM]; +} DecMemInfo; + -+/* Output frame properties */ -+struct CIMXOutputFrame { -+ // Render a picture. Calls RenderingFrames.Queue -+ void Render(struct v4l2_crop &); -+ // Clear a picture by settings the frameNo to "expired" -+ void Release() { frameNo = 0; } -+ -+ int v4l2BufferIdx; -+ VpuFieldType field; -+ VpuRect picCrop; -+ unsigned int nQ16ShiftWidthDivHeightRatio; -+ int frameNo; -+#ifdef IMX_PROFILE -+ unsigned long long pushTS; -+#endif -+}; -+ -+class CIMXRenderingFrames ++class CDVDVideoCodecIMXBuffer : public CDVDVideoCodecBuffer +{ +public: -+ static CIMXRenderingFrames& GetInstance(); -+ bool AllocateBuffers(const struct v4l2_format *, int); -+ void *GetVirtAddr(int idx); -+ void *GetPhyAddr(int idx); -+ void ReleaseBuffers(); -+ int FindBuffer(void *); -+ int DeQueue(bool wait); -+ void Queue(CIMXOutputFrame *, struct v4l2_crop &); ++#ifdef TRACE_FRAMES ++ CDVDVideoCodecIMXBuffer(int idx); ++#else ++ CDVDVideoCodecIMXBuffer(); ++#endif + -+private: -+ CIMXRenderingFrames(); -+ void __ReleaseBuffers(); ++ // reference counting ++ virtual void Lock(); ++ virtual long Release(); ++ virtual bool IsValid(); + -+ static const char *m_v4lDeviceName; // V4L2 device Name -+ static CIMXRenderingFrames* m_instance; // Unique instance of the class ++ void Invalidate(VpuDecHandle *handle); ++ bool Rendered(); ++ void Queue(VpuFrameBuffer *buffer); ++ VpuDecRetCode ClearDisplay(VpuDecHandle *handle); ++ void SetPts(double pts); ++ double GetPts(void) const; + -+ CCriticalSection m_renderingFramesLock; // Lock to ensure multithreading safety for class fields -+ bool m_ready; // Buffers are allocated and frames can be Queued/Dequeue -+ int m_v4lfd; // fd on V4L2 device -+ struct v4l2_buffer *m_v4lBuffers; // Table of V4L buffer info (as returned by VIDIOC_QUERYBUF) -+ int m_bufferNum; // Number of allocated V4L2 buffers -+ struct v4l2_crop m_crop; // Current cropping properties -+ bool m_streamOn; // Flag that indicates whether streaming in on (from V4L point of view) -+ int m_pushedFrames; // Number of frames queued in V4L2 -+ void **m_virtAddr; // Table holding virtual adresses of mmaped V4L2 buffers -+ int m_motionCtrl; // Current motion control algo ++protected: ++ // private because we are reference counted ++ virtual ~CDVDVideoCodecIMXBuffer(); ++ ++#ifdef TRACE_FRAMES ++ int m_idx; ++#endif ++ long m_refs; ++ VpuFrameBuffer *m_frameBuffer; ++ bool m_rendered; ++ double m_pts; +}; + +class CDVDVideoCodecIMX : public CDVDVideoCodec +{ ++ friend class CDVDVideoCodecIMXBuffer; ++ +public: + CDVDVideoCodecIMX(); + virtual ~CDVDVideoCodecIMX(); @@ -2051,6 +1256,7 @@ diff -Naur xbmc-gotham-latest.test/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideo + virtual void Dispose(void); + virtual int Decode(BYTE *pData, int iSize, double dts, double pts); + virtual void Reset(void); ++ virtual bool ClearPicture(DVDVideoPicture *pDvdVideoPicture); + virtual bool GetPicture(DVDVideoPicture *pDvdVideoPicture); + virtual void SetDropState(bool bDrop); + virtual const char* GetName(void) { return (const char*)m_pFormatName; } @@ -2062,1301 +1268,634 @@ diff -Naur xbmc-gotham-latest.test/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideo + bool VpuAllocBuffers(VpuMemInfo *); + bool VpuFreeBuffers(void); + bool VpuAllocFrameBuffers(void); -+ bool VpuPushFrame(VpuDecOutFrameInfo*); -+ bool VpuDeQueueFrame(bool); -+ int GetAvailableBufferNb(void); -+ void InitFB(void); -+ void RestoreFB(void); -+ void FlushDecodedFrames(void); -+ bool VpuReleaseBufferV4L(int); -+ -+ /* Helper structure which holds a queued output frame -+ * and its associated decoder frame buffer.*/ -+ struct VpuV4LFrameBuffer -+ { -+ // Returns whether the buffer is currently used (associated) -+ bool used() const { return buffer != NULL; } -+ int frameNo() const { return outputFrame.frameNo; } -+ bool expired(int frameNo) const -+ { return (buffer != NULL) && (outputFrame.frameNo < frameNo); } -+ // Associate a VPU frame buffer -+ void store(VpuFrameBuffer *b, int frameNo) { -+ buffer = b; -+ outputFrame.frameNo = frameNo; -+ } -+ // Reset the state -+ void clear() { store(NULL, 0); } -+ -+ VpuFrameBuffer *buffer; -+ CIMXOutputFrame outputFrame; -+ }; ++ int VpuFindBuffer(void *frameAddr); + + static const int m_extraVpuBuffers; // Number of additional buffers for VPU ++ static CCriticalSection m_codecBufferLock; + -+ CIMXRenderingFrames&m_renderingFrames; // The global RenderingFrames instance + CDVDStreamInfo m_hints; // Hints from demuxer at stream opening + const char *m_pFormatName; // Current decoder format name + VpuDecOpenParam m_decOpenParam; // Parameters required to call VPU_DecOpen + DecMemInfo m_decMemInfo; // VPU dedicated memory description + VpuDecHandle m_vpuHandle; // Handle for VPU library calls + VpuDecInitInfo m_initInfo; // Initial info returned from VPU at decoding start -+ void *m_tsm; // fsl Timestamp manager (from gstreamer implementation) + bool m_tsSyncRequired; // state whether timestamp manager has to be sync'ed + bool m_dropState; // Current drop state + int m_vpuFrameBufferNum; // Total number of allocated frame buffers + VpuFrameBuffer *m_vpuFrameBuffers; // Table of VPU frame buffers description ++ CDVDVideoCodecIMXBuffer **m_outputBuffers; + VpuMemDesc *m_extraMem; // Table of allocated extra Memory -+ VpuV4LFrameBuffer *m_outputBuffers; // Table of V4L buffers out of VPU (index is V4L buf index) (used to call properly VPU_DecOutFrameDisplayed) -+ std::queue m_decodedFrames; // Decoded Frames ready to be retrieved by GetPicture ++// VpuMemDesc *m_outputBuffers; // Table of buffers out of VPU (used to call properly VPU_DecOutFrameDisplayed) + int m_frameCounter; // Decoded frames counter + bool m_usePTS; // State whether pts out of decoding process should be used -+ -+ /* FIXME : Rework is still required for fields below this line */ -+ -+ /* create a real class and share with openmax ? */ -+ // bitstream to bytestream (Annex B) conversion support. -+ bool bitstream_convert_init(void *in_extradata, int in_extrasize); -+ bool bitstream_convert(BYTE* pData, int iSize, uint8_t **poutbuf, int *poutbuf_size); -+ static void bitstream_alloc_and_copy( uint8_t **poutbuf, int *poutbuf_size, -+ const uint8_t *sps_pps, uint32_t sps_pps_size, const uint8_t *in, uint32_t in_size); -+ typedef struct omx_bitstream_ctx { -+ uint8_t length_size; -+ uint8_t first_idr; -+ uint8_t *sps_pps_data; -+ uint32_t size; -+ omx_bitstream_ctx() -+ { -+ length_size = 0; -+ first_idr = 0; -+ sps_pps_data = NULL; -+ size = 0; -+ } -+ } omx_bitstream_ctx; -+ uint32_t m_sps_pps_size; -+ omx_bitstream_ctx m_sps_pps_context; -+ bool m_convert_bitstream; -+ ++ VpuDecOutFrameInfo m_frameInfo; ++ CBitstreamConverter *m_converter; ++ bool m_convert_bitstream; +}; -diff -Naur xbmc-gotham-latest.test/xbmc/cores/dvdplayer/DVDCodecs/Video/Makefile.in xbmc-wolfgar-imx-wip.test/xbmc/cores/dvdplayer/DVDCodecs/Video/Makefile.in ---- xbmc-gotham-latest.test/xbmc/cores/dvdplayer/DVDCodecs/Video/Makefile.in 2014-02-09 01:41:14.966138502 +0100 -+++ xbmc-wolfgar-imx-wip.test/xbmc/cores/dvdplayer/DVDCodecs/Video/Makefile.in 2014-02-09 01:40:25.810083206 +0100 -@@ -23,6 +23,22 @@ +diff -Naur xbmc-gotham-latest.test/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecInfo.h xbmc-imx6.test/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecInfo.h +--- xbmc-gotham-latest.test/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecInfo.h 1970-01-01 01:00:00.000000000 +0100 ++++ xbmc-imx6.test/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecInfo.h 2014-02-19 22:25:21.444528775 +0100 +@@ -0,0 +1,38 @@ ++/* ++ * Copyright (C) 2010-2013 Team XBMC ++ * http://xbmc.org ++ * ++ * This Program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2, or (at your option) ++ * any later version. ++ * ++ * This Program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with XBMC; see the file COPYING. If not, see ++ * . ++ * ++ */ ++ ++#ifndef DVDVIDEOCODECINFO_H ++#define DVDVIDEOCODECINFO_H ++ ++class CDVDVideoCodecBuffer ++{ ++public: ++ // reference counting ++ virtual void Lock() = 0; ++ virtual long Release() = 0; ++ virtual bool IsValid() = 0; ++ ++ uint32_t iWidth; ++ uint32_t iHeight; ++ uint8_t* data[4]; // [4] = alpha channel, currently not used ++ int iLineSize[4]; // [4] = alpha channel, currently not used ++}; ++ ++#endif // DVDVIDEOCODECINFO_H +diff -Naur xbmc-gotham-latest.test/xbmc/cores/dvdplayer/DVDCodecs/Video/Makefile.in xbmc-imx6.test/xbmc/cores/dvdplayer/DVDCodecs/Video/Makefile.in +--- xbmc-gotham-latest.test/xbmc/cores/dvdplayer/DVDCodecs/Video/Makefile.in 2014-02-19 22:24:45.332494853 +0100 ++++ xbmc-imx6.test/xbmc/cores/dvdplayer/DVDCodecs/Video/Makefile.in 2014-02-19 22:25:21.443528774 +0100 +@@ -24,6 +24,9 @@ SRCS += OpenMaxVideo.cpp SRCS += DVDVideoCodecOpenMax.cpp endif +ifeq (@USE_IMXVPU@,1) -+SRCS += DVDVideoCodecIMX.cpp mfw_gst_ts.c ++SRCS += DVDVideoCodecIMX.cpp +endif -+ -+ifeq (@USE_LIBSTAGEFRIGHT@,1) -+SRCS += StageFrightVideo.cpp -+SRCS += StageFrightVideoPrivate.cpp -+SRCS += DVDVideoCodecStageFright.cpp -+INCLUDES += -I${prefix}/opt/android-source/frameworks/base/include -+INCLUDES += -I${prefix}/opt/android-source/frameworks/base/native/include -+INCLUDES += -I${prefix}/opt/android-source/frameworks/base/include/media/stagefright -+INCLUDES += -I${prefix}/opt/android-source/frameworks/base/include/media/stagefright/openmax -+INCLUDES += -I${prefix}/opt/android-source/system/core/include -+INCLUDES += -I${prefix}/opt/android-source/libhardware/include -+endif -+ ifeq (@USE_LIBAMCODEC@,1) SRCS += AMLCodec.cpp SRCS += DVDVideoCodecAmlogic.cpp -diff -Naur xbmc-gotham-latest.test/xbmc/cores/dvdplayer/DVDCodecs/Video/mfw_gst_ts.c xbmc-wolfgar-imx-wip.test/xbmc/cores/dvdplayer/DVDCodecs/Video/mfw_gst_ts.c ---- xbmc-gotham-latest.test/xbmc/cores/dvdplayer/DVDCodecs/Video/mfw_gst_ts.c 1970-01-01 01:00:00.000000000 +0100 -+++ xbmc-wolfgar-imx-wip.test/xbmc/cores/dvdplayer/DVDCodecs/Video/mfw_gst_ts.c 2014-02-09 01:40:25.855083256 +0100 -@@ -0,0 +1,752 @@ -+/* -+ * Copyright (c) 2010-2012, Freescale Semiconductor, Inc. All rights reserved. -+ * -+ */ -+ -+/* -+ * This library is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU Library General Public -+ * License as published by the Free Software Foundation; either -+ * version 2 of the License, or (at your option) any later version. -+ * -+ * This library is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * Library General Public License for more details. -+ * -+ * You should have received a copy of the GNU Library General Public -+ * License along with this library; if not, write to the -+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330, -+ * Boston, MA 02111-1307, USA. -+ */ -+ -+/* -+ * Module Name: TimeStamp.c -+ * -+ * Description: include TimeStamp stratege for VPU / SW video decoder plugin -+ * -+ * Portability: This code is written for Linux OS and Gstreamer -+ */ -+ -+/* -+ * Changelog: -+ 11/2/2010 draft version Lyon Wang -+ * -+ */ -+#include -+#include -+#include -+ -+#include "mfw_gst_ts.h" -+ -+ -+const char *debug_env = "ME_DEBUG"; -+char *debug = NULL; -+int debug_level = 0; -+ -+ -+enum -+{ -+ DEBUG_LEVEL_ERROR = 1, -+ DEBUG_LEVEL_WARNING, -+ DEBUG_LEVEL_LOG, -+ DEBUG_LEVEL_VERBOSE, -+}; -+ -+ -+#define TSM_MESSAGE(level, fmt, ...)\ -+ do{\ -+ if (debug_level>=(level)){\ -+ printf("TSM:"fmt, ##__VA_ARGS__);\ -+ }\ -+ }while(0) -+ -+#define TSM_ERROR(...) TSM_MESSAGE(DEBUG_LEVEL_ERROR, ##__VA_ARGS__) -+#define TSM_WARNING(...) TSM_MESSAGE(DEBUG_LEVEL_WARNING, ##__VA_ARGS__) -+#define TSM_LOG(...) TSM_MESSAGE(DEBUG_LEVEL_LOG, ##__VA_ARGS__) -+#define TSM_VERBOSE(...) TSM_MESSAGE(DEBUG_LEVEL_VERBOSE, ##__VA_ARGS__) -+ -+#define TSM_HISTORY_POWER 5 -+#define TSM_HISTORY_SIZE (1<dur_history_total>>TSM_HISTORY_POWER) -+ -+#define TSM_SECOND ((TSM_TIMESTAMP)1000000000) -+#define TSM_DEFAULT_INTERVAL (TSM_SECOND/30) -+#define TSM_DEFAULT_TS_BUFFER_SIZE (128) -+ -+#define TSM_TS_IS_VALID(ts) \ -+ ((ts) != TSM_TIMESTAMP_NONE) -+ -+#define TSM_KEY_IS_VALID(key) \ -+ ((key) != TSM_KEY_NONE) -+ -+#define TSM_DISTANCE(tsm)\ -+ (((tsm->rx)>=(tsm->tx))?((tsm->rx)-(tsm->tx)):(tsm->ts_buf_size-(tsm->tx)+(tsm->rx))) -+ -+#define TSM_PLUS_AGE(tsm)\ -+ (TSM_DISTANCE(tsm)+tsm->invalid_ts_count+2) -+ -+#define TSM_ABS(ts0, ts1)\ -+ (((ts0)>(ts1))?((ts0)-(ts1)):((ts1)-(ts0))) -+ -+#define TSM_TIME_FORMAT "u:%02u:%02u.%09u" -+ -+#define TSM_TIME_ARGS(t) \ -+ TSM_TS_IS_VALID (t) ? \ -+ (unsigned int) (((TSM_TIMESTAMP)(t)) / (TSM_SECOND * 60 * 60)) : 99, \ -+ TSM_TS_IS_VALID (t) ? \ -+ (unsigned int) ((((TSM_TIMESTAMP)(t)) / (TSM_SECOND * 60)) % 60) : 99, \ -+ TSM_TS_IS_VALID (t) ? \ -+ (unsigned int) ((((TSM_TIMESTAMP)(t)) / TSM_SECOND) % 60) : 99, \ -+ TSM_TS_IS_VALID (t) ? \ -+ (unsigned int) (((TSM_TIMESTAMP)(t)) % TSM_SECOND) : 999999999 -+ -+#define TSM_BUFFER_SET(buf, value, size) \ -+ do {\ -+ int i;\ -+ for (i=0;i<(size);i++){\ -+ (buf)[i] = (value);\ -+ }\ -+ }while(0) -+ -+#define TSM_RECEIVED_NUNBER 512 -+ -+ -+typedef struct -+{ -+ TSM_TIMESTAMP ts; -+ unsigned long long age; -+ void *key; -+} TSMControl; -+ -+typedef struct _TSMReceivedEntry -+{ -+ TSM_TIMESTAMP ts; -+ struct _TSMReceivedEntry *next; -+ unsigned int used:1; -+ unsigned int subentry:1; -+ int size; -+} TSMReceivedEntry; -+ -+typedef struct _TSMReceivedEntryMemory -+{ -+ struct _TSMReceivedEntryMemory *next; -+ TSMReceivedEntry entrys[TSM_RECEIVED_NUNBER]; -+} TSMReceivedEntryMemory; -+ -+typedef struct -+{ -+ TSMReceivedEntry *head; -+ TSMReceivedEntry *tail; -+ TSMReceivedEntry *free; -+ TSMReceivedEntryMemory *memory; -+ int cnt; -+} TSMRecivedCtl; -+ -+typedef struct _TSManager -+{ -+ int first_tx; -+ int first_rx; -+ int rx; //timestamps received -+ int tx; //timestamps transfered -+ TSM_TIMESTAMP last_ts_sent; //last time stamp sent -+ TSM_TIMESTAMP last_ts_received; -+ TSM_TIMESTAMP suspicious_ts; -+ -+ TSM_TIMESTAMP discont_threshold; -+ -+ unsigned int invalid_ts_count; -+ TSMGR_MODE mode; -+ int ts_buf_size; -+ int dur_history_tx; -+ TSM_TIMESTAMP dur_history_total; -+ TSM_TIMESTAMP dur_history_buf[TSM_HISTORY_SIZE]; -+ TSMControl *ts_buf; -+ unsigned long long age; -+ int tx_cnt; -+ int rx_cnt; -+ int cnt; -+ int valid_ts_received:1; -+ int big_cnt; -+ -+ TSMRecivedCtl rctl; -+} TSManager; -+ -+ -+static void -+tsm_free_received_entry (TSMRecivedCtl * rctl, TSMReceivedEntry * entry) -+{ -+ entry->next = rctl->free; -+ rctl->free = entry; -+} -+ -+ -+static TSMReceivedEntry * -+tsm_new_received_entry (TSMRecivedCtl * rctl) -+{ -+ TSMReceivedEntry *ret = NULL; -+ if (rctl->free) { -+ ret = rctl->free; -+ rctl->free = ret->next; -+ } else { -+ TSMReceivedEntryMemory *p = malloc (sizeof (TSMReceivedEntryMemory)); -+ if (p) { -+ int i; -+ for (i = 1; i < TSM_RECEIVED_NUNBER; i++) { -+ TSMReceivedEntry *e = &p->entrys[i]; -+ tsm_free_received_entry (rctl, e); -+ }; -+ -+ p->next = rctl->memory; -+ rctl->memory = p; -+ -+ ret = p->entrys; -+ } -+ } -+ return ret; -+} -+ -+ -+void -+TSManagerReceive2 (void *handle, TSM_TIMESTAMP timestamp, int size) -+{ -+#define CLEAR_TSM_RENTRY(entry)\ -+ do { \ -+ (entry)->used = 0; \ -+ (entry)->subentry = 0; \ -+ (entry)->next = NULL; \ -+ } while (0) -+ TSManager *tsm = (TSManager *) handle; -+ -+ TSM_VERBOSE ("receive2 %" TSM_TIME_FORMAT " size %d\n", -+ TSM_TIME_ARGS (timestamp), size); -+ -+ if (tsm) { -+ if (size > 0) { -+ TSMRecivedCtl *rctl = &tsm->rctl; -+ TSMReceivedEntry *e = tsm_new_received_entry (rctl); -+ if (e) { -+ CLEAR_TSM_RENTRY (e); -+ if ((rctl->tail) && (rctl->tail->ts == timestamp)) { -+ e->subentry = 1; -+ } -+ e->ts = timestamp; -+ e->size = size; -+ if (rctl->tail) { -+ rctl->tail->next = e; -+ rctl->tail = e; -+ } else { -+ rctl->head = rctl->tail = e; -+ } -+ } -+ rctl->cnt++; -+ } else { -+ TSManagerReceive (handle, timestamp); -+ } -+ } -+} -+ -+ -+static TSM_TIMESTAMP -+TSManagerGetLastTimeStamp (TSMRecivedCtl * rctl, int size, int use) -+{ -+ TSM_TIMESTAMP ts = TSM_TIMESTAMP_NONE; -+ TSMReceivedEntry *e; -+ while ((size > 0) && (e = rctl->head)) { -+ ts = ((e->used) ? (TSM_TIMESTAMP_NONE) : (e->ts)); -+ if (use) -+ e->used = 1; -+ if (size >= e->size) { -+ rctl->head = e->next; -+ if (rctl->head == NULL) { -+ rctl->tail = NULL; -+ } else { -+ if (rctl->head->subentry) { -+ rctl->head->used = e->used; -+ } -+ } -+ size -= e->size; -+ rctl->cnt--; -+ tsm_free_received_entry (rctl, e); -+ } else { -+ e->size -= size; -+ size = 0; -+ } -+ } -+ return ts; -+} -+ -+ -+void -+TSManagerFlush2 (void *handle, int size) -+{ -+ TSManager *tsm = (TSManager *) handle; -+ if (tsm) { -+ TSManagerGetLastTimeStamp (&tsm->rctl, size, 0); -+ } -+ -+} -+ -+ -+/*====================================================================================== -+FUNCTION: mfw_gst_receive_ts -+ -+DESCRIPTION: Check timestamp and do frame dropping if enabled -+ -+ARGUMENTS PASSED: pTimeStamp_Object - TimeStamp Manager to handle related timestamp -+ timestamp - time stamp of the input buffer which has video data. -+ -+RETURN VALUE: None -+PRE-CONDITIONS: None -+POST-CONDITIONS: None -+IMPORTANT NOTES: None -+=======================================================================================*/ -+static void -+_TSManagerReceive (void *handle, TSM_TIMESTAMP timestamp, void *key) -+{ -+ TSManager *tsm = (TSManager *) handle; -+ -+ if (tsm) { -+ if (TSM_TS_IS_VALID (timestamp) && (tsm->rx_cnt)) -+ tsm->valid_ts_received = 1; -+ tsm->rx_cnt++; -+ if (tsm->cnt < tsm->ts_buf_size - 1) { -+ tsm->cnt++; -+ if (tsm->mode == MODE_AI) { -+ -+ if (TSM_TS_IS_VALID (timestamp)) { -+ if (tsm->first_rx) { -+ tsm->last_ts_received = timestamp; -+ tsm->first_rx = 0; -+ } else { -+ if (tsm->suspicious_ts) { -+ if (timestamp >= tsm->suspicious_ts) { -+ tsm->last_ts_received = timestamp; -+ } -+ tsm->suspicious_ts = 0; -+ } -+ if ((timestamp > tsm->last_ts_received) -+ && (timestamp - tsm->last_ts_received > tsm->discont_threshold)) { -+ tsm->suspicious_ts = timestamp; -+ timestamp = TSM_TIMESTAMP_NONE; -+ } -+ } -+ } -+ -+ if (TSM_TS_IS_VALID (timestamp)) // && (TSM_ABS(timestamp, tsm->last_ts_sent)ts_buf[tsm->rx].ts = timestamp; -+ tsm->ts_buf[tsm->rx].age = tsm->age + TSM_PLUS_AGE (tsm); -+ tsm->ts_buf[tsm->rx].key = key; -+ tsm->last_ts_received = timestamp; -+#ifdef DEBUG -+ //printf("age should %lld %lld\n", tsm->age, tsm->ts_buf[tsm->rx].age); -+ //printf("++++++ distance = %d tx=%d, rx=%d, invalid count=%d\n", TSM_DISTANCE(tsm), tsm->tx, tsm->rx,tsm->invalid_ts_count); -+#endif -+ tsm->rx = ((tsm->rx + 1) % tsm->ts_buf_size); -+ } else { -+ tsm->invalid_ts_count++; -+ } -+ } else if (tsm->mode == MODE_FIFO) { -+ tsm->ts_buf[tsm->rx].ts = timestamp; -+ tsm->rx = ((tsm->rx + 1) % tsm->ts_buf_size); -+ } -+ TSM_LOG ("++Receive %d:%" TSM_TIME_FORMAT -+ ", invalid:%d, size:%d key %p\n", tsm->rx_cnt, -+ TSM_TIME_ARGS (timestamp), tsm->invalid_ts_count, tsm->cnt, key); -+ } else { -+ TSM_ERROR ("Too many timestamps recieved!! (cnt=%d)\n", tsm->cnt); -+ } -+ } -+} -+ -+ -+void -+TSManagerValid2 (void *handle, int size, void *key) -+{ -+ TSManager *tsm = (TSManager *) handle; -+ -+ TSM_VERBOSE ("valid2 size %d\n", size); -+ -+ if (tsm) { -+ TSM_TIMESTAMP ts; -+ ts = TSManagerGetLastTimeStamp (&tsm->rctl, size, 1); -+ _TSManagerReceive (tsm, ts, key); -+ } -+} -+ -+ -+void -+TSManagerReceive (void *handle, TSM_TIMESTAMP timestamp) -+{ -+ _TSManagerReceive (handle, timestamp, TSM_KEY_NONE); -+} -+ -+ -+/*====================================================================================== -+FUNCTION: TSManagerSend -+ -+DESCRIPTION: Check timestamp and do frame dropping if enabled -+ -+ARGUMENTS PASSED: pTimeStamp_Object - TimeStamp Manager to handle related timestamp -+ ptimestamp - returned timestamp to use at render -+ -+RETURN VALUE: None -+PRE-CONDITIONS: None -+POST-CONDITIONS: None -+IMPORTANT NOTES: None -+=======================================================================================*/ -+static TSM_TIMESTAMP -+_TSManagerSend2 (void *handle, void *key, int send) -+{ -+ TSManager *tsm = (TSManager *) handle; -+ int i = tsm->tx; -+ int index = -1; -+ TSM_TIMESTAMP ts0 = 0, tstmp = TSM_TIMESTAMP_NONE; -+ unsigned long long age = 0; -+ TSM_TIMESTAMP half_interval = TSM_ADAPTIVE_INTERVAL (tsm) >> 1; -+ -+ if (tsm) { -+ if (send) { -+ tsm->tx_cnt++; -+ } else { -+ tsm->cnt++; -+ tsm->invalid_ts_count++; -+ } -+ if (tsm->cnt > 0) { -+ if (send) { -+ tsm->cnt--; -+ } -+ if (tsm->mode == MODE_AI) { -+ -+ if (tsm->first_tx == 0) { -+ tstmp = tsm->last_ts_sent + TSM_ADAPTIVE_INTERVAL (tsm); -+ } else { -+ tstmp = tsm->last_ts_sent; -+ } -+ -+ while (i != tsm->rx) { -+ if (index >= 0) { -+ if (tsm->ts_buf[i].ts < ts0) { -+ ts0 = tsm->ts_buf[i].ts; -+ age = tsm->ts_buf[i].age; -+ index = i; -+ } -+ } else { -+ ts0 = tsm->ts_buf[i].ts; -+ age = tsm->ts_buf[i].age; -+ index = i; -+ } -+ if ((TSM_KEY_IS_VALID (key)) && (key == tsm->ts_buf[i].key)) -+ break; -+ i = ((i + 1) % tsm->ts_buf_size); -+ } -+ if (index >= 0) { -+ if ((tsm->invalid_ts_count) && (ts0 >= ((tstmp) + half_interval)) -+ && (age > tsm->age)) { -+ /* use calculated ts0 */ -+ if (send) { -+ tsm->invalid_ts_count--; -+ } -+ } else { -+ -+ if (send) { -+ if (index != tsm->tx) { -+ tsm->ts_buf[index] = tsm->ts_buf[tsm->tx]; -+ } -+ tsm->tx = ((tsm->tx + 1) % tsm->ts_buf_size); -+ -+ } -+#if 0 -+ if (ts0 >= ((tstmp) + half_interval)) -+ tstmp = tstmp; -+ else -+ tstmp = ts0; -+#else -+ tstmp = ts0; -+#endif -+ } -+ -+ } else { -+ if (send) { -+ tsm->invalid_ts_count--; -+ } -+ } -+ -+ if (tsm->first_tx == 0) { -+ -+ if (tstmp > tsm->last_ts_sent) { -+ ts0 = (tstmp - tsm->last_ts_sent); -+ } else { -+ ts0 = 0; -+ tstmp = tsm->last_ts_sent; -+ } -+ -+ if (ts0 > TSM_ADAPTIVE_INTERVAL (tsm) * 3 / 2) { -+ TSM_WARNING ("Jitter1:%" TSM_TIME_FORMAT " %" TSM_TIME_FORMAT "\n", -+ TSM_TIME_ARGS (ts0), -+ TSM_TIME_ARGS (TSM_ADAPTIVE_INTERVAL (tsm) * 3 / 2)); -+ } else if (ts0 == 0) { -+ TSM_WARNING ("Jitter:%" TSM_TIME_FORMAT "\n", TSM_TIME_ARGS (ts0)); -+ } -+ -+ if (send) { -+ if ((ts0 < TSM_ADAPTIVE_INTERVAL (tsm) * 2) || (tsm->big_cnt > 3)) { -+ tsm->big_cnt = 0; -+ tsm->dur_history_total -= -+ tsm->dur_history_buf[tsm->dur_history_tx]; -+ tsm->dur_history_buf[tsm->dur_history_tx] = ts0; -+ tsm->dur_history_tx = -+ ((tsm->dur_history_tx + 1) % TSM_HISTORY_SIZE); -+ tsm->dur_history_total += ts0; -+ } else { -+ tsm->big_cnt++; -+ } -+ } -+ } -+ -+ if (send) { -+ tsm->last_ts_sent = tstmp; -+ tsm->age++; -+ tsm->first_tx = 0; -+ } -+ -+ } else if (tsm->mode == MODE_FIFO) { -+ tstmp = tsm->ts_buf[tsm->tx].ts; -+ if (send) { -+ tsm->tx = ((tsm->tx + 1) % tsm->ts_buf_size); -+ } -+ ts0 = tstmp - tsm->last_ts_sent; -+ if (send) { -+ tsm->last_ts_sent = tstmp; -+ } -+ } -+ -+ if (send) { -+ TSM_LOG ("--Send %d:%" TSM_TIME_FORMAT ", int:%" TSM_TIME_FORMAT -+ ", avg:%" TSM_TIME_FORMAT " inkey %p\n", tsm->tx_cnt, -+ TSM_TIME_ARGS (tstmp), TSM_TIME_ARGS (ts0), -+ TSM_TIME_ARGS (TSM_ADAPTIVE_INTERVAL (tsm)), key); -+ } -+ -+ } else { -+ if (tsm->valid_ts_received == 0) { -+ if (tsm->first_tx) { -+ tstmp = tsm->last_ts_sent; -+ } else { -+ tstmp = tsm->last_ts_sent + TSM_ADAPTIVE_INTERVAL (tsm); -+ } -+ if (send) { -+ tsm->first_tx = 0; -+ tsm->last_ts_sent = tstmp; -+ } -+ } -+ TSM_ERROR ("Too many timestamps send!!\n"); -+ } -+ -+ if (send == 0) { -+ tsm->cnt--; -+ tsm->invalid_ts_count--; -+ } -+ -+ } -+ -+ return tstmp; -+} -+ -+ -+TSM_TIMESTAMP -+TSManagerSend2 (void *handle, void *key) -+{ -+ return _TSManagerSend2 (handle, key, 1); -+} -+ -+ -+TSM_TIMESTAMP -+TSManagerQuery2 (void *handle, void *key) -+{ -+ return _TSManagerSend2 (handle, key, 0); -+} -+ -+ -+TSM_TIMESTAMP -+TSManagerSend (void *handle) -+{ -+ return TSManagerSend2 (handle, TSM_KEY_NONE); -+} -+ -+ -+TSM_TIMESTAMP -+TSManagerQuery (void *handle) -+{ -+ return TSManagerQuery2 (handle, TSM_KEY_NONE); -+} -+ -+ -+void -+resyncTSManager (void *handle, TSM_TIMESTAMP synctime, TSMGR_MODE mode) -+{ -+ TSManager *tsm = (TSManager *) handle; -+ if (tsm) { -+ TSMRecivedCtl *rctl = &tsm->rctl; -+ TSMReceivedEntry *e = rctl->head; -+ -+ while ((e = rctl->head)) { -+ rctl->head = e->next; -+ tsm_free_received_entry (rctl, e); -+ }; -+ rctl->cnt = 0; -+ -+ rctl->tail = NULL; -+ -+ tsm->first_tx = 1; -+ tsm->first_rx = 1; -+ tsm->suspicious_ts = 0; -+ -+ if (TSM_TS_IS_VALID (synctime)) -+ tsm->last_ts_sent = synctime; -+ -+ tsm->tx = tsm->rx = 0; -+ tsm->invalid_ts_count = 0; -+ tsm->mode = mode; -+ tsm->age = 0; -+ tsm->rx_cnt = tsm->tx_cnt = tsm->cnt = 0; -+ tsm->valid_ts_received = 0; -+ -+ tsm->big_cnt = 0; -+ } -+} -+ -+ -+/*====================================================================================== -+FUNCTION: mfw_gst_init_ts -+ -+DESCRIPTION: malloc and initialize timestamp strcture -+ -+ARGUMENTS PASSED: ppTimeStamp_Object - pointer of TimeStamp Manager to handle related timestamp -+ -+RETURN VALUE: TimeStamp structure pointer -+PRE-CONDITIONS: None -+POST-CONDITIONS: None -+IMPORTANT NOTES: None -+=======================================================================================*/ -+void * -+createTSManager (int ts_buf_size) -+{ -+ TSManager *tsm = (TSManager *) malloc (sizeof (TSManager)); -+ debug = getenv (debug_env); -+ if (debug) { -+ debug_level = atoi (debug); -+ } -+ // printf("debug = %s \n ++++++++++++++++++++++++++++",debug); -+ if (tsm) { -+ memset (tsm, 0, sizeof (TSManager)); -+ if (ts_buf_size <= 0) { -+ ts_buf_size = TSM_DEFAULT_TS_BUFFER_SIZE; -+ } -+ tsm->ts_buf_size = ts_buf_size; -+ tsm->ts_buf = malloc (sizeof (TSMControl) * ts_buf_size); -+ -+ if (tsm->ts_buf == NULL) { -+ goto fail; -+ } -+ -+ resyncTSManager (tsm, (TSM_TIMESTAMP) 0, MODE_AI); -+ -+ tsm->dur_history_tx = 0; -+ TSM_BUFFER_SET (tsm->dur_history_buf, TSM_DEFAULT_INTERVAL, -+ TSM_HISTORY_SIZE); -+ tsm->dur_history_total = TSM_DEFAULT_INTERVAL << TSM_HISTORY_POWER; -+ -+ tsm->discont_threshold = 10000000000LL; // 10s -+ } -+ return tsm; -+fail: -+ if (tsm) { -+ if (tsm->ts_buf) { -+ free (tsm->ts_buf); -+ } -+ free (tsm); -+ tsm = NULL; -+ } -+ return tsm; -+} -+ -+ -+void -+destroyTSManager (void *handle) -+{ -+ TSManager *tsm = (TSManager *) handle; -+ if (tsm) { -+ TSMRecivedCtl *rctl = &tsm->rctl; -+ TSMReceivedEntryMemory *rmem; -+ if (tsm->ts_buf) { -+ free (tsm->ts_buf); -+ } -+ -+ while ((rmem = rctl->memory)) { -+ rctl->memory = rmem->next; -+ free (rmem); -+ } -+ free (tsm); -+ tsm = NULL; -+ } -+} -+ -+ -+void -+setTSManagerFrameRate (void *handle, int fps_n, int fps_d) -+//void setTSManagerFrameRate(void * handle, float framerate) -+{ -+ TSManager *tsm = (TSManager *) handle; -+ TSM_TIMESTAMP ts; -+ if ((fps_n > 0) && (fps_d > 0) && (fps_n / fps_d <= 80)) -+ ts = TSM_SECOND * fps_d / fps_n; -+ else -+ ts = TSM_DEFAULT_INTERVAL; -+ // TSM_TIMESTAMP ts = TSM_SECOND / framerate; -+ -+ if (tsm) { -+ TSM_BUFFER_SET (tsm->dur_history_buf, ts, TSM_HISTORY_SIZE); -+ tsm->dur_history_total = (ts << TSM_HISTORY_POWER); -+ if (debug) -+ TSM_LOG ("Set frame intrval:%" TSM_TIME_FORMAT "\n", TSM_TIME_ARGS (ts)); -+ } -+} -+ -+ -+TSM_TIMESTAMP -+getTSManagerFrameInterval (void *handle) -+{ -+ TSManager *tsm = (TSManager *) handle; -+ TSM_TIMESTAMP ts = 0; -+ if (tsm) { -+ ts = TSM_ADAPTIVE_INTERVAL (tsm); -+ } -+ return ts; -+} -+ -+ -+TSM_TIMESTAMP -+getTSManagerPosition (void *handle) -+{ -+ TSManager *tsm = (TSManager *) handle; -+ TSM_TIMESTAMP ts = 0; -+ if (tsm) { -+ ts = tsm->last_ts_sent; -+ } -+ return ts; -+} -+ -+ -+int -+getTSManagerPreBufferCnt (void *handle) -+{ -+ int i = 0; -+ TSManager *tsm = (TSManager *) handle; -+ if (tsm) { -+ i = tsm->rctl.cnt; -+ } -+ return i; -+} -diff -Naur xbmc-gotham-latest.test/xbmc/cores/dvdplayer/DVDCodecs/Video/mfw_gst_ts.h xbmc-wolfgar-imx-wip.test/xbmc/cores/dvdplayer/DVDCodecs/Video/mfw_gst_ts.h ---- xbmc-gotham-latest.test/xbmc/cores/dvdplayer/DVDCodecs/Video/mfw_gst_ts.h 1970-01-01 01:00:00.000000000 +0100 -+++ xbmc-wolfgar-imx-wip.test/xbmc/cores/dvdplayer/DVDCodecs/Video/mfw_gst_ts.h 2014-02-09 01:40:25.830083229 +0100 -@@ -0,0 +1,170 @@ -+/* -+ * Copyright (c) 2010-2012, Freescale Semiconductor, Inc. All rights reserved. -+ * -+ */ -+ -+/* -+ * This library is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU Library General Public -+ * License as published by the Free Software Foundation; either -+ * version 2 of the License, or (at your option) any later version. -+ * -+ * This library is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * Library General Public License for more details. -+ * -+ * You should have received a copy of the GNU Library General Public -+ * License along with this library; if not, write to the -+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330, -+ * Boston, MA 02111-1307, USA. -+ */ -+ -+/* -+ * Module Name: TimeStamp.h -+ * -+ * Description: include TimeStamp stratege for VPU / SW video decoder plugin -+ * -+ * Portability: This code is written for Linux OS and Gstreamer -+ */ -+ -+/* -+ * Changelog: -+ 11/2/2010 draft version Lyon Wang -+ * -+ */ -+ -+#ifndef _TIMESTAMP_H_ -+#define _TIMESTAMP_H_ -+ -+ -+/** -+ * GST_CLOCK_TIME_NONE: -+ * -+ * Constant to define an undefined clock time. -+ */ -+ -+typedef long long TSM_TIMESTAMP; -+ -+typedef enum -+{ -+ MODE_AI, -+ MODE_FIFO, -+} TSMGR_MODE; -+ -+#define TSM_TIMESTAMP_NONE ((long long)(-1)) -+#define TSM_KEY_NONE ((void *)0) -+ -+/** -+ * GST_CLOCK_TIME_IS_VALID: -+ * @time: clock time to validate -+ * -+ * Tests if a given #GstClockTime represents a valid defined time. -+ */ -+ -+#ifdef __cplusplus -+#define EXTERN -+#else -+#define EXTERN extern -+#endif -+ -+#ifdef __cplusplus -+extern "C" -+{ -+#endif -+ -+/*! -+ * This function receive timestamp into timestamp manager. -+ * -+ * @param handle handle of timestamp manager. -+ * -+ * @param timestamp timestamp received -+ * -+ * @return -+ */ -+ EXTERN void TSManagerReceive (void *handle, TSM_TIMESTAMP timestamp); -+ -+ EXTERN void TSManagerReceive2 (void *handle, TSM_TIMESTAMP timestamp, -+ int size); -+ -+ EXTERN void TSManagerFlush2 (void *handle, int size); -+ -+ EXTERN void TSManagerValid2 (void *handle, int size, void *key); -+ -+/*! -+ * This function send the timestamp for next output frame. -+ * -+ * @param handle handle of timestamp manager. -+ * -+ * @return timestamp for next output frame. -+ */ -+ EXTERN TSM_TIMESTAMP TSManagerSend (void *handle); -+ -+ EXTERN TSM_TIMESTAMP TSManagerSend2 (void *handle, void *key); -+ -+ EXTERN TSM_TIMESTAMP TSManagerQuery2 (void *handle, void *key); -+ -+ EXTERN TSM_TIMESTAMP TSManagerQuery (void *handle); -+/*! -+ * This function resync timestamp handler when reset and seek -+ * -+ * @param handle handle of timestamp manager. -+ * -+ * @param synctime the postion time needed to set, if value invalid, position keeps original -+ * -+ * @param mode playing mode (AI or FIFO) -+ * -+ * @return -+ */ -+ EXTERN void resyncTSManager (void *handle, TSM_TIMESTAMP synctime, -+ TSMGR_MODE mode); -+/*! -+ * This function create and reset timestamp handler -+ * -+ * @param ts_buf_size time stamp queue buffer size -+ * -+ * @return -+ */ -+ EXTERN void *createTSManager (int ts_buf_size); -+/*! -+ * This function destory timestamp handler -+ * -+ * @param handle handle of timestamp manager. -+ * -+ * @return -+ */ -+ EXTERN void destroyTSManager (void *handle); -+/*! -+ * This function set history buffer frame interval by fps_n and fps_d -+ * -+ * @param handle handle of timestamp manager. -+ * -+ * @param framerate the framerate to be set -+ * -+ * @return -+ */ -+ EXTERN void setTSManagerFrameRate (void *handle, int fps_n, int fps_d); -+//EXTERN void setTSManagerFrameRate(void * handle, float framerate); -+/*! -+ * This function set the current calculated Frame Interval -+ * -+ * @param handle handle of timestamp manager. -+ * -+ * @return -+ */ -+ EXTERN TSM_TIMESTAMP getTSManagerFrameInterval (void *handle); -+/*! -+ * This function get the current time stamp postion -+ * -+ * @param handle handle of timestamp manager. -+ * -+ * @return -+ */ -+ EXTERN TSM_TIMESTAMP getTSManagerPosition (void *handle); -+ EXTERN int getTSManagerPreBufferCnt (void *handle); -+ -+#ifdef __cplusplus -+} -+#endif -+ -+#endif /*_TIMESTAMP_H_ */ -diff -Naur xbmc-gotham-latest.test/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp xbmc-wolfgar-imx-wip.test/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp ---- xbmc-gotham-latest.test/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp 2014-02-09 01:41:15.126138681 +0100 -+++ xbmc-wolfgar-imx-wip.test/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp 2014-02-09 01:40:26.047083473 +0100 -@@ -994,6 +994,7 @@ - case RENDER_FMT_CVBREF: return "BGRA"; +diff -Naur xbmc-gotham-latest.test/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp xbmc-imx6.test/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp +--- xbmc-gotham-latest.test/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp 2014-02-19 22:24:45.653495155 +0100 ++++ xbmc-imx6.test/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp 2014-02-19 22:25:21.465528794 +0100 +@@ -995,6 +995,8 @@ case RENDER_FMT_EGLIMG: return "EGLIMG"; case RENDER_FMT_BYPASS: return "BYPASS"; -+ case RENDER_FMT_IMX: return "IMX"; case RENDER_FMT_MEDIACODEC:return "MEDIACODEC"; ++ case RENDER_FMT_YV12_BUFFER: return "YV12BUF"; ++ case RENDER_FMT_IMXMAP: return "IMXMAP"; case RENDER_FMT_NONE: return "NONE"; } -diff -Naur xbmc-gotham-latest.test/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp xbmc-wolfgar-imx-wip.test/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp ---- xbmc-gotham-latest.test/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp 2014-02-09 01:41:14.829138348 +0100 -+++ xbmc-wolfgar-imx-wip.test/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp 2014-02-09 01:40:25.675083053 +0100 -@@ -20,6 +20,10 @@ - - //#define DEBUG_VERBOSE 1 - -+#ifdef HAS_IMXVPU -+#include -+#endif -+ - #include "system.h" - #if (defined HAVE_CONFIG_H) && (!defined TARGET_WINDOWS) - #include "config.h" -@@ -63,6 +67,11 @@ - #ifdef TARGET_DARWIN_IOS - #include "osx/DarwinUtils.h" + return "UNKNOWN"; +diff -Naur xbmc-gotham-latest.test/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp xbmc-imx6.test/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp +--- xbmc-gotham-latest.test/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp 2014-02-19 22:24:45.278494803 +0100 ++++ xbmc-imx6.test/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp 2014-02-19 22:25:21.442528773 +0100 +@@ -26,6 +26,9 @@ #endif -+ + + #if HAS_GLES == 2 +#ifdef HAS_IMXVPU -+#include "DVDCodecs/Video/DVDVideoCodecIMX.h" ++#define GL_GLEXT_PROTOTYPES ++#endif + #include "system_gl.h" + + #include +@@ -76,6 +79,12 @@ + static PFNGLEGLIMAGETARGETTEXTURE2DOESPROC glEGLImageTargetTexture2DOES; + #endif + ++#ifdef HAS_IMXVPU ++// GLES extension functions ++#include ++#include +#endif + - #if defined(HAS_LIBSTAGEFRIGHT) - #include - #include -@@ -100,6 +109,10 @@ + #if defined(TARGET_ANDROID) + #include "DVDCodecs/Video/DVDVideoCodecAndroidMediaCodec.h" + #endif +@@ -100,6 +109,7 @@ #if defined(TARGET_ANDROID) mediacodec = NULL; #endif -+#ifdef HAS_IMXVPU -+ imxOutputFrame = NULL; -+#endif -+ ++ codecinfo = NULL; } CLinuxRendererGLES::YUVBUFFER::~YUVBUFFER() -@@ -110,6 +123,23 @@ - { - m_textureTarget = GL_TEXTURE_2D; - -+ /* FIXME a verifier */ -+#if 0 -+ -+ for (int i = 0; i < NUM_BUFFERS; i++) -+ { -+#if defined(HAVE_LIBOPENMAX) -+ m_buffers[i].openMaxBuffer = 0; -+#endif -+#ifdef HAVE_VIDEOTOOLBOXDECODER -+ m_buffers[i].cvBufferRef = NULL; -+#endif -+#ifdef HAS_IMXVPU -+ m_buffers[i].imx = NULL; -+#endif -+ } -+#endif -+ - m_renderMethod = RENDER_GLSL; - m_oldRenderMethod = m_renderMethod; - m_renderQuality = RQ_SINGLEPASS; -@@ -491,6 +521,8 @@ - - if (m_renderMethod & RENDER_BYPASS) +@@ -279,6 +289,10 @@ { -+ -+ - 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. -@@ -498,18 +530,53 @@ - (*m_RenderUpdateCallBackFn)(m_RenderUpdateCallBackCtx, m_sourceRect, m_destRect); - - CRect old = g_graphicsContext.GetScissors(); -+ RESOLUTION res = GetResolution(); -+ int iWidth = CDisplaySettings::Get().GetResolutionInfo(res).iWidth; -+ int iHeight = CDisplaySettings::Get().GetResolutionInfo(res).iHeight; - - g_graphicsContext.BeginPaint(); -+ if (clear) -+ { -+ glScissor(0, -+ 0, -+ iWidth, -+ iHeight); -+ glClearColor(GLfloat(0.0), GLfloat(0.0), GLfloat(0.0), 0); -+ glClear(GL_COLOR_BUFFER_BIT); -+ } -+ - g_graphicsContext.SetScissors(m_destRect); -+ /* CLog::Log(LOGDEBUG, "%s - m_destRect : %f %f %f %f\n", -+ __FUNCTION__, m_destRect.x1, m_destRect.x2, m_destRect.y1,m_destRect.y2);*/ - -- glEnable(GL_BLEND); -- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); -- glClearColor(0, 0, 0, 0); -+ -+/* glEnable(GL_BLEND); -+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);*/ -+ glClearColor(GLfloat(2.0/31.0), GLfloat(2.0/63.0), GLfloat(2.0/31.0), 0); - glClear(GL_COLOR_BUFFER_BIT); - - g_graphicsContext.SetScissors(old); - g_graphicsContext.EndPaint(); -+ -+#ifdef HAS_IMXVPU -+ // FIXME : move in its own render mode instead of mixup with BYPASS -+ if (m_format == RENDER_FMT_IMX) -+ { -+ int index = m_iYV12RenderBuffer; -+ struct v4l2_crop crop; -+ crop.c.top = (int)m_destRect.y1; -+ crop.c.left = (int)m_destRect.x1; -+ crop.c.width = (int)(m_destRect.x2 - m_destRect.x1); -+ crop.c.height = (int)(m_destRect.y2 - m_destRect.y1); -+ CIMXOutputFrame *imxPicture = m_buffers[index].imxOutputFrame; -+ if (imxPicture != NULL) -+ { -+ imxPicture->Render(crop); -+ m_buffers[index].imxOutputFrame = NULL; -+ } -+ } - return; -+#endif + return source; } ++ if ( m_renderMethod & RENDER_IMXMAP ) ++ { ++ return source; ++ } - // this needs to be checked after texture validation -@@ -597,6 +664,9 @@ #ifdef HAVE_VIDEOTOOLBOXDECODER - m_formats.push_back(RENDER_FMT_CVBREF); + if (m_renderMethod & RENDER_CVREF ) +@@ -604,6 +618,10 @@ + #if defined(TARGET_ANDROID) + m_formats.push_back(RENDER_FMT_MEDIACODEC); #endif ++ m_formats.push_back(RENDER_FMT_YV12_BUFFER); +#ifdef HAS_IMXVPU -+ m_formats.push_back(RENDER_FMT_IMX); ++ m_formats.push_back(RENDER_FMT_IMXMAP); +#endif - #ifdef HAS_LIBSTAGEFRIGHT - m_formats.push_back(RENDER_FMT_EGLIMG); - #endif -@@ -726,6 +796,13 @@ - m_renderMethod = RENDER_CVREF; + + // setup the background colour + m_clearColour = (float)(g_advancedSettings.m_videoBlackBarColour & 0xff) / 0xff; +@@ -715,6 +733,16 @@ + m_renderMethod = RENDER_MEDIACODEC; break; } -+ else if (m_format == RENDER_FMT_IMX) ++ else if (m_format == RENDER_FMT_YV12_BUFFER) + { -+ CLog::Log(LOGNOTICE, "GL: IMX format Uses BYPASS render method"); -+ m_renderMethod = RENDER_BYPASS; ++ CLog::Log(LOGNOTICE, "GL: Using YV12 Buffer render method"); ++ } ++ else if (m_format == RENDER_FMT_IMXMAP) ++ { ++ CLog::Log(LOGNOTICE, "GL: Using IMXMAP render method"); ++ m_renderMethod = RENDER_IMXMAP; + break; + } -+ - #if defined(TARGET_DARWIN_IOS) - else if (ios_version < 5.0 && m_format == RENDER_FMT_YUV420P) + else if (m_format == RENDER_FMT_BYPASS) { -@@ -890,6 +967,18 @@ - SAFE_RELEASE(buf.mediacodec); + CLog::Log(LOGNOTICE, "GL: Using BYPASS render method"); +@@ -807,6 +835,18 @@ + m_textureCreate = &CLinuxRendererGLES::CreateNV12Texture; + m_textureDelete = &CLinuxRendererGLES::DeleteNV12Texture; } - #endif -+#ifdef HAS_IMXVPU -+ if (buf.imxOutputFrame != NULL) ++ else if (m_format == RENDER_FMT_YV12_BUFFER) + { -+ // If we take that branch the buffer was not queued to V4L2 -+ // So release the picture now so that VPU will be given -+ // the buffer back as soon as next ::Decode() call -+ buf.imxOutputFrame->Release(); -+ buf.imxOutputFrame = NULL; ++ m_textureUpload = &CLinuxRendererGLES::UploadYV12BufferTexture; ++ m_textureCreate = &CLinuxRendererGLES::CreateYV12Texture; ++ m_textureDelete = &CLinuxRendererGLES::DeleteYV12Texture; + } -+ return; -+#endif -+ ++ else if (m_format == RENDER_FMT_IMXMAP) ++ { ++ m_textureUpload = &CLinuxRendererGLES::UploadIMXMAPTexture; ++ m_textureCreate = &CLinuxRendererGLES::CreateIMXMAPTexture; ++ m_textureDelete = &CLinuxRendererGLES::DeleteIMXMAPTexture; ++ } + else + { + // default to YV12 texture handlers +@@ -952,6 +992,10 @@ + { + RenderSurfaceTexture(index, m_currentField); + } ++ else if (m_renderMethod & RENDER_IMXMAP) ++ { ++ RenderIMXMAPTexture(index, m_currentField); ++ } + else + { + RenderSoftware(index, m_currentField); +@@ -1156,7 +1200,7 @@ + // imgwidth *= planes[0].pixpertex_x; + // imgheight *= planes[0].pixpertex_y; + // } +-// ++// + // glBegin(GL_QUADS); + // + // glMultiTexCoord2fARB(GL_TEXTURE0, planes[0].rect.x1, planes[0].rect.y1); +@@ -1578,6 +1622,75 @@ + #endif } - void CLinuxRendererGLES::Render(DWORD flags, int index) -@@ -2667,6 +2756,15 @@ - CVBufferRetain(buf.cvBufferRef); - } - #endif ++void CLinuxRendererGLES::RenderIMXMAPTexture(int index, int field) ++{ ++#if defined(HAS_IMXVPU) ++#ifdef DEBUG_VERBOSE ++ unsigned int time = XbmcThreads::SystemClockMillis(); ++#endif + ++ YUVPLANE &plane = m_buffers[index].fields[field][0]; ++ CDVDVideoCodecBuffer* codecinfo = m_buffers[index].codecinfo; ++ ++ if((codecinfo == NULL) || !codecinfo->IsValid()) return; ++ ++ glDisable(GL_DEPTH_TEST); ++ ++ glActiveTexture(GL_TEXTURE0); ++ glBindTexture(m_textureTarget, plane.id); ++ ++ g_Windowing.EnableGUIShader(SM_TEXTURE_RGBA); ++ ++ GLubyte idx[4] = {0, 1, 3, 2}; //determines order of triangle strip ++ GLfloat ver[4][4]; ++ GLfloat tex[4][2]; ++ GLfloat col[3] = {1.0f, 1.0f, 1.0f}; ++ ++ GLint posLoc = g_Windowing.GUIShaderGetPos(); ++ GLint texLoc = g_Windowing.GUIShaderGetCoord0(); ++ GLint colLoc = g_Windowing.GUIShaderGetCol(); ++ ++ glVertexAttribPointer(posLoc, 4, GL_FLOAT, 0, 0, ver); ++ glVertexAttribPointer(texLoc, 2, GL_FLOAT, 0, 0, tex); ++ glVertexAttribPointer(colLoc, 3, GL_FLOAT, 0, 0, col); ++ ++ glEnableVertexAttribArray(posLoc); ++ glEnableVertexAttribArray(texLoc); ++ glEnableVertexAttribArray(colLoc); ++ ++ // Set vertex coordinates ++ for(int i = 0; i < 4; i++) ++ { ++ ver[i][0] = m_rotatedDestCoords[i].x; ++ ver[i][1] = m_rotatedDestCoords[i].y; ++ ver[i][2] = 0.0f;// set z to 0 ++ ver[i][3] = 1.0f; ++ } ++ ++ // Set texture coordinates ++ tex[0][0] = tex[3][0] = plane.rect.x1; ++ tex[0][1] = tex[1][1] = plane.rect.y1; ++ tex[1][0] = tex[2][0] = plane.rect.x2; ++ tex[2][1] = tex[3][1] = plane.rect.y2; ++ ++ glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_BYTE, idx); ++ ++ glDisableVertexAttribArray(posLoc); ++ glDisableVertexAttribArray(texLoc); ++ glDisableVertexAttribArray(colLoc); ++ ++ g_Windowing.DisableGUIShader(); ++ VerifyGLState(); ++ ++ glBindTexture(m_textureTarget, 0); ++ VerifyGLState(); ++ ++#ifdef DEBUG_VERBOSE ++ CLog::Log(LOGDEBUG, "RenderIMXMAPTexture %d: tm:%d\n", index, XbmcThreads::SystemClockMillis() - time); ++#endif ++#endif ++} ++ + bool CLinuxRendererGLES::RenderCapture(CRenderCapture* capture) + { + if (!m_bValidated) +@@ -2299,7 +2412,7 @@ + + glTexParameteri(m_textureTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(m_textureTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR); +- // This is necessary for non-power-of-two textures ++ // This is necessary for non-power-of-two textures + glTexParameteri(m_textureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(m_textureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glPixelStorei(GL_UNPACK_ALIGNMENT, 4); +@@ -2405,7 +2518,7 @@ + + glTexParameteri(m_textureTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(m_textureTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR); +- // This is necessary for non-power-of-two textures ++ // This is necessary for non-power-of-two textures + glTexParameteri(m_textureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(m_textureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + +@@ -2479,6 +2592,84 @@ + return true; + } + ++//******************************************************************************************************** ++// Buffer creation, deletion, copying + clearing ++//******************************************************************************************************** ++void CLinuxRendererGLES::UploadYV12BufferTexture(int index) ++{ ++ YUVBUFFER& buf = m_buffers[index]; ++ YV12Image* im = &buf.image; ++ YUVFIELDS& fields = buf.fields; ++ ++ if (!buf.codecinfo || !(im->flags & IMAGE_FLAG_READY)) ++ return; ++ ++ bool deinterlacing; ++ if (m_currentField == FIELD_FULL) ++ deinterlacing = false; ++ else ++ deinterlacing = true; ++ ++ glEnable(m_textureTarget); ++ VerifyGLState(); ++ ++ glPixelStorei(GL_UNPACK_ALIGNMENT,1); ++ ++ if (deinterlacing) ++ { ++ // Load Even Y Field ++ LoadPlane( fields[FIELD_TOP][0] , GL_LUMINANCE, buf.flipindex ++ , im->width, im->height >> 1 ++ , buf.codecinfo->iLineSize[0]*2, im->bpp, buf.codecinfo->data[0] ); ++ ++ // Load Odd Y fields ++ LoadPlane( fields[FIELD_BOT][0], GL_LUMINANCE, buf.flipindex ++ , im->width, im->height >> 1 ++ , buf.codecinfo->iLineSize[0]*2, im->bpp, buf.codecinfo->data[0] + buf.codecinfo->iLineSize[0]) ; ++ ++ // Load Even U & V Fields ++ LoadPlane( fields[FIELD_TOP][1], GL_LUMINANCE, buf.flipindex ++ , im->width >> im->cshift_x, im->height >> (im->cshift_y + 1) ++ , buf.codecinfo->iLineSize[1]*2, im->bpp, buf.codecinfo->data[1] ); ++ ++ LoadPlane( fields[FIELD_TOP][2], GL_ALPHA, buf.flipindex ++ , im->width >> im->cshift_x, im->height >> (im->cshift_y + 1) ++ , buf.codecinfo->iLineSize[2]*2, im->bpp, buf.codecinfo->data[2] ); ++ ++ // Load Odd U & V Fields ++ LoadPlane( fields[FIELD_BOT][1], GL_LUMINANCE, buf.flipindex ++ , im->width >> im->cshift_x, im->height >> (im->cshift_y + 1) ++ , buf.codecinfo->iLineSize[1]*2, im->bpp, buf.codecinfo->data[1] + buf.codecinfo->iLineSize[1] ); ++ ++ LoadPlane( fields[FIELD_BOT][2], GL_ALPHA, buf.flipindex ++ , im->width >> im->cshift_x, im->height >> (im->cshift_y + 1) ++ , buf.codecinfo->iLineSize[2]*2, im->bpp, buf.codecinfo->data[2] + buf.codecinfo->iLineSize[2] ); ++ } ++ else ++ { ++ // Load Y plane ++ LoadPlane( fields[FIELD_FULL][0], GL_LUMINANCE, buf.flipindex ++ , im->width, im->height ++ , buf.codecinfo->iLineSize[0], im->bpp, buf.codecinfo->data[0] ); ++ ++ //load U plane ++ LoadPlane( fields[FIELD_FULL][1], GL_LUMINANCE, buf.flipindex ++ , im->width >> im->cshift_x, im->height >> im->cshift_y ++ , buf.codecinfo->iLineSize[1], im->bpp, buf.codecinfo->data[1] ); ++ ++ //load V plane ++ LoadPlane( fields[FIELD_FULL][2], GL_ALPHA, buf.flipindex ++ , im->width >> im->cshift_x, im->height >> im->cshift_y ++ , buf.codecinfo->iLineSize[2], im->bpp, buf.codecinfo->data[2] ); ++ } ++ ++ VerifyGLState(); ++ ++ CalculateTextureSourceRects(index, 3); ++ ++ glDisable(m_textureTarget); ++} ++ + void CLinuxRendererGLES::SetTextureFilter(GLenum method) + { + for (int i = 0 ; iIsValid()) ++ { ++ YUVPLANE &plane = m_buffers[index].fields[0][0]; ++ ++ glActiveTexture(GL_TEXTURE0); ++ glBindTexture(m_textureTarget, plane.id); ++ ++ GLuint physical = ~0U; ++ glTexDirectVIVMap(m_textureTarget, codecinfo->iWidth, codecinfo->iHeight, GL_VIV_NV12, ++ (GLvoid **)(&codecinfo->data[0]), &physical); ++ glTexDirectInvalidateVIV(m_textureTarget); ++ ++ glBindTexture(m_textureTarget, 0); ++ ++ plane.flipindex = m_buffers[index].flipindex; ++ } ++ ++ YUVFIELDS &fields = m_buffers[index].fields; ++ YUVPLANE &plane = fields[0][0]; ++ plane.texwidth = codecinfo->iWidth; ++ plane.texheight = codecinfo->iHeight; ++ ++ CalculateTextureSourceRects(index, 1); ++#endif ++} ++void CLinuxRendererGLES::DeleteIMXMAPTexture(int index) +{ + YUVBUFFER &buf = m_buffers[index]; -+ buf.imxOutputFrame = imx; -+} -+#endif ++ YUVPLANE &plane = buf.fields[0][0]; + - #ifdef HAS_LIBSTAGEFRIGHT - void CLinuxRendererGLES::AddProcessor(CDVDVideoCodecStageFright* stf, EGLImageKHR eglimg, int index) ++ if(plane.id && glIsTexture(plane.id)) ++ glDeleteTextures(1, &plane.id); ++ plane.id = 0; ++ ++ SAFE_RELEASE(buf.codecinfo); ++} ++bool CLinuxRendererGLES::CreateIMXMAPTexture(int index) ++{ ++ YV12Image &im = m_buffers[index].image; ++ YUVFIELDS &fields = m_buffers[index].fields; ++ YUVPLANE &plane = fields[0][0]; ++ ++ DeleteEGLIMGTexture(index); ++ ++ memset(&im , 0, sizeof(im)); ++ memset(&fields, 0, sizeof(fields)); ++ ++ im.height = m_sourceHeight; ++ im.width = m_sourceWidth; ++ ++ plane.texwidth = 0; // Must be actual frame width for pseudo-cropping ++ plane.texheight = 0; // Must be actual frame height for pseudo-cropping ++ plane.pixpertex_x = 1; ++ plane.pixpertex_y = 1; ++ ++ glEnable(m_textureTarget); ++ glGenTextures(1, &plane.id); ++ VerifyGLState(); ++ ++ glBindTexture(m_textureTarget, plane.id); ++ ++ glTexParameteri(m_textureTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR); ++ glTexParameteri(m_textureTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR); ++ ++ glDisable(m_textureTarget); ++ return true; ++} ++ ++ + bool CLinuxRendererGLES::Supports(ERENDERFEATURE feature) { -@@ -2688,6 +2786,7 @@ + // Player controls render, let it dictate available render features +@@ -2737,5 +3006,16 @@ } #endif ++void CLinuxRendererGLES::AddProcessor(CDVDVideoCodecBuffer *codecinfo, int index) ++{ ++ YUVBUFFER &buf = m_buffers[index]; ++ ++ SAFE_RELEASE(buf.codecinfo); ++ buf.codecinfo = codecinfo; ++ ++ if (codecinfo) ++ codecinfo->Lock(); ++} + - #if defined(TARGET_ANDROID) - void CLinuxRendererGLES::AddProcessor(CDVDMediaCodecInfo *mediacodec, int index) - { -diff -Naur xbmc-gotham-latest.test/xbmc/cores/VideoRenderers/LinuxRendererGLES.h xbmc-wolfgar-imx-wip.test/xbmc/cores/VideoRenderers/LinuxRendererGLES.h ---- xbmc-gotham-latest.test/xbmc/cores/VideoRenderers/LinuxRendererGLES.h 2014-02-09 01:41:14.826138345 +0100 -+++ xbmc-wolfgar-imx-wip.test/xbmc/cores/VideoRenderers/LinuxRendererGLES.h 2014-02-09 01:40:25.665083043 +0100 -@@ -42,6 +42,7 @@ - class COpenMaxVideo; - class CDVDVideoCodecStageFright; - class CDVDMediaCodecInfo; -+class CIMXOutputFrame; - typedef std::vector Features; - - -@@ -169,6 +170,9 @@ - #ifdef HAS_LIBSTAGEFRIGHT - virtual void AddProcessor(CDVDVideoCodecStageFright* stf, EGLImageKHR eglimg, int index); #endif -+#ifdef HAS_IMXVPU -+ virtual void AddProcessor(CIMXOutputFrame *imx, int index); -+#endif - #if defined(TARGET_ANDROID) + +diff -Naur xbmc-gotham-latest.test/xbmc/cores/VideoRenderers/LinuxRendererGLES.h xbmc-imx6.test/xbmc/cores/VideoRenderers/LinuxRendererGLES.h +--- xbmc-gotham-latest.test/xbmc/cores/VideoRenderers/LinuxRendererGLES.h 2014-02-19 22:24:45.276494801 +0100 ++++ xbmc-imx6.test/xbmc/cores/VideoRenderers/LinuxRendererGLES.h 2014-02-19 22:25:21.441528772 +0100 +@@ -33,6 +33,7 @@ + #include "guilib/GraphicContext.h" + #include "BaseRenderer.h" + #include "xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h" ++#include "xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecInfo.h" + + class CRenderCapture; + +@@ -89,7 +90,8 @@ + RENDER_CVREF = 0x080, + RENDER_BYPASS = 0x100, + RENDER_EGLIMG = 0x200, +- RENDER_MEDIACODEC = 0x400 ++ RENDER_MEDIACODEC = 0x400, ++ RENDER_IMXMAP = 0x800 + }; + + enum RenderQuality +@@ -173,6 +175,7 @@ // mediaCodec virtual void AddProcessor(CDVDMediaCodecInfo *mediacodec, int index); -@@ -280,6 +284,9 @@ - #ifdef HAVE_VIDEOTOOLBOXDECODER - struct __CVBuffer *cvBufferRef; #endif -+#ifdef HAS_IMXVPU -+ CIMXOutputFrame *imxOutputFrame; -+#endif - #ifdef HAS_LIBSTAGEFRIGHT - CDVDVideoCodecStageFright* stf; - EGLImageKHR eglimg; -diff -Naur xbmc-gotham-latest.test/xbmc/cores/VideoRenderers/RenderFormats.h xbmc-wolfgar-imx-wip.test/xbmc/cores/VideoRenderers/RenderFormats.h ---- xbmc-gotham-latest.test/xbmc/cores/VideoRenderers/RenderFormats.h 2014-02-09 01:41:14.827138346 +0100 -+++ xbmc-wolfgar-imx-wip.test/xbmc/cores/VideoRenderers/RenderFormats.h 2014-02-09 01:40:25.674083053 +0100 -@@ -35,6 +35,7 @@ - RENDER_FMT_OMXEGL, - RENDER_FMT_CVBREF, ++ virtual void AddProcessor(CDVDVideoCodecBuffer *codecinfo, int index); + + protected: + virtual void Render(DWORD flags, int index); +@@ -212,6 +215,12 @@ + void DeleteSurfaceTexture(int index); + bool CreateSurfaceTexture(int index); + ++ void UploadYV12BufferTexture(int index); ++ ++ void UploadIMXMAPTexture(int index); ++ void DeleteIMXMAPTexture(int index); ++ bool CreateIMXMAPTexture(int index); ++ + void CalculateTextureSourceRects(int source, int num_planes); + + // renderers +@@ -222,6 +231,7 @@ + void RenderEglImage(int index, int field); // Android OES texture + void RenderCoreVideoRef(int index, int field); // CoreVideo reference + void RenderSurfaceTexture(int index, int field);// MediaCodec rendering using SurfaceTexture ++ void RenderIMXMAPTexture(int index, int field); // IMXMAP rendering + + CFrameBufferObject m_fbo; + +@@ -288,6 +298,7 @@ + // mediacodec + CDVDMediaCodecInfo *mediacodec; + #endif ++ CDVDVideoCodecBuffer *codecinfo; + }; + + typedef YUVBUFFER YUVBUFFERS[NUM_BUFFERS]; +diff -Naur xbmc-gotham-latest.test/xbmc/cores/VideoRenderers/RenderFormats.h xbmc-imx6.test/xbmc/cores/VideoRenderers/RenderFormats.h +--- xbmc-gotham-latest.test/xbmc/cores/VideoRenderers/RenderFormats.h 2014-02-19 22:24:45.277494802 +0100 ++++ xbmc-imx6.test/xbmc/cores/VideoRenderers/RenderFormats.h 2014-02-19 22:25:21.442528773 +0100 +@@ -37,6 +37,8 @@ RENDER_FMT_BYPASS, -+ RENDER_FMT_IMX, RENDER_FMT_EGLIMG, RENDER_FMT_MEDIACODEC, ++ RENDER_FMT_YV12_BUFFER, ++ RENDER_FMT_IMXMAP, }; -diff -Naur xbmc-gotham-latest.test/xbmc/cores/VideoRenderers/RenderManager.cpp xbmc-wolfgar-imx-wip.test/xbmc/cores/VideoRenderers/RenderManager.cpp ---- xbmc-gotham-latest.test/xbmc/cores/VideoRenderers/RenderManager.cpp 2014-02-09 01:41:14.826138345 +0100 -+++ xbmc-wolfgar-imx-wip.test/xbmc/cores/VideoRenderers/RenderManager.cpp 2014-02-09 01:40:25.674083053 +0100 -@@ -920,6 +920,10 @@ - else if(pic.format == RENDER_FMT_VAAPI) - m_pRenderer->AddProcessor(*pic.vaapi, index); + #endif -+#ifdef HAS_IMXVPU -+ else if(pic.format == RENDER_FMT_IMX) -+ m_pRenderer->AddProcessor(pic.imxOutputFrame, index); -+#endif - #ifdef HAS_LIBSTAGEFRIGHT - else if(pic.format == RENDER_FMT_EGLIMG) - m_pRenderer->AddProcessor(pic.stf, pic.eglimg, index); -diff -Naur xbmc-gotham-latest.test/xbmc/input/linux/LinuxInputDevices.cpp xbmc-wolfgar-imx-wip.test/xbmc/input/linux/LinuxInputDevices.cpp ---- xbmc-gotham-latest.test/xbmc/input/linux/LinuxInputDevices.cpp 2014-02-09 01:41:09.587132460 +0100 -+++ xbmc-wolfgar-imx-wip.test/xbmc/input/linux/LinuxInputDevices.cpp 2014-02-09 01:40:22.522079500 +0100 +diff -Naur xbmc-gotham-latest.test/xbmc/cores/VideoRenderers/RenderManager.cpp xbmc-imx6.test/xbmc/cores/VideoRenderers/RenderManager.cpp +--- xbmc-gotham-latest.test/xbmc/cores/VideoRenderers/RenderManager.cpp 2014-02-19 22:24:45.276494801 +0100 ++++ xbmc-imx6.test/xbmc/cores/VideoRenderers/RenderManager.cpp 2014-02-19 22:25:21.441528772 +0100 +@@ -928,6 +928,8 @@ + else if(pic.format == RENDER_FMT_MEDIACODEC) + m_pRenderer->AddProcessor(pic.mediacodec, index); + #endif ++ else if(pic.format == RENDER_FMT_YV12_BUFFER || pic.format == RENDER_FMT_IMXMAP) ++ m_pRenderer->AddProcessor(pic.codecinfo, index); + + m_pRenderer->ReleaseImage(index, false); + +diff -Naur xbmc-gotham-latest.test/xbmc/cores/VideoRenderers/VideoShaders/YUV2RGBShader.cpp xbmc-imx6.test/xbmc/cores/VideoRenderers/VideoShaders/YUV2RGBShader.cpp +--- xbmc-gotham-latest.test/xbmc/cores/VideoRenderers/VideoShaders/YUV2RGBShader.cpp 2014-02-19 22:24:45.264494789 +0100 ++++ xbmc-imx6.test/xbmc/cores/VideoRenderers/VideoShaders/YUV2RGBShader.cpp 2014-02-19 22:25:21.441528772 +0100 +@@ -39,12 +39,12 @@ + // + // Transformation matrixes for different colorspaces. + // +-static float yuv_coef_bt601[4][4] = ++static float yuv_coef_bt601[4][4] = + { + { 1.0f, 1.0f, 1.0f, 0.0f }, + { 0.0f, -0.344f, 1.773f, 0.0f }, + { 1.403f, -0.714f, 0.0f, 0.0f }, +- { 0.0f, 0.0f, 0.0f, 0.0f } ++ { 0.0f, 0.0f, 0.0f, 0.0f } + }; + + static float yuv_coef_bt709[4][4] = +@@ -55,7 +55,7 @@ + { 0.0f, 0.0f, 0.0f, 0.0f } + }; + +-static float yuv_coef_ebu[4][4] = ++static float yuv_coef_ebu[4][4] = + { + { 1.0f, 1.0f, 1.0f, 0.0f }, + { 0.0f, -0.3960f, 2.029f, 0.0f }, +@@ -74,19 +74,19 @@ + static float** PickYUVConversionMatrix(unsigned flags) + { + // Pick the matrix. +- ++ + switch(CONF_FLAGS_YUVCOEF_MASK(flags)) + { + case CONF_FLAGS_YUVCOEF_240M: + return (float**)yuv_coef_smtp240m; break; + case CONF_FLAGS_YUVCOEF_BT709: + return (float**)yuv_coef_bt709; break; +- case CONF_FLAGS_YUVCOEF_BT601: ++ case CONF_FLAGS_YUVCOEF_BT601: + return (float**)yuv_coef_bt601; break; + case CONF_FLAGS_YUVCOEF_EBU: + return (float**)yuv_coef_ebu; break; + } +- ++ + return (float**)yuv_coef_bt601; + } + +@@ -228,7 +228,7 @@ + m_hProj = -1; + m_hModel = -1; + m_hAlpha = -1; +- if (m_format == RENDER_FMT_YUV420P) ++ if (m_format == RENDER_FMT_YUV420P || m_format == RENDER_FMT_YV12_BUFFER) + m_defines += "#define XBMC_YV12\n"; + else if (m_format == RENDER_FMT_NV12) + m_defines += "#define XBMC_NV12\n"; +diff -Naur xbmc-gotham-latest.test/xbmc/input/linux/LinuxInputDevices.cpp xbmc-imx6.test/xbmc/input/linux/LinuxInputDevices.cpp +--- xbmc-gotham-latest.test/xbmc/input/linux/LinuxInputDevices.cpp 2014-02-19 22:24:41.644491389 +0100 ++++ xbmc-imx6.test/xbmc/input/linux/LinuxInputDevices.cpp 2014-02-19 22:25:21.177528524 +0100 @@ -1222,7 +1222,8 @@ if ((now - m_lastHotplugCheck) >= 10) @@ -3367,31 +1906,11 @@ diff -Naur xbmc-gotham-latest.test/xbmc/input/linux/LinuxInputDevices.cpp xbmc-w m_lastHotplugCheck = now; } } -diff -Naur xbmc-gotham-latest.test/xbmc/powermanagement/PowerManager.cpp xbmc-wolfgar-imx-wip.test/xbmc/powermanagement/PowerManager.cpp -diff -Naur xbmc-gotham-latest.test/xbmc/video/dialogs/GUIDialogVideoOSD.cpp xbmc-wolfgar-imx-wip.test/xbmc/video/dialogs/GUIDialogVideoOSD.cpp -diff -Naur xbmc-gotham-latest.test/xbmc/windowing/egl/EGLNativeTypeAmlogic.cpp xbmc-wolfgar-imx-wip.test/xbmc/windowing/egl/EGLNativeTypeAmlogic.cpp ---- xbmc-gotham-latest.test/xbmc/windowing/egl/EGLNativeTypeAmlogic.cpp 2014-02-09 01:41:14.415137886 +0100 -+++ xbmc-wolfgar-imx-wip.test/xbmc/windowing/egl/EGLNativeTypeAmlogic.cpp 2014-02-09 01:40:25.076082379 +0100 -@@ -17,6 +17,7 @@ - * . - * - */ -+#include - - #include "EGLNativeTypeAmlogic.h" - #include "guilib/gui3d.h" -@@ -24,7 +25,6 @@ - #include "utils/StringUtils.h" - - #include --#include - #include - #include - -diff -Naur xbmc-gotham-latest.test/xbmc/windowing/egl/EGLNativeTypeIMX.cpp xbmc-wolfgar-imx-wip.test/xbmc/windowing/egl/EGLNativeTypeIMX.cpp +diff -Naur xbmc-gotham-latest.test/xbmc/powermanagement/PowerManager.cpp xbmc-imx6.test/xbmc/powermanagement/PowerManager.cpp +diff -Naur xbmc-gotham-latest.test/xbmc/windowing/egl/EGLNativeTypeIMX.cpp xbmc-imx6.test/xbmc/windowing/egl/EGLNativeTypeIMX.cpp --- xbmc-gotham-latest.test/xbmc/windowing/egl/EGLNativeTypeIMX.cpp 1970-01-01 01:00:00.000000000 +0100 -+++ xbmc-wolfgar-imx-wip.test/xbmc/windowing/egl/EGLNativeTypeIMX.cpp 2014-02-09 01:40:25.076082379 +0100 -@@ -0,0 +1,272 @@ ++++ xbmc-imx6.test/xbmc/windowing/egl/EGLNativeTypeIMX.cpp 2014-02-19 22:25:21.434528766 +0100 +@@ -0,0 +1,225 @@ +/* + * Copyright (C) 2011-2013 Team XBMC + * http://www.xbmc.org @@ -3446,7 +1965,7 @@ diff -Naur xbmc-gotham-latest.test/xbmc/windowing/egl/EGLNativeTypeIMX.cpp xbmc- +void CEGLNativeTypeIMX::Initialize() +{ + struct mxcfb_gbl_alpha alpha; -+ int fd, fd2; ++ int fd; + + + fd = open("/dev/fb0",O_RDWR); @@ -3455,46 +1974,20 @@ diff -Naur xbmc-gotham-latest.test/xbmc/windowing/egl/EGLNativeTypeIMX.cpp xbmc- + CLog::Log(LOGERROR, "%s - Error while opening /dev/fb0.\n", __FUNCTION__); + return; + } -+ fd2 = open("/dev/fb1",O_RDWR); -+ if (fd2 < 0) -+ { -+ CLog::Log(LOGERROR, "%s - Error while opening /dev/fb1.\n", __FUNCTION__); -+ return; -+ } -+ + /* Store screen info */ + if (ioctl(fd, FBIOGET_VSCREENINFO, &m_screeninfo) != 0) + { + CLog::Log(LOGERROR, "%s - Error while querying frame buffer.\n", __FUNCTION__); + return; + } -+ /* Configure overlay in the same way as BG plane */ -+ if (ioctl(fd2, FBIOPUT_VSCREENINFO, &m_screeninfo) != 0) -+ { -+ CLog::Log(LOGERROR, "%s - Error while setting overlay frame buffer.\n", __FUNCTION__); -+ return; -+ } + -+ /* set fb0 as the only visible layer - ioctl on /dev/fb0 so that fb0 is BG and fb1 is FG */ -+ alpha.alpha = 255; -+ alpha.enable = 1; -+ if (ioctl(fd, MXCFB_SET_GBL_ALPHA, &alpha) != 0) -+ { -+ CLog::Log(LOGERROR, "%s - Error while initializing frame buffer.\n", __FUNCTION__); -+ } -+ + /* Unblank the fbs */ + if (ioctl(fd, FBIOBLANK, 0) < 0) + { + CLog::Log(LOGERROR, "%s - Error while unblanking fb0.\n", __FUNCTION__); + } -+ if (ioctl(fd2, FBIOBLANK, 0) < 0) -+ { -+ CLog::Log(LOGERROR, "%s - Error while unblanking fb0.\n", __FUNCTION__); -+ } + + close(fd); -+ close(fd2); + + return; +} @@ -3503,7 +1996,6 @@ diff -Naur xbmc-gotham-latest.test/xbmc/windowing/egl/EGLNativeTypeIMX.cpp xbmc- +{ + struct fb_fix_screeninfo fixed_info; + void *fb_buffer; -+ struct mxcfb_gbl_alpha alpha; + int fd; + + fd = open("/dev/fb0",O_RDWR); @@ -3512,13 +2004,6 @@ diff -Naur xbmc-gotham-latest.test/xbmc/windowing/egl/EGLNativeTypeIMX.cpp xbmc- + CLog::Log(LOGERROR, "%s - Error while opening /dev/fb0.\n", __FUNCTION__); + return; + } -+ /* only fb0 visible */ -+ alpha.alpha = 255; -+ alpha.enable = 1; -+ if (ioctl(fd, MXCFB_SET_GBL_ALPHA, &alpha) != 0) -+ { -+ CLog::Log(LOGERROR, "%s - Error while initializing frame buffer.\n", __FUNCTION__); -+ } + + ioctl( fd, FBIOGET_FSCREENINFO, &fixed_info); + /* Black fb0 */ @@ -3534,19 +2019,6 @@ diff -Naur xbmc-gotham-latest.test/xbmc/windowing/egl/EGLNativeTypeIMX.cpp xbmc- + } + + close(fd); -+ -+ /* Blank overlay */ -+ fd = open("/dev/fb1",O_RDWR); -+ if (fd < 0) -+ { -+ CLog::Log(LOGERROR, "%s - Error while opening /dev/fb1.\n", __FUNCTION__); -+ return; -+ } -+ if (ioctl(fd, FBIOBLANK, 1) < 0) -+ { -+ CLog::Log(LOGERROR, "%s - Error while blanking fb1.\n", __FUNCTION__); -+ } -+ close(fd); + + return; +} @@ -3664,9 +2136,9 @@ diff -Naur xbmc-gotham-latest.test/xbmc/windowing/egl/EGLNativeTypeIMX.cpp xbmc- + } + return 0; +} -diff -Naur xbmc-gotham-latest.test/xbmc/windowing/egl/EGLNativeTypeIMX.h xbmc-wolfgar-imx-wip.test/xbmc/windowing/egl/EGLNativeTypeIMX.h +diff -Naur xbmc-gotham-latest.test/xbmc/windowing/egl/EGLNativeTypeIMX.h xbmc-imx6.test/xbmc/windowing/egl/EGLNativeTypeIMX.h --- xbmc-gotham-latest.test/xbmc/windowing/egl/EGLNativeTypeIMX.h 1970-01-01 01:00:00.000000000 +0100 -+++ xbmc-wolfgar-imx-wip.test/xbmc/windowing/egl/EGLNativeTypeIMX.h 2014-02-09 01:40:25.078082381 +0100 ++++ xbmc-imx6.test/xbmc/windowing/egl/EGLNativeTypeIMX.h 2014-02-19 22:25:21.434528766 +0100 @@ -0,0 +1,62 @@ +#pragma once + @@ -3730,15 +2202,14 @@ diff -Naur xbmc-gotham-latest.test/xbmc/windowing/egl/EGLNativeTypeIMX.h xbmc-wo + struct fb_var_screeninfo m_screeninfo; + +}; -diff -Naur xbmc-gotham-latest.test/xbmc/windowing/egl/EGLWrapper.cpp xbmc-wolfgar-imx-wip.test/xbmc/windowing/egl/EGLWrapper.cpp ---- xbmc-gotham-latest.test/xbmc/windowing/egl/EGLWrapper.cpp 2014-02-09 01:41:14.417137884 +0100 -+++ xbmc-wolfgar-imx-wip.test/xbmc/windowing/egl/EGLWrapper.cpp 2014-02-09 01:40:25.077082380 +0100 -@@ -17,11 +17,10 @@ +diff -Naur xbmc-gotham-latest.test/xbmc/windowing/egl/EGLWrapper.cpp xbmc-imx6.test/xbmc/windowing/egl/EGLWrapper.cpp +--- xbmc-gotham-latest.test/xbmc/windowing/egl/EGLWrapper.cpp 2014-02-19 22:24:44.600494166 +0100 ++++ xbmc-imx6.test/xbmc/windowing/egl/EGLWrapper.cpp 2014-02-19 22:25:21.434528766 +0100 +@@ -17,16 +17,17 @@ * . * */ - -+#include "EGLNativeTypeIMX.h" #include "system.h" #ifdef HAS_EGL @@ -3746,24 +2217,38 @@ diff -Naur xbmc-gotham-latest.test/xbmc/windowing/egl/EGLWrapper.cpp xbmc-wolfga #include "utils/log.h" #include "EGLNativeTypeAndroid.h" #include "EGLNativeTypeAmlogic.h" -@@ -83,7 +82,8 @@ + #include "EGLNativeTypeRaspberryPI.h" + #include "EGLNativeTypeWayland.h" ++#ifdef HAS_IMXVPU ++#include "EGLNativeTypeIMX.h" ++#endif + #include "EGLWrapper.h" + + #define CheckError() m_result = eglGetError(); if(m_result != EGL_SUCCESS) CLog::Log(LOGERROR, "EGL error in %s: %x",__FUNCTION__, m_result); +@@ -83,7 +84,11 @@ if ((nativeGuess = CreateEGLNativeType(implementation)) || (nativeGuess = CreateEGLNativeType(implementation)) || (nativeGuess = CreateEGLNativeType(implementation)) || - (nativeGuess = CreateEGLNativeType(implementation))) -+ (nativeGuess = CreateEGLNativeType(implementation)) || -+ (nativeGuess = CreateEGLNativeType(implementation))) ++ (nativeGuess = CreateEGLNativeType(implementation)) ++#ifdef HAS_IMXVPU ++ || (nativeGuess = CreateEGLNativeType(implementation)) ++#endif ++ ) { m_nativeTypes = nativeGuess; -diff -Naur xbmc-gotham-latest.test/xbmc/windowing/egl/Makefile.in xbmc-wolfgar-imx-wip.test/xbmc/windowing/egl/Makefile.in ---- xbmc-gotham-latest.test/xbmc/windowing/egl/Makefile.in 2014-02-09 01:41:14.375137840 +0100 -+++ xbmc-wolfgar-imx-wip.test/xbmc/windowing/egl/Makefile.in 2014-02-09 01:40:25.055082355 +0100 -@@ -5,6 +5,7 @@ - SRCS+= EGLNativeTypeAndroid.cpp - SRCS+= EGLNativeTypeRaspberryPI.cpp - SRCS+= EGLNativeTypeWayland.cpp -+SRCS+= EGLNativeTypeIMX.cpp - SRCS+= EGLWrapper.cpp +diff -Naur xbmc-gotham-latest.test/xbmc/windowing/egl/Makefile.in xbmc-imx6.test/xbmc/windowing/egl/Makefile.in +--- xbmc-gotham-latest.test/xbmc/windowing/egl/Makefile.in 2014-02-19 22:24:44.557494125 +0100 ++++ xbmc-imx6.test/xbmc/windowing/egl/Makefile.in 2014-02-19 22:25:21.433528765 +0100 +@@ -24,6 +24,10 @@ + wayland/XBMCSurface.cpp + endif - # Wayland specific detail ++ifeq (@USE_IMXVPU@,1) ++SRCS+= EGLNativeTypeIMX.cpp ++endif ++ + LIB = windowing_egl.a + + include ../../../Makefile.include