diff --git a/projects/Odroid_C2/patches/kodi/kodi-0001-owersun-odroid.patch b/projects/Odroid_C2/patches/kodi/kodi-0001-owersun-odroid.patch index 1ce9332838..db7bfa0b45 100644 --- a/projects/Odroid_C2/patches/kodi/kodi-0001-owersun-odroid.patch +++ b/projects/Odroid_C2/patches/kodi/kodi-0001-owersun-odroid.patch @@ -1,161 +1,19 @@ -From aeef849a8f4307cd1792600602ec8e3d47a7b52e Mon Sep 17 00:00:00 2001 -From: Owersun -Date: Sat, 23 Apr 2016 22:34:30 +0200 -Subject: [PATCH 1/2] Odroids: All the codecs and display drivers +From 99f9fb9e1df7f6877bbce3cf90ebf24cacea1797 Mon Sep 17 00:00:00 2001 +From: Markus Pfau +Date: Tue, 23 Aug 2016 00:06:43 +0200 +Subject: [PATCH] oversun-changes --- - configure.ac | 41 +- - m4/xbmc_arch.m4 | 6 + - xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp | 39 +- - .../VideoPlayer/DVDCodecs/DVDFactoryCodec.cpp | 5 + - .../cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp | 18 +- - .../DVDCodecs/Video/DVDVideoCodecMFC.cpp | 585 +++++++++++++++++++++ - .../VideoPlayer/DVDCodecs/Video/DVDVideoCodecMFC.h | 64 +++ - xbmc/cores/VideoPlayer/DVDCodecs/Video/Makefile.in | 5 +- - xbmc/linux/LinuxV4l2Sink.cpp | 311 +++++++++++ - xbmc/linux/LinuxV4l2Sink.h | 71 +++ - xbmc/linux/Makefile.in | 1 + - xbmc/utils/AMLUtils.cpp | 93 +++- - xbmc/utils/CPUInfo.cpp | 25 +- - xbmc/windowing/X11/WinSystemX11.cpp | 2 +- - xbmc/windowing/egl/EGLNativeTypeAmlogic.cpp | 98 +++- - xbmc/windowing/egl/EGLNativeTypeAmlogic.h | 19 +- - xbmc/windowing/egl/EGLNativeTypeFbdev.cpp | 183 +++++++ - xbmc/windowing/egl/EGLNativeTypeFbdev.h | 68 +++ - xbmc/windowing/egl/EGLNativeTypeHybris.cpp | 279 ++++++++++ - xbmc/windowing/egl/EGLNativeTypeHybris.h | 77 +++ - xbmc/windowing/egl/EGLWrapper.cpp | 14 +- - xbmc/windowing/egl/Makefile.in | 4 + - 22 files changed, 1933 insertions(+), 75 deletions(-) - create mode 100644 xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecMFC.cpp - create mode 100644 xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecMFC.h - create mode 100644 xbmc/linux/LinuxV4l2Sink.cpp - create mode 100644 xbmc/linux/LinuxV4l2Sink.h - create mode 100644 xbmc/windowing/egl/EGLNativeTypeFbdev.cpp - create mode 100644 xbmc/windowing/egl/EGLNativeTypeFbdev.h - create mode 100644 xbmc/windowing/egl/EGLNativeTypeHybris.cpp - create mode 100644 xbmc/windowing/egl/EGLNativeTypeHybris.h + xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp | 39 ++++++--- + .../cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp | 13 +-- + xbmc/utils/AMLUtils.cpp | 93 ++++++++++++++++++-- + xbmc/utils/CPUInfo.cpp | 25 +++--- + xbmc/windowing/egl/EGLNativeTypeAmlogic.cpp | 98 ++++++++++++++++------ + xbmc/windowing/egl/EGLNativeTypeAmlogic.h | 19 ++++- + 6 files changed, 221 insertions(+), 66 deletions(-) -diff --git a/configure.ac b/configure.ac -index 8cc0ba8..6a727bd 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -213,6 +213,10 @@ libbluetooth_enabled="== libbluetooth enabled. ==" - libbluetooth_disabled="== libbluetooth disabled. Bluetooth support will not be available. ==" - - -+# Odroid stuff -+hybris_enabled="== Libhybris enabled. ==" -+hybris_disabled="== Libhybris disabled. ==" -+ - AC_ARG_WITH([ffmpeg], - [AS_HELP_STRING([--with-ffmpeg], - [ffmpeg options: auto (search pkg-config or auto build), force (always build ffmpeg), shared (link dynamically), path_to_ffmpeg [default=force]])], -@@ -474,7 +478,7 @@ AC_ARG_ENABLE([breakpad], - - 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 and imxvpu)])], -+ [enable additional codecs from a list of comma separated names, (default is none, choices are mfc, amcodec and imxvpu)])], - [add_codecs=$enableval], - [add_codecs=no]) - -@@ -485,6 +489,13 @@ AC_ARG_ENABLE([libav-compat], - [use_libav_hacks=$enableval], - [use_libav_hacks=no]) - -+# Odroid stuff -+AC_ARG_ENABLE([hybris], -+ [AS_HELP_STRING([--enable-hybris], -+ [enable use of Libhybris (default is no) 'Linux only'])], -+ [use_hybris=$enableval], -+ [use_hybris=no]) -+ - ### End of external library options - - if test "x$host_vendor" != "xapple"; then -@@ -1480,6 +1491,23 @@ else - AC_MSG_NOTICE($libcap_disabled) - fi - -+# Odroid stuff -+if test "x$use_hybris" != "xno"; then -+ AC_SUBST(ARCH_DEFINES, "-DTARGET_POSIX -DTARGET_LINUX -D_LINUX -DTARGET_HYBRIS") -+ USE_HYBRIS=1; -+ AC_DEFINE(HAS_EGLGLES, [1], [Define if supporting EGL based GLES Framebuffer]) -+ AC_DEFINE(HAS_HYBRIS, [1], [Define if supporting Hybris based systems]) -+ PKG_CHECK_MODULES([HWCOMPOSEREGL], [hwcomposer-egl >= 0.1], -+ [INCLUDES="$INCLUDES -I/usr/include/hybris $HWCOMPOSEREGL_CFLAGS"; LIBS="$LIBS $HWCOMPOSEREGL_LIBS"], -+ AC_MSG_ERROR($missing_library)) -+ PKG_CHECK_MODULES([HYBRISEGL], [hybris-egl-platform >= 0.1], -+ [INCLUDES="$INCLUDES $HYBRISEGL_CFLAGS"; LIBS="$LIBS $HYBRISEGL_LIBS"], -+ AC_MSG_ERROR($missing_library)) -+ PKG_CHECK_MODULES([LIBHARDWARE], [libhardware >= 0.1], -+ [INCLUDES="$INCLUDES $LIBHARDWARE_CFLAGS"; LIBS="$LIBS $LIBHARDWARE_LIBS -lsync -lmedia"], -+ AC_MSG_ERROR($missing_library)) -+fi -+ - # FFmpeg - FFMPEG_LIBNAMES="libavcodec >= 56.26.100 - libavfilter >= 5.11.102 -@@ -1701,6 +1729,9 @@ esac - # remember to convert commas to spaces - for codecs in `echo $add_codecs | sed 's/,/ /g'`; do - case $codecs in -+ *mfc*) -+ XB_ADD_CODEC([MFC], [mfc], [$codecs]) -+ ;; - *amcodec*) - AC_CHECK_HEADER([amcodec/codec_error.h],, AC_MSG_ERROR($missing_headers)) - XB_ADD_CODEC([LIBAMCODEC], [amcodec], [$codecs]) -@@ -2098,6 +2129,13 @@ else - final_message="$final_message\n additional codecs:\tNo" - fi - -+# Odroid stuff -+if test "x$use_hybris" != "xno"; then -+ final_message="$final_message\n Odroid Hybris support:\tYes" -+else -+ final_message="$final_message\n Odroid Hybris support:\tNo" -+fi -+ - ### External libraries messages - - if test "$host_vendor" = "apple" ; then -@@ -2290,6 +2328,7 @@ AC_SUBST(USE_MMAL) - AC_SUBST(USE_X11) - AC_SUBST(USE_OPTICAL_DRIVE) - AC_SUBST(USE_BREAKPAD) -+AC_SUBST(USE_HYBRIS) - AC_SUBST(CROSS_COMPILING) - - # pushd and popd are not available in other shells besides bash, so implement -diff --git a/m4/xbmc_arch.m4 b/m4/xbmc_arch.m4 -index d28f263..07f1770 100644 ---- a/m4/xbmc_arch.m4 -+++ b/m4/xbmc_arch.m4 -@@ -26,6 +26,9 @@ case $build in - arm*-*-linux-gnu*|arm*-*-linux-uclibc*) - AC_SUBST(NATIVE_ARCH_DEFINES, "-DTARGET_POSIX -DTARGET_LINUX -D_LINUX") - ;; -+ aarch64-*-linux-gnu*) -+ AC_SUBST(NATIVE_ARCH_DEFINES, "-DTARGET_POSIX -DTARGET_LINUX -D_LINUX") -+ ;; - *) - AC_MSG_ERROR(unsupported native build platform: $build) - esac -@@ -63,6 +66,9 @@ case $host in - arm*-*-linux-gnu*|arm*-*-linux-uclibc*|aarch64*-*-linux-gnu*|aarch64*-*-linux-uclibc*) - AC_SUBST(ARCH_DEFINES, "-DTARGET_POSIX -DTARGET_LINUX -D_LINUX") - ;; -+ aarch64-*-linux-gnu*) -+ AC_SUBST(ARCH_DEFINES, "-DTARGET_POSIX -DTARGET_LINUX -D_LINUX") -+ ;; - mips*-*-linux-gnu*|mips*-*-linux-uclibc*) - AC_SUBST(ARCH_DEFINES, "-DTARGET_POSIX -DTARGET_LINUX -D_LINUX") - ;; diff --git a/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp b/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp -index 6a9066b..30653a3 100644 +index 4bb159f..ea2db01 100644 --- a/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp +++ b/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp @@ -490,6 +490,7 @@ snd_pcm_chmap_t* CAESinkALSA::SelectALSAChannelMap(const CAEChannelInfo& info) @@ -242,7 +100,7 @@ index 6a9066b..30653a3 100644 CLog::Log(LOGDEBUG, "CAESinkALSA::InitializeHW - Got: periodSize %lu, bufferSize %lu", periodSize, bufferSize); /* set the format parameters */ -@@ -1301,6 +1305,15 @@ void CAESinkALSA::EnumerateDevicesEx(AEDeviceInfoList &list, bool force) +@@ -1302,6 +1306,15 @@ void CAESinkALSA::EnumerateDevicesEx(AEDeviceInfoList &list, bool force) AEDeviceType CAESinkALSA::AEDeviceTypeFromName(const std::string &name) { @@ -258,7 +116,7 @@ index 6a9066b..30653a3 100644 if (name.substr(0, 4) == "hdmi") return AE_DEVTYPE_HDMI; else if (name.substr(0, 6) == "iec958" || name.substr(0, 5) == "spdif") -@@ -1405,9 +1418,9 @@ void CAESinkALSA::EnumerateDevice(AEDeviceInfoList &list, const std::string &dev +@@ -1406,9 +1419,9 @@ void CAESinkALSA::EnumerateDevice(AEDeviceInfoList &list, const std::string &dev if (badHDMI) { @@ -271,34 +129,11 @@ index 6a9066b..30653a3 100644 * AMD (fglrx) hardware, so it is not safe to close those * handles */ -diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/DVDFactoryCodec.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/DVDFactoryCodec.cpp -index bb5bfe0..9351b3e 100644 ---- a/xbmc/cores/VideoPlayer/DVDCodecs/DVDFactoryCodec.cpp -+++ b/xbmc/cores/VideoPlayer/DVDCodecs/DVDFactoryCodec.cpp -@@ -41,6 +41,9 @@ - #include "Video/DVDVideoCodecAndroidMediaCodec.h" - #include "platform/android/activity/AndroidFeatures.h" - #endif -+#if defined(HAS_MFC) -+#include "Video/DVDVideoCodecMFC.h" -+#endif - #include "Audio/DVDAudioCodecFFmpeg.h" - #include "Audio/DVDAudioCodecPassthrough.h" - #include "Overlay/DVDOverlayCodecSSA.h" -@@ -149,6 +152,8 @@ CDVDVideoCodec* CDVDFactoryCodec::CreateVideoCodec(CDVDStreamInfo &hint, CProces - pCodec = OpenCodec(new CDVDVideoCodecOpenMax(processInfo), hint, options); - #elif defined(HAS_MMAL) - pCodec = OpenCodec(new CMMALVideo(processInfo), hint, options); -+#elif defined(HAS_MFC) -+ pCodec = OpenCodec(new CDVDVideoCodecMFC(processInfo), hint, options); - #endif - if (pCodec) - return pCodec; diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp -index aa30474..bfc862e 100644 +index 5dadf82..ca8e964 100644 --- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp +++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp -@@ -398,18 +398,19 @@ void dumpfile_write(am_private_t *para, void* buf, int bufsiz) +@@ -398,7 +398,7 @@ void dumpfile_write(am_private_t *para, void* buf, int bufsiz) } if (para->dumpdemux && para->dumpfile != -1) @@ -306,21 +141,8 @@ index aa30474..bfc862e 100644 + int ret = write(para->dumpfile, buf, bufsiz); } - static int set_pts_pcrscr(int64_t value) - { -+ int ret; - int fd = open("/sys/class/tsync/pts_pcrscr", O_WRONLY); - if (fd >= 0) - { - char pts_str[64]; - unsigned long pts = (unsigned long)value; - sprintf(pts_str, "0x%lx", pts); -- write(fd, pts_str, strlen(pts_str)); -+ ret = write(fd, pts_str, strlen(pts_str)); - close(fd); - return 0; - } -@@ -730,7 +731,7 @@ int write_av_packet(am_private_t *para, am_packet_t *pkt) + static vformat_t codecid_to_vformat(enum AVCodecID id) +@@ -713,7 +713,7 @@ int write_av_packet(am_private_t *para, am_packet_t *pkt) } pkt->newflag = 0; } @@ -329,7 +151,7 @@ index aa30474..bfc862e 100644 buf = pkt->data; size = pkt->data_size ; if (size == 0 && pkt->isvalid) { -@@ -1580,7 +1581,7 @@ bool CAMLCodec::OpenDecoder(CDVDStreamInfo &hints) +@@ -1563,7 +1563,7 @@ bool CAMLCodec::OpenDecoder(CDVDStreamInfo &hints) // h264 in an avi file if (m_hints.ptsinvalid) am_private->gcodec.param = (void*)(EXTERNAL_PTS | SYNC_OUTSIDE); @@ -338,7 +160,7 @@ index aa30474..bfc862e 100644 case VFORMAT_REAL: am_private->stream_type = AM_STREAM_RM; am_private->vcodec.noblock = 1; -@@ -1645,7 +1646,7 @@ bool CAMLCodec::OpenDecoder(CDVDStreamInfo &hints) +@@ -1628,7 +1628,7 @@ bool CAMLCodec::OpenDecoder(CDVDStreamInfo &hints) Create(); @@ -347,7 +169,7 @@ index aa30474..bfc862e 100644 std::string strScaler; SysfsUtils::GetString("/sys/class/ppmgr/ppscaler", strScaler); -@@ -2187,7 +2188,6 @@ void CAMLCodec::SetVideoRect(const CRect &SrcRect, const CRect &DestRect) +@@ -2154,7 +2154,6 @@ void CAMLCodec::SetVideoRect(const CRect &SrcRect, const CRect &DestRect) int diff = (int) ((dst_rect.Height() - dst_rect.Width()) / 2); dst_rect = CRect(DestRect.x1 - diff, DestRect.y1, DestRect.x2 + diff, DestRect.y2); } @@ -355,7 +177,7 @@ index aa30474..bfc862e 100644 } if (m_dst_rect != dst_rect) -@@ -2209,7 +2209,7 @@ void CAMLCodec::SetVideoRect(const CRect &SrcRect, const CRect &DestRect) +@@ -2176,7 +2175,7 @@ void CAMLCodec::SetVideoRect(const CRect &SrcRect, const CRect &DestRect) #ifdef TARGET_ANDROID display = m_display_rect; #else @@ -364,7 +186,7 @@ index aa30474..bfc862e 100644 #endif if (gui != display) { -@@ -2281,6 +2281,8 @@ void CAMLCodec::SetVideoRect(const CRect &SrcRect, const CRect &DestRect) +@@ -2248,6 +2247,8 @@ void CAMLCodec::SetVideoRect(const CRect &SrcRect, const CRect &DestRect) std::string s_gui = StringUtils::Format("%i,%i,%i,%i", (int)gui.x1, (int)gui.y1, (int)gui.Width(), (int)gui.Height()); @@ -373,1095 +195,11 @@ index aa30474..bfc862e 100644 CLog::Log(LOGDEBUG, "CAMLCodec::SetVideoRect:display(%s)", s_display.c_str()); CLog::Log(LOGDEBUG, "CAMLCodec::SetVideoRect:gui(%s)", s_gui.c_str()); CLog::Log(LOGDEBUG, "CAMLCodec::SetVideoRect:m_dst_rect(%s)", s_m_dst_rect.c_str()); -diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecMFC.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecMFC.cpp -new file mode 100644 -index 0000000..900c5d8 ---- /dev/null -+++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecMFC.cpp -@@ -0,0 +1,585 @@ -+#include "system.h" -+ -+#ifndef THIS_IS_NOT_XBMC -+ #if (defined HAVE_CONFIG_H) && (!defined WIN32) -+ #include "config.h" -+ #endif -+ #include "DVDDemuxers/DVDDemux.h" -+ #include "DVDStreamInfo.h" -+ #include "DVDClock.h" -+ #include "guilib/GraphicContext.h" -+ #include "DVDCodecs/DVDCodecs.h" -+ #include "DVDCodecs/DVDCodecUtils.h" -+ #include "settings/Settings.h" -+ #include "settings/DisplaySettings.h" -+ #include "settings/AdvancedSettings.h" -+ #include "utils/log.h" -+#endif -+ -+#include "DVDVideoCodecMFC.h" -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#ifdef CLASSNAME -+#undef CLASSNAME -+#endif -+#define CLASSNAME "CDVDVideoCodecMFC" -+ -+CDVDVideoCodecMFC::CDVDVideoCodecMFC(CProcessInfo &processInfo) : CDVDVideoCodec(processInfo) { -+ -+ m_iDecoderHandle = NULL; -+ m_iConverterHandle = NULL; -+ m_MFCOutput = NULL; -+ m_MFCCapture = NULL; -+ m_FIMCOutput = NULL; -+ m_FIMCCapture = NULL; -+ -+ m_Buffer = NULL; -+ m_BufferNowOnScreen = NULL; -+ -+ memzero(m_videoBuffer); -+ -+} -+ -+CDVDVideoCodecMFC::~CDVDVideoCodecMFC() { -+ -+ Dispose(); -+ -+} -+ -+bool CDVDVideoCodecMFC::OpenDevices() { -+ DIR *dir; -+ -+ if ((dir = opendir ("/sys/class/video4linux/")) != NULL) { -+ struct dirent *ent; -+ while ((ent = readdir (dir)) != NULL) { -+ if (strncmp(ent->d_name, "video", 5) == 0) { -+ char *p; -+ char name[64]; -+ char devname[64]; -+ char sysname[64]; -+ char drivername[32]; -+ char target[1024]; -+ int ret; -+ -+ snprintf(sysname, 64, "/sys/class/video4linux/%s", ent->d_name); -+ snprintf(name, 64, "/sys/class/video4linux/%s/name", ent->d_name); -+ -+ FILE* fp = fopen(name, "r"); -+ if (fgets(drivername, 32, fp) != NULL) { -+ p = strchr(drivername, '\n'); -+ if (p != NULL) -+ *p = '\0'; -+ } else { -+ fclose(fp); -+ continue; -+ } -+ fclose(fp); -+ -+ ret = readlink(sysname, target, sizeof(target)); -+ if (ret < 0) -+ continue; -+ target[ret] = '\0'; -+ p = strrchr(target, '/'); -+ if (p == NULL) -+ continue; -+ -+ sprintf(devname, "/dev/%s", ++p); -+ -+ if (!m_iDecoderHandle && strstr(drivername, "mfc") != NULL && strstr(drivername, "dec") != NULL) { -+ int fd = open(devname, O_RDWR | O_NONBLOCK, 0); -+ if (fd > -1) { -+ struct v4l2_capability cap; -+ memzero(cap); -+ if (ioctl(fd, VIDIOC_QUERYCAP, &cap) == 0) -+ if (cap.capabilities & V4L2_CAP_STREAMING && -+ (cap.capabilities & V4L2_CAP_VIDEO_M2M_MPLANE || -+ (cap.capabilities & (V4L2_CAP_VIDEO_CAPTURE_MPLANE | V4L2_CAP_VIDEO_OUTPUT_MPLANE)))) { -+ m_iDecoderHandle = new V4l2Device; -+ m_iDecoderHandle->device = fd; -+ strcpy(m_iDecoderHandle->name, drivername); -+ CLog::Log(LOGDEBUG, "%s::%s - MFC Found %s %s", CLASSNAME, __func__, drivername, devname); -+ struct v4l2_format fmt; -+ memzero(fmt); -+ fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; -+ fmt.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_NV12M; -+ if (ioctl(fd, VIDIOC_TRY_FMT, &fmt) == 0) { -+ CLog::Log(LOGDEBUG, "%s::%s - Direct decoding to untiled picture on device %s is supported, no conversion needed", CLASSNAME, __func__, m_iDecoderHandle->name); -+ delete m_iConverterHandle; -+ m_iConverterHandle = NULL; -+ return true; -+ } -+ } -+ } -+ if (!m_iDecoderHandle) -+ close(fd); -+ } -+ if (!m_iConverterHandle && strstr(drivername, "fimc") != NULL && strstr(drivername, "m2m") != NULL) { -+ int fd = open(devname, O_RDWR | O_NONBLOCK, 0); -+ if (fd > -1) { -+ struct v4l2_capability cap; -+ memzero(cap); -+ if (ioctl(fd, VIDIOC_QUERYCAP, &cap) == 0) -+ if (cap.capabilities & V4L2_CAP_STREAMING && -+ (cap.capabilities & V4L2_CAP_VIDEO_M2M_MPLANE || -+ (cap.capabilities & (V4L2_CAP_VIDEO_CAPTURE_MPLANE | V4L2_CAP_VIDEO_OUTPUT_MPLANE)))) { -+ m_iConverterHandle = new V4l2Device; -+ m_iConverterHandle->device = fd; -+ strcpy(m_iConverterHandle->name, drivername); -+ CLog::Log(LOGDEBUG, "%s::%s - FIMC Found %s %s", CLASSNAME, __func__, drivername, devname); -+ } -+ } -+ if (!m_iConverterHandle) -+ close(fd); -+ } -+ if (m_iDecoderHandle && m_iConverterHandle) { -+ closedir (dir); -+ return true; -+ } -+ } -+ } -+ closedir (dir); -+ } -+ -+ return false; -+ -+} -+ -+void CDVDVideoCodecMFC::Dispose() { -+ -+ CLog::Log(LOGDEBUG, "%s::%s - Starting cleanup", CLASSNAME, __func__); -+ -+ delete m_BufferNowOnScreen; -+ delete m_Buffer; -+ -+ m_Buffer = NULL; -+ m_BufferNowOnScreen = NULL; -+ -+ delete m_FIMCCapture; -+ delete m_FIMCOutput; -+ delete m_MFCCapture; -+ delete m_MFCOutput; -+ -+ m_MFCOutput = NULL; -+ m_MFCCapture = NULL; -+ m_FIMCOutput = NULL; -+ m_FIMCCapture = NULL; -+ -+ if (m_iConverterHandle) { -+ close(m_iConverterHandle->device); -+ delete m_iConverterHandle; -+ m_iConverterHandle = NULL; -+ } -+ -+ if (m_iDecoderHandle) { -+ close(m_iDecoderHandle->device); -+ delete m_iDecoderHandle; -+ m_iDecoderHandle = NULL; -+ } -+ -+} -+ -+bool CDVDVideoCodecMFC::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options) { -+ struct v4l2_format fmt; -+ struct v4l2_crop crop; -+ struct V4l2SinkBuffer sinkBuffer; -+ V4l2Device *finalSink = NULL; -+ int finalFormat = -1; -+ int resultVideoWidth; -+ int resultVideoHeight; -+ int resultLineSize; -+ unsigned int extraSize = 0; -+ uint8_t *extraData = NULL; -+ -+ m_hints = hints; -+ if (m_hints.software) -+ return false; -+ -+ Dispose(); -+ -+ m_Buffer = new V4l2SinkBuffer(); -+ m_BufferNowOnScreen = new V4l2SinkBuffer(); -+ m_BufferNowOnScreen->iIndex = -1; -+ m_bVideoConvert = false; -+ m_bDropPictures = false; -+ memzero(m_videoBuffer); -+ -+ if (!OpenDevices()) { -+ CLog::Log(LOGERROR, "%s::%s - No Exynos MFC Decoder/Converter found", CLASSNAME, __func__); -+ return false; -+ } -+ -+ m_bVideoConvert = m_converter.Open(m_hints.codec, (uint8_t *)m_hints.extradata, m_hints.extrasize, true); -+ -+ if(m_bVideoConvert) { -+ if(m_converter.GetExtraData() != NULL && m_converter.GetExtraSize() > 0) { -+ extraSize = m_converter.GetExtraSize(); -+ extraData = m_converter.GetExtraData(); -+ } -+ } else { -+ if(m_hints.extrasize > 0 && m_hints.extradata != NULL) { -+ extraSize = m_hints.extrasize; -+ extraData = (uint8_t*)m_hints.extradata; -+ } -+ } -+ -+ // Test what formats we can get finally -+ // If converter is present, it is our final sink -+ (m_iConverterHandle) ? finalSink = m_iConverterHandle : finalSink = m_iDecoderHandle; -+ // Test NV12 2 Planes Y/CbCr -+ memzero(fmt); -+ fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; -+ fmt.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_NV12M; -+ if (ioctl(finalSink->device, VIDIOC_TRY_FMT, &fmt) == 0) -+ finalFormat = V4L2_PIX_FMT_NV12M; -+ memzero(fmt); -+/* -+ // Test YUV420 3 Planes Y/Cb/Cr -+ fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; -+ fmt.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_YUV420M; -+ if (ioctl(finalSink->device, VIDIOC_TRY_FMT, &fmt) == 0) -+ finalFormat = V4L2_PIX_FMT_YUV420M; -+*/ -+ -+ // No suitable output formats available -+ if (finalFormat < 0) { -+ CLog::Log(LOGERROR, "%s::%s - No suitable format on %s to convert to found", CLASSNAME, __func__, finalSink->name); -+ return false; -+ } -+ -+ // Create MFC Output sink (the one where encoded frames are feed) -+ m_MFCOutput = new CLinuxV4l2Sink(m_iDecoderHandle, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); -+ memzero(fmt); -+ switch(m_hints.codec) -+ { -+ case AV_CODEC_ID_VC1: -+ fmt.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_VC1_ANNEX_G; -+ m_name = "mfc-vc1"; -+ break; -+ case AV_CODEC_ID_MPEG1VIDEO: -+ fmt.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_MPEG1; -+ m_name = "mfc-mpeg1"; -+ break; -+ case AV_CODEC_ID_MPEG2VIDEO: -+ fmt.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_MPEG2; -+ m_name = "mfc-mpeg2"; -+ break; -+ case AV_CODEC_ID_MPEG4: -+ fmt.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_MPEG4; -+ m_name = "mfc-mpeg4"; -+ break; -+ case AV_CODEC_ID_H263: -+ fmt.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_H263; -+ m_name = "mfc-h263"; -+ break; -+ case AV_CODEC_ID_H264: -+ fmt.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_H264; -+ m_name = "mfc-h264"; -+ break; -+ default: -+ return false; -+ break; -+ } -+ fmt.fmt.pix_mp.plane_fmt[0].sizeimage = BUFFER_SIZE; -+ // Set encoded format -+ if (!m_MFCOutput->SetFormat(&fmt)) -+ return false; -+ // Init with number of input buffers predefined -+ if (!m_MFCOutput->Init(INPUT_BUFFERS)) -+ return false; -+ -+ // Get empty buffer to fill -+ if (!m_MFCOutput->GetBuffer(&sinkBuffer)) -+ return false; -+ // Fill it with the header -+ sinkBuffer.iBytesUsed[0] = extraSize; -+ memcpy(sinkBuffer.cPlane[0], extraData, extraSize); -+ // Enqueue buffer -+ if (!m_MFCOutput->PushBuffer(&sinkBuffer)) -+ return false; -+ -+ // Create MFC Capture sink (the one from which decoded frames are read) -+ m_MFCCapture = new CLinuxV4l2Sink(m_iDecoderHandle, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); -+ memzero(fmt); -+ // If there is no converter set output format on the MFC Capture sink -+ if (!m_iConverterHandle) { -+ fmt.fmt.pix_mp.pixelformat = finalFormat; -+ if (!m_MFCCapture->SetFormat(&fmt)) -+ return false; -+ } -+ -+ // Turn on MFC Output with header in it to initialize MFC with all we just setup -+ m_MFCOutput->StreamOn(VIDIOC_STREAMON); -+ -+ // Initialize MFC Capture -+ if (!m_MFCCapture->Init(0)) -+ return false; -+ // Queue all buffers (empty) to MFC Capture -+ m_MFCCapture->QueueAll(); -+ -+ // Read the format of MFC Capture -+ if (!m_MFCCapture->GetFormat(&fmt)) -+ return false; -+ // Size of resulting picture coming out of MFC -+ // It will be aligned by 16 since the picture is tiled -+ // We need this to know where to split buffer line by line -+ resultLineSize = fmt.fmt.pix_mp.width; -+ // Get MFC capture crop settings -+ if (!m_MFCCapture->GetCrop(&crop)) -+ return false; -+ // This is the picture boundaries we are interested in, everything outside is alignement because of tiled MFC output -+ resultVideoWidth = crop.c.width; -+ resultVideoHeight = crop.c.height; -+ -+ // Turn on MFC Capture -+ m_MFCCapture->StreamOn(VIDIOC_STREAMON); -+ -+ // If converter is needed (we need to untile the picture from format MFC produces it) -+ if (m_iConverterHandle) { -+ // Create FIMC Output sink -+ m_FIMCOutput = new CLinuxV4l2Sink(m_iConverterHandle, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); -+ // Set the FIMC Output format to the one read from MFC -+ if (!m_FIMCOutput->SetFormat(&fmt)) -+ return false; -+ // Set the FIMC Output crop to the one read from MFC -+ if (!m_FIMCOutput->SetCrop(&crop)) -+ return false; -+ // Init FIMC Output and link it to buffers of MFC Capture -+ if (!m_FIMCOutput->Init(m_MFCCapture)) -+ return false; -+ // Get FIMC Output crop settings -+ if (!m_FIMCOutput->GetCrop(&crop)) -+ return false; -+ -+ // Create FIMC Capture sink -+ m_FIMCCapture = new CLinuxV4l2Sink(m_iConverterHandle, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); -+ // Set the final picture format and the same picture dimension settings to FIMC Capture -+ // as picture crop coming from MFC (original picture dimensions) -+ memzero(fmt); -+ fmt.fmt.pix_mp.pixelformat = finalFormat; -+ fmt.fmt.pix_mp.width = crop.c.width; -+ fmt.fmt.pix_mp.height = crop.c.height; -+ fmt.fmt.pix_mp.field = V4L2_FIELD_ANY; -+ if (!m_FIMCCapture->SetFormat(&fmt)) -+ return false; -+ // Init FIMC capture with number of buffers predefined -+ if (!m_FIMCCapture->Init(OUTPUT_BUFFERS)) -+ return false; -+ -+ // Queue all buffers (empty) to FIMC Capture -+ m_FIMCCapture->QueueAll(); -+ -+ // Read FIMC capture format settings -+ if (!m_FIMCCapture->GetFormat(&fmt)) -+ return false; -+ resultLineSize = fmt.fmt.pix_mp.width; -+ // Read FIMC capture crop settings -+ if (!m_FIMCCapture->GetCrop(&crop)) -+ return false; -+ resultVideoWidth = crop.c.width; -+ resultVideoHeight = crop.c.height; -+ -+ // Turn on FIMC Output and Capture enabling the converter -+ m_FIMCOutput->StreamOn(VIDIOC_STREAMON); -+ m_FIMCCapture->StreamOn(VIDIOC_STREAMON); -+ } -+ -+ m_videoBuffer.iFlags = DVP_FLAG_ALLOCATED; -+ -+ m_videoBuffer.color_range = 0; -+ m_videoBuffer.color_matrix = 4; -+ -+ m_videoBuffer.iDisplayWidth = resultVideoWidth; -+ m_videoBuffer.iDisplayHeight = resultVideoHeight; -+ m_videoBuffer.iWidth = resultVideoWidth; -+ m_videoBuffer.iHeight = resultVideoHeight; -+ -+ m_videoBuffer.data[0] = NULL; -+ m_videoBuffer.data[1] = NULL; -+ m_videoBuffer.data[2] = NULL; -+ m_videoBuffer.data[3] = NULL; -+ -+ m_videoBuffer.pts = DVD_NOPTS_VALUE; -+ m_videoBuffer.dts = DVD_NOPTS_VALUE; -+ -+ m_videoBuffer.iLineSize[0] = resultLineSize; -+ m_videoBuffer.iLineSize[3] = 0; -+ -+ if (finalFormat == V4L2_PIX_FMT_NV12M) { -+ m_videoBuffer.format = RENDER_FMT_NV12; -+ m_videoBuffer.iLineSize[1] = resultLineSize; -+ m_videoBuffer.iLineSize[2] = 0; -+ } else if (finalFormat == V4L2_PIX_FMT_YUV420M) { -+ /* -+ Due to BUG in MFC v8 (-XU3) firmware the Y plane of the picture has the right line size, -+ but the U and V planes line sizes are actually halves of Y plane line size padded to 32 -+ This is pure workaround for -XU3 MFCv8 firmware "MFC v8.0, F/W: 14yy, 01mm, 13dd (D) -+ Seems that only MPEG2 is affected -+ */ -+ // Only on -XU3 there are no converter, but the output format can be YUV420 -+ // So this is the easiest way to distinguish -XU3 from -U3 with FIMC -+ if (!m_iConverterHandle && m_hints.codec == AV_CODEC_ID_MPEG2VIDEO) -+ resultLineSize = resultLineSize + (32 - resultLineSize%32); -+ -+ m_videoBuffer.format = RENDER_FMT_YUV420P; -+ m_videoBuffer.iLineSize[1] = resultLineSize >> 1; -+ m_videoBuffer.iLineSize[2] = resultLineSize >> 1; -+ } -+ -+ m_BufferNowOnScreen->iIndex = -1; -+ m_bCodecHealthy = true; -+ -+ CLog::Log(LOGNOTICE, "%s::%s - MFC Setup succesfull (%dx%d, linesize %d, format 0x%x), start streaming", CLASSNAME, __func__, resultVideoWidth, resultVideoHeight, resultLineSize, finalFormat); -+ -+ return true; -+ -+} -+ -+void CDVDVideoCodecMFC::SetDropState(bool bDrop) { -+ -+ m_bDropPictures = bDrop; -+ if (m_bDropPictures) -+ m_videoBuffer.iFlags |= DVP_FLAG_DROPPED; -+ else -+ m_videoBuffer.iFlags &= ~DVP_FLAG_DROPPED; -+ -+} -+ -+int CDVDVideoCodecMFC::Decode(BYTE* pData, int iSize, double dts, double pts) { -+ -+ if (m_hints.ptsinvalid) -+ pts = DVD_NOPTS_VALUE; -+ -+ //unsigned int dtime = XbmcThreads::SystemClockMillis(); -+ debug_log(LOGDEBUG, "%s::%s - input frame iSize %d, pts %lf, dts %lf", CLASSNAME, __func__, iSize, pts, dts); -+ -+ if(pData) { -+ int demuxer_bytes = iSize; -+ uint8_t *demuxer_content = pData; -+ -+ if(m_bVideoConvert) { -+ m_converter.Convert(demuxer_content, demuxer_bytes); -+ demuxer_bytes = m_converter.GetConvertSize(); -+ demuxer_content = m_converter.GetConvertBuffer(); -+ } -+ -+ m_MFCOutput->Poll(1000/3); // Wait up to 0.3 of a second for buffer availability -+ if (m_MFCOutput->GetBuffer(m_Buffer)) { -+ debug_log(LOGDEBUG, "%s::%s - Got empty buffer %d from MFC Output, filling", CLASSNAME, __func__, m_Buffer->iIndex); -+ m_Buffer->iBytesUsed[0] = demuxer_bytes; -+ memcpy((uint8_t *)m_Buffer->cPlane[0], demuxer_content, m_Buffer->iBytesUsed[0]); -+ long* longPts = (long*)&pts; -+ m_Buffer->timeStamp.tv_sec = longPts[0]; -+ m_Buffer->timeStamp.tv_usec = longPts[1]; -+ -+ if (!m_MFCOutput->PushBuffer(m_Buffer)) { -+ m_bCodecHealthy = false; -+ return VC_FLUSHED; // MFC unrecoverable error, reset needed -+ } -+ } else { -+ if (errno == EAGAIN) -+ CLog::Log(LOGERROR, "%s::%s - MFC OUTPUT All buffers are queued and busy, no space for new frame to decode. Very broken situation. Current encoded frame will be lost", CLASSNAME, __func__); -+ else { -+ m_bCodecHealthy = false; -+ return VC_FLUSHED; // MFC unrecoverable error, reset needed -+ } -+ } -+ } -+ -+ // Get a buffer from MFC Capture -+ if (!m_MFCCapture->DequeueBuffer(m_Buffer)) { -+ if (errno == EAGAIN) -+ return VC_BUFFER; -+ else -+ return VC_ERROR; -+ } -+ -+ if (m_bDropPictures) { -+ -+ CLog::Log(LOGWARNING, "%s::%s - Dropping frame with index %d", CLASSNAME, __func__, m_Buffer->iIndex); -+ // Queue it back to MFC CAPTURE since the picture is dropped anyway -+ m_MFCCapture->PushBuffer(m_Buffer); -+ return VC_DROPPED | VC_BUFFER; -+ -+ } -+ -+ if (m_iConverterHandle) { -+ // Push the buffer got from MFC Capture to FIMC Output (decoded from decoder to converter) -+ if (!m_FIMCOutput->PushBuffer(m_Buffer)) { -+ m_bCodecHealthy = false; -+ return VC_FLUSHED; // FIMC unrecoverable error, reset needed -+ } -+ // Get a buffer from FIMC Capture -+ if (!m_FIMCCapture->DequeueBuffer(m_Buffer)) { -+ if (errno == EAGAIN) -+ return VC_BUFFER; -+ else -+ return VC_ERROR; -+ } -+ } -+ -+ // We got a new buffer to show, so we can enqeue back the buffer wich was on screen -+ if (m_BufferNowOnScreen->iIndex > -1) { -+ if (m_iConverterHandle) -+ m_FIMCCapture->PushBuffer(m_BufferNowOnScreen); -+ else -+ m_MFCCapture->PushBuffer(m_BufferNowOnScreen); -+ m_BufferNowOnScreen->iIndex = -1; -+ } -+ -+ long longPts[2] = { m_Buffer->timeStamp.tv_sec, m_Buffer->timeStamp.tv_usec }; -+ m_videoBuffer.data[0] = (BYTE*)m_Buffer->cPlane[0]; -+ m_videoBuffer.data[1] = (BYTE*)m_Buffer->cPlane[1]; -+ m_videoBuffer.data[2] = (BYTE*)m_Buffer->cPlane[2]; -+ m_videoBuffer.pts = *((double*)&longPts[0]); -+ -+ std::swap(m_Buffer, m_BufferNowOnScreen); -+ -+ if (m_iConverterHandle && m_FIMCOutput->DequeueBuffer(m_Buffer)) -+ m_MFCCapture->PushBuffer(m_Buffer); -+ -+ //debug_log("Decode time: %d", XbmcThreads::SystemClockMillis() - dtime); -+ // Picture is finally ready to be processed further and more info can be enqueued -+ return VC_PICTURE | VC_BUFFER; -+ -+} -+ -+void CDVDVideoCodecMFC::Reset() { -+ -+ if (m_bCodecHealthy) { -+ CLog::Log(LOGDEBUG, "%s::%s - Codec Reset requested, but codec is healthy, doing soft-flush", CLASSNAME, __func__); -+ m_MFCOutput->SoftRestart(); -+ m_MFCCapture->SoftRestart(); -+ if (!m_iConverterHandle) -+ m_BufferNowOnScreen->iIndex = -1; -+ } else { -+ CLog::Log(LOGERROR, "%s::%s - Codec Reset. Reinitializing", CLASSNAME, __func__); -+ CDVDCodecOptions options; -+ // We need full MFC/FIMC reset with device reopening. -+ // I wasn't able to reinitialize both IP's without fully closing and reopening them. -+ // There are always some clips that cause MFC or FIMC go into state which cannot be reset without close/open -+ Open(m_hints, options); -+ } -+ -+} -+ -+bool CDVDVideoCodecMFC::GetPicture(DVDVideoPicture* pDvdVideoPicture) { -+ -+ *pDvdVideoPicture = m_videoBuffer; -+ debug_log(LOGDEBUG, "%s::%s - output frame pts %lf", CLASSNAME, __func__, m_videoBuffer.pts); -+ return true; -+ -+} -+ -+bool CDVDVideoCodecMFC::ClearPicture(DVDVideoPicture* pDvdVideoPicture) { -+ -+ return CDVDVideoCodec::ClearPicture(pDvdVideoPicture); -+ -+} -diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecMFC.h b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecMFC.h -new file mode 100644 -index 0000000..679cf8c ---- /dev/null -+++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecMFC.h -@@ -0,0 +1,64 @@ -+#pragma once -+ -+#ifndef THIS_IS_NOT_XBMC -+ #include "DVDVideoCodec.h" -+ #include "DVDStreamInfo.h" -+ #include "utils/BitstreamConverter.h" -+ #include "xbmc/linux/LinuxV4l2Sink.h" -+#else -+ #include "xbmcstubs.h" -+ #include "LinuxV4l2Sink.h" -+#endif -+ -+#ifndef V4L2_CAP_VIDEO_M2M_MPLANE -+ #define V4L2_CAP_VIDEO_M2M_MPLANE 0x00004000 -+#endif -+ -+#define BUFFER_SIZE 1048576 // Compressed frame size. 1080p mpeg4 10Mb/s can be >256k in size, so this is to make sure frame fits into the buffer -+ // For very unknown reason lesser than 1Mb buffer causes MFC to corrupt its own setup, setting inapropriate values -+#define INPUT_BUFFERS 3 // 3 input buffers. 2 is enough almost for everything, but on some heavy videos 3 makes a difference -+#define OUTPUT_BUFFERS 3 // Triple buffering for smooth output -+ -+#define memzero(x) memset(&(x), 0, sizeof (x)) -+ -+class CDVDVideoCodecMFC : public CDVDVideoCodec -+{ -+public: -+ CDVDVideoCodecMFC(CProcessInfo &processInfo); -+ virtual ~CDVDVideoCodecMFC(); -+ virtual bool Open(CDVDStreamInfo &hints, CDVDCodecOptions &options); -+ virtual void Dispose(); -+ virtual int Decode(BYTE* pData, int iSize, double dts, double pts); -+ virtual void Reset(); -+ bool GetPictureCommon(DVDVideoPicture* pDvdVideoPicture); -+ virtual bool GetPicture(DVDVideoPicture* pDvdVideoPicture); -+ virtual bool ClearPicture(DVDVideoPicture* pDvdVideoPicture); -+ virtual void SetDropState(bool bDrop); -+ virtual const char* GetName() { return m_name.c_str(); }; // m_name is never changed after open -+ -+protected: -+ std::string m_name; -+ -+ bool m_bCodecHealthy; -+ -+ V4l2Device *m_iDecoderHandle; -+ V4l2Device *m_iConverterHandle; -+ -+ CLinuxV4l2Sink *m_MFCCapture; -+ CLinuxV4l2Sink *m_MFCOutput; -+ CLinuxV4l2Sink *m_FIMCCapture; -+ CLinuxV4l2Sink *m_FIMCOutput; -+ -+ V4l2SinkBuffer *m_Buffer; -+ V4l2SinkBuffer *m_BufferNowOnScreen; -+ -+ bool m_bVideoConvert; -+ CDVDStreamInfo m_hints; -+ -+ CBitstreamConverter m_converter; -+ bool m_bDropPictures; -+ -+ DVDVideoPicture m_videoBuffer; -+ -+ bool OpenDevices(); -+}; -diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/Makefile.in b/xbmc/cores/VideoPlayer/DVDCodecs/Video/Makefile.in -index 62d44ce..99a5556 100644 ---- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/Makefile.in -+++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/Makefile.in -@@ -34,8 +34,11 @@ ifeq (@USE_MMAL@,1) - SRCS += MMALCodec.cpp MMALFFmpeg.cpp - endif - -+ifeq (@USE_MFC@,1) -+SRCS += DVDVideoCodecMFC.cpp -+endif -+ - LIB=Video.a - - include @abs_top_srcdir@/Makefile.include - -include $(patsubst %.cpp,%.P,$(patsubst %.c,%.P,$(SRCS))) -- -diff --git a/xbmc/linux/LinuxV4l2Sink.cpp b/xbmc/linux/LinuxV4l2Sink.cpp -new file mode 100644 -index 0000000..bd5201e ---- /dev/null -+++ b/xbmc/linux/LinuxV4l2Sink.cpp -@@ -0,0 +1,311 @@ -+#include "system.h" -+ -+#ifndef THIS_IS_NOT_XBMC -+ #if (defined HAVE_CONFIG_H) && (!defined WIN32) -+ #include "config.h" -+ #endif -+ -+ #include "utils/log.h" -+#endif -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "LinuxV4l2Sink.h" -+ -+#ifdef CLASSNAME -+#undef CLASSNAME -+#endif -+#define CLASSNAME "CLinuxV4l2Sink" -+ -+CLinuxV4l2Sink::CLinuxV4l2Sink(V4l2Device *device, enum v4l2_buf_type type) { -+ CLog::Log(LOGDEBUG, "%s::%s - Creating Sink, Device %s, Type %d", CLASSNAME, __func__, device->name, type); -+ m_Device = device; -+ m_Type = type; -+ m_NumBuffers = 0; -+ m_NumPlanes = 0; -+ m_Addresses = NULL; -+ m_Buffers = NULL; -+ m_Planes = NULL; -+} -+ -+CLinuxV4l2Sink::~CLinuxV4l2Sink() { -+ CLog::Log(LOGDEBUG, "%s::%s - Destroying Sink, Device %s, Type %d", CLASSNAME, __func__, m_Device->name, m_Type); -+ -+ StreamOn(VIDIOC_STREAMOFF); -+ -+ if (m_Memory == V4L2_MEMORY_MMAP) -+ for (int i = 0; i < m_NumBuffers*m_NumPlanes; i++) -+ if(m_Addresses[i] != (unsigned long)MAP_FAILED) -+ if (munmap((void *)m_Addresses[i], m_Planes[i].length) == 0) -+ CLog::Log(LOGDEBUG, "%s::%s - Device %s, Munmapped Plane %d size %u at 0x%lx", CLASSNAME, __func__, m_Device->name, i, m_Planes[i].length, m_Addresses[i]); -+ if (m_Planes) -+ delete[] m_Planes; -+ if (m_Buffers) -+ delete[] m_Buffers; -+ if (m_Addresses) -+ delete[] m_Addresses; -+} -+ -+// Init for MMAP buffers -+bool CLinuxV4l2Sink::Init(int buffersCount = 0) { -+ CLog::Log(LOGDEBUG, "%s::%s - Device %s, Type %d, Init MMAP %d buffers", CLASSNAME, __func__, m_Device->name, m_Type, buffersCount); -+ m_Memory = V4L2_MEMORY_MMAP; -+ -+ struct v4l2_format format; -+ if (!GetFormat(&format)) -+ return false; -+ -+ if (buffersCount == 0 && m_Type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { -+ struct v4l2_control ctrl; -+ ctrl.id = V4L2_CID_MIN_BUFFERS_FOR_CAPTURE; -+ if (ioctl(m_Device->device, VIDIOC_G_CTRL, &ctrl)) { -+ CLog::Log(LOGERROR, "%s::%s - Device %s, Type %d, Error getting number of buffers for capture (V4L2_CID_MIN_BUFFERS_FOR_CAPTURE VIDIOC_G_CTRL)", CLASSNAME, __func__, m_Device->name, m_Type); -+ return false; -+ } -+ buffersCount = (int)(ctrl.value * 1.5); //Most of the time we need 50% more extra capture buffers than device reported would be enough -+ } -+ -+ m_NumBuffers = RequestBuffers(buffersCount); -+ if (m_NumBuffers < 1) -+ return false; -+ m_Buffers = new v4l2_buffer[m_NumBuffers]; -+ m_Planes = new v4l2_plane[m_NumPlanes * m_NumBuffers]; -+ m_Addresses = new unsigned long[m_NumPlanes * m_NumBuffers]; -+ if (!QueryBuffers()) -+ return false; -+ if (!MmapBuffers()) -+ return false; -+ return true; -+} -+// Init for USERPTR buffers -+bool CLinuxV4l2Sink::Init(CLinuxV4l2Sink *sink) { -+ CLog::Log(LOGDEBUG, "%s::%s - Device %s, Type %d, Init UserPTR", CLASSNAME, __func__, m_Device->name, m_Type); -+ m_Memory = V4L2_MEMORY_USERPTR; -+ -+ struct v4l2_format format; -+ if (!GetFormat(&format)) -+ return false; -+ -+ m_NumBuffers = sink->m_NumBuffers; -+ m_NumBuffers = RequestBuffers(m_NumBuffers); -+ if (m_NumBuffers < 1) -+ return false; -+ m_Buffers = new v4l2_buffer[m_NumBuffers]; -+ m_Planes = new v4l2_plane[m_NumPlanes * m_NumBuffers]; -+ m_Addresses = new unsigned long[m_NumPlanes * m_NumBuffers]; -+ if (!QueryBuffers()) -+ return false; -+ for (int i = 0; i < m_NumPlanes * m_NumBuffers; i++) { -+ m_Addresses[i] = sink->m_Addresses[i]; -+ m_Planes[i].m.userptr = m_Addresses[i]; -+ } -+ return true; -+} -+ -+void CLinuxV4l2Sink::SoftRestart() { -+ StreamOn(VIDIOC_STREAMOFF); -+ -+ while (!iFreeBuffers.empty()) -+ iFreeBuffers.pop(); -+ for (int i = 0; i < m_NumBuffers; i++) -+ iFreeBuffers.push(m_Buffers[i].index); -+ -+ if (m_Type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) -+ QueueAll(); -+ -+ StreamOn(VIDIOC_STREAMON); -+} -+ -+bool CLinuxV4l2Sink::GetFormat(v4l2_format *format) { -+ memset(format, 0, sizeof(struct v4l2_format)); -+ format->type = m_Type; -+ if (ioctl(m_Device->device, VIDIOC_G_FMT, format)) { -+ CLog::Log(LOGERROR, "%s::%s - Error getting sink format. Device %s, Type %d. (VIDIOC_G_FMT)", CLASSNAME, __func__, m_Device->name, m_Type); -+ return false; -+ } -+ m_NumPlanes = format->fmt.pix_mp.num_planes; -+ CLog::Log(LOGDEBUG, "%s::%s - G_FMT Device %s, Type %d format 0x%x (%dx%d), planes=%d, plane[0]=%d plane[1]=%d, plane[2]=%d", CLASSNAME, __func__, m_Device->name, format->type, format->fmt.pix_mp.pixelformat, format->fmt.pix_mp.width, format->fmt.pix_mp.height, format->fmt.pix_mp.num_planes, format->fmt.pix_mp.plane_fmt[0].sizeimage, format->fmt.pix_mp.plane_fmt[1].sizeimage, format->fmt.pix_mp.plane_fmt[2].sizeimage); -+ return true; -+} -+ -+bool CLinuxV4l2Sink::SetFormat(v4l2_format *format) { -+ format->type = m_Type; -+ CLog::Log(LOGDEBUG, "%s::%s - S_FMT Device %s, Type %d format 0x%x (%dx%d), planes=%d, plane[0]=%d plane[1]=%d, plane[2]=%d", CLASSNAME, __func__, m_Device->name, format->type, format->fmt.pix_mp.pixelformat, format->fmt.pix_mp.width, format->fmt.pix_mp.height, format->fmt.pix_mp.num_planes, format->fmt.pix_mp.plane_fmt[0].sizeimage, format->fmt.pix_mp.plane_fmt[1].sizeimage, format->fmt.pix_mp.plane_fmt[2].sizeimage); -+ if (ioctl(m_Device->device, VIDIOC_S_FMT, format)) { -+ CLog::Log(LOGERROR, "%s::%s - Error setting sink format. Device %s, Type %d. (VIDIOC_G_FMT)", CLASSNAME, __func__, m_Device->name, m_Type); -+ return false; -+ } -+ return true; -+} -+ -+bool CLinuxV4l2Sink::GetCrop(v4l2_crop *crop) { -+ memset(crop, 0, sizeof(struct v4l2_crop)); -+ crop->type = m_Type; -+ if (ioctl(m_Device->device, VIDIOC_G_CROP, crop)) { -+ CLog::Log(LOGERROR, "%s::%s - Error getting sink crop. Device %s, Type %d. (VIDIOC_G_CROP)", CLASSNAME, __func__, m_Device->name, m_Type); -+ return false; -+ } -+ CLog::Log(LOGDEBUG, "%s::%s - G_CROP Device %s, Type %d, crop (%dx%d)", CLASSNAME, __func__, m_Device->name, crop->type, crop->c.width, crop->c.height); -+ return true; -+} -+ -+bool CLinuxV4l2Sink::SetCrop(v4l2_crop *crop) { -+ crop->type = m_Type; -+ CLog::Log(LOGDEBUG, "%s::%s - S_CROP Device %s, Type %d, crop (%dx%d)", CLASSNAME, __func__, m_Device->name, crop->type, crop->c.width, crop->c.height); -+ if (ioctl(m_Device->device, VIDIOC_S_CROP, crop)) { -+ CLog::Log(LOGERROR, "%s::%s - Error setting sink crop. Device %s, Type %d. (VIDIOC_G_CROP)", CLASSNAME, __func__, m_Device->name, m_Type); -+ return false; -+ } -+ return true; -+} -+ -+int CLinuxV4l2Sink::RequestBuffers(int buffersCount) { -+ CLog::Log(LOGDEBUG, "%s::%s - Device %s, Type %d, Memory %d, RequestBuffers %d", CLASSNAME, __func__, m_Device->name, m_Type, m_Memory, buffersCount); -+ struct v4l2_requestbuffers reqbuf; -+ memset(&reqbuf, 0, sizeof(struct v4l2_requestbuffers)); -+ reqbuf.type = m_Type; -+ reqbuf.memory = m_Memory; -+ reqbuf.count = buffersCount; -+ -+ if (ioctl(m_Device->device, VIDIOC_REQBUFS, &reqbuf)) { -+ CLog::Log(LOGERROR, "%s::%s - Error requesting buffers. Device %s, Type %d, Memory %d. (VIDIOC_REQBUFS)", CLASSNAME, __func__, m_Device->name, m_Type, m_Memory); -+ return V4L2_ERROR; -+ } -+ -+ CLog::Log(LOGDEBUG, "%s::%s - Device %s, Type %d, Memory %d, Buffers allowed %d", CLASSNAME, __func__, m_Device->name, m_Type, m_Memory, reqbuf.count); -+ return reqbuf.count; -+} -+ -+bool CLinuxV4l2Sink::QueryBuffers() { -+ memset(m_Buffers, 0, m_NumBuffers * sizeof(struct v4l2_buffer)); -+ memset(m_Planes, 0, m_NumBuffers * m_NumPlanes * sizeof(struct v4l2_plane)); -+ -+ for(int i = 0; i < m_NumBuffers; i++) { -+ m_Buffers[i].type = m_Type; -+ m_Buffers[i].memory = m_Memory; -+ m_Buffers[i].index = i; -+ m_Buffers[i].m.planes = &m_Planes[i*m_NumPlanes]; -+ m_Buffers[i].length = m_NumPlanes; -+ -+ if (ioctl(m_Device->device, VIDIOC_QUERYBUF, &m_Buffers[i])) { -+ CLog::Log(LOGERROR, "%s::%s - Error querying buffers. Device %s, Type %d, Memory %d. (VIDIOC_QUERYBUF)", CLASSNAME, __func__, m_Device->name, m_Type, m_Memory); -+ return false; -+ } -+ -+ iFreeBuffers.push(m_Buffers[i].index); -+ } -+ return true; -+} -+ -+bool CLinuxV4l2Sink::MmapBuffers() { -+ for(int i = 0; i < m_NumBuffers * m_NumPlanes; i++) { -+ if(m_Planes[i].length) { -+ m_Addresses[i] = (unsigned long)mmap(NULL, m_Planes[i].length, PROT_READ | PROT_WRITE, MAP_SHARED, m_Device->device, m_Planes[i].m.mem_offset); -+ if (m_Addresses[i] == (unsigned long)MAP_FAILED) -+ return false; -+ CLog::Log(LOGDEBUG, "%s::%s - Device %s, Type %d, MMapped Plane %d at 0x%x to address 0x%lx", CLASSNAME, __func__, m_Device->name, m_Type, i, m_Planes[i].m.mem_offset, m_Addresses[i]); -+ } -+ } -+ return true; -+} -+ -+bool CLinuxV4l2Sink::StreamOn(int state) { -+ if(ioctl(m_Device->device, state, &m_Type)) { -+ CLog::Log(LOGERROR, "%s::%s - Error setting device state to %d, Device %s, Type %d.", CLASSNAME, __func__, state, m_Device->name, m_Type); -+ return false; -+ } -+ CLog::Log(LOGDEBUG, "%s::%s - Device %s, Type %d, %d", CLASSNAME, __func__, m_Device->name, m_Type, state); -+ return true; -+} -+ -+bool CLinuxV4l2Sink::QueueBuffer(v4l2_buffer *buffer) { -+ debug_log(LOGDEBUG, "%s::%s - Device %s, Type %d, Memory %d <- %d", CLASSNAME, __func__, m_Device->name, buffer->type, buffer->memory, buffer->index); -+ if (ioctl(m_Device->device, VIDIOC_QBUF, buffer)) { -+ CLog::Log(LOGERROR, "%s::%s - Error queueing buffer. Device %s, Type %d, Memory %d. Buffer %d, errno %d", CLASSNAME, __func__, m_Device->name, buffer->type, buffer->memory, buffer->index, errno); -+ return false; -+ } -+ return true; -+} -+bool CLinuxV4l2Sink::DequeueBuffer(v4l2_buffer *buffer) { -+ if (ioctl(m_Device->device, VIDIOC_DQBUF, buffer)) { -+ if (errno != EAGAIN) CLog::Log(LOGERROR, "%s::%s - Error dequeueing buffer. Device %s, Type %d, Memory %d. Buffer %d, errno %d", CLASSNAME, __func__, m_Device->name, buffer->type, buffer->memory, buffer->index, errno); -+ return false; -+ } -+ debug_log(LOGDEBUG, "%s::%s - Device %s, Type %d, Memory %d -> %d", CLASSNAME, __func__, m_Device->name, buffer->type, buffer->memory, buffer->index); -+ return true; -+} -+ -+bool CLinuxV4l2Sink::DequeueBuffer(V4l2SinkBuffer *buffer) { -+ struct v4l2_buffer buf; -+ struct v4l2_plane planes[m_NumPlanes]; -+ memset(&planes, 0, sizeof(struct v4l2_plane) * m_NumPlanes); -+ memset(&buf, 0, sizeof(struct v4l2_buffer)); -+ buf.type = m_Type; -+ buf.memory = m_Memory; -+ buf.m.planes = planes; -+ buf.length = m_NumPlanes; -+ if (!DequeueBuffer(&buf)) -+ return false; -+ -+ buffer->iIndex = buf.index; -+ buffer->timeStamp = buf.timestamp; -+ for (int i = 0; i < m_NumPlanes; i++) -+ buffer->cPlane[i] = (void *)m_Addresses[buffer->iIndex * m_NumPlanes + i]; -+ return true; -+} -+ -+bool CLinuxV4l2Sink::GetBuffer(V4l2SinkBuffer *buffer) { -+ if (iFreeBuffers.empty()) { -+ if (!DequeueBuffer(buffer)) -+ return false; -+ } else { -+ buffer->iIndex = iFreeBuffers.front(); -+ buffer->timeStamp = m_Buffers[buffer->iIndex].timestamp; -+ iFreeBuffers.pop(); -+ for (int i = 0; i < m_NumPlanes; i++) -+ buffer->cPlane[i] = (void *)m_Addresses[buffer->iIndex * m_NumPlanes + i]; -+ } -+ return true; -+} -+ -+bool CLinuxV4l2Sink::PushBuffer(V4l2SinkBuffer *buffer) { -+ if (m_Memory == V4L2_MEMORY_USERPTR) -+ for (int i = 0; i < m_NumPlanes; i++) -+ m_Buffers[buffer->iIndex].m.planes[i].m.userptr = (long unsigned int)buffer->cPlane[i]; -+ -+ if (m_Type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { -+ m_Buffers[buffer->iIndex].timestamp = buffer->timeStamp; -+ m_Buffers[buffer->iIndex].flags |= V4L2_BUF_FLAG_TIMESTAMP_COPY; -+ for (int i = 0; i < m_NumPlanes; i++) -+ m_Buffers[buffer->iIndex].m.planes[i].bytesused = buffer->iBytesUsed[i]; -+ } -+ -+ if (!QueueBuffer(&m_Buffers[buffer->iIndex])) -+ return false; -+ return true; -+} -+ -+int CLinuxV4l2Sink::Poll(int timeout) { -+ struct pollfd p; -+ p.fd = m_Device->device; -+ p.events = POLLERR; -+ (m_Type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) ? p.events |= POLLOUT : p.events |= POLLIN; -+ -+ return poll(&p, 1, timeout); -+} -+ -+bool CLinuxV4l2Sink::QueueAll() { -+ while (!iFreeBuffers.empty()) { -+ if (!QueueBuffer(&m_Buffers[iFreeBuffers.front()])) -+ return false; -+ iFreeBuffers.pop(); -+ } -+ return true; -+} -diff --git a/xbmc/linux/LinuxV4l2Sink.h b/xbmc/linux/LinuxV4l2Sink.h -new file mode 100644 -index 0000000..d04d52d ---- /dev/null -+++ b/xbmc/linux/LinuxV4l2Sink.h -@@ -0,0 +1,71 @@ -+#pragma once -+ -+#include -+#include -+#include -+#include -+ -+#ifndef V4L2_BUF_FLAG_TIMESTAMP_COPY -+ #define V4L2_BUF_FLAG_TIMESTAMP_COPY 0x4000 -+#endif -+ -+#define V4L2_ERROR -1 -+#define V4L2_BUSY 1 -+#define V4L2_READY 2 -+#define V4L2_OK 3 -+ -+#ifdef _DEBUG -+ #define debug_log(...) CLog::Log(__VA_ARGS__) -+#else -+ #define debug_log(...) -+#endif -+ -+typedef struct V4l2Device -+{ -+ int device; -+ char name[32]; -+} V4l2Device; -+ -+typedef struct V4l2SinkBuffer -+{ -+ int iIndex; -+ int iBytesUsed[4]; -+ void *cPlane[4]; -+ struct timeval timeStamp; -+} V4l2SinkBuffer; -+ -+class CLinuxV4l2Sink -+{ -+public: -+ CLinuxV4l2Sink(V4l2Device *device, enum v4l2_buf_type type); -+ ~CLinuxV4l2Sink(); -+ -+ bool Init(int buffersCount); -+ bool Init(CLinuxV4l2Sink *sink); -+ void SoftRestart(); -+ bool GetFormat(v4l2_format *format); -+ bool SetFormat(v4l2_format *format); -+ bool GetCrop(v4l2_crop *crop); -+ bool SetCrop(v4l2_crop *crop); -+ bool GetBuffer(V4l2SinkBuffer* buffer); -+ bool DequeueBuffer(V4l2SinkBuffer* buffer); -+ bool PushBuffer(V4l2SinkBuffer* buffer); -+ bool StreamOn(int state); -+ bool QueueAll(); -+ int Poll(int timeout); -+private: -+ V4l2Device *m_Device; -+ int m_NumPlanes; -+ int m_NumBuffers; -+ std::queue iFreeBuffers; -+ enum v4l2_memory m_Memory; -+ enum v4l2_buf_type m_Type; -+ v4l2_buffer *m_Buffers; -+ v4l2_plane *m_Planes; -+ unsigned long *m_Addresses; -+ int RequestBuffers(int buffersCount); -+ bool QueryBuffers(); -+ bool MmapBuffers(); -+ bool QueueBuffer(v4l2_buffer *buffer); -+ bool DequeueBuffer(v4l2_buffer *buffer); -+}; -diff --git a/xbmc/linux/Makefile.in b/xbmc/linux/Makefile.in -index 0cf90d1..ff2c2dc 100644 ---- a/xbmc/linux/Makefile.in -+++ b/xbmc/linux/Makefile.in -@@ -12,6 +12,7 @@ SRCS += XFileUtils.cpp - SRCS += XHandle.cpp - SRCS += XMemUtils.cpp - SRCS += XTimeUtils.cpp -+SRCS += LinuxV4l2Sink.cpp - - SRCS += RBP.cpp - diff --git a/xbmc/utils/AMLUtils.cpp b/xbmc/utils/AMLUtils.cpp -index 4ae45f3..f4911119 100644 +index 80fb453..0f0fef0 100644 --- a/xbmc/utils/AMLUtils.cpp +++ b/xbmc/utils/AMLUtils.cpp -@@ -79,7 +79,7 @@ bool aml_wired_present() +@@ -78,7 +78,7 @@ bool aml_wired_present() } bool aml_permissions() @@ -1470,7 +208,7 @@ index 4ae45f3..f4911119 100644 if (!aml_present()) return false; -@@ -210,7 +210,8 @@ bool aml_support_h264_4k2k() +@@ -209,7 +209,8 @@ bool aml_support_h264_4k2k() void aml_set_audio_passthrough(bool passthrough) { @@ -1480,7 +218,7 @@ index 4ae45f3..f4911119 100644 } void aml_probe_hdmi_audio() -@@ -228,7 +229,7 @@ void aml_probe_hdmi_audio() +@@ -227,7 +228,7 @@ void aml_probe_hdmi_audio() { char valstr[1024] = {0}; @@ -1489,7 +227,7 @@ index 4ae45f3..f4911119 100644 valstr[strlen(valstr)] = '\0'; close(fd); -@@ -363,6 +364,60 @@ bool aml_mode_to_resolution(const char *mode, RESOLUTION_INFO *res) +@@ -362,6 +363,60 @@ bool aml_mode_to_resolution(const char *mode, RESOLUTION_INFO *res) res->fRefreshRate = 50; res->dwFlags = D3DPRESENTFLAG_PROGRESSIVE; } @@ -1550,7 +288,7 @@ index 4ae45f3..f4911119 100644 else if (StringUtils::EqualsNoCase(fromMode, "720p") || StringUtils::EqualsNoCase(fromMode, "720p60hz")) { res->iWidth = 1280; -@@ -408,6 +463,24 @@ bool aml_mode_to_resolution(const char *mode, RESOLUTION_INFO *res) +@@ -407,6 +462,24 @@ bool aml_mode_to_resolution(const char *mode, RESOLUTION_INFO *res) res->fRefreshRate = 24; res->dwFlags = D3DPRESENTFLAG_PROGRESSIVE; } @@ -1575,7 +313,7 @@ index 4ae45f3..f4911119 100644 else if (StringUtils::EqualsNoCase(fromMode, "1080p30hz")) { res->iWidth = 1920; -@@ -516,7 +589,7 @@ bool aml_mode_to_resolution(const char *mode, RESOLUTION_INFO *res) +@@ -515,7 +588,7 @@ bool aml_mode_to_resolution(const char *mode, RESOLUTION_INFO *res) res->fRefreshRate = 30; res->dwFlags = D3DPRESENTFLAG_PROGRESSIVE; } @@ -1584,7 +322,7 @@ index 4ae45f3..f4911119 100644 { res->iWidth = 1920; res->iHeight= 1080; -@@ -525,7 +598,16 @@ bool aml_mode_to_resolution(const char *mode, RESOLUTION_INFO *res) +@@ -524,7 +597,16 @@ bool aml_mode_to_resolution(const char *mode, RESOLUTION_INFO *res) res->fRefreshRate = 50; res->dwFlags = D3DPRESENTFLAG_PROGRESSIVE; } @@ -1602,17 +340,17 @@ index 4ae45f3..f4911119 100644 { res->iWidth = 1920; res->iHeight= 1080; -@@ -550,4 +632,3 @@ bool aml_mode_to_resolution(const char *mode, RESOLUTION_INFO *res) +@@ -549,4 +631,3 @@ bool aml_mode_to_resolution(const char *mode, RESOLUTION_INFO *res) return res->iWidth > 0 && res->iHeight> 0; } - diff --git a/xbmc/utils/CPUInfo.cpp b/xbmc/utils/CPUInfo.cpp -index a2a775f..f1f9751 100644 +index 6377d35..b50b288 100644 --- a/xbmc/utils/CPUInfo.cpp +++ b/xbmc/utils/CPUInfo.cpp -@@ -117,7 +117,7 @@ CCPUInfo::CCPUInfo(void) - #if defined(TARGET_DARWIN) +@@ -120,7 +120,7 @@ CCPUInfo::CCPUInfo(void) + size_t len = 4; std::string cpuVendor; - @@ -1620,7 +358,7 @@ index a2a775f..f1f9751 100644 // The number of cores. if (sysctlbyname("hw.activecpu", &m_cpuCount, &len, NULL, 0) == -1) m_cpuCount = 1; -@@ -138,7 +138,7 @@ CCPUInfo::CCPUInfo(void) +@@ -141,7 +141,7 @@ CCPUInfo::CCPUInfo(void) len = 512; if (sysctlbyname("machdep.cpu.vendor", &buffer, &len, NULL, 0) == 0) cpuVendor = buffer; @@ -1629,7 +367,7 @@ index a2a775f..f1f9751 100644 #endif // Go through each core. for (int i=0; isecond.m_fSpeed); else -@@ -587,7 +587,7 @@ bool CCPUInfo::getTemperature(CTemperature& temperature) +@@ -597,7 +597,7 @@ bool CCPUInfo::getTemperature(CTemperature& temperature) { int value = 0; char scale = 0; @@ -1659,7 +397,7 @@ index a2a775f..f1f9751 100644 #ifdef TARGET_POSIX #if defined(TARGET_DARWIN_OSX) value = SMCGetTemperature(SMC_KEY_CPU_TEMP); -@@ -616,23 +616,24 @@ bool CCPUInfo::getTemperature(CTemperature& temperature) +@@ -626,23 +626,24 @@ bool CCPUInfo::getTemperature(CTemperature& temperature) // procfs is deprecated in the linux kernel, we should move away from // using it for temperature data. It doesn't seem that sysfs has a // general enough interface to bother implementing ATM. @@ -1688,7 +426,7 @@ index a2a775f..f1f9751 100644 #endif #endif // TARGET_POSIX -@@ -642,7 +643,7 @@ bool CCPUInfo::getTemperature(CTemperature& temperature) +@@ -652,7 +653,7 @@ bool CCPUInfo::getTemperature(CTemperature& temperature) temperature = CTemperature::CreateFromFahrenheit(value); else return false; @@ -1697,7 +435,7 @@ index a2a775f..f1f9751 100644 return true; } -@@ -697,7 +698,7 @@ bool CCPUInfo::readProcStat(unsigned long long& user, unsigned long long& nice, +@@ -707,7 +708,7 @@ bool CCPUInfo::readProcStat(unsigned long long& user, unsigned long long& nice, const LONGLONG deltaTotal = coreTotal - curCore.m_total, deltaIdle = coreIdle - curCore.m_idle; const double load = (double(deltaTotal - deltaIdle) * 100.0) / double(deltaTotal); @@ -1706,19 +444,6 @@ index a2a775f..f1f9751 100644 // win32 has some problems with calculation of load if load close to zero curCore.m_fPct = (load < 0) ? 0 : load; if (load >= 0 || deltaTotal > 5 * 10 * 1000 * 1000) // do not update (smooth) values for 5 seconds on negative loads -diff --git a/xbmc/windowing/X11/WinSystemX11.cpp b/xbmc/windowing/X11/WinSystemX11.cpp -index ee85585..7261f78 100644 ---- a/xbmc/windowing/X11/WinSystemX11.cpp -+++ b/xbmc/windowing/X11/WinSystemX11.cpp -@@ -203,7 +203,7 @@ bool CWinSystemX11::SetFullScreen(bool fullScreen, RESOLUTION_INFO& res, bool bl - mode.hz = CDisplaySettings::GetInstance().GetResolutionInfo(RES_DESKTOP).fRefreshRate; - mode.id = CDisplaySettings::GetInstance().GetResolutionInfo(RES_DESKTOP).strId; - } -- -+ - XMode currmode = g_xrandr.GetCurrentMode(out.name); - if (!currmode.name.empty()) - { diff --git a/xbmc/windowing/egl/EGLNativeTypeAmlogic.cpp b/xbmc/windowing/egl/EGLNativeTypeAmlogic.cpp index 88cd385..cc62734 100644 --- a/xbmc/windowing/egl/EGLNativeTypeAmlogic.cpp @@ -2000,723 +725,6 @@ index cfb33ca..bdb08b6 100644 std::string m_framebuffer_name; }; -diff --git a/xbmc/windowing/egl/EGLNativeTypeFbdev.cpp b/xbmc/windowing/egl/EGLNativeTypeFbdev.cpp -new file mode 100644 -index 0000000..5c25eb6 ---- /dev/null -+++ b/xbmc/windowing/egl/EGLNativeTypeFbdev.cpp -@@ -0,0 +1,183 @@ -+/* -+ * Copyright (C) 2011-2012 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 "EGLNativeTypeFbdev.h" -+#include "utils/log.h" -+#include -+#include -+#include -+#include "utils/StringUtils.h" -+#include "guilib/gui3d.h" -+#include -+ -+#include -+ -+#include "utils/StringUtils.h" -+ -+#ifdef CLASSNAME -+#undef CLASSNAME -+#endif -+#define CLASSNAME "CEGLNativeTypeFbdev" -+ -+CEGLNativeTypeFbdev::CEGLNativeTypeFbdev() -+{ -+ m_iFBHandle = -1; -+ m_nativeWindow = NULL; -+ m_nativeDisplay = NULL; -+} -+ -+CEGLNativeTypeFbdev::~CEGLNativeTypeFbdev() -+{ -+} -+ -+bool CEGLNativeTypeFbdev::CheckCompatibility() -+{ -+ m_iFBHandle = open("/dev/fb0", O_RDWR, 0); -+ if(m_iFBHandle < 0) -+ return false; -+ -+ vinfo = new fb_var_screeninfo(); -+ if(ioctl(m_iFBHandle, FBIOGET_VSCREENINFO, vinfo) == -1) -+ return false; -+ -+ CLog::Log(LOGNOTICE, "%s::%s FBDev device: %d, info.xres %d info.yres %d info.upper_margin %d info.lower_margin %d info.pixclock %d", -+ CLASSNAME, __func__, m_iFBHandle, vinfo->xres, vinfo->yres, vinfo->upper_margin, vinfo->lower_margin, vinfo->pixclock); -+ -+ finfo = new fb_fix_screeninfo(); -+ if(ioctl(m_iFBHandle, FBIOGET_FSCREENINFO, finfo) == -1) -+ return false; -+ -+ return true; -+} -+ -+void CEGLNativeTypeFbdev::Initialize() -+{ -+ return; -+} -+void CEGLNativeTypeFbdev::Destroy() -+{ -+ return; -+} -+ -+bool CEGLNativeTypeFbdev::CreateNativeDisplay() -+{ -+ m_nativeDisplay = EGL_DEFAULT_DISPLAY; -+ return true; -+} -+ -+bool CEGLNativeTypeFbdev::CreateNativeWindow() -+{ -+ fbdev_window *nativeWindow = new fbdev_window; -+ if (!nativeWindow) -+ return false; -+ -+ nativeWindow->width = vinfo->xres; -+ nativeWindow->height = vinfo->yres; -+ m_nativeWindow = nativeWindow; -+ return true; -+} -+ -+bool CEGLNativeTypeFbdev::GetNativeDisplay(XBNativeDisplayType **nativeDisplay) const -+{ -+ if (!nativeDisplay) -+ return false; -+ *nativeDisplay = (XBNativeDisplayType*) &m_nativeDisplay; -+ return true; -+} -+ -+bool CEGLNativeTypeFbdev::GetNativeWindow(XBNativeWindowType **nativeWindow) const -+{ -+ if (!nativeWindow) -+ return false; -+ *nativeWindow = (XBNativeWindowType*) &m_nativeWindow; -+ return true; -+} -+ -+bool CEGLNativeTypeFbdev::DestroyNativeDisplay() -+{ -+ return true; -+} -+ -+bool CEGLNativeTypeFbdev::DestroyNativeWindow() -+{ -+ free(m_nativeWindow); -+ return true; -+} -+ -+bool CEGLNativeTypeFbdev::GetNativeResolution(RESOLUTION_INFO *res) const -+{ -+ res->iWidth = vinfo->xres; -+ res->iHeight = vinfo->yres; -+ res->fRefreshRate = 60; -+ res->dwFlags = D3DPRESENTFLAG_PROGRESSIVE; -+ res->iScreen = 0; -+ res->bFullScreen = true; -+ res->iSubtitles = (int)(0.965 * res->iHeight); -+ res->fPixelRatio = 1.0f; -+ res->iScreenWidth = res->iWidth; -+ res->iScreenHeight = res->iHeight; -+ res->strMode = StringUtils::Format("%dx%d @ %.2f%s - Full Screen", res->iScreenWidth, res->iScreenHeight, res->fRefreshRate, res->dwFlags & D3DPRESENTFLAG_INTERLACED ? "i" : ""); -+ -+ CLog::Log(LOGNOTICE, "Current resolution: %s", res->strMode.c_str()); -+ return true; -+} -+ -+bool CEGLNativeTypeFbdev::SetNativeResolution(const RESOLUTION_INFO &res) -+{ -+ -+ vinfo->activate = FB_ACTIVATE_NOW; -+ -+ if (ioctl(m_iFBHandle, FBIOPUT_VSCREENINFO, vinfo) == -1) -+ { -+ CLog::Log(LOGERROR, "%s::%s - FBIOPUT_VSCREENINFO error", CLASSNAME, __func__); -+ return false; -+ } -+ if (ioctl(m_iFBHandle, FBIOPAN_DISPLAY, vinfo) == -1) -+ { -+ CLog::Log(LOGERROR, "%s::%s - FBIOPAN_DISPLAY error", CLASSNAME, __func__); -+ return false; -+ } -+ -+ CLog::Log(LOGNOTICE, "%s::%s width %d height %d refresh %f", CLASSNAME, __func__, res.iScreenWidth, res.iScreenHeight, res.fRefreshRate); -+ -+ return true; -+} -+ -+bool CEGLNativeTypeFbdev::ProbeResolutions(std::vector &resolutions) -+{ -+ RESOLUTION_INFO res; -+ if (GetNativeResolution(&res) && res.iWidth > 1 && res.iHeight > 1) -+ { -+ resolutions.push_back(res); -+ return true; -+ } -+ return false; -+} -+ -+bool CEGLNativeTypeFbdev::GetPreferredResolution(RESOLUTION_INFO *res) const -+{ -+ GetNativeResolution(res); -+ return true; -+} -+ -+bool CEGLNativeTypeFbdev::ShowWindow(bool show) -+{ -+ return false; -+} -diff --git a/xbmc/windowing/egl/EGLNativeTypeFbdev.h b/xbmc/windowing/egl/EGLNativeTypeFbdev.h -new file mode 100644 -index 0000000..04e7023 ---- /dev/null -+++ b/xbmc/windowing/egl/EGLNativeTypeFbdev.h -@@ -0,0 +1,68 @@ -+#pragma once -+ -+/* -+ * Copyright (C) 2011-2012 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 "EGLNativeType.h" -+#include -+#include -+ -+#ifndef _FBDEV_WINDOW_H_ -+// Define it right here, since some platforms doesn't has fbdev_window.h at all. -+// This will not make it fail on these platforms badly, since it will fail softly anyway on some other init steps. -+#define _FBDEV_WINDOW_H_ -+typedef struct fbdev_window -+{ -+ unsigned short width; -+ unsigned short height; -+} fbdev_window; -+#endif -+ -+class CEGLNativeTypeFbdev : public CEGLNativeType -+{ -+public: -+ CEGLNativeTypeFbdev(); -+ virtual ~CEGLNativeTypeFbdev(); -+ virtual std::string GetNativeName() const { return "FBDev"; }; -+ 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: -+ int m_iFBHandle; -+ fb_var_screeninfo *vinfo; -+ fb_fix_screeninfo *finfo; -+}; -diff --git a/xbmc/windowing/egl/EGLNativeTypeHybris.cpp b/xbmc/windowing/egl/EGLNativeTypeHybris.cpp -new file mode 100644 -index 0000000..767946e ---- /dev/null -+++ b/xbmc/windowing/egl/EGLNativeTypeHybris.cpp -@@ -0,0 +1,279 @@ -+/* -+ * Copyright (C) 2011-2012 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 -+ * . -+ * -+ */ -+#if defined(TARGET_HYBRIS) -+#include -+#include -+#include -+#endif -+ -+#include "system.h" -+#include -+#include "EGLNativeTypeHybris.h" -+#include "utils/log.h" -+#include "guilib/gui3d.h" -+ -+#include "utils/StringUtils.h" -+ -+HWComposer::HWComposer(unsigned int width, -+ unsigned int height, -+ unsigned int format, -+ hwc_composer_device_1_t *device, -+ hwc_display_contents_1_t **mList, -+ hwc_layer_1_t *layer) -+ : HWComposerNativeWindow(width, height, format) -+{ -+ fblayer = layer; -+ hwcdevice = device; -+ mlist = mList; -+} -+ -+void HWComposer::present(HWComposerNativeWindowBuffer *buffer) -+{ -+ int oldretire = mlist[0]->retireFenceFd; -+ mlist[0]->retireFenceFd = -1; -+ fblayer->handle = buffer->handle; -+ fblayer->acquireFenceFd = getFenceBufferFd(buffer); -+ fblayer->releaseFenceFd = -1; -+ int err = hwcdevice->prepare(hwcdevice, HWC_NUM_DISPLAY_TYPES, mlist); -+ assert(err == 0); -+ -+ err = hwcdevice->set(hwcdevice, HWC_NUM_DISPLAY_TYPES, mlist); -+ assert(err == 0); -+ setFenceBufferFd(buffer, fblayer->releaseFenceFd); -+ -+ if (oldretire != -1) -+ { -+ sync_wait(oldretire, -1); -+ close(oldretire); -+ } -+} -+ -+CEGLNativeTypeHybris::CEGLNativeTypeHybris() -+#if defined(TARGET_HYBRIS) -+ : m_hwcModule(NULL), m_bufferList(NULL), m_hwcDevicePtr(NULL) -+{ -+ m_nativeWindow = NULL; -+ m_hwNativeWindow = NULL; -+ m_swNativeWindow = NULL; -+} -+#else -+{ -+} -+#endif -+ -+CEGLNativeTypeHybris::~CEGLNativeTypeHybris() -+{ -+} -+ -+bool CEGLNativeTypeHybris::CheckCompatibility() -+{ -+#if defined(TARGET_HYBRIS) -+ if(hw_get_module(HWC_HARDWARE_MODULE_ID, (const hw_module_t **) &m_hwcModule)) -+ { -+ return false; -+ } -+ -+ if(hwc_open_1(m_hwcModule, &m_hwcDevicePtr)) -+ { -+ return false; -+ } -+ -+ m_hwcDevicePtr->blank(m_hwcDevicePtr, 0, 0); -+ return true; -+#else -+ return false; -+#endif -+} -+ -+void CEGLNativeTypeHybris::Initialize() -+{ -+} -+ -+void CEGLNativeTypeHybris::Destroy() -+{ -+ return; -+} -+ -+bool CEGLNativeTypeHybris::CreateNativeDisplay() -+{ -+ m_nativeDisplay = EGL_DEFAULT_DISPLAY; -+ return true; -+} -+ -+bool CEGLNativeTypeHybris::CreateNativeWindow() -+{ -+#if defined(TARGET_HYBRIS) -+ RESOLUTION_INFO res; -+ if (!GetNativeResolution(&res)) -+ return false; -+ -+ size_t size = sizeof(hwc_display_contents_1_t) + 2 * sizeof(hwc_layer_1_t); -+ hwc_display_contents_1_t *list = (hwc_display_contents_1_t *) malloc(size); -+ m_bufferList = (hwc_display_contents_1_t **) malloc(HWC_NUM_DISPLAY_TYPES * sizeof(hwc_display_contents_1_t *)); -+ const hwc_rect_t r = { 0, 0, res.iWidth, res.iHeight }; -+ -+ for (int counter = 0; counter < HWC_NUM_DISPLAY_TYPES; counter++) -+ m_bufferList[counter] = list; -+ -+ hwc_layer_1_t *layer; -+ -+ layer = &list->hwLayers[0]; -+ memset(layer, 0, sizeof(hwc_layer_1_t)); -+ layer->compositionType = HWC_FRAMEBUFFER; -+ layer->hints = 0; -+ layer->flags = 0; -+ layer->handle = 0; -+ layer->transform = 0; -+ layer->blending = HWC_BLENDING_NONE; -+ layer->sourceCrop = r; -+ layer->displayFrame = r; -+ layer->visibleRegionScreen.numRects = 1; -+ layer->visibleRegionScreen.rects = &layer->displayFrame; -+ layer->acquireFenceFd = -1; -+ layer->releaseFenceFd = -1; -+ -+ layer = &list->hwLayers[1]; -+ memset(layer, 0, sizeof(hwc_layer_1_t)); -+ layer->compositionType = HWC_FRAMEBUFFER_TARGET; -+ layer->hints = 0; -+ layer->flags = 0; -+ layer->handle = 0; -+ layer->transform = 0; -+ layer->blending = HWC_BLENDING_NONE; -+ layer->sourceCrop = r; -+ layer->displayFrame = r; -+ layer->visibleRegionScreen.numRects = 1; -+ layer->visibleRegionScreen.rects = &layer->displayFrame; -+ layer->acquireFenceFd = -1; -+ layer->releaseFenceFd = -1; -+ -+ list->retireFenceFd = -1; -+ list->flags = HWC_GEOMETRY_CHANGED; -+ list->numHwLayers = 2; -+ -+ m_hwNativeWindow = new HWComposer(res.iWidth, res.iHeight, HAL_PIXEL_FORMAT_RGBA_8888, m_hwcDevicePtr, m_bufferList, &list->hwLayers[1]); -+ if (m_hwNativeWindow == NULL) -+ { -+ CLog::Log(LOGERROR, "HWComposer native window failed!"); -+ return false; -+ } -+ m_swNativeWindow = (static_cast (m_hwNativeWindow)); -+ -+ return true; -+#else -+ return false; -+#endif -+} -+ -+bool CEGLNativeTypeHybris::GetNativeDisplay(XBNativeDisplayType **nativeDisplay) const -+{ -+ if (!nativeDisplay) -+ return false; -+ -+ *nativeDisplay = (XBNativeDisplayType*) &m_nativeDisplay; -+ -+ return true; -+} -+ -+bool CEGLNativeTypeHybris::GetNativeWindow(XBNativeWindowType **nativeWindow) const -+{ -+ if (!nativeWindow) -+ return false; -+ -+#if defined(TARGET_HYBRIS) -+ *nativeWindow = (XBNativeWindowType*) &m_swNativeWindow; -+ return (m_swNativeWindow != NULL); -+#else -+ return false; -+#endif -+} -+ -+bool CEGLNativeTypeHybris::DestroyNativeDisplay() -+{ -+ return true; -+} -+ -+bool CEGLNativeTypeHybris::DestroyNativeWindow() -+{ -+ m_nativeWindow = NULL; -+ return true; -+} -+ -+bool CEGLNativeTypeHybris::GetNativeResolution(RESOLUTION_INFO *res) const -+{ -+#if defined(TARGET_HYBRIS) -+ uint32_t configs[5]; -+ size_t numConfigs = 5; -+ -+ int err = m_hwcDevicePtr->getDisplayConfigs(m_hwcDevicePtr, 0, configs, &numConfigs); -+ if (err) { -+ CLog::Log(LOGERROR, "getDisplayConfigs failed!"); -+ return false; -+ } -+ int32_t attr_values[3]; -+ uint32_t attributes[] = { HWC_DISPLAY_WIDTH, HWC_DISPLAY_HEIGHT, HWC_DISPLAY_VSYNC_PERIOD, HWC_DISPLAY_NO_ATTRIBUTE }; -+ -+ m_hwcDevicePtr->getDisplayAttributes(m_hwcDevicePtr, 0, configs[0], attributes, attr_values); -+ -+ res->iWidth = attr_values[0]; -+ res->iHeight = attr_values[1]; -+ res->fRefreshRate = 1000000000 / attr_values[2]; -+ -+ res->dwFlags = D3DPRESENTFLAG_PROGRESSIVE; -+ res->iScreen = 0; -+ res->bFullScreen = true; -+ res->iSubtitles = (int)(0.965 * res->iHeight); -+ res->fPixelRatio = 1.0f; -+ res->iScreenWidth = res->iWidth; -+ res->iScreenHeight = res->iHeight; -+ res->strMode = StringUtils::Format("%dx%d @ %.2f%s - Full Screen", res->iScreenWidth, res->iScreenHeight, res->fRefreshRate, -+ res->dwFlags & D3DPRESENTFLAG_INTERLACED ? "i" : ""); -+ CLog::Log(LOGNOTICE,"Current resolution: %s\n",res->strMode.c_str()); -+ return true; -+#endif -+} -+ -+bool CEGLNativeTypeHybris::SetNativeResolution(const RESOLUTION_INFO &res) -+{ -+ return false; -+} -+ -+bool CEGLNativeTypeHybris::ProbeResolutions(std::vector &resolutions) -+{ -+ RESOLUTION_INFO res; -+ if (GetNativeResolution(&res) && res.iWidth > 1 && res.iHeight > 1) -+ { -+ resolutions.push_back(res); -+ return true; -+ } -+ return false; -+} -+ -+bool CEGLNativeTypeHybris::GetPreferredResolution(RESOLUTION_INFO *res) const -+{ -+ if (GetNativeResolution(res)) -+ return true; -+ return false; -+} -+ -+bool CEGLNativeTypeHybris::ShowWindow(bool show) -+{ -+ return true; -+} -diff --git a/xbmc/windowing/egl/EGLNativeTypeHybris.h b/xbmc/windowing/egl/EGLNativeTypeHybris.h -new file mode 100644 -index 0000000..73aa14d ---- /dev/null -+++ b/xbmc/windowing/egl/EGLNativeTypeHybris.h -@@ -0,0 +1,77 @@ -+#pragma once -+ -+/* -+ * Copyright (C) 2011-2012 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 -+ * . -+ * -+ */ -+ -+#if defined(TARGET_HYBRIS) -+#include -+#include -+#include -+#endif -+ -+#include "EGLNativeType.h" -+#include "threads/Thread.h" -+ -+class HWComposer : public HWComposerNativeWindow -+{ -+ private: -+ hwc_layer_1_t *fblayer; -+ hwc_composer_device_1_t *hwcdevice; -+ hwc_display_contents_1_t **mlist; -+ protected: -+ void present(HWComposerNativeWindowBuffer *buffer); -+ public: -+ HWComposer(unsigned int width, unsigned int height, unsigned int format, hwc_composer_device_1_t *device, hwc_display_contents_1_t **mList, hwc_layer_1_t *layer); -+}; -+ -+class CEGLNativeTypeHybris : public CEGLNativeType -+{ -+public: -+ CEGLNativeTypeHybris(); -+ virtual ~CEGLNativeTypeHybris(); -+ virtual std::string GetNativeName() const { return "hybris"; }; -+ virtual bool CheckCompatibility(); -+ virtual void Initialize(); -+ virtual void Destroy(); -+ virtual int GetQuirks() { return 0; }; -+ -+ 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); -+#if defined(TARGET_HYBRIS) -+private: -+ hw_module_t *m_hwcModule; -+ hwc_display_contents_1_t **m_bufferList; -+ hwc_composer_device_1_t *m_hwcDevicePtr; -+ HWComposerNativeWindow *m_hwNativeWindow; -+ ANativeWindow *m_swNativeWindow; -+#endif -+}; -diff --git a/xbmc/windowing/egl/EGLWrapper.cpp b/xbmc/windowing/egl/EGLWrapper.cpp -index 0074027..526a9fe 100644 ---- a/xbmc/windowing/egl/EGLWrapper.cpp -+++ b/xbmc/windowing/egl/EGLWrapper.cpp -@@ -34,6 +34,10 @@ - #include "EGLNativeTypeIMX.h" - #endif - #include "EGLNativeTypeAmlogic.h" -+#ifdef HAS_HYBRIS -+#include "EGLNativeTypeHybris.h" -+#endif -+#include "EGLNativeTypeFbdev.h" - #include "EGLWrapper.h" - - #define CheckError() m_result = eglGetError(); if(m_result != EGL_SUCCESS) CLog::Log(LOGERROR, "EGL error in %s: %x",__FUNCTION__, m_result); -@@ -94,11 +98,14 @@ bool CEGLWrapper::Initialize(const std::string &implementation) - (nativeGuess = CreateEGLNativeType(implementation)) || - #endif - #if defined(TARGET_RASPBERRY_PI) -- (nativeGuess = CreateEGLNativeType(implementation)) -+ (nativeGuess = CreateEGLNativeType(implementation)) || - #elif defined(HAS_IMXVPU) -- (nativeGuess = CreateEGLNativeType(implementation)) -+ (nativeGuess = CreateEGLNativeType(implementation)) || -+#elif defined(HAS_HYBRIS) -+ (nativeGuess = CreateEGLNativeType(implementation)) || - #else -- (nativeGuess = CreateEGLNativeType(implementation)) -+ (nativeGuess = CreateEGLNativeType(implementation)) || -+ (nativeGuess = CreateEGLNativeType(implementation)) - #endif - ) - { -@@ -420,4 +427,3 @@ bool CEGLWrapper::SurfaceAttrib(EGLDisplay display, EGLSurface surface, EGLint a - return eglSurfaceAttrib(display, surface, attribute, value); - } - #endif -- -diff --git a/xbmc/windowing/egl/Makefile.in b/xbmc/windowing/egl/Makefile.in -index 3754233..c863504 100644 ---- a/xbmc/windowing/egl/Makefile.in -+++ b/xbmc/windowing/egl/Makefile.in -@@ -13,6 +13,10 @@ endif - ifeq (@USE_IMXVPU@,1) - SRCS+= EGLNativeTypeIMX.cpp - endif -+ifeq (@USE_HYBRIS@,1) -+SRCS+= EGLNativeTypeHybris.cpp -+endif -+SRCS+= EGLNativeTypeFbdev.cpp - SRCS+= EGLWrapper.cpp - - LIB = windowing_egl.a +-- +1.9.1 -From b8dec29c61200cc84d4f7bc5cb1fe195daa63a2b Mon Sep 17 00:00:00 2001 -From: Owersun -Date: Tue, 10 May 2016 22:18:03 +0200 -Subject: [PATCH 2/2] Changes missing for native compilation - ---- - m4/xbmc_arch.m4 | 8 +------- - 1 file changed, 1 insertion(+), 7 deletions(-) - -diff --git a/m4/xbmc_arch.m4 b/m4/xbmc_arch.m4 -index 07f1770..b8511d5 100644 ---- a/m4/xbmc_arch.m4 -+++ b/m4/xbmc_arch.m4 -@@ -23,10 +23,7 @@ case $build in - powerpc64-*-linux-gnu*|powerpc64-*-linux-uclibc*) - AC_SUBST(NATIVE_ARCH_DEFINES, "-DTARGET_POSIX -DTARGET_LINUX -D_LINUX -D_POWERPC64") - ;; -- arm*-*-linux-gnu*|arm*-*-linux-uclibc*) -- AC_SUBST(NATIVE_ARCH_DEFINES, "-DTARGET_POSIX -DTARGET_LINUX -D_LINUX") -- ;; -- aarch64-*-linux-gnu*) -+ arm*-*-linux-gnu*|arm*-*-linux-uclibc*|aarch64*-*-linux-gnu*|aarch64*-*-linux-uclibc*) - AC_SUBST(NATIVE_ARCH_DEFINES, "-DTARGET_POSIX -DTARGET_LINUX -D_LINUX") - ;; - *) -@@ -66,9 +63,6 @@ case $host in - arm*-*-linux-gnu*|arm*-*-linux-uclibc*|aarch64*-*-linux-gnu*|aarch64*-*-linux-uclibc*) - AC_SUBST(ARCH_DEFINES, "-DTARGET_POSIX -DTARGET_LINUX -D_LINUX") - ;; -- aarch64-*-linux-gnu*) -- AC_SUBST(ARCH_DEFINES, "-DTARGET_POSIX -DTARGET_LINUX -D_LINUX") -- ;; - mips*-*-linux-gnu*|mips*-*-linux-uclibc*) - AC_SUBST(ARCH_DEFINES, "-DTARGET_POSIX -DTARGET_LINUX -D_LINUX") - ;;