diff --git a/projects/Cuboxi/patches/xbmc/xbmc-001-imx6_support.patch b/projects/Cuboxi/patches/xbmc/xbmc-001-imx6_support.patch deleted file mode 100644 index 2c7a4f0daa..0000000000 --- a/projects/Cuboxi/patches/xbmc/xbmc-001-imx6_support.patch +++ /dev/null @@ -1,3568 +0,0 @@ -diff -Naur xbmc-13b4/configure.in xbmc-imx6-13b4/configure.in ---- xbmc-13b4/configure.in 2014-04-24 11:49:30.784354037 +0200 -+++ xbmc-imx6-13b4/configure.in 2014-04-24 11:50:13.695216693 +0200 -@@ -558,7 +558,7 @@ - - AC_ARG_ENABLE([codec], - [AS_HELP_STRING([--enable-codec], -- [enable additional codecs from a list of comma separated names, (default is none, choices are amcodec, libstagefright)])], -+ [enable additional codecs from a list of comma separated names, (default is none, choices are amcodec, libstagefright and imxvpu)])], - [add_codecs=$enableval], - [add_codecs=no]) - -@@ -1034,6 +1034,15 @@ - AC_MSG_RESULT($wayland_disabled) - fi - -+# i.MX6 -+AC_MSG_CHECKING([for i.MX framebuffer support]) -+AC_CHECK_HEADER([linux/mxcfb.h], have_imxfb=yes,have_imxfb=no) -+AC_MSG_RESULT($have_imxfb) -+if test "x$have_imxfb" = "xyes"; then -+ AC_DEFINE([HAS_IMXFB], [1], [Whether i.MX framebuffer support is enabled.]) -+ AC_SUBST([USE_IMXFB], 1) -+fi -+ - # Checks for platforms libraries. - if test "$use_gles" = "yes"; then - use_gl="no" -@@ -1991,6 +2000,17 @@ - *libstagefright*) - XB_ADD_CODEC([LIBSTAGEFRIGHT], [libstagefright], [$codecs]) - ;; -+ *imxvpu*) -+ AC_CHECK_HEADER([imx-mm/vpu/vpu_wrapper.h],, AC_MSG_ERROR($missing_headers)) -+ AC_CHECK_LIB([vpu], main, LIBS="$LIBS -lfslvpuwrap -lvpu", AC_MSG_ERROR($missing_library)) -+ XB_ADD_CODEC([IMXVPU], [imxvpu], [$codecs]) -+ CXXFLAGS="$CXXFLAGS -Wno-psabi -DLINUX " -+ CFLAGS="$CFLAGS -DLINUX" -+ if test "$use_x11" = "no"; then -+ CXXFLAGS="$CXXFLAGS -DEGL_API_FB" -+ CFLAGS="$CFLAGS -DEGL_API_FB" -+ fi -+ ;; - *) - esac - done -diff -Naur xbmc-13b4/lib/ffmpeg/libavcodec/arm/dca.h xbmc-imx6-13b4/lib/ffmpeg/libavcodec/arm/dca.h ---- xbmc-13b4/lib/ffmpeg/libavcodec/arm/dca.h 2014-04-24 11:49:35.908218231 +0200 -+++ xbmc-imx6-13b4/lib/ffmpeg/libavcodec/arm/dca.h 2014-04-24 11:50:13.827213196 +0200 -@@ -30,9 +30,9 @@ - - #define decode_blockcodes decode_blockcodes - static inline int decode_blockcodes(int code1, int code2, int levels, -- int *values) -+ int32_t *values) - { -- int v0, v1, v2, v3, v4, v5; -+ int32_t v0, v1, v2, v3, v4, v5; - - __asm__ ("smmul %0, %6, %10 \n" - "smmul %3, %7, %10 \n" -@@ -101,3 +101,4 @@ - #endif - - #endif /* AVCODEC_ARM_DCA_H */ -+ -diff -Naur xbmc-13b4/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResample.cpp xbmc-imx6-13b4/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResample.cpp ---- xbmc-13b4/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResample.cpp 2014-04-24 11:49:41.288075640 +0200 -+++ xbmc-imx6-13b4/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResample.cpp 2014-04-24 11:50:14.007208425 +0200 -@@ -279,14 +279,16 @@ - if (format == AE_FMT_U8) return AV_SAMPLE_FMT_U8; - else if (format == AE_FMT_S16NE) return AV_SAMPLE_FMT_S16; - else if (format == AE_FMT_S32NE) return AV_SAMPLE_FMT_S32; -- else if (format == AE_FMT_S24NE4) return AV_SAMPLE_FMT_S32; -+ else if (format == AE_FMT_S24NE4H) return AV_SAMPLE_FMT_S32; -+ else if (format == AE_FMT_S24NE4L) return AV_SAMPLE_FMT_S32; - else if (format == AE_FMT_FLOAT) return AV_SAMPLE_FMT_FLT; - else if (format == AE_FMT_DOUBLE) return AV_SAMPLE_FMT_DBL; - - else if (format == AE_FMT_U8P) return AV_SAMPLE_FMT_U8P; - else if (format == AE_FMT_S16NEP) return AV_SAMPLE_FMT_S16P; - else if (format == AE_FMT_S32NEP) return AV_SAMPLE_FMT_S32P; -- else if (format == AE_FMT_S24NE4P) return AV_SAMPLE_FMT_S32P; -+ else if (format == AE_FMT_S24NE4HP) return AV_SAMPLE_FMT_S32P; -+ else if (format == AE_FMT_S24NE4LP) return AV_SAMPLE_FMT_S32P; - else if (format == AE_FMT_FLOATP) return AV_SAMPLE_FMT_FLTP; - else if (format == AE_FMT_DOUBLEP) return AV_SAMPLE_FMT_DBLP; - -@@ -298,14 +300,14 @@ - if (format == AV_SAMPLE_FMT_U8) return AE_FMT_U8; - else if (format == AV_SAMPLE_FMT_S16) return AE_FMT_S16NE; - else if (format == AV_SAMPLE_FMT_S32 && bits == 32) return AE_FMT_S32NE; -- else if (format == AV_SAMPLE_FMT_S32 && bits == 24) return AE_FMT_S24NE4; -+ else if (format == AV_SAMPLE_FMT_S32 && bits == 24) return AE_FMT_S24NE4H; - else if (format == AV_SAMPLE_FMT_FLT) return AE_FMT_FLOAT; - else if (format == AV_SAMPLE_FMT_DBL) return AE_FMT_DOUBLE; - - else if (format == AV_SAMPLE_FMT_U8P) return AE_FMT_U8P; - else if (format == AV_SAMPLE_FMT_S16P) return AE_FMT_S16NEP; - else if (format == AV_SAMPLE_FMT_S32P && bits == 32) return AE_FMT_S32NEP; -- else if (format == AV_SAMPLE_FMT_S32P && bits == 24) return AE_FMT_S24NE4P; -+ else if (format == AV_SAMPLE_FMT_S32P && bits == 24) return AE_FMT_S24NE4HP; - else if (format == AV_SAMPLE_FMT_FLTP) return AE_FMT_FLOATP; - else if (format == AV_SAMPLE_FMT_DBLP) return AE_FMT_DOUBLEP; - -diff -Naur xbmc-13b4/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAESink.cpp xbmc-imx6-13b4/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAESink.cpp ---- xbmc-13b4/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAESink.cpp 2014-04-24 11:49:41.280075852 +0200 -+++ xbmc-imx6-13b4/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAESink.cpp 2014-04-24 11:50:14.007208425 +0200 -@@ -796,6 +796,12 @@ - } - } - -+static inline void RShift8_32_buf(uint32_t *src, uint32_t *dst, uint32_t count) -+{ -+ while (count--) -+ *dst++ = *src++ >> 8; -+} -+ - unsigned int CActiveAESink::OutputSamples(CSampleBuffer* samples) - { - uint8_t *buffer = samples->pkt->data[0]; -@@ -816,14 +822,22 @@ - case NEED_BYTESWAP: - Endian_Swap16_buf((uint16_t *)buffer, (uint16_t *)buffer, frames * samples->pkt->config.channels); - break; -+ case NEED_RSHIFT8: -+ RShift8_32_buf((uint32_t *)buffer, (uint32_t *)buffer, frames * samples->pkt->config.channels); -+ break; - case CHECK_CONVERT: - ConvertInit(samples); - if (m_convertState == NEED_CONVERT) - buffer = Convert(samples); - else if (m_convertState == NEED_BYTESWAP) - Endian_Swap16_buf((uint16_t *)buffer, (uint16_t *)buffer, frames * samples->pkt->config.channels); -+ else if (m_convertState == NEED_RSHIFT8) -+ RShift8_32_buf((uint32_t *)buffer, (uint32_t *)buffer, frames * samples->pkt->config.channels); -+ else if (m_convertState == SKIP_OUTPUT) -+ frames = 0; - break; -- default: -+ case SKIP_OUTPUT: -+ frames = 0; - break; - } - -@@ -862,15 +876,38 @@ - - void CActiveAESink::ConvertInit(CSampleBuffer* samples) - { -- if (CActiveAEResample::GetAESampleFormat(samples->pkt->config.fmt, samples->pkt->config.bits_per_sample) != m_sinkFormat.m_dataFormat) -+ AEDataFormat srcFmt = CActiveAEResample::GetAESampleFormat(samples->pkt->config.fmt, samples->pkt->config.bits_per_sample); -+ -+ if (srcFmt != m_sinkFormat.m_dataFormat) - { -- m_convertFn = CAEConvert::FrFloat(m_sinkFormat.m_dataFormat); -- if (m_convertBuffer) -- _aligned_free(m_convertBuffer); -- m_convertBufferSampleSize = samples->pkt->max_nb_samples; -- m_convertBuffer = (uint8_t*)_aligned_malloc(samples->pkt->max_nb_samples * m_sinkFormat.m_channelLayout.Count() * m_sinkFormat.m_frameSize, 16); -- memset(m_convertBuffer, 0, samples->pkt->max_nb_samples * m_sinkFormat.m_channelLayout.Count() * m_sinkFormat.m_frameSize); -- m_convertState = NEED_CONVERT; -+ switch (srcFmt) -+ { -+ case AE_FMT_FLOAT: -+ case AE_FMT_FLOATP: -+ m_convertFn = CAEConvert::FrFloat(m_sinkFormat.m_dataFormat); -+ if (m_convertBuffer) -+ _aligned_free(m_convertBuffer); -+ m_convertBufferSampleSize = samples->pkt->max_nb_samples; -+ m_convertBuffer = (uint8_t*)_aligned_malloc(samples->pkt->max_nb_samples * m_sinkFormat.m_channelLayout.Count() * m_sinkFormat.m_frameSize, 16); -+ memset(m_convertBuffer, 0, samples->pkt->max_nb_samples * m_sinkFormat.m_channelLayout.Count() * m_sinkFormat.m_frameSize); -+ m_convertState = NEED_CONVERT; -+ break; -+ case AE_FMT_S24NE4H: -+ m_convertState = (m_sinkFormat.m_dataFormat == AE_FMT_S24NE4L) ? NEED_RSHIFT8 : SKIP_OUTPUT; -+ break; -+ case AE_FMT_S24NE4HP: -+ m_convertState = (m_sinkFormat.m_dataFormat == AE_FMT_S24NE4LP) ? NEED_RSHIFT8 : SKIP_OUTPUT; -+ break; -+ default: -+ m_convertState = SKIP_OUTPUT; -+ break; -+ } -+ -+ if (m_convertState == SKIP_OUTPUT) -+ { -+ CLog::Log(LOGERROR, "CActiveAESink::ConvertInit - cannot convert from %s to %s", -+ CAEUtil::DataFormatToStr(srcFmt), CAEUtil::DataFormatToStr(m_sinkFormat.m_dataFormat)); -+ } - } - else if (AE_IS_RAW(m_requestedFormat.m_dataFormat) && CAEUtil::S16NeedsByteSwap(AE_FMT_S16NE, m_sinkFormat.m_dataFormat)) - { -diff -Naur xbmc-13b4/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAESink.h xbmc-imx6-13b4/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAESink.h ---- xbmc-13b4/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAESink.h 2014-04-24 11:49:41.288075640 +0200 -+++ xbmc-imx6-13b4/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAESink.h 2014-04-24 11:50:14.007208425 +0200 -@@ -139,6 +139,8 @@ - NEED_CONVERT, - NEED_BYTESWAP, - SKIP_CONVERT, -+ NEED_RSHIFT8, -+ SKIP_OUTPUT - } m_convertState; - - std::string m_deviceFriendlyName; -diff -Naur xbmc-13b4/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp xbmc-imx6-13b4/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp ---- xbmc-13b4/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp 2014-04-24 11:49:41.256076488 +0200 -+++ xbmc-imx6-13b4/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp 2014-04-24 11:50:14.007208425 +0200 -@@ -268,7 +268,7 @@ - case AE_FMT_S16NE : return SND_PCM_FORMAT_S16; - case AE_FMT_S16LE : return SND_PCM_FORMAT_S16_LE; - case AE_FMT_S16BE : return SND_PCM_FORMAT_S16_BE; -- case AE_FMT_S24NE4: return SND_PCM_FORMAT_S24; -+ case AE_FMT_S24NE4L: return SND_PCM_FORMAT_S24; - #ifdef __BIG_ENDIAN__ - case AE_FMT_S24NE3: return SND_PCM_FORMAT_S24_3BE; - #else -@@ -343,7 +343,7 @@ - { - /* if we opened in 32bit and only have 24bits, pack into 24 */ - if (fmtBits == 32 && bits == 24) -- i = AE_FMT_S24NE4; -+ i = AE_FMT_S24NE4L; - else - continue; - } -@@ -720,7 +720,10 @@ - * will automatically add "@" instead to enable surroundXX mangling. - * We don't want to do that if "default" can handle multichannel - * itself (e.g. in case of a pulseaudio server). */ -- EnumerateDevice(list, "default", "", config); -+ -+ /* For Wandboard, we do not enurate default device as it will be grabbed -+ * as one of the sysdefault devices... */ -+ - - void **hints; - -@@ -771,8 +774,8 @@ - * found by the enumeration process. Skip them as well ("hw", "dmix", - * "plughw", "dsnoop"). */ - -+ /* For wandboard all devices are prefixed by sysdefault so do not ignore them */ - else if (baseName != "default" -- && baseName != "sysdefault" - && baseName != "surround40" - && baseName != "surround41" - && baseName != "surround50" -@@ -881,6 +884,22 @@ - - AEDeviceType CAESinkALSA::AEDeviceTypeFromName(const std::string &name) - { -+ std::size_t found; -+ -+ /* Hack : Check for specific wandboard sound device names */ -+ found = name.find("imxspdif"); -+ if (found!=std::string::npos) -+ return AE_DEVTYPE_IEC958; -+ -+ found = name.find("imxhdmisoc"); -+ if (found!=std::string::npos) -+ return AE_DEVTYPE_HDMI; -+ -+ found = name.find("sgtl5000audio"); -+ if (found!=std::string::npos) -+ return AE_DEVTYPE_PCM; -+ -+ - if (name.substr(0, 4) == "hdmi") - return AE_DEVTYPE_HDMI; - else if (name.substr(0, 6) == "iec958" || name.substr(0, 5) == "spdif") -diff -Naur xbmc-13b4/xbmc/cores/AudioEngine/Sinks/AESinkPULSE.cpp xbmc-imx6-13b4/xbmc/cores/AudioEngine/Sinks/AESinkPULSE.cpp ---- xbmc-13b4/xbmc/cores/AudioEngine/Sinks/AESinkPULSE.cpp 2014-04-24 11:49:41.268076170 +0200 -+++ xbmc-imx6-13b4/xbmc/cores/AudioEngine/Sinks/AESinkPULSE.cpp 2014-04-24 11:50:14.007208425 +0200 -@@ -80,9 +80,9 @@ - case AE_FMT_S24LE3: return PA_SAMPLE_S24LE; - case AE_FMT_S24BE3: return PA_SAMPLE_S24BE; - case AE_FMT_S24NE3: return PA_SAMPLE_S24NE; -- case AE_FMT_S24LE4: return PA_SAMPLE_S24_32LE; -- case AE_FMT_S24BE4: return PA_SAMPLE_S24_32BE; -- case AE_FMT_S24NE4: return PA_SAMPLE_S24_32NE; -+ case AE_FMT_S24LE4L: return PA_SAMPLE_S24_32LE; -+ case AE_FMT_S24BE4L: return PA_SAMPLE_S24_32BE; -+ case AE_FMT_S24NE4L: return PA_SAMPLE_S24_32NE; - case AE_FMT_S32BE : return PA_SAMPLE_S32BE; - case AE_FMT_S32LE : return PA_SAMPLE_S32LE; - case AE_FMT_S32NE : return PA_SAMPLE_S32NE; -@@ -119,9 +119,9 @@ - AE_FMT_S24LE3, - AE_FMT_S24BE3, - AE_FMT_S24NE3, -- AE_FMT_S24LE4, -- AE_FMT_S24BE4, -- AE_FMT_S24NE4, -+ AE_FMT_S24LE4L, -+ AE_FMT_S24BE4L, -+ AE_FMT_S24NE4L, - AE_FMT_S32BE, - AE_FMT_S32LE, - AE_FMT_S32NE, -diff -Naur xbmc-13b4/xbmc/cores/AudioEngine/Sinks/AESinkWASAPI.cpp xbmc-imx6-13b4/xbmc/cores/AudioEngine/Sinks/AESinkWASAPI.cpp ---- xbmc-13b4/xbmc/cores/AudioEngine/Sinks/AESinkWASAPI.cpp 2014-04-24 11:49:41.276075958 +0200 -+++ xbmc-imx6-13b4/xbmc/cores/AudioEngine/Sinks/AESinkWASAPI.cpp 2014-04-24 11:50:14.007208425 +0200 -@@ -111,7 +111,7 @@ - /* Sample formats go from float -> 32 bit int -> 24 bit int (packed in 32) -> -> 24 bit int -> 16 bit int */ - static const sampleFormat testFormats[] = { {KSDATAFORMAT_SUBTYPE_IEEE_FLOAT, 32, 32, AE_FMT_FLOAT}, - {KSDATAFORMAT_SUBTYPE_PCM, 32, 32, AE_FMT_S32NE}, -- {KSDATAFORMAT_SUBTYPE_PCM, 32, 24, AE_FMT_S24NE4}, -+ {KSDATAFORMAT_SUBTYPE_PCM, 32, 24, AE_FMT_S24NE4H}, - {KSDATAFORMAT_SUBTYPE_PCM, 24, 24, AE_FMT_S24NE3}, - {KSDATAFORMAT_SUBTYPE_PCM, 16, 16, AE_FMT_S16NE} }; - -@@ -758,7 +758,7 @@ - wfxex.Format.wBitsPerSample = CAEUtil::DataFormatToBits((AEDataFormat) p); - wfxex.Format.nBlockAlign = wfxex.Format.nChannels * (wfxex.Format.wBitsPerSample >> 3); - wfxex.Format.nAvgBytesPerSec = wfxex.Format.nSamplesPerSec * wfxex.Format.nBlockAlign; -- if (p <= AE_FMT_S24NE4 && p >= AE_FMT_S24BE4) -+ if (p <= AE_FMT_S24NE4H && p >= AE_FMT_S24BE4H) - { - wfxex.Samples.wValidBitsPerSample = 24; - } -@@ -1149,7 +1149,7 @@ - else if (wfxex.Samples.wValidBitsPerSample == 32) - format.m_dataFormat = AE_FMT_S32NE; - else -- format.m_dataFormat = AE_FMT_S24NE4; -+ format.m_dataFormat = AE_FMT_S24NE4H; - } - else if (wfxex.Format.wBitsPerSample == 24) - format.m_dataFormat = AE_FMT_S24NE3; -diff -Naur xbmc-13b4/xbmc/cores/AudioEngine/Utils/AEAudioFormat.h xbmc-imx6-13b4/xbmc/cores/AudioEngine/Utils/AEAudioFormat.h ---- xbmc-13b4/xbmc/cores/AudioEngine/Utils/AEAudioFormat.h 2014-04-24 11:49:41.296075428 +0200 -+++ xbmc-imx6-13b4/xbmc/cores/AudioEngine/Utils/AEAudioFormat.h 2014-04-24 11:50:14.011208319 +0200 -@@ -41,9 +41,13 @@ - AE_FMT_S32LE, - AE_FMT_S32NE, - -- AE_FMT_S24BE4, -- AE_FMT_S24LE4, -- AE_FMT_S24NE4, /* S24 in 4 bytes */ -+ AE_FMT_S24BE4H, -+ AE_FMT_S24LE4H, -+ AE_FMT_S24NE4H, /* S24 in upper 4 bytes */ -+ -+ AE_FMT_S24BE4L, -+ AE_FMT_S24LE4L, -+ AE_FMT_S24NE4L, /* S24 in lower 4 bytes */ - - AE_FMT_S24BE3, - AE_FMT_S24LE3, -@@ -65,7 +69,8 @@ - AE_FMT_U8P, - AE_FMT_S16NEP, - AE_FMT_S32NEP, -- AE_FMT_S24NE4P, -+ AE_FMT_S24NE4HP, -+ AE_FMT_S24NE4LP, - AE_FMT_S24NE3P, - AE_FMT_DOUBLEP, - AE_FMT_FLOATP, -diff -Naur xbmc-13b4/xbmc/cores/AudioEngine/Utils/AEConvert.cpp xbmc-imx6-13b4/xbmc/cores/AudioEngine/Utils/AEConvert.cpp ---- xbmc-13b4/xbmc/cores/AudioEngine/Utils/AEConvert.cpp 2014-04-24 11:49:41.292075533 +0200 -+++ xbmc-imx6-13b4/xbmc/cores/AudioEngine/Utils/AEConvert.cpp 2014-04-24 11:50:14.007208425 +0200 -@@ -69,18 +69,22 @@ - #ifdef __BIG_ENDIAN__ - case AE_FMT_S16NE : return &S16BE_Float; - case AE_FMT_S32NE : return &S32BE_Float; -- case AE_FMT_S24NE4: return &S24BE4_Float; -+ case AE_FMT_S24NE4H: return &S24BE4H_Float; -+ case AE_FMT_S24NE4L: return &S24BE4L_Float; - case AE_FMT_S24NE3: return &S24BE3_Float; - #else - case AE_FMT_S16NE : return &S16LE_Float; - case AE_FMT_S32NE : return &S32LE_Float; -- case AE_FMT_S24NE4: return &S24LE4_Float; -+ case AE_FMT_S24NE4H: return &S24LE4H_Float; -+ case AE_FMT_S24NE4L: return &S24LE4L_Float; - case AE_FMT_S24NE3: return &S24LE3_Float; - #endif - case AE_FMT_S16LE : return &S16LE_Float; - case AE_FMT_S16BE : return &S16BE_Float; -- case AE_FMT_S24LE4: return &S24LE4_Float; -- case AE_FMT_S24BE4: return &S24BE4_Float; -+ case AE_FMT_S24LE4H: return &S24LE4H_Float; -+ case AE_FMT_S24LE4L: return &S24LE4L_Float; -+ case AE_FMT_S24BE4H: return &S24BE4H_Float; -+ case AE_FMT_S24BE4L: return &S24BE4L_Float; - case AE_FMT_S24LE3: return &S24LE3_Float; - case AE_FMT_S24BE3: return &S24BE3_Float; - #if defined(__ARM_NEON__) -@@ -112,7 +116,8 @@ - #endif - case AE_FMT_S16LE : return &Float_S16LE; - case AE_FMT_S16BE : return &Float_S16BE; -- case AE_FMT_S24NE4: return &Float_S24NE4; -+ case AE_FMT_S24NE4H: return &Float_S24NE4H; -+ case AE_FMT_S24NE4L: return &Float_S24NE4L; - case AE_FMT_S24NE3: return &Float_S24NE3; - #if defined(__ARM_NEON__) - case AE_FMT_S32LE : return &Float_S32LE_Neon; -@@ -210,7 +215,17 @@ - return samples; - } - --unsigned int CAEConvert::S24LE4_Float(uint8_t *data, const unsigned int samples, float *dest) -+unsigned int CAEConvert::S24LE4H_Float(uint8_t *data, const unsigned int samples, float *dest) -+{ -+ for (unsigned int i = 0; i < samples; ++i, data += 4) -+ { -+ int s = (data[3] << 24) | (data[2] << 16) | (data[1] << 8); -+ *dest++ = (float)s * INT32_SCALE; -+ } -+ return samples; -+} -+ -+unsigned int CAEConvert::S24LE4L_Float(uint8_t *data, const unsigned int samples, float *dest) - { - for (unsigned int i = 0; i < samples; ++i, data += 4) - { -@@ -220,7 +235,7 @@ - return samples; - } - --unsigned int CAEConvert::S24BE4_Float(uint8_t *data, const unsigned int samples, float *dest) -+unsigned int CAEConvert::S24BE4H_Float(uint8_t *data, const unsigned int samples, float *dest) - { - for (unsigned int i = 0; i < samples; ++i, data += 4) - { -@@ -230,6 +245,16 @@ - return samples; - } - -+unsigned int CAEConvert::S24BE4L_Float(uint8_t *data, const unsigned int samples, float *dest) -+{ -+ for (unsigned int i = 0; i < samples; ++i, data += 4) -+ { -+ int s = (data[1] << 24) | (data[2] << 16) | (data[3] << 8); -+ *dest++ = (float)s * INT32_SCALE; -+ } -+ return samples; -+} -+ - unsigned int CAEConvert::S24LE3_Float(uint8_t *data, const unsigned int samples, float *dest) - { - for (unsigned int i = 0; i < samples; ++i, data += 3) -@@ -244,7 +269,7 @@ - { - for (unsigned int i = 0; i < samples; ++i, data += 3) - { -- int s = (data[1] << 24) | (data[2] << 16) | (data[3] << 8); -+ int s = (data[0] << 24) | (data[1] << 16) | (data[2] << 8); - *dest++ = (float)s * INT32_SCALE; - } - return samples; -@@ -786,7 +811,7 @@ - return samples << 1; - } - --unsigned int CAEConvert::Float_S24NE4(float *data, const unsigned int samples, uint8_t *dest) -+unsigned int CAEConvert::Float_S24NE4H(float *data, const unsigned int samples, uint8_t *dest) - { - int32_t *dst = (int32_t*)dest; - #ifdef __SSE2__ -@@ -797,7 +822,7 @@ - /* work around invalid alignment */ - while ((((uintptr_t)data & 0xF) || ((uintptr_t)dest & 0xF)) && count > 0) - { -- dst[0] = (safeRound(data[0] * ((float)INT24_MAX+.5f)) & 0xFFFFFF) << 8; -+ dst[0] = safeRound(data[0] * ((float)INT24_MAX+.5f)) << 8; - ++data; - ++dst; - --count; -@@ -816,7 +841,7 @@ - { - const uint32_t odd = count - even; - if (odd == 1) -- dst[0] = (safeRound(data[0] * ((float)INT24_MAX+.5f)) & 0xFFFFFF) << 8; -+ dst[0] = safeRound(data[0] * ((float)INT24_MAX+.5f)) << 8; - else - { - __m128 in; -@@ -841,7 +866,69 @@ - _mm_empty(); - #else /* no SSE2 */ - for (uint32_t i = 0; i < samples; ++i) -- *dst++ = (safeRound(*data++ * ((float)INT24_MAX+.5f)) & 0xFFFFFF) << 8; -+ *dst++ = safeRound(*data++ * ((float)INT24_MAX+.5f)) << 8; -+ #endif -+ -+ return samples << 2; -+} -+ -+unsigned int CAEConvert::Float_S24NE4L(float *data, const unsigned int samples, uint8_t *dest) -+{ -+ int32_t *dst = (int32_t*)dest; -+ #ifdef __SSE2__ -+ -+ const __m128i msk = _mm_set1_epi32(0xFFFFFF); -+ const __m128 mul = _mm_set_ps1((float)INT24_MAX+.5f); -+ unsigned int count = samples; -+ -+ /* work around invalid alignment */ -+ while ((((uintptr_t)data & 0xF) || ((uintptr_t)dest & 0xF)) && count > 0) -+ { -+ dst[0] = safeRound(data[0] * ((float)INT24_MAX+.5f)) & 0xFFFFFF; -+ ++data; -+ ++dst; -+ --count; -+ } -+ -+ const uint32_t even = count & ~0x3; -+ for (uint32_t i = 0; i < even; i += 4, data += 4, dst += 4) -+ { -+ __m128 in = _mm_mul_ps(_mm_load_ps(data), mul); -+ __m128i con = _mm_cvtps_epi32(in); -+ con = _mm_and_si128(con, msk); -+ memcpy(dst, &con, sizeof(int32_t) * 4); -+ } -+ -+ if (count != even) -+ { -+ const uint32_t odd = count - even; -+ if (odd == 1) -+ dst[0] = safeRound(data[0] * ((float)INT24_MAX+.5f)) & 0xFFFFFF; -+ else -+ { -+ __m128 in; -+ if (odd == 2) -+ { -+ in = _mm_setr_ps(data[0], data[1], 0, 0); -+ in = _mm_mul_ps(in, mul); -+ __m128i con = _mm_cvtps_epi32(in); -+ con = _mm_and_si128(con, msk); -+ memcpy(dst, &con, sizeof(int32_t) * 2); -+ } -+ else -+ { -+ in = _mm_setr_ps(data[0], data[1], data[2], 0); -+ in = _mm_mul_ps(in, mul); -+ __m128i con = _mm_cvtps_epi32(in); -+ con = _mm_and_si128(con, msk); -+ memcpy(dst, &con, sizeof(int32_t) * 3); -+ } -+ } -+ } -+ _mm_empty(); -+ #else /* no SSE2 */ -+ for (uint32_t i = 0; i < samples; ++i) -+ *dst++ = safeRound(*data++ * ((float)INT24_MAX+.5f)) & 0xFFFFFF; - #endif - - return samples << 2; -diff -Naur xbmc-13b4/xbmc/cores/AudioEngine/Utils/AEConvert.h xbmc-imx6-13b4/xbmc/cores/AudioEngine/Utils/AEConvert.h ---- xbmc-13b4/xbmc/cores/AudioEngine/Utils/AEConvert.h 2014-04-24 11:49:41.292075533 +0200 -+++ xbmc-imx6-13b4/xbmc/cores/AudioEngine/Utils/AEConvert.h 2014-04-24 11:50:14.007208425 +0200 -@@ -28,8 +28,10 @@ - static unsigned int S8_Float (uint8_t *data, const unsigned int samples, float *dest); - static unsigned int S16LE_Float (uint8_t *data, const unsigned int samples, float *dest); - static unsigned int S16BE_Float (uint8_t *data, const unsigned int samples, float *dest); -- static unsigned int S24LE4_Float(uint8_t *data, const unsigned int samples, float *dest); -- static unsigned int S24BE4_Float(uint8_t *data, const unsigned int samples, float *dest); -+ static unsigned int S24LE4H_Float(uint8_t *data, const unsigned int samples, float *dest); -+ static unsigned int S24LE4L_Float(uint8_t *data, const unsigned int samples, float *dest); -+ static unsigned int S24BE4H_Float(uint8_t *data, const unsigned int samples, float *dest); -+ static unsigned int S24BE4L_Float(uint8_t *data, const unsigned int samples, float *dest); - static unsigned int S24LE3_Float(uint8_t *data, const unsigned int samples, float *dest); - static unsigned int S24BE3_Float(uint8_t *data, const unsigned int samples, float *dest); - static unsigned int S32LE_Float (uint8_t *data, const unsigned int samples, float *dest); -@@ -41,7 +43,8 @@ - static unsigned int Float_S8 (float *data, const unsigned int samples, uint8_t *dest); - static unsigned int Float_S16LE (float *data, const unsigned int samples, uint8_t *dest); - static unsigned int Float_S16BE (float *data, const unsigned int samples, uint8_t *dest); -- static unsigned int Float_S24NE4(float *data, const unsigned int samples, uint8_t *dest); -+ static unsigned int Float_S24NE4H(float *data, const unsigned int samples, uint8_t *dest); -+ static unsigned int Float_S24NE4L(float *data, const unsigned int samples, uint8_t *dest); - static unsigned int Float_S24NE3(float *data, const unsigned int samples, uint8_t *dest); - static unsigned int Float_S32LE (float *data, const unsigned int samples, uint8_t *dest); - static unsigned int Float_S32BE (float *data, const unsigned int samples, uint8_t *dest); -diff -Naur xbmc-13b4/xbmc/cores/AudioEngine/Utils/AEUtil.cpp xbmc-imx6-13b4/xbmc/cores/AudioEngine/Utils/AEUtil.cpp ---- xbmc-13b4/xbmc/cores/AudioEngine/Utils/AEUtil.cpp 2014-04-24 11:49:41.296075428 +0200 -+++ xbmc-imx6-13b4/xbmc/cores/AudioEngine/Utils/AEUtil.cpp 2014-04-24 11:50:14.007208425 +0200 -@@ -92,9 +92,13 @@ - 32, /* S32LE */ - 32, /* S32NE */ - -- 32, /* S24BE */ -- 32, /* S24LE */ -- 32, /* S24NE */ -+ 32, /* S24BE4H */ -+ 32, /* S24LE4H */ -+ 32, /* S24NE4H */ -+ -+ 32, /* S24BE4L */ -+ 32, /* S24LE4L */ -+ 32, /* S24NE4L */ - - 24, /* S24BE3 */ - 24, /* S24LE3 */ -@@ -114,8 +118,9 @@ - 8, /* U8P */ - 16, /* S16NEP */ - 32, /* S32NEP */ -- 32, /* S24NEP */ -- 24, /* S24NE3P*/ -+ 32, /* S24NE4HP */ -+ 32, /* S24NE4LP */ -+ 24, /* S24NE3P */ - sizeof(double) << 3, /* DOUBLEP */ - sizeof(float ) << 3 /* FLOATP */ - }; -@@ -125,7 +130,8 @@ - - const unsigned int CAEUtil::DataFormatToUsedBits(const enum AEDataFormat dataFormat) - { -- if (dataFormat == AE_FMT_S24BE4 || dataFormat == AE_FMT_S24LE4 || dataFormat == AE_FMT_S24NE4) -+ if (dataFormat == AE_FMT_S24BE4H || dataFormat == AE_FMT_S24LE4H || dataFormat == AE_FMT_S24NE4H || -+ dataFormat == AE_FMT_S24BE4L || dataFormat == AE_FMT_S24LE4L || dataFormat == AE_FMT_S24NE4L) - return 24; - else - return DataFormatToBits(dataFormat); -@@ -149,9 +155,13 @@ - "AE_FMT_S32LE", - "AE_FMT_S32NE", - -- "AE_FMT_S24BE4", -- "AE_FMT_S24LE4", -- "AE_FMT_S24NE4", /* S24 in 4 bytes */ -+ "AE_FMT_S24BE4H", -+ "AE_FMT_S24LE4H", -+ "AE_FMT_S24NE4H", /* S24 in upper 4 bytes */ -+ -+ "AE_FMT_S24BE4L", -+ "AE_FMT_S24LE4L", -+ "AE_FMT_S24NE4L", /* S24 in lower 4 bytes */ - - "AE_FMT_S24BE3", - "AE_FMT_S24LE3", -@@ -173,7 +183,8 @@ - "AE_FMT_U8P", - "AE_FMT_S16NEP", - "AE_FMT_S32NEP", -- "AE_FMT_S24NE4P", -+ "AE_FMT_S24NE4HP", -+ "AE_FMT_S24NE4LP", - "AE_FMT_S24NE3P", - "AE_FMT_DOUBLEP", - "AE_FMT_FLOATP" -diff -Naur xbmc-13b4/xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.cpp xbmc-imx6-13b4/xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.cpp ---- xbmc-13b4/xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.cpp 2014-04-24 11:49:41.204077867 +0200 -+++ xbmc-imx6-13b4/xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.cpp 2014-04-24 11:50:14.007208425 +0200 -@@ -35,6 +35,9 @@ - #include "Video/DVDVideoCodecFFmpeg.h" - #include "Video/DVDVideoCodecOpenMax.h" - #include "Video/DVDVideoCodecLibMpeg2.h" -+#if defined(HAS_IMXVPU) -+#include "Video/DVDVideoCodecIMX.h" -+#endif - #include "Video/DVDVideoCodecStageFright.h" - #if defined(HAVE_LIBCRYSTALHD) - #include "Video/DVDVideoCodecCrystalHD.h" -@@ -191,7 +194,11 @@ - #elif defined(TARGET_POSIX) && !defined(TARGET_DARWIN) - hwSupport += "VAAPI:no "; - #endif -- -+#if defined(HAS_IMXVPU) -+ hwSupport += "iMXVPU:yes "; -+#else -+ hwSupport += "iMXVPU:no "; -+#endif - CLog::Log(LOGDEBUG, "CDVDFactoryCodec: compiled in hardware support: %s", hwSupport.c_str()); - #if defined(HAS_LIBAMCODEC) - // amcodec can handle dvd playback. -@@ -205,6 +212,15 @@ - } - } - -+/*#endif*/ -+ -+#if defined(HAS_IMXVPU) -+ if (!hint.software) -+ { -+ if ( (pCodec = OpenCodec(new CDVDVideoCodecIMX(), hint, options)) ) return pCodec; -+ } -+#endif -+ - #if defined(TARGET_DARWIN_OSX) - if (!hint.software && CSettings::Get().GetBool("videoplayer.usevda")) - { -diff -Naur xbmc-13b4/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h xbmc-imx6-13b4/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h ---- xbmc-13b4/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h 2014-04-24 11:49:41.200077973 +0200 -+++ xbmc-imx6-13b4/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h 2014-04-24 11:50:14.007208425 +0200 -@@ -27,6 +27,7 @@ - #include - #include - #include "cores/VideoRenderers/RenderFormats.h" -+#include "DVDVideoCodecInfo.h" - - struct DVDCodecAvailableType - { -@@ -91,6 +92,11 @@ - struct { - CDVDMediaCodecInfo *mediacodec; - }; -+ -+ struct { -+ CDVDVideoCodecBuffer *codecinfo; -+ }; -+ - }; - - unsigned int iFlags; -diff -Naur xbmc-13b4/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp xbmc-imx6-13b4/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp ---- xbmc-13b4/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp 1970-01-01 01:00:00.000000000 +0100 -+++ xbmc-imx6-13b4/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp 2014-04-24 11:50:14.007208425 +0200 -@@ -0,0 +1,1501 @@ -+/* -+ * Copyright (C) 2010-2013 Team XBMC -+ * http://www.xbmc.org -+ * -+ * This Program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2, or (at your option) -+ * any later version. -+ * -+ * This Program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with XBMC; see the file COPYING. If not, see -+ * . -+ * -+ */ -+ -+#include "DVDVideoCodecIMX.h" -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include "threads/SingleLock.h" -+#include "utils/log.h" -+#include "DVDClock.h" -+#include "threads/Atomics.h" -+ -+ -+// FIXME get rid of these defines properly -+#define FRAME_ALIGN 16 -+#define MEDIAINFO 1 -+#define _4CC(c1,c2,c3,c4) (((uint32_t)(c4)<<24)|((uint32_t)(c3)<<16)|((uint32_t)(c2)<<8)|(uint32_t)(c1)) -+#define Align(ptr,align) (((unsigned int)ptr + (align) - 1)/(align)*(align)) -+ -+// Extrace physical and virtual addresses from CDVDVideoCodecBuffer pointers -+#define GET_PHYS_ADDR(buf) (buf)->data[1] -+#define GET_VIRT_ADDR(buf) (buf)->data[0] -+#define GET_DEINTERLACER(buf) (buf)->data[2] -+#define GET_FIELDTYPE(buf) (buf)->data[3] -+ -+// Experiments show that we need at least one more (+1) V4L buffer than the min value returned by the VPU -+const int CDVDVideoCodecIMX::m_extraVpuBuffers = 6; -+const int CDVDVideoCodecIMX::m_maxVpuDecodeLoops = 5; -+CCriticalSection CDVDVideoCodecIMX::m_codecBufferLock; -+ -+bool CDVDVideoCodecIMX::VpuAllocBuffers(VpuMemInfo *pMemBlock) -+{ -+ int i, size; -+ void* ptr; -+ VpuMemDesc vpuMem; -+ VpuDecRetCode ret; -+ -+ for(i=0; inSubBlockNum; i++) -+ { -+ size = pMemBlock->MemSubBlock[i].nAlignment + pMemBlock->MemSubBlock[i].nSize; -+ if (pMemBlock->MemSubBlock[i].MemType == VPU_MEM_VIRT) -+ { // Allocate standard virtual memory -+ ptr = malloc(size); -+ if(ptr == NULL) -+ { -+ CLog::Log(LOGERROR, "%s - Unable to malloc %d bytes.\n", __FUNCTION__, size); -+ goto AllocFailure; -+ } -+ pMemBlock->MemSubBlock[i].pVirtAddr = (unsigned char*)Align(ptr, pMemBlock->MemSubBlock[i].nAlignment); -+ -+ m_decMemInfo.nVirtNum++; -+ m_decMemInfo.virtMem = (void**)realloc(m_decMemInfo.virtMem, m_decMemInfo.nVirtNum*sizeof(void*)); -+ m_decMemInfo.virtMem[m_decMemInfo.nVirtNum-1] = ptr; -+ } -+ else -+ { // Allocate contigous mem for DMA -+ vpuMem.nSize = size; -+ ret = VPU_DecGetMem(&vpuMem); -+ if(ret != VPU_DEC_RET_SUCCESS) -+ { -+ CLog::Log(LOGERROR, "%s - Unable alloc %d bytes of physical memory (%d).\n", __FUNCTION__, size, ret); -+ goto AllocFailure; -+ } -+ pMemBlock->MemSubBlock[i].pVirtAddr = (unsigned char*)Align(vpuMem.nVirtAddr, pMemBlock->MemSubBlock[i].nAlignment); -+ pMemBlock->MemSubBlock[i].pPhyAddr = (unsigned char*)Align(vpuMem.nPhyAddr, pMemBlock->MemSubBlock[i].nAlignment); -+ -+ m_decMemInfo.nPhyNum++; -+ m_decMemInfo.phyMem = (VpuMemDesc*)realloc(m_decMemInfo.phyMem, m_decMemInfo.nPhyNum*sizeof(VpuMemDesc)); -+ m_decMemInfo.phyMem[m_decMemInfo.nPhyNum-1].nPhyAddr = vpuMem.nPhyAddr; -+ m_decMemInfo.phyMem[m_decMemInfo.nPhyNum-1].nVirtAddr = vpuMem.nVirtAddr; -+ m_decMemInfo.phyMem[m_decMemInfo.nPhyNum-1].nCpuAddr = vpuMem.nCpuAddr; -+ m_decMemInfo.phyMem[m_decMemInfo.nPhyNum-1].nSize = size; -+ } -+ } -+ -+ return true; -+ -+AllocFailure: -+ VpuFreeBuffers(); -+ return false; -+} -+ -+int CDVDVideoCodecIMX::VpuFindBuffer(void *frameAddr) -+{ -+ for (int i=0; i1) -+ { -+ ySize=Align(ySize,nAlign); -+ uvSize=Align(uvSize,nAlign); -+ } -+ -+ m_outputBuffers = new CDVDVideoCodecIMXBuffer*[m_vpuFrameBufferNum]; -+ -+ for (int i=0 ; i < m_vpuFrameBufferNum; i++) -+ { -+ totalSize=(ySize+uvSize+mvSize+nAlign)*1; -+ -+ vpuMem.nSize=totalSize; -+ ret = VPU_DecGetMem(&vpuMem); -+ if(ret != VPU_DEC_RET_SUCCESS) -+ { -+ CLog::Log(LOGERROR, "%s: vpu malloc frame buf failure: ret=%d \r\n",__FUNCTION__,ret); -+ return false; -+ } -+ -+ //record memory info for release -+ m_decMemInfo.nPhyNum++; -+ m_decMemInfo.phyMem = (VpuMemDesc*)realloc(m_decMemInfo.phyMem, m_decMemInfo.nPhyNum*sizeof(VpuMemDesc)); -+ m_decMemInfo.phyMem[m_decMemInfo.nPhyNum-1].nPhyAddr = vpuMem.nPhyAddr; -+ m_decMemInfo.phyMem[m_decMemInfo.nPhyNum-1].nVirtAddr = vpuMem.nVirtAddr; -+ m_decMemInfo.phyMem[m_decMemInfo.nPhyNum-1].nCpuAddr = vpuMem.nCpuAddr; -+ m_decMemInfo.phyMem[m_decMemInfo.nPhyNum-1].nSize = vpuMem.nSize; -+ -+ //fill frameBuf -+ ptr=(unsigned char*)vpuMem.nPhyAddr; -+ ptrVirt=(unsigned char*)vpuMem.nVirtAddr; -+ -+ //align the base address -+ if(nAlign>1) -+ { -+ ptr=(unsigned char*)Align(ptr,nAlign); -+ ptrVirt=(unsigned char*)Align(ptrVirt,nAlign); -+ } -+ -+ // fill stride info -+ m_vpuFrameBuffers[i].nStrideY=yStride; -+ m_vpuFrameBuffers[i].nStrideC=uvStride; -+ -+ // fill phy addr -+ m_vpuFrameBuffers[i].pbufY=ptr; -+ m_vpuFrameBuffers[i].pbufCb=ptr+ySize; -+ m_vpuFrameBuffers[i].pbufCr=0; -+ m_vpuFrameBuffers[i].pbufMvCol=ptr+ySize+uvSize; -+ //ptr+=ySize+uSize+vSize+mvSize; -+ // fill virt addr -+ m_vpuFrameBuffers[i].pbufVirtY=ptrVirt; -+ m_vpuFrameBuffers[i].pbufVirtCb=ptrVirt+ySize; -+ m_vpuFrameBuffers[i].pbufVirtCr=0; -+ m_vpuFrameBuffers[i].pbufVirtMvCol=ptrVirt+ySize+uvSize; -+ //ptrVirt+=ySize+uSize+vSize+mvSize; -+ -+ m_vpuFrameBuffers[i].pbufY_tilebot=0; -+ m_vpuFrameBuffers[i].pbufCb_tilebot=0; -+ m_vpuFrameBuffers[i].pbufVirtY_tilebot=0; -+ m_vpuFrameBuffers[i].pbufVirtCb_tilebot=0; -+ -+#ifdef TRACE_FRAMES -+ m_outputBuffers[i] = new CDVDVideoCodecIMXBuffer(i); -+#else -+ m_outputBuffers[i] = new CDVDVideoCodecIMXBuffer(); -+#endif -+ } -+ -+ if (m_initInfo.nInterlace) -+ { -+ CLog::Log(LOGNOTICE, "IMX: Enable hardware deinterlacing\n"); -+ if (!m_deinterlacer.Init(m_initInfo.nPicWidth, m_initInfo.nPicHeight, GetAllowedReferences()+1, nAlign)) -+ { -+ CLog::Log(LOGWARNING, "IMX: Failed to initialize IPU buffers: deinterlacing disabled\n"); -+ } -+ else -+ { -+ for (int i=0; iOpen(hints.codec, (uint8_t *)hints.extradata, hints.extrasize, true); -+ } -+ } -+ break; -+ case CODEC_ID_VC1: -+ m_decOpenParam.CodecFormat = VPU_V_VC1_AP; -+ m_pFormatName = "iMX-vc1"; -+ break; -+/* FIXME TODO -+ * => for this type we have to set height, width, nChromaInterleave and nMapType -+ case CODEC_ID_MJPEG: -+ m_decOpenParam.CodecFormat = VPU_V_MJPG; -+ m_pFormatName = "iMX-mjpg"; -+ break;*/ -+ case CODEC_ID_CAVS: -+ case CODEC_ID_AVS: -+ m_decOpenParam.CodecFormat = VPU_V_AVS; -+ m_pFormatName = "iMX-AVS"; -+ break; -+ case CODEC_ID_RV10: -+ case CODEC_ID_RV20: -+ case CODEC_ID_RV30: -+ case CODEC_ID_RV40: -+ m_decOpenParam.CodecFormat = VPU_V_RV; -+ m_pFormatName = "iMX-RV"; -+ break; -+ case CODEC_ID_KMVC: -+ m_decOpenParam.CodecFormat = VPU_V_AVC_MVC; -+ m_pFormatName = "iMX-MVC"; -+ break; -+ case CODEC_ID_VP8: -+ m_decOpenParam.CodecFormat = VPU_V_VP8; -+ m_pFormatName = "iMX-vp8"; -+ break; -+ case CODEC_ID_MPEG4: -+ switch(m_hints.codec_tag) -+ { -+ case _4CC('D','I','V','X'): -+ m_decOpenParam.CodecFormat = VPU_V_XVID; // VPU_V_DIVX4 -+ m_pFormatName = "iMX-divx4"; -+ break; -+ case _4CC('D','X','5','0'): -+ case _4CC('D','I','V','5'): -+ m_decOpenParam.CodecFormat = VPU_V_XVID; // VPU_V_DIVX56 -+ m_pFormatName = "iMX-divx5"; -+ break; -+ case _4CC('X','V','I','D'): -+ case _4CC('M','P','4','V'): -+ case _4CC('P','M','P','4'): -+ case _4CC('F','M','P','4'): -+ m_decOpenParam.CodecFormat = VPU_V_XVID; -+ m_pFormatName = "iMX-xvid"; -+ break; -+ default: -+ CLog::Log(LOGERROR, "iMX VPU : MPEG4 codec tag %d is not (yet) handled.\n", m_hints.codec_tag); -+ return false; -+ } -+ break; -+ default: -+ CLog::Log(LOGERROR, "iMX VPU : codecid %d is not (yet) handled.\n", m_hints.codec); -+ return false; -+ } -+ -+ return true; -+} -+ -+void CDVDVideoCodecIMX::Dispose(void) -+{ -+ VpuDecRetCode ret; -+ bool VPU_loaded = m_vpuHandle; -+ -+ // Block render thread from using that framebuffers -+ Enter(); -+ -+ // Release last buffer -+ if(m_lastBuffer) -+ SAFE_RELEASE(m_lastBuffer); -+ -+ // Invalidate output buffers to prevent the renderer from mapping this memory -+ for (int i=0; iReleaseFramebuffer(&m_vpuHandle); -+ SAFE_RELEASE(m_outputBuffers[i]); -+ } -+ -+ Leave(); -+ -+ if (m_vpuHandle) -+ { -+ ret = VPU_DecFlushAll(m_vpuHandle); -+ if (ret != VPU_DEC_RET_SUCCESS) -+ { -+ CLog::Log(LOGERROR, "%s - VPU flush failed with error code %d.\n", __FUNCTION__, ret); -+ } -+ ret = VPU_DecClose(m_vpuHandle); -+ if (ret != VPU_DEC_RET_SUCCESS) -+ { -+ CLog::Log(LOGERROR, "%s - VPU close failed with error code %d.\n", __FUNCTION__, ret); -+ } -+ m_vpuHandle = 0; -+ } -+ -+ m_frameCounter = 0; -+ m_deinterlacer.Close(); -+ -+ // Clear memory -+ if (m_outputBuffers != NULL) -+ { -+ delete m_outputBuffers; -+ m_outputBuffers = NULL; -+ } -+ -+ VpuFreeBuffers(); -+ m_vpuFrameBufferNum = 0; -+ -+ if (m_vpuFrameBuffers != NULL) -+ { -+ delete m_vpuFrameBuffers; -+ m_vpuFrameBuffers = NULL; -+ } -+ -+ if (VPU_loaded) -+ { -+ ret = VPU_DecUnLoad(); -+ if (ret != VPU_DEC_RET_SUCCESS) -+ { -+ CLog::Log(LOGERROR, "%s - VPU unload failed with error code %d.\n", __FUNCTION__, ret); -+ } -+ } -+ -+ if (m_converter) -+ { -+ m_converter->Close(); -+ SAFE_DELETE(m_converter); -+ } -+ return; -+} -+ -+int CDVDVideoCodecIMX::Decode(BYTE *pData, int iSize, double dts, double pts) -+{ -+ VpuDecFrameLengthInfo frameLengthInfo; -+ VpuBufferNode inData; -+ VpuDecRetCode ret; -+ int decRet = 0; -+ int retStatus = 0; -+ int demuxer_bytes = iSize; -+ uint8_t *demuxer_content = pData; -+ int retries = 0; -+ int idx; -+ -+#ifdef IMX_PROFILE -+ static unsigned long long previous, current; -+ unsigned long long before_dec; -+#endif -+ -+ if (!m_vpuHandle) -+ { -+ VpuOpen(); -+ if (!m_vpuHandle) -+ return VC_ERROR; -+ } -+ -+ for (int i=0; i < m_vpuFrameBufferNum; i++) -+ { -+ if (m_outputBuffers[i]->Rendered()) -+ { -+ ret = m_outputBuffers[i]->ReleaseFramebuffer(&m_vpuHandle); -+ if(ret != VPU_DEC_RET_SUCCESS) -+ { -+ CLog::Log(LOGERROR, "%s: vpu clear frame display failure: ret=%d \r\n",__FUNCTION__,ret); -+ } -+ } -+ } -+ -+#ifdef IMX_PROFILE -+ current = XbmcThreads::SystemClockMillis(); -+ CLog::Log(LOGDEBUG, "%s - delta time decode : %llu - demux size : %d dts : %f - pts : %f\n", __FUNCTION__, current - previous, iSize, dts, pts); -+ previous = current; -+#endif -+ -+ if ((pData && iSize) || -+ (m_bytesToBeConsumed)) -+ { -+ if ((m_convert_bitstream) && (iSize)) -+ { -+ // convert demuxer packet from bitstream to bytestream (AnnexB) -+ if (m_converter->Convert(demuxer_content, demuxer_bytes)) -+ { -+ demuxer_content = m_converter->GetConvertBuffer(); -+ demuxer_bytes = m_converter->GetConvertSize(); -+ } -+ else -+ CLog::Log(LOGERROR,"%s - bitstream_convert error", __FUNCTION__); -+ } -+ -+ inData.nSize = demuxer_bytes; -+ inData.pPhyAddr = NULL; -+ inData.pVirAddr = demuxer_content; -+ // FIXME TODO VP8 & DivX3 require specific sCodecData values -+ if ((m_decOpenParam.CodecFormat == VPU_V_MPEG2) || -+ (m_decOpenParam.CodecFormat == VPU_V_VC1_AP)|| -+ (m_decOpenParam.CodecFormat == VPU_V_XVID)) -+ { -+ inData.sCodecData.pData = (unsigned char *)m_hints.extradata; -+ inData.sCodecData.nSize = m_hints.extrasize; -+ } -+ else -+ { -+ inData.sCodecData.pData = NULL; -+ inData.sCodecData.nSize = 0; -+ } -+ -+ while (true) // Decode as long as the VPU consumes data -+ { -+#ifdef IMX_PROFILE -+ before_dec = XbmcThreads::SystemClockMillis(); -+#endif -+ if (m_frameReported) -+ m_bytesToBeConsumed += inData.nSize; -+ ret = VPU_DecDecodeBuf(m_vpuHandle, &inData, &decRet); -+#ifdef IMX_PROFILE -+ CLog::Log(LOGDEBUG, "%s - VPU dec 0x%x decode takes : %lld\n\n", __FUNCTION__, decRet, XbmcThreads::SystemClockMillis() - before_dec); -+#endif -+ -+ if (ret != VPU_DEC_RET_SUCCESS) -+ { -+ CLog::Log(LOGERROR, "%s - VPU decode failed with error code %d.\n", __FUNCTION__, ret); -+ goto out_error; -+ } -+ -+ if (decRet & VPU_DEC_INIT_OK) -+ // VPU decoding init OK : We can retrieve stream info -+ { -+ ret = VPU_DecGetInitialInfo(m_vpuHandle, &m_initInfo); -+ if (ret == VPU_DEC_RET_SUCCESS) -+ { -+ CLog::Log(LOGDEBUG, "%s - VPU Init Stream Info : %dx%d (interlaced : %d - Minframe : %d)"\ -+ " - Align : %d bytes - crop : %d %d %d %d - Q16Ratio : %x\n", __FUNCTION__, -+ m_initInfo.nPicWidth, m_initInfo.nPicHeight, m_initInfo.nInterlace, m_initInfo.nMinFrameBufferCount, -+ m_initInfo.nAddressAlignment, m_initInfo.PicCropRect.nLeft, m_initInfo.PicCropRect.nTop, -+ m_initInfo.PicCropRect.nRight, m_initInfo.PicCropRect.nBottom, m_initInfo.nQ16ShiftWidthDivHeightRatio); -+ if (VpuAllocFrameBuffers()) -+ { -+ ret = VPU_DecRegisterFrameBuffer(m_vpuHandle, m_vpuFrameBuffers, m_vpuFrameBufferNum); -+ if (ret != VPU_DEC_RET_SUCCESS) -+ { -+ CLog::Log(LOGERROR, "%s - VPU error while registering frame buffers (%d).\n", __FUNCTION__, ret); -+ goto out_error; -+ } -+ } -+ else -+ { -+ goto out_error; -+ } -+ } -+ else -+ { -+ CLog::Log(LOGERROR, "%s - VPU get initial info failed (%d).\n", __FUNCTION__, ret); -+ goto out_error; -+ } -+ } //VPU_DEC_INIT_OK -+ -+ if (decRet & VPU_DEC_ONE_FRM_CONSUMED) -+ { -+ ret = VPU_DecGetConsumedFrameInfo(m_vpuHandle, &frameLengthInfo); -+ if (ret != VPU_DEC_RET_SUCCESS) -+ { -+ CLog::Log(LOGERROR, "%s - VPU error retireving info about consummed frame (%d).\n", __FUNCTION__, ret); -+ } -+ m_bytesToBeConsumed -= (frameLengthInfo.nFrameLength + frameLengthInfo.nStuffLength); -+ if (frameLengthInfo.pFrame) -+ { -+ idx = VpuFindBuffer(frameLengthInfo.pFrame->pbufY); -+ if (m_bytesToBeConsumed < 50) -+ m_bytesToBeConsumed = 0; -+ if (idx != -1) -+ { -+ if (m_previousPts != DVD_NOPTS_VALUE) -+ { -+ m_outputBuffers[idx]->SetPts(m_previousPts); -+ m_previousPts = DVD_NOPTS_VALUE; -+ } -+ else -+ m_outputBuffers[idx]->SetPts(pts); -+ } -+ else -+ CLog::Log(LOGERROR, "%s - could not find frame buffer\n", __FUNCTION__); -+ } -+ } //VPU_DEC_ONE_FRM_CONSUMED -+ -+ if (decRet & VPU_DEC_OUTPUT_DIS) -+ // Frame ready to be displayed -+ { -+ if (retStatus & VC_PICTURE) -+ CLog::Log(LOGERROR, "%s - Second picture in the same decode call !\n", __FUNCTION__); -+ -+ ret = VPU_DecGetOutputFrame(m_vpuHandle, &m_frameInfo); -+ if(ret != VPU_DEC_RET_SUCCESS) -+ { -+ CLog::Log(LOGERROR, "%s - VPU Cannot get output frame(%d).\n", __FUNCTION__, ret); -+ goto out_error; -+ } -+ -+ // Some codecs (VC1?) lie about their frame size (mod 16). Adjust... -+ m_frameInfo.pExtInfo->nFrmWidth = (((m_frameInfo.pExtInfo->nFrmWidth) + 15) & ~15); -+ m_frameInfo.pExtInfo->nFrmHeight = (((m_frameInfo.pExtInfo->nFrmHeight) + 15) & ~15); -+ -+ retStatus |= VC_PICTURE; -+ } //VPU_DEC_OUTPUT_DIS -+ -+ // According to libfslvpuwrap: If this flag is set then the frame should -+ // be dropped. It is just returned to gather decoder information but not -+ // for display. -+ if (decRet & VPU_DEC_OUTPUT_MOSAIC_DIS) -+ { -+ ret = VPU_DecGetOutputFrame(m_vpuHandle, &m_frameInfo); -+ if(ret != VPU_DEC_RET_SUCCESS) -+ { -+ CLog::Log(LOGERROR, "%s - VPU Cannot get output frame(%d).\n", __FUNCTION__, ret); -+ goto out_error; -+ } -+ -+ // Display frame -+ ret = VPU_DecOutFrameDisplayed(m_vpuHandle, m_frameInfo.pDisplayFrameBuf); -+ if(ret != VPU_DEC_RET_SUCCESS) -+ { -+ CLog::Log(LOGERROR, "%s: VPU Clear frame display failure(%d)\n",__FUNCTION__,ret); -+ goto out_error; -+ } -+ } //VPU_DEC_OUTPUT_MOSAIC_DIS -+ -+ if (decRet & VPU_DEC_OUTPUT_REPEAT) -+ { -+ CLog::Log(LOGDEBUG, "%s - Frame repeat.\n", __FUNCTION__); -+ } -+ if (decRet & VPU_DEC_OUTPUT_DROPPED) -+ { -+ CLog::Log(LOGDEBUG, "%s - Frame dropped.\n", __FUNCTION__); -+ } -+ if (decRet & VPU_DEC_NO_ENOUGH_BUF) -+ { -+ CLog::Log(LOGERROR, "%s - No frame buffer available.\n", __FUNCTION__); -+ } -+ if (decRet & VPU_DEC_SKIP) -+ { -+ CLog::Log(LOGDEBUG, "%s - Frame skipped.\n", __FUNCTION__); -+ } -+ if (decRet & VPU_DEC_FLUSH) -+ { -+ CLog::Log(LOGNOTICE, "%s - VPU requires a flush.\n", __FUNCTION__); -+ Reset(); -+ retStatus = VC_FLUSHED; -+ } -+ if (decRet & VPU_DEC_OUTPUT_EOS) -+ { -+ CLog::Log(LOGNOTICE, "%s - EOS encountered.\n", __FUNCTION__); -+ } -+ if ((decRet & VPU_DEC_NO_ENOUGH_INBUF) || -+ (decRet & VPU_DEC_OUTPUT_DIS)) -+ { -+ // We are done with VPU decoder that time -+ break; -+ } -+ -+ retries++; -+ if (retries >= m_maxVpuDecodeLoops) -+ { -+ CLog::Log(LOGERROR, "%s - Leaving VPU decoding loop after %d iterations\n", __FUNCTION__, m_maxVpuDecodeLoops); -+ break; -+ } -+ -+ if (!(decRet & VPU_DEC_INPUT_USED)) -+ { -+ CLog::Log(LOGERROR, "%s - input not used : addr %p size :%d!\n", __FUNCTION__, inData.pVirAddr, inData.nSize); -+ } -+ -+ // Let's process again as VPU_DEC_NO_ENOUGH_INBUF was not set -+ // and we don't have an image ready if we reach that point -+ inData.pVirAddr = NULL; -+ inData.nSize = 0; -+ } // Decode loop -+ } //(pData && iSize) -+ -+ if (retStatus == 0) -+ { -+ retStatus |= VC_BUFFER; -+ } -+ -+ if (m_bytesToBeConsumed > 0) -+ { -+ // Remember the current pts because the data which has just -+ // been sent to the VPU has not yet been consumed. -+ // This pts is related to the frame that will be consumed -+ // at next call... -+ m_previousPts = pts; -+ } -+ // Store current dts (will be used only if VC_PICTURE is set) -+ m_dts = dts; -+ -+#ifdef IMX_PROFILE -+ CLog::Log(LOGDEBUG, "%s - returns %x - duration %lld\n", __FUNCTION__, retStatus, XbmcThreads::SystemClockMillis() - previous); -+#endif -+ return retStatus; -+ -+out_error: -+ return VC_ERROR; -+} -+ -+void CDVDVideoCodecIMX::Reset() -+{ -+ int ret; -+ -+ CLog::Log(LOGDEBUG, "%s - called\n", __FUNCTION__); -+ -+ // Release last buffer -+ if(m_lastBuffer) -+ SAFE_RELEASE(m_lastBuffer); -+ -+ // Invalidate all buffers -+ for(int i=0; i < m_vpuFrameBufferNum; i++) -+ m_outputBuffers[i]->ReleaseFramebuffer(&m_vpuHandle); -+ -+ m_frameCounter = 0; -+ m_deinterlacer.Reset(); -+ m_bytesToBeConsumed = 0; -+ m_previousPts = DVD_NOPTS_VALUE; -+ -+ // Flush VPU -+ ret = VPU_DecFlushAll(m_vpuHandle); -+ if (ret != VPU_DEC_RET_SUCCESS) -+ { -+ CLog::Log(LOGERROR, "%s - VPU flush failed with error code %d.\n", __FUNCTION__, ret); -+ } -+ -+} -+ -+unsigned CDVDVideoCodecIMX::GetAllowedReferences() -+{ -+ return 3; -+} -+ -+bool CDVDVideoCodecIMX::ClearPicture(DVDVideoPicture* pDvdVideoPicture) -+{ -+ if (pDvdVideoPicture) -+ { -+ SAFE_RELEASE(pDvdVideoPicture->codecinfo); -+ } -+ -+ return true; -+} -+ -+bool CDVDVideoCodecIMX::GetPicture(DVDVideoPicture* pDvdVideoPicture) -+{ -+#ifdef IMX_PROFILE -+ static unsigned int previous = 0; -+ unsigned int current; -+ -+ current = XbmcThreads::SystemClockMillis(); -+ CLog::Log(LOGDEBUG, "%s tm:%03d\n", __FUNCTION__, current - previous); -+ previous = current; -+#endif -+ -+ m_frameCounter++; -+ -+ pDvdVideoPicture->iFlags = DVP_FLAG_ALLOCATED; -+ if (m_dropState) -+ pDvdVideoPicture->iFlags |= DVP_FLAG_DROPPED; -+ else -+ pDvdVideoPicture->iFlags &= ~DVP_FLAG_DROPPED; -+ -+ pDvdVideoPicture->format = RENDER_FMT_IMXMAP; -+ pDvdVideoPicture->dts = DVD_NOPTS_VALUE; -+ pDvdVideoPicture->iWidth = m_frameInfo.pExtInfo->FrmCropRect.nRight - m_frameInfo.pExtInfo->FrmCropRect.nLeft; -+ pDvdVideoPicture->iHeight = m_frameInfo.pExtInfo->FrmCropRect.nBottom - m_frameInfo.pExtInfo->FrmCropRect.nTop; -+ -+ pDvdVideoPicture->iDisplayWidth = ((pDvdVideoPicture->iWidth * m_frameInfo.pExtInfo->nQ16ShiftWidthDivHeightRatio) + 32767) >> 16; -+ pDvdVideoPicture->iDisplayHeight = pDvdVideoPicture->iHeight; -+ -+ int idx = VpuFindBuffer(m_frameInfo.pDisplayFrameBuf->pbufY); -+ if (idx != -1) -+ { -+ CDVDVideoCodecIMXBuffer *buffer = m_outputBuffers[idx]; -+ -+ pDvdVideoPicture->pts = buffer->GetPts(); -+ pDvdVideoPicture->dts = m_dts; -+ if (!m_usePTS) -+ { -+ pDvdVideoPicture->pts = DVD_NOPTS_VALUE; -+ pDvdVideoPicture->dts = DVD_NOPTS_VALUE; -+ } -+ -+ buffer->Queue(&m_frameInfo, m_lastBuffer); -+ -+#ifdef TRACE_FRAMES -+ CLog::Log(LOGDEBUG, "+ %02d dts %f pts %f (VPU)\n", idx, pDvdVideoPicture->dts, pDvdVideoPicture->pts); -+#endif -+ -+ /* -+ // This does not work reliably since some streams do not report -+ // correctly if a frame is interlaced. -+ if (m_frameInfo.eFieldType != VPU_FIELD_NONE) -+ GET_DEINTERLACER(buffer) = (uint8_t*)&m_deinterlacer; -+ else -+ GET_DEINTERLACER(buffer) = NULL; -+ */ -+ -+ pDvdVideoPicture->codecinfo = buffer; -+ pDvdVideoPicture->codecinfo->Lock(); -+ -+ // Save last buffer -+ if (m_lastBuffer) -+ SAFE_RELEASE(m_lastBuffer); -+ -+ m_lastBuffer = buffer; -+ m_lastBuffer->Lock(); -+ } -+ else -+ { -+ CLog::Log(LOGERROR, "%s - could not find frame buffer\n", __FUNCTION__); -+ } -+ -+ return true; -+} -+ -+void CDVDVideoCodecIMX::SetDropState(bool bDrop) -+{ -+ -+ // We are fast enough to continue to really decode every frames -+ // and avoid artefacts... -+ // (Of course these frames won't be rendered but only decoded !) -+ -+ if (m_dropState != bDrop) -+ { -+ m_dropState = bDrop; -+#ifdef TRACE_FRAMES -+ CLog::Log(LOGDEBUG, "%s : %d\n", __FUNCTION__, bDrop); -+#endif -+ } -+} -+ -+void CDVDVideoCodecIMX::Enter() -+{ -+ m_codecBufferLock.lock(); -+} -+ -+void CDVDVideoCodecIMX::Leave() -+{ -+ m_codecBufferLock.unlock(); -+} -+ -+/*******************************************/ -+ -+#ifdef TRACE_FRAMES -+CDVDVideoCodecIMXBuffer::CDVDVideoCodecIMXBuffer(int idx) -+ : m_refs(1) -+ , m_idx(idx) -+#else -+CDVDVideoCodecIMXBuffer::CDVDVideoCodecIMXBuffer() -+ : m_refs(1) -+#endif -+ , m_frameBuffer(NULL) -+ , m_rendered(false) -+ , m_pts(DVD_NOPTS_VALUE) -+ , m_previousBuffer(NULL) -+{ -+ GET_DEINTERLACER(this) = NULL; -+} -+ -+void CDVDVideoCodecIMXBuffer::Lock() -+{ -+#ifdef TRACE_FRAMES -+ long count = AtomicIncrement(&m_refs); -+ CLog::Log(LOGDEBUG, "R+ %02d - ref : %d (VPU)\n", m_idx, count); -+#else -+ AtomicIncrement(&m_refs); -+#endif -+} -+ -+long CDVDVideoCodecIMXBuffer::Release() -+{ -+ long count = AtomicDecrement(&m_refs); -+#ifdef TRACE_FRAMES -+ CLog::Log(LOGDEBUG, "R- %02d - ref : %d (VPU)\n", m_idx, count); -+#endif -+ if (count == 2) -+ { -+ // Only referenced by the coded and its next frame, release the previous -+ SAFE_RELEASE(m_previousBuffer); -+ } -+ if (count == 1) -+ { -+ // If count drops to 1 then the only reference is being held by the codec -+ // that it can be released in the next Decode call. -+ if(m_frameBuffer != NULL) -+ { -+ m_rendered = true; -+ SAFE_RELEASE(m_previousBuffer); -+#ifdef TRACE_FRAMES -+ CLog::Log(LOGDEBUG, "R %02d (VPU)\n", m_idx); -+#endif -+ } -+ } -+ else if (count == 0) -+ { -+ delete this; -+ } -+ -+ return count; -+} -+ -+bool CDVDVideoCodecIMXBuffer::IsValid() -+{ -+ return m_frameBuffer != NULL; -+} -+ -+bool CDVDVideoCodecIMXBuffer::Rendered() const -+{ -+ return m_rendered; -+} -+ -+void CDVDVideoCodecIMXBuffer::Queue(VpuDecOutFrameInfo *frameInfo, -+ CDVDVideoCodecIMXBuffer *previous) -+{ -+ // No lock necessary because at this time there is definitely no -+ // thread still holding a reference -+ m_frameBuffer = frameInfo->pDisplayFrameBuf; -+ m_rendered = false; -+ m_previousBuffer = previous; -+ if (m_previousBuffer) -+ m_previousBuffer->Lock(); -+ -+ iWidth = frameInfo->pExtInfo->nFrmWidth; -+ iHeight = frameInfo->pExtInfo->nFrmHeight; -+ GET_VIRT_ADDR(this) = m_frameBuffer->pbufVirtY; -+ GET_PHYS_ADDR(this) = m_frameBuffer->pbufY; -+ GET_FIELDTYPE(this) = (uint8_t*)frameInfo->eFieldType; -+} -+ -+VpuDecRetCode CDVDVideoCodecIMXBuffer::ReleaseFramebuffer(VpuDecHandle *handle) -+{ -+ // Again no lock required because this is only issued after the last -+ // external reference was released -+ VpuDecRetCode ret = VPU_DEC_RET_FAILURE; -+ -+ if((m_frameBuffer != NULL) && *handle) -+ { -+ ret = VPU_DecOutFrameDisplayed(*handle, m_frameBuffer); -+ if(ret != VPU_DEC_RET_SUCCESS) -+ CLog::Log(LOGERROR, "%s: vpu clear frame display failure: ret=%d \r\n",__FUNCTION__,ret); -+ } -+#ifdef TRACE_FRAMES -+ CLog::Log(LOGDEBUG, "- %02d (VPU)\n", m_idx); -+#endif -+ m_rendered = false; -+ m_frameBuffer = NULL; -+ m_pts = DVD_NOPTS_VALUE; -+ SAFE_RELEASE(m_previousBuffer); -+ -+ return ret; -+} -+ -+void CDVDVideoCodecIMXBuffer::SetPts(double pts) -+{ -+ m_pts = pts; -+} -+ -+double CDVDVideoCodecIMXBuffer::GetPts(void) const -+{ -+ return m_pts; -+} -+ -+CDVDVideoCodecIMXBuffer *CDVDVideoCodecIMXBuffer::GetPreviousBuffer() const -+{ -+ return m_previousBuffer; -+} -+ -+CDVDVideoCodecIMXBuffer::~CDVDVideoCodecIMXBuffer() -+{ -+ assert(m_refs == 0); -+#ifdef TRACE_FRAMES -+ CLog::Log(LOGDEBUG, "~ %02d (VPU)\n", m_idx); -+#endif -+} -+ -+#ifdef TRACE_FRAMES -+CDVDVideoCodecIPUBuffer::CDVDVideoCodecIPUBuffer(int idx) -+ : m_refs(1) -+ , m_idx(idx) -+#else -+CDVDVideoCodecIPUBuffer::CDVDVideoCodecIPUBuffer() -+ : m_refs(1) -+#endif -+ , m_source(NULL) -+ , m_pPhyAddr(NULL) -+ , m_pVirtAddr(NULL) -+ , m_nSize(0) -+{ -+} -+ -+CDVDVideoCodecIPUBuffer::~CDVDVideoCodecIPUBuffer() -+{ -+ assert(m_refs == 0); -+#ifdef TRACE_FRAMES -+ CLog::Log(LOGDEBUG, "~ %02d (IPU)\n", m_idx); -+#endif -+} -+ -+void CDVDVideoCodecIPUBuffer::Lock() -+{ -+#ifdef TRACE_FRAMES -+ long count = AtomicIncrement(&m_refs); -+ CLog::Log(LOGDEBUG, "R+ %02d - ref : %d (IPU)\n", m_idx, count); -+#else -+ AtomicIncrement(&m_refs); -+#endif -+ -+} -+ -+long CDVDVideoCodecIPUBuffer::Release() -+{ -+ long count = AtomicDecrement(&m_refs); -+#ifdef TRACE_FRAMES -+ CLog::Log(LOGDEBUG, "R- %02d - ref : %d (IPU)\n", m_idx, count); -+#endif -+ if (count == 1) -+ { -+ ReleaseFrameBuffer(); -+ } -+ else if (count == 0) -+ { -+ delete this; -+ } -+ -+ return count; -+} -+ -+bool CDVDVideoCodecIPUBuffer::IsValid() -+{ -+ return m_source && m_source->IsValid() && m_pPhyAddr; -+} -+ -+bool CDVDVideoCodecIPUBuffer::Process(int fd, CDVDVideoCodecIMXBuffer *buffer, -+ VpuFieldType fieldType, int fieldFmt, -+ bool lowMotion) -+{ -+ CDVDVideoCodecIMXBuffer *previousBuffer; -+ struct ipu_task task; -+ memset(&task, 0, sizeof(task)); -+ task.priority = IPU_TASK_PRIORITY_HIGH; -+ -+ if (lowMotion) -+ previousBuffer = buffer->GetPreviousBuffer(); -+ else -+ previousBuffer = NULL; -+ -+ SAFE_RELEASE(m_source); -+ -+ iWidth = buffer->iWidth; -+ iHeight = buffer->iHeight; -+ -+ // Input is the VPU decoded frame -+ task.input.width = iWidth; -+ task.input.height = iHeight; -+ task.input.format = IPU_PIX_FMT_NV12; -+ -+ // Output is our IPU buffer -+ task.output.width = iWidth; -+ task.output.height = iHeight; -+ task.output.format = IPU_PIX_FMT_NV12; -+ task.output.paddr = (int)GET_PHYS_ADDR(this); -+ -+ // Fill current and next buffer address -+ if (lowMotion && previousBuffer && previousBuffer->IsValid()) -+ { -+ task.input.paddr = (int)GET_PHYS_ADDR(previousBuffer); -+ task.input.paddr_n = (int)GET_PHYS_ADDR(buffer); -+ task.input.deinterlace.motion = LOW_MOTION; -+ } -+ else -+ { -+ task.input.paddr = (int)GET_PHYS_ADDR(buffer); -+ task.input.deinterlace.motion = HIGH_MOTION; -+ } -+ -+ task.input.deinterlace.enable = 1; -+ task.input.deinterlace.field_fmt = fieldFmt; -+ -+ switch (fieldType) -+ { -+ case VPU_FIELD_TOP: -+ case VPU_FIELD_TB: -+ task.input.deinterlace.field_fmt |= IPU_DEINTERLACE_FIELD_TOP; -+ break; -+ case VPU_FIELD_BOTTOM: -+ case VPU_FIELD_BT: -+ task.input.deinterlace.field_fmt |= IPU_DEINTERLACE_FIELD_BOTTOM; -+ break; -+ default: -+ break; -+ } -+ -+#ifdef IMX_PROFILE -+ unsigned int time = XbmcThreads::SystemClockMillis(); -+#endif -+ int ret = ioctl(fd, IPU_QUEUE_TASK, &task); -+#ifdef IMX_PROFILE -+ CLog::Log(LOGDEBUG, "DEINT: tm:%d\n", XbmcThreads::SystemClockMillis() - time); -+#endif -+ if (ret < 0) -+ { -+ CLog::Log(LOGERROR, "IPU task failed: %s\n", strerror(errno)); -+ return false; -+ } -+ -+ buffer->Lock(); -+ -+ // Remember the source buffer. This is actually not necessary since the output -+ // buffer is the one that is used by the renderer. But keep it bound for now -+ // since this state is used in IsValid which then needs to become a flag in -+ // this class. -+ m_source = buffer; -+ m_source->Lock(); -+ -+ buffer->Release(); -+ -+ return true; -+} -+ -+void CDVDVideoCodecIPUBuffer::ReleaseFrameBuffer() -+{ -+#ifdef TRACE_FRAMES -+ CLog::Log(LOGDEBUG, "- %02d (IPU)\n", m_idx); -+#endif -+ CSingleLock lock(CDVDVideoCodecIMX::m_codecBufferLock); -+ SAFE_RELEASE(m_source); -+} -+ -+bool CDVDVideoCodecIPUBuffer::Allocate(int fd, int width, int height, int nAlign) -+{ -+ m_iWidth = Align(width,FRAME_ALIGN); -+ m_iHeight = Align(height,(2*FRAME_ALIGN)); -+ // NV12 == 12 bpp -+ m_nSize = m_iWidth*m_iHeight*12/8; -+ m_pPhyAddr = m_nSize; -+ -+ GET_PHYS_ADDR(this) = GET_VIRT_ADDR(this) = NULL; -+ -+ int r = ioctl(fd, IPU_ALLOC, &m_pPhyAddr); -+ if (r < 0) -+ { -+ m_pPhyAddr = 0; -+ CLog::Log(LOGERROR, "ioctl IPU_ALLOC fail: disable deinterlacing: %s\n", strerror(errno)); -+ return false; -+ } -+ -+ CLog::Log(LOGNOTICE, "IPU: alloc %d bytes for frame of %dx%d at 0x%x\n", -+ m_nSize, m_iWidth, m_iHeight, m_pPhyAddr); -+ -+ m_pVirtAddr = (uint8_t*)mmap(0, m_nSize, PROT_READ | PROT_WRITE, MAP_SHARED, -+ fd, m_pPhyAddr); -+ if (!m_pVirtAddr) -+ { -+ CLog::Log(LOGERROR, "IPU mmap failed: disable deinterlacing: %s\n", strerror(errno)); -+ return false; -+ } -+ -+ if (nAlign>1) -+ { -+ GET_PHYS_ADDR(this) = (uint8_t*)Align(m_pPhyAddr, nAlign); -+ GET_VIRT_ADDR(this) = (uint8_t*)Align(m_pVirtAddr, nAlign); -+ } -+ else -+ { -+ GET_PHYS_ADDR(this) = (uint8_t*)m_pPhyAddr; -+ GET_VIRT_ADDR(this) = (uint8_t*)m_pVirtAddr; -+ } -+ -+ GET_DEINTERLACER(this) = NULL; -+ -+ return true; -+} -+ -+bool CDVDVideoCodecIPUBuffer::Free(int fd) -+{ -+ CSingleLock lock(CDVDVideoCodecIMX::m_codecBufferLock); -+ bool ret = true; -+ -+ // Unmap virtual memory -+ if (m_pVirtAddr != NULL) -+ { -+ if(munmap(m_pVirtAddr, m_nSize)) -+ { -+ CLog::Log(LOGERROR, "IPU unmap failed: %s\n", strerror(errno)); -+ ret = false; -+ } -+ -+ m_pVirtAddr = NULL; -+ } -+ -+ // Free IPU memory -+ if (m_pPhyAddr) -+ { -+ if (ioctl(fd, IPU_FREE, &m_pPhyAddr)) -+ { -+ CLog::Log(LOGERROR, "IPU free buffer 0x%x failed: %s\n", -+ m_pPhyAddr, strerror(errno)); -+ ret = false; -+ } -+ -+ m_pPhyAddr = 0; -+ } -+ -+ GET_PHYS_ADDR(this) = GET_VIRT_ADDR(this) = NULL; -+ SAFE_RELEASE(m_source); -+ -+ return ret; -+} -+ -+CDVDVideoCodecIPUBuffers::CDVDVideoCodecIPUBuffers() -+ : m_ipuHandle(0) -+ , m_bufferNum(0) -+ , m_buffers(NULL) -+ , m_currentFieldFmt(0) -+{ -+} -+ -+CDVDVideoCodecIPUBuffers::~CDVDVideoCodecIPUBuffers() -+{ -+ Close(); -+} -+ -+bool CDVDVideoCodecIPUBuffers::Init(int width, int height, int numBuffers, int nAlign) -+{ -+ if (numBuffers<=0) -+ { -+ CLog::Log(LOGERROR, "IPU Init: invalid number of buffers: %d\n", numBuffers); -+ return false; -+ } -+ -+ m_ipuHandle = open("/dev/mxc_ipu", O_RDWR, 0); -+ if (m_ipuHandle<=0) -+ { -+ CLog::Log(LOGWARNING, "Failed to initialize IPU: deinterlacing disabled: %s\n", -+ strerror(errno)); -+ m_ipuHandle = 0; -+ return false; -+ } -+ -+ m_bufferNum = numBuffers; -+ m_buffers = new CDVDVideoCodecIPUBuffer*[m_bufferNum]; -+ m_currentFieldFmt = 0; -+ -+ for (int i=0; i < m_bufferNum; i++) -+ { -+#ifdef TRACE_FRAMES -+ m_buffers[i] = new CDVDVideoCodecIPUBuffer(i); -+#else -+ m_buffers[i] = new CDVDVideoCodecIPUBuffer; -+#endif -+ if (!m_buffers[i]->Allocate(m_ipuHandle, width, height, nAlign)) -+ { -+ Close(); -+ return false; -+ } -+ } -+ -+ return true; -+} -+ -+bool CDVDVideoCodecIPUBuffers::Reset() -+{ -+ for (int i=0; i < m_bufferNum; i++) -+ m_buffers[i]->ReleaseFrameBuffer(); -+ m_currentFieldFmt = 0; -+} -+ -+bool CDVDVideoCodecIPUBuffers::Close() -+{ -+ bool ret = true; -+ -+ if (m_ipuHandle) -+ { -+ for (int i=0; i < m_bufferNum; i++) -+ { -+ if (m_buffers[i] == NULL ) continue; -+ if (!m_buffers[i]->Free(m_ipuHandle)) -+ ret = false; -+ } -+ -+ // Close IPU device -+ if (close(m_ipuHandle)) -+ { -+ CLog::Log(LOGERROR, "IPU failed to close interface: %s\n", strerror(errno)); -+ ret = false; -+ } -+ -+ m_ipuHandle = 0; -+ } -+ -+ if (m_buffers) -+ { -+ for (int i=0; i < m_bufferNum; i++) -+ SAFE_RELEASE(m_buffers[i]); -+ -+ delete m_buffers; -+ m_buffers = NULL; -+ } -+ -+ m_bufferNum = 0; -+ return true; -+} -+ -+CDVDVideoCodecIPUBuffer * -+CDVDVideoCodecIPUBuffers::Process(CDVDVideoCodecBuffer *sourceBuffer, -+ VpuFieldType fieldType, bool lowMotion) -+{ -+ CDVDVideoCodecIPUBuffer *target = NULL; -+ bool ret = true; -+ -+ // TODO: Needs further checks on real streams -+ if (!m_bufferNum /*|| (fieldType == VPU_FIELD_NONE)*/) -+ return NULL; -+ -+ for (int i=0; i < m_bufferNum; i++ ) -+ { -+ if (!m_buffers[i]->Rendered()) continue; -+ -+ // IPU process: -+ // SRC: Current VPU physical buffer address + last VPU buffer address -+ // DST: IPU buffer[i] -+ ret = m_buffers[i]->Process(m_ipuHandle, (CDVDVideoCodecIMXBuffer*)sourceBuffer, -+ fieldType, m_currentFieldFmt/* | IPU_DEINTERLACE_RATE_EN*/, -+ lowMotion); -+ if (ret) -+ { -+#ifdef TRACE_FRAMES -+ CLog::Log(LOGDEBUG, "+ %02d (IPU)\n", i); -+#endif -+ target = m_buffers[i]; -+ } -+ break; -+ } -+ -+ // Buffers are there but there is no free one, this is an error! -+ // Rendering will continue with unprocessed frames ... -+ if (ret && target==NULL) -+ { -+ CLog::Log(LOGERROR, "Deinterlacing: did not find free buffer, forward unprocessed frame\n"); -+ } -+ -+ // Toggle frame index bit -+ //m_currentFieldFmt ^= IPU_DEINTERLACE_RATE_FRAME1; -+ -+ return target; -+} -diff -Naur xbmc-13b4/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h xbmc-imx6-13b4/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h ---- xbmc-13b4/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h 1970-01-01 01:00:00.000000000 +0100 -+++ xbmc-imx6-13b4/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h 2014-04-24 11:50:14.007208425 +0200 -@@ -0,0 +1,215 @@ -+#pragma once -+/* -+ * Copyright (C) 2010-2013 Team XBMC -+ * http://www.xbmc.org -+ * -+ * This Program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2, or (at your option) -+ * any later version. -+ * -+ * This Program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with XBMC; see the file COPYING. If not, see -+ * . -+ * -+ */ -+#include -+#include -+#include "DVDVideoCodec.h" -+#include "DVDStreamInfo.h" -+#include "DVDVideoCodecInfo.h" -+#include "threads/CriticalSection.h" -+#include "utils/BitstreamConverter.h" -+ -+ -+//#define IMX_PROFILE -+//#define TRACE_FRAMES -+ -+class CDecMemInfo -+{ -+public: -+ CDecMemInfo() -+ : nVirtNum(0) -+ , virtMem(NULL) -+ , nPhyNum(0) -+ , phyMem(NULL) -+ {} -+ -+ //virtual mem info -+ int nVirtNum; -+ void** virtMem; -+ -+ //phy mem info -+ int nPhyNum; -+ VpuMemDesc* phyMem; -+}; -+ -+class CDVDVideoCodecIPUBuffer; -+ -+class CDVDVideoCodecIMXBuffer : public CDVDVideoCodecBuffer -+{ -+public: -+#ifdef TRACE_FRAMES -+ CDVDVideoCodecIMXBuffer(int idx); -+#else -+ CDVDVideoCodecIMXBuffer(); -+#endif -+ -+ // reference counting -+ virtual void Lock(); -+ virtual long Release(); -+ virtual bool IsValid(); -+ -+ bool Rendered() const; -+ void Queue(VpuDecOutFrameInfo *frameInfo, -+ CDVDVideoCodecIMXBuffer *previous); -+ VpuDecRetCode ReleaseFramebuffer(VpuDecHandle *handle); -+ void SetPts(double pts); -+ double GetPts(void) const; -+ CDVDVideoCodecIMXBuffer *GetPreviousBuffer() const; -+ -+private: -+ // private because we are reference counted -+ virtual ~CDVDVideoCodecIMXBuffer(); -+ -+private: -+#ifdef TRACE_FRAMES -+ int m_idx; -+#endif -+ long m_refs; -+ VpuFrameBuffer *m_frameBuffer; -+ bool m_rendered; -+ double m_pts; -+ CDVDVideoCodecIMXBuffer *m_previousBuffer; // Holds a the reference counted -+ // previous buffer -+}; -+ -+// Shared buffer that holds an IPU allocated memory block and serves as target -+// for IPU operations such as deinterlacing, rotation or color conversion. -+class CDVDVideoCodecIPUBuffer : public CDVDVideoCodecBuffer -+{ -+public: -+#ifdef TRACE_FRAMES -+ CDVDVideoCodecIPUBuffer(int idx); -+#else -+ CDVDVideoCodecIPUBuffer(); -+#endif -+ -+ // reference counting -+ virtual void Lock(); -+ virtual long Release(); -+ virtual bool IsValid(); -+ -+ // Returns whether the buffer is ready to be used -+ bool Rendered() const { return m_source == NULL; } -+ bool Process(int fd, CDVDVideoCodecIMXBuffer *buffer, -+ VpuFieldType fieldType, int fieldFmt, -+ bool lowMotion); -+ void ReleaseFrameBuffer(); -+ -+ bool Allocate(int fd, int width, int height, int nAlign); -+ bool Free(int fd); -+ -+private: -+ virtual ~CDVDVideoCodecIPUBuffer(); -+ -+private: -+#ifdef TRACE_FRAMES -+ int m_idx; -+#endif -+ long m_refs; -+ CDVDVideoCodecBuffer *m_source; -+ int m_pPhyAddr; -+ uint8_t *m_pVirtAddr; -+ int m_iWidth; -+ int m_iHeight; -+ int m_nSize; -+}; -+ -+// Collection class that manages a pool of IPU buffers that are used for -+// deinterlacing. In future they can also serve rotation or color conversion -+// buffers. -+class CDVDVideoCodecIPUBuffers -+{ -+ public: -+ CDVDVideoCodecIPUBuffers(); -+ ~CDVDVideoCodecIPUBuffers(); -+ -+ bool Init(int width, int height, int numBuffers, int nAlign); -+ bool Reset(); -+ bool Close(); -+ -+ CDVDVideoCodecIPUBuffer *Process(CDVDVideoCodecBuffer *sourceBuffer, -+ VpuFieldType fieldType, bool lowMotion); -+ -+ private: -+ int m_ipuHandle; -+ int m_bufferNum; -+ CDVDVideoCodecIPUBuffer **m_buffers; -+ int m_currentFieldFmt; -+}; -+ -+ -+class CDVDVideoCodecIMX : public CDVDVideoCodec -+{ -+ friend class CDVDVideoCodecIMXBuffer; -+ friend class CDVDVideoCodecIPUBuffer; -+ -+public: -+ CDVDVideoCodecIMX(); -+ virtual ~CDVDVideoCodecIMX(); -+ -+ // Methods from CDVDVideoCodec which require overrides -+ virtual bool Open(CDVDStreamInfo &hints, CDVDCodecOptions &options); -+ virtual void Dispose(void); -+ virtual int Decode(BYTE *pData, int iSize, double dts, double pts); -+ virtual void Reset(void); -+ virtual bool ClearPicture(DVDVideoPicture *pDvdVideoPicture); -+ virtual bool GetPicture(DVDVideoPicture *pDvdVideoPicture); -+ virtual void SetDropState(bool bDrop); -+ virtual const char* GetName(void) { return (const char*)m_pFormatName; } -+ virtual unsigned GetAllowedReferences(); -+ -+ static void Enter(); -+ static void Leave(); -+ -+protected: -+ -+ bool VpuOpen(); -+ bool VpuAllocBuffers(VpuMemInfo *); -+ bool VpuFreeBuffers(); -+ bool VpuAllocFrameBuffers(); -+ int VpuFindBuffer(void *frameAddr); -+ -+ static const int m_extraVpuBuffers; // Number of additional buffers for VPU -+ static const int m_maxVpuDecodeLoops; // Maximum iterations in VPU decoding loop -+ static CCriticalSection m_codecBufferLock; -+ -+ CDVDStreamInfo m_hints; // Hints from demuxer at stream opening -+ const char *m_pFormatName; // Current decoder format name -+ VpuDecOpenParam m_decOpenParam; // Parameters required to call VPU_DecOpen -+ CDecMemInfo m_decMemInfo; // VPU dedicated memory description -+ VpuDecHandle m_vpuHandle; // Handle for VPU library calls -+ VpuDecInitInfo m_initInfo; // Initial info returned from VPU at decoding start -+ bool m_dropState; // Current drop state -+ int m_vpuFrameBufferNum; // Total number of allocated frame buffers -+ VpuFrameBuffer *m_vpuFrameBuffers; // Table of VPU frame buffers description -+ CDVDVideoCodecIPUBuffers m_deinterlacer; -+ CDVDVideoCodecIMXBuffer **m_outputBuffers; -+ CDVDVideoCodecIMXBuffer *m_lastBuffer; -+ VpuMemDesc *m_extraMem; // Table of allocated extra Memory -+ int m_frameCounter; // Decoded frames counter -+ bool m_usePTS; // State whether pts out of decoding process should be used -+ VpuDecOutFrameInfo m_frameInfo; -+ CBitstreamConverter *m_converter; -+ bool m_convert_bitstream; -+ int m_bytesToBeConsumed; // Remaining bytes in VPU -+ double m_previousPts; // Enable to keep pts when needed -+ bool m_frameReported; // State whether the frame consumed event will be reported by libfslvpu -+ double m_dts; // Current dts -+}; -diff -Naur xbmc-13b4/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecInfo.h xbmc-imx6-13b4/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecInfo.h ---- xbmc-13b4/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecInfo.h 1970-01-01 01:00:00.000000000 +0100 -+++ xbmc-imx6-13b4/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecInfo.h 2014-04-24 11:50:14.007208425 +0200 -@@ -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-13b4/xbmc/cores/dvdplayer/DVDCodecs/Video/Makefile.in xbmc-imx6-13b4/xbmc/cores/dvdplayer/DVDCodecs/Video/Makefile.in ---- xbmc-13b4/xbmc/cores/dvdplayer/DVDCodecs/Video/Makefile.in 2014-04-24 11:49:41.192078185 +0200 -+++ xbmc-imx6-13b4/xbmc/cores/dvdplayer/DVDCodecs/Video/Makefile.in 2014-04-24 11:50:14.007208425 +0200 -@@ -24,6 +24,9 @@ - SRCS += OpenMaxVideo.cpp - SRCS += DVDVideoCodecOpenMax.cpp - endif -+ifeq (@USE_IMXVPU@,1) -+SRCS += DVDVideoCodecIMX.cpp -+endif - ifeq (@USE_LIBAMCODEC@,1) - SRCS += AMLCodec.cpp - SRCS += DVDVideoCodecAmlogic.cpp -diff -Naur xbmc-13b4/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp xbmc-imx6-13b4/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp ---- xbmc-13b4/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp 2014-04-24 11:49:41.128079881 +0200 -+++ xbmc-imx6-13b4/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp 2014-04-24 11:50:14.003208531 +0200 -@@ -995,6 +995,8 @@ - case RENDER_FMT_EGLIMG: return "EGLIMG"; - case RENDER_FMT_BYPASS: return "BYPASS"; - case RENDER_FMT_MEDIACODEC:return "MEDIACODEC"; -+ case RENDER_FMT_YV12_BUFFER: return "YV12BUF"; -+ case RENDER_FMT_IMXMAP: return "IMXMAP"; - case RENDER_FMT_NONE: return "NONE"; - } - return "UNKNOWN"; -diff -Naur xbmc-13b4/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp xbmc-imx6-13b4/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp ---- xbmc-13b4/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp 2014-04-24 11:49:41.300075322 +0200 -+++ xbmc-imx6-13b4/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp 2014-04-24 11:50:14.011208319 +0200 -@@ -75,6 +75,17 @@ - static PFNGLEGLIMAGETARGETTEXTURE2DOESPROC glEGLImageTargetTexture2DOES; - #endif - -+#ifdef HAS_IMXVPU -+#include "windowing/egl/EGLWrapper.h" -+#include "DVDCodecs/Video/DVDVideoCodecIMX.h" -+ -+#define GL_VIV_NV12 0x8FC1 -+typedef void (GL_APIENTRYP PFNGLTEXDIRECTVIVMAPPROC) (GLenum Target, GLsizei Width, GLsizei Height, GLenum Format, GLvoid ** Logical, const GLuint * Physical); -+typedef void (GL_APIENTRYP PFNGLTEXDIRECTINVALIDATEVIVPROC) (GLenum Target); -+static PFNGLTEXDIRECTVIVMAPPROC glTexDirectVIVMap; -+static PFNGLTEXDIRECTINVALIDATEVIVPROC glTexDirectInvalidateVIV; -+#endif -+ - #if defined(TARGET_ANDROID) - #include "DVDCodecs/Video/DVDVideoCodecAndroidMediaCodec.h" - #endif -@@ -99,6 +110,7 @@ - #if defined(TARGET_ANDROID) - mediacodec = NULL; - #endif -+ codecinfo = NULL; - } - - CLinuxRendererGLES::YUVBUFFER::~YUVBUFFER() -@@ -150,6 +162,12 @@ - if (!glEGLImageTargetTexture2DOES) - glEGLImageTargetTexture2DOES = (PFNGLEGLIMAGETARGETTEXTURE2DOESPROC) CEGLWrapper::GetProcAddress("glEGLImageTargetTexture2DOES"); - #endif -+#ifdef HAS_IMXVPU -+ if (!glTexDirectVIVMap) -+ glTexDirectVIVMap = (PFNGLTEXDIRECTVIVMAPPROC) CEGLWrapper::GetProcAddress("glTexDirectVIVMap"); -+ if (!glTexDirectInvalidateVIV) -+ glTexDirectInvalidateVIV = (PFNGLTEXDIRECTINVALIDATEVIVPROC) CEGLWrapper::GetProcAddress("glTexDirectInvalidateVIV"); -+#endif - } - - CLinuxRendererGLES::~CLinuxRendererGLES() -@@ -278,6 +296,10 @@ - { - return source; - } -+ if ( m_renderMethod & RENDER_IMXMAP ) -+ { -+ return source; -+ } - - #ifdef HAVE_VIDEOTOOLBOXDECODER - if (m_renderMethod & RENDER_CVREF ) -@@ -603,6 +625,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_IMXMAP); -+#endif - - // setup the background colour - m_clearColour = (float)(g_advancedSettings.m_videoBlackBarColour & 0xff) / 0xff; -@@ -713,6 +739,16 @@ - m_renderMethod = RENDER_MEDIACODEC; - break; - } -+ else if (m_format == RENDER_FMT_YV12_BUFFER) -+ { -+ CLog::Log(LOGNOTICE, "GL: Using YV12 Buffer render method"); -+ } -+ else if (m_format == RENDER_FMT_IMXMAP) -+ { -+ CLog::Log(LOGNOTICE, "GL: Using IMXMAP render method"); -+ m_renderMethod = RENDER_IMXMAP; -+ break; -+ } - else if (m_format == RENDER_FMT_BYPASS) - { - CLog::Log(LOGNOTICE, "GL: Using BYPASS render method"); -@@ -805,6 +841,18 @@ - m_textureCreate = &CLinuxRendererGLES::CreateNV12Texture; - m_textureDelete = &CLinuxRendererGLES::DeleteNV12Texture; - } -+ else if (m_format == RENDER_FMT_YV12_BUFFER) -+ { -+ m_textureUpload = &CLinuxRendererGLES::UploadYV12BufferTexture; -+ m_textureCreate = &CLinuxRendererGLES::CreateYV12Texture; -+ m_textureDelete = &CLinuxRendererGLES::DeleteYV12Texture; -+ } -+ else if (m_format == RENDER_FMT_IMXMAP) -+ { -+ m_textureUpload = &CLinuxRendererGLES::UploadIMXMAPTexture; -+ m_textureCreate = &CLinuxRendererGLES::CreateIMXMAPTexture; -+ m_textureDelete = &CLinuxRendererGLES::DeleteIMXMAPTexture; -+ } - else - { - // default to YV12 texture handlers -@@ -956,6 +1004,10 @@ - { - RenderSurfaceTexture(index, m_currentField); - } -+ else if (m_renderMethod & RENDER_IMXMAP) -+ { -+ RenderIMXMAPTexture(index, m_currentField); -+ } - else - { - RenderSoftware(index, m_currentField); -@@ -1160,7 +1212,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); -@@ -1582,6 +1634,85 @@ - #endif - } - -+void CLinuxRendererGLES::RenderIMXMAPTexture(int index, int field) -+{ -+#if defined(HAS_IMXVPU) -+#ifdef DEBUG_VERBOSE -+ unsigned int time = XbmcThreads::SystemClockMillis(); -+#endif -+ -+ YUVPLANE &plane = m_buffers[index].fields[field][0]; -+ CDVDVideoCodecBuffer* codecinfo = m_buffers[index].codecinfo; -+ -+ if(codecinfo == NULL) return; -+ -+ CDVDVideoCodecIMX::Enter(); -+ -+ if(!codecinfo->IsValid()) -+ { -+ CDVDVideoCodecIMX::Leave(); -+ return; -+ } -+ -+ glDisable(GL_DEPTH_TEST); -+ -+ glActiveTexture(GL_TEXTURE0); -+ glBindTexture(m_textureTarget, plane.id); -+ -+ g_Windowing.EnableGUIShader(SM_TEXTURE_RGBA); -+ -+ GLubyte idx[4] = {0, 1, 3, 2}; //determines order of triangle strip -+ GLfloat ver[4][4]; -+ GLfloat tex[4][2]; -+ GLfloat col[3] = {1.0f, 1.0f, 1.0f}; -+ -+ GLint posLoc = g_Windowing.GUIShaderGetPos(); -+ GLint texLoc = g_Windowing.GUIShaderGetCoord0(); -+ GLint colLoc = g_Windowing.GUIShaderGetCol(); -+ -+ glVertexAttribPointer(posLoc, 4, GL_FLOAT, 0, 0, ver); -+ glVertexAttribPointer(texLoc, 2, GL_FLOAT, 0, 0, tex); -+ glVertexAttribPointer(colLoc, 3, GL_FLOAT, 0, 0, col); -+ -+ glEnableVertexAttribArray(posLoc); -+ glEnableVertexAttribArray(texLoc); -+ glEnableVertexAttribArray(colLoc); -+ -+ // Set vertex coordinates -+ for(int i = 0; i < 4; i++) -+ { -+ ver[i][0] = m_rotatedDestCoords[i].x; -+ ver[i][1] = m_rotatedDestCoords[i].y; -+ ver[i][2] = 0.0f;// set z to 0 -+ ver[i][3] = 1.0f; -+ } -+ -+ // Set texture coordinates -+ tex[0][0] = tex[3][0] = plane.rect.x1; -+ tex[0][1] = tex[1][1] = plane.rect.y1; -+ tex[1][0] = tex[2][0] = plane.rect.x2; -+ tex[2][1] = tex[3][1] = plane.rect.y2; -+ -+ glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_BYTE, idx); -+ -+ glDisableVertexAttribArray(posLoc); -+ glDisableVertexAttribArray(texLoc); -+ glDisableVertexAttribArray(colLoc); -+ -+ g_Windowing.DisableGUIShader(); -+ VerifyGLState(); -+ -+ glBindTexture(m_textureTarget, 0); -+ VerifyGLState(); -+ -+ CDVDVideoCodecIMX::Leave(); -+ -+#ifdef DEBUG_VERBOSE -+ CLog::Log(LOGDEBUG, "RenderIMXMAPTexture %d: tm:%d\n", index, XbmcThreads::SystemClockMillis() - time); -+#endif -+#endif -+} -+ - bool CLinuxRendererGLES::RenderCapture(CRenderCapture* capture) - { - if (!m_bValidated) -@@ -2303,7 +2434,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); -@@ -2409,7 +2540,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); - -@@ -2483,6 +2614,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()) -+ { -+ CDVDVideoCodecIMX::Leave(); -+ return; -+ } -+ -+ YUVPLANE &plane = m_buffers[index].fields[0][0]; -+ CDVDVideoCodecIPUBuffers *deinterlacer = (CDVDVideoCodecIPUBuffers*)codecinfo->data[2]; -+ -+ if (deinterlacer) -+ { -+ EDEINTERLACEMODE deinterlacemode = CMediaSettings::Get().GetCurrentVideoSettings().m_DeinterlaceMode; -+ -+ if (deinterlacemode != VS_DEINTERLACEMODE_OFF) -+ { -+ CDVDVideoCodecBuffer *deint; -+ EINTERLACEMETHOD interlacemethod = CMediaSettings::Get().GetCurrentVideoSettings().m_InterlaceMethod; -+ deint = deinterlacer->Process(codecinfo, (VpuFieldType)(int)codecinfo->data[3], -+ interlacemethod == VS_INTERLACEMETHOD_DEINTERLACE); -+ if (deint) -+ { -+ SAFE_RELEASE(buf.codecinfo); -+ buf.codecinfo = deint; -+ buf.codecinfo->Lock(); -+ codecinfo = buf.codecinfo; -+ } -+ } -+ } -+ -+ glActiveTexture(GL_TEXTURE0); -+ glBindTexture(m_textureTarget, plane.id); -+ -+ GLuint physical = ~0U; -+ GLvoid *virt = (GLvoid*)codecinfo->data[0]; -+ glTexDirectVIVMap(m_textureTarget, codecinfo->iWidth, codecinfo->iHeight, GL_VIV_NV12, -+ (GLvoid **)&virt, &physical); -+ glTexDirectInvalidateVIV(m_textureTarget); -+ -+ glBindTexture(m_textureTarget, 0); -+ -+ plane.flipindex = m_buffers[index].flipindex; -+ plane.texwidth = codecinfo->iWidth; -+ plane.texheight = codecinfo->iHeight; -+ -+ CalculateTextureSourceRects(index, 1); -+ -+ CDVDVideoCodecIMX::Leave(); -+ } -+ -+#endif -+} -+void CLinuxRendererGLES::DeleteIMXMAPTexture(int index) -+{ -+ YUVBUFFER &buf = m_buffers[index]; -+ YUVPLANE &plane = buf.fields[0][0]; -+ -+ if(plane.id && glIsTexture(plane.id)) -+ glDeleteTextures(1, &plane.id); -+ plane.id = 0; -+ -+ SAFE_RELEASE(buf.codecinfo); -+} -+bool CLinuxRendererGLES::CreateIMXMAPTexture(int index) -+{ -+ YV12Image &im = m_buffers[index].image; -+ YUVFIELDS &fields = m_buffers[index].fields; -+ YUVPLANE &plane = fields[0][0]; -+ -+ DeleteEGLIMGTexture(index); -+ -+ memset(&im , 0, sizeof(im)); -+ memset(&fields, 0, sizeof(fields)); -+ -+ im.height = m_sourceHeight; -+ im.width = m_sourceWidth; -+ -+ plane.texwidth = 0; // Must be actual frame width for pseudo-cropping -+ plane.texheight = 0; // Must be actual frame height for pseudo-cropping -+ plane.pixpertex_x = 1; -+ plane.pixpertex_y = 1; -+ -+ glEnable(m_textureTarget); -+ glGenTextures(1, &plane.id); -+ VerifyGLState(); -+ -+ glBindTexture(m_textureTarget, plane.id); -+ -+ glTexParameteri(m_textureTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR); -+ glTexParameteri(m_textureTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR); -+ -+ glDisable(m_textureTarget); -+ return true; -+} -+ -+ - bool CLinuxRendererGLES::Supports(ERENDERFEATURE feature) - { - // Player controls render, let it dictate available render features -@@ -2578,9 +2895,14 @@ - if(m_renderMethod & RENDER_CVREF) - return false; - -+#ifdef HAS_IMXVPU -+ if(mode == VS_DEINTERLACEMODE_AUTO) -+ return true; -+#else - if(mode == VS_DEINTERLACEMODE_AUTO - || mode == VS_DEINTERLACEMODE_FORCE) - return true; -+#endif - - return false; - } -@@ -2609,6 +2931,15 @@ - if(method == VS_INTERLACEMETHOD_AUTO) - return true; - -+ if(m_renderMethod & RENDER_IMXMAP) -+ { -+ if(method == VS_INTERLACEMETHOD_DEINTERLACE -+ || method == VS_INTERLACEMETHOD_DEINTERLACE_HALF) -+ return true; -+ else -+ return false; -+ } -+ - #if defined(__i386__) || defined(__x86_64__) - if(method == VS_INTERLACEMETHOD_DEINTERLACE - || method == VS_INTERLACEMETHOD_DEINTERLACE_HALF -@@ -2657,6 +2988,9 @@ - if(m_renderMethod & RENDER_CVREF) - return VS_INTERLACEMETHOD_NONE; - -+ if(m_renderMethod & RENDER_IMXMAP) -+ return VS_INTERLACEMETHOD_DEINTERLACE_HALF; -+ - #if defined(__i386__) || defined(__x86_64__) - return VS_INTERLACEMETHOD_DEINTERLACE_HALF; - #else -@@ -2741,5 +3075,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(); -+} -+ - #endif - -diff -Naur xbmc-13b4/xbmc/cores/VideoRenderers/LinuxRendererGLES.h xbmc-imx6-13b4/xbmc/cores/VideoRenderers/LinuxRendererGLES.h ---- xbmc-13b4/xbmc/cores/VideoRenderers/LinuxRendererGLES.h 2014-04-24 11:49:41.304075216 +0200 -+++ xbmc-imx6-13b4/xbmc/cores/VideoRenderers/LinuxRendererGLES.h 2014-04-24 11:50:14.011208319 +0200 -@@ -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); - #endif -+ 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-13b4/xbmc/cores/VideoRenderers/RenderFormats.h xbmc-imx6-13b4/xbmc/cores/VideoRenderers/RenderFormats.h ---- xbmc-13b4/xbmc/cores/VideoRenderers/RenderFormats.h 2014-04-24 11:49:41.300075322 +0200 -+++ xbmc-imx6-13b4/xbmc/cores/VideoRenderers/RenderFormats.h 2014-04-24 11:50:14.011208319 +0200 -@@ -37,6 +37,8 @@ - RENDER_FMT_BYPASS, - RENDER_FMT_EGLIMG, - RENDER_FMT_MEDIACODEC, -+ RENDER_FMT_YV12_BUFFER, -+ RENDER_FMT_IMXMAP, - }; - - #endif -diff -Naur xbmc-13b4/xbmc/cores/VideoRenderers/RenderManager.cpp xbmc-imx6-13b4/xbmc/cores/VideoRenderers/RenderManager.cpp ---- xbmc-13b4/xbmc/cores/VideoRenderers/RenderManager.cpp 2014-04-24 11:49:41.308075110 +0200 -+++ xbmc-imx6-13b4/xbmc/cores/VideoRenderers/RenderManager.cpp 2014-04-24 11:50:14.011208319 +0200 -@@ -928,6 +928,10 @@ - else if(pic.format == RENDER_FMT_MEDIACODEC) - m_pRenderer->AddProcessor(pic.mediacodec, index); - #endif -+#ifdef HAS_IMXVPU -+ else if(pic.format == RENDER_FMT_YV12_BUFFER || pic.format == RENDER_FMT_IMXMAP) -+ m_pRenderer->AddProcessor(pic.codecinfo, index); -+#endif - - m_pRenderer->ReleaseImage(index, false); - -diff -Naur xbmc-13b4/xbmc/cores/VideoRenderers/VideoShaders/YUV2RGBShader.cpp xbmc-imx6-13b4/xbmc/cores/VideoRenderers/VideoShaders/YUV2RGBShader.cpp ---- xbmc-13b4/xbmc/cores/VideoRenderers/VideoShaders/YUV2RGBShader.cpp 2014-04-24 11:49:41.304075216 +0200 -+++ xbmc-imx6-13b4/xbmc/cores/VideoRenderers/VideoShaders/YUV2RGBShader.cpp 2014-04-24 11:50:14.011208319 +0200 -@@ -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-13b4/xbmc/input/linux/LinuxInputDevices.cpp xbmc-imx6-13b4/xbmc/input/linux/LinuxInputDevices.cpp -diff -Naur xbmc-13b4/xbmc/powermanagement/PowerManager.cpp xbmc-imx6-13b4/xbmc/powermanagement/PowerManager.cpp -diff -Naur xbmc-13b4/xbmc/windowing/egl/EGLNativeTypeIMX.cpp xbmc-imx6-13b4/xbmc/windowing/egl/EGLNativeTypeIMX.cpp ---- xbmc-13b4/xbmc/windowing/egl/EGLNativeTypeIMX.cpp 1970-01-01 01:00:00.000000000 +0100 -+++ xbmc-imx6-13b4/xbmc/windowing/egl/EGLNativeTypeIMX.cpp 2014-04-24 11:50:14.019208107 +0200 -@@ -0,0 +1,321 @@ -+/* -+ * Copyright (C) 2011-2013 Team XBMC -+ * http://www.xbmc.org -+ * -+ * This Program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2, or (at your option) -+ * any later version. -+ * -+ * This Program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with XBMC; see the file COPYING. If not, see -+ * . -+ * -+ */ -+ -+#include -+#include "system.h" -+#include -+ -+#include "EGLNativeTypeIMX.h" -+#include -+#include -+#include -+#include "utils/log.h" -+#include "utils/RegExp.h" -+#include "utils/StringUtils.h" -+#include "utils/Environment.h" -+#include "guilib/gui3d.h" -+#include "windowing/WindowingFactory.h" -+#include "cores/AudioEngine/AEFactory.h" -+#include -+ -+CEGLNativeTypeIMX::CEGLNativeTypeIMX() -+ : m_display(NULL) -+ , m_window(NULL) -+{ -+} -+ -+CEGLNativeTypeIMX::~CEGLNativeTypeIMX() -+{ -+} -+ -+bool CEGLNativeTypeIMX::CheckCompatibility() -+{ -+ std::ifstream file("/sys/class/graphics/fb0/fsl_disp_dev_property"); -+ return file; -+} -+ -+void CEGLNativeTypeIMX::Initialize() -+{ -+ int fd; -+ -+ fd = open("/dev/fb0",O_RDWR); -+ if (fd < 0) -+ { -+ CLog::Log(LOGERROR, "%s - Error while opening /dev/fb0.\n", __FUNCTION__); -+ return; -+ } -+ -+ // Unblank the fb -+ if (ioctl(fd, FBIOBLANK, 0) < 0) -+ { -+ CLog::Log(LOGERROR, "%s - Error while unblanking fb0.\n", __FUNCTION__); -+ } -+ -+ close(fd); -+ -+ // Check if we can change the framebuffer resolution -+ fd = open("/sys/class/graphics/fb0/mode", O_RDWR); -+ if (fd >= 0) -+ { -+ CLog::Log(LOGNOTICE, "%s - graphics sysfs is writable", __FUNCTION__); -+ m_readonly = false; -+ } -+ else -+ { -+ CLog::Log(LOGNOTICE, "%s - graphics sysfs is read-only", __FUNCTION__); -+ m_readonly = true; -+ } -+ close(fd); -+ -+ return; -+} -+ -+void CEGLNativeTypeIMX::Destroy() -+{ -+ struct fb_fix_screeninfo fixed_info; -+ void *fb_buffer; -+ int fd; -+ -+ fd = open("/dev/fb0",O_RDWR); -+ if (fd < 0) -+ { -+ CLog::Log(LOGERROR, "%s - Error while opening /dev/fb0.\n", __FUNCTION__); -+ return; -+ } -+ -+ ioctl( fd, FBIOGET_FSCREENINFO, &fixed_info); -+ // Black fb0 -+ fb_buffer = mmap(NULL, fixed_info.smem_len, PROT_WRITE, MAP_SHARED, fd, 0); -+ if (fb_buffer == MAP_FAILED) -+ { -+ CLog::Log(LOGERROR, "%s - fb mmap failed %s.\n", __FUNCTION__, strerror(errno)); -+ } -+ else -+ { -+ memset(fb_buffer, 0x0, fixed_info.smem_len); -+ munmap(fb_buffer, fixed_info.smem_len); -+ } -+ -+ close(fd); -+ -+ return; -+} -+ -+bool CEGLNativeTypeIMX::CreateNativeDisplay() -+{ -+ // Force double-buffering -+ CEnvironment::setenv("FB_MULTI_BUFFER", "2", 0); -+ -+ // EGL will be rendered on fb0 -+ m_display = fbGetDisplayByIndex(0); -+ m_nativeDisplay = &m_display; -+ return true; -+} -+ -+bool CEGLNativeTypeIMX::CreateNativeWindow() -+{ -+ m_window = fbCreateWindow(m_display, 0, 0, 0, 0); -+ m_nativeWindow = &m_window; -+ return true; -+} -+ -+bool CEGLNativeTypeIMX::GetNativeDisplay(XBNativeDisplayType **nativeDisplay) const -+{ -+ if (!nativeDisplay) -+ return false; -+ if (!m_nativeDisplay) -+ return false; -+ *nativeDisplay = (XBNativeDisplayType*)m_nativeDisplay; -+ return true; -+} -+ -+bool CEGLNativeTypeIMX::GetNativeWindow(XBNativeWindowType **nativeWindow) const -+{ -+ if (!nativeWindow) -+ return false; -+ if (!m_nativeWindow || !m_window) -+ return false; -+ *nativeWindow = (XBNativeWindowType*)m_nativeWindow; -+ return true; -+} -+ -+bool CEGLNativeTypeIMX::DestroyNativeDisplay() -+{ -+ if (m_display) -+ fbDestroyDisplay(m_display); -+ m_display = NULL; -+ return true; -+} -+ -+bool CEGLNativeTypeIMX::DestroyNativeWindow() -+{ -+ if (m_window) -+ fbDestroyWindow(m_window); -+ m_window = NULL; -+ return true; -+} -+ -+bool CEGLNativeTypeIMX::GetNativeResolution(RESOLUTION_INFO *res) const -+{ -+ std::string mode; -+ get_sysfs_str("/sys/class/graphics/fb0/mode", mode); -+ return ModeToResolution(mode, res); -+} -+ -+bool CEGLNativeTypeIMX::SetNativeResolution(const RESOLUTION_INFO &res) -+{ -+ if (m_readonly) -+ return false; -+ -+ std::string mode; -+ get_sysfs_str("/sys/class/graphics/fb0/mode", mode); -+ if (res.strId == mode) -+ return false; -+ -+ DestroyNativeWindow(); -+ DestroyNativeDisplay(); -+ -+ set_sysfs_str("/sys/class/graphics/fb0/mode", res.strId); -+ -+ CreateNativeDisplay(); -+ -+ CLog::Log(LOGDEBUG, "%s: %s",__FUNCTION__, res.strId.c_str()); -+ -+ // Reset AE -+ CAEFactory::DeviceChange(); -+ -+ return true; -+} -+ -+bool CEGLNativeTypeIMX::ProbeResolutions(std::vector &resolutions) -+{ -+ if (m_readonly) -+ return false; -+ -+ std::string valstr; -+ get_sysfs_str("/sys/class/graphics/fb0/modes", valstr); -+ std::vector probe_str; -+ StringUtils::SplitString(valstr, "\n", probe_str); -+ -+ resolutions.clear(); -+ RESOLUTION_INFO res; -+ for (size_t i = 0; i < probe_str.size(); i++) -+ { -+ if(!StringUtils::StartsWith(probe_str[i], "S:")) -+ continue; -+ if(ModeToResolution(probe_str[i], &res)) -+ resolutions.push_back(res); -+ } -+ return resolutions.size() > 0; -+} -+ -+bool CEGLNativeTypeIMX::GetPreferredResolution(RESOLUTION_INFO *res) const -+{ -+ return GetNativeResolution(res); -+} -+ -+bool CEGLNativeTypeIMX::ShowWindow(bool show) -+{ -+ // Force vsync by default -+ eglSwapInterval(g_Windowing.GetEGLDisplay(), 1); -+ EGLint result = eglGetError(); -+ if(result != EGL_SUCCESS) -+ CLog::Log(LOGERROR, "EGL error in %s: %x",__FUNCTION__, result); -+ -+ return false; -+} -+ -+int CEGLNativeTypeIMX::get_sysfs_str(std::string path, std::string& valstr) const -+{ -+ int len; -+ char buf[256] = {0}; -+ -+ int fd = open(path.c_str(), O_RDONLY); -+ if (fd >= 0) -+ { -+ while ((len = read(fd, buf, 255)) > 0) -+ valstr.append(buf, len); -+ close(fd); -+ } -+ else -+ { -+ CLog::Log(LOGERROR, "%s: error reading %s",__FUNCTION__, path.c_str()); -+ valstr = "fail"; -+ return -1; -+ } -+ return 0; -+} -+ -+int CEGLNativeTypeIMX::set_sysfs_str(std::string path, std::string val) const -+{ -+ int fd = open(path.c_str(), O_WRONLY); -+ if (fd >= 0) -+ { -+ val += '\n'; -+ write(fd, val.c_str(), val.size()); -+ close(fd); -+ return 0; -+ } -+ CLog::Log(LOGERROR, "%s: error writing %s",__FUNCTION__, path.c_str()); -+ return -1; -+} -+ -+bool CEGLNativeTypeIMX::ModeToResolution(std::string mode, RESOLUTION_INFO *res) const -+{ -+ if (!res) -+ return false; -+ -+ res->iWidth = 0; -+ res->iHeight= 0; -+ -+ if(mode.empty()) -+ return false; -+ -+ std::string fromMode = StringUtils::Mid(mode, 2); -+ StringUtils::Trim(fromMode); -+ -+ CRegExp split(true); -+ split.RegComp("([0-9]+)x([0-9]+)([pi])-([0-9]+)"); -+ if (split.RegFind(fromMode) < 0) -+ return false; -+ -+ int w = atoi(split.GetMatch(1).c_str()); -+ int h = atoi(split.GetMatch(2).c_str()); -+ std::string p = split.GetMatch(3); -+ int r = atoi(split.GetMatch(4).c_str()); -+ -+ res->iWidth = w; -+ res->iHeight= h; -+ res->iScreenWidth = w; -+ res->iScreenHeight= h; -+ res->fRefreshRate = r; -+ res->dwFlags = p[0] == 'p' ? D3DPRESENTFLAG_PROGRESSIVE : D3DPRESENTFLAG_INTERLACED; -+ -+ res->iScreen = 0; -+ res->bFullScreen = true; -+ res->iSubtitles = (int)(0.965 * res->iHeight); -+ res->fPixelRatio = 1.0f; -+ res->strMode = StringUtils::Format("%dx%d @ %.2f%s - Full Screen", res->iScreenWidth, res->iScreenHeight, res->fRefreshRate, -+ res->dwFlags & D3DPRESENTFLAG_INTERLACED ? "i" : ""); -+ res->strId = mode; -+ -+ return res->iWidth > 0 && res->iHeight> 0; -+} -+ -diff -Naur xbmc-13b4/xbmc/windowing/egl/EGLNativeTypeIMX.h xbmc-imx6-13b4/xbmc/windowing/egl/EGLNativeTypeIMX.h ---- xbmc-13b4/xbmc/windowing/egl/EGLNativeTypeIMX.h 1970-01-01 01:00:00.000000000 +0100 -+++ xbmc-imx6-13b4/xbmc/windowing/egl/EGLNativeTypeIMX.h 2014-04-24 11:50:14.019208107 +0200 -@@ -0,0 +1,60 @@ -+#pragma once -+ -+/* -+ * Copyright (C) 2011-2013 Team XBMC -+ * http://www.xbmc.org -+ * -+ * This Program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2, or (at your option) -+ * any later version. -+ * -+ * This Program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with XBMC; see the file COPYING. If not, see -+ * . -+ * -+ */ -+#include -+#include "EGLNativeType.h" -+#include "EGL/eglvivante.h" -+ -+class CEGLNativeTypeIMX : public CEGLNativeType -+{ -+public: -+ CEGLNativeTypeIMX(); -+ virtual ~CEGLNativeTypeIMX(); -+ virtual std::string GetNativeName() const { return "iMX"; } -+ virtual bool CheckCompatibility(); -+ virtual void Initialize(); -+ virtual void Destroy(); -+ virtual int GetQuirks() { return EGL_QUIRK_NONE; } -+ -+ virtual bool CreateNativeDisplay(); -+ virtual bool CreateNativeWindow(); -+ virtual bool GetNativeDisplay(XBNativeDisplayType **nativeDisplay) const; -+ virtual bool GetNativeWindow(XBNativeWindowType **nativeWindow) const; -+ -+ virtual bool DestroyNativeWindow(); -+ virtual bool DestroyNativeDisplay(); -+ -+ virtual bool GetNativeResolution(RESOLUTION_INFO *res) const; -+ virtual bool SetNativeResolution(const RESOLUTION_INFO &res); -+ virtual bool ProbeResolutions(std::vector &resolutions); -+ virtual bool GetPreferredResolution(RESOLUTION_INFO *res) const; -+ -+ virtual bool ShowWindow(bool show); -+ -+protected: -+ bool m_readonly; -+ int get_sysfs_str(std::string path, std::string& valstr) const; -+ int set_sysfs_str(std::string path, std::string val) const; -+ bool ModeToResolution(std::string mode, RESOLUTION_INFO *res) const; -+ -+ EGLNativeDisplayType m_display; -+ EGLNativeWindowType m_window; -+}; -diff -Naur xbmc-13b4/xbmc/windowing/egl/EGLWrapper.cpp xbmc-imx6-13b4/xbmc/windowing/egl/EGLWrapper.cpp ---- xbmc-13b4/xbmc/windowing/egl/EGLWrapper.cpp 2014-04-24 11:49:41.748063448 +0200 -+++ xbmc-imx6-13b4/xbmc/windowing/egl/EGLWrapper.cpp 2014-04-24 11:50:14.019208107 +0200 -@@ -17,16 +17,17 @@ - * . - * - */ -- - #include "system.h" - - #ifdef HAS_EGL -- - #include "utils/log.h" - #include "EGLNativeTypeAndroid.h" - #include "EGLNativeTypeAmlogic.h" - #include "EGLNativeTypeRaspberryPI.h" - #include "EGLNativeTypeWayland.h" -+#ifdef HAS_IMXVPU -+#include "EGLNativeTypeIMX.h" -+#endif - #include "EGLWrapper.h" - - #define CheckError() m_result = eglGetError(); if(m_result != EGL_SUCCESS) CLog::Log(LOGERROR, "EGL error in %s: %x",__FUNCTION__, m_result); -@@ -83,7 +84,11 @@ - if ((nativeGuess = CreateEGLNativeType(implementation)) || - (nativeGuess = CreateEGLNativeType(implementation)) || - (nativeGuess = CreateEGLNativeType(implementation)) || -- (nativeGuess = CreateEGLNativeType(implementation))) -+ (nativeGuess = CreateEGLNativeType(implementation)) -+#ifdef HAS_IMXFB -+ || (nativeGuess = CreateEGLNativeType(implementation)) -+#endif -+ ) - { - m_nativeTypes = nativeGuess; - -diff -Naur xbmc-13b4/xbmc/windowing/egl/Makefile.in xbmc-imx6-13b4/xbmc/windowing/egl/Makefile.in ---- xbmc-13b4/xbmc/windowing/egl/Makefile.in 2014-04-24 11:49:41.736063766 +0200 -+++ xbmc-imx6-13b4/xbmc/windowing/egl/Makefile.in 2014-04-24 11:50:14.019208107 +0200 -@@ -24,6 +24,10 @@ - wayland/XBMCSurface.cpp - endif - -+ifeq (@USE_IMXFB@,1) -+SRCS+= EGLNativeTypeIMX.cpp -+endif -+ - LIB = windowing_egl.a - - include ../../../Makefile.include