FIX: [stagefright] dyload the whole codec to prevent potential future api breakage
authorChris "koying" Browet <cbro@semperpax.com>
Sat, 27 Jul 2013 09:44:00 +0000 (11:44 +0200)
committerChris "Koying" Browet <cbro@semperpax.com>
Wed, 6 Nov 2013 10:42:53 +0000 (11:42 +0100)
21 files changed:
Makefile.in
configure.in
xbmc/DllPaths_generated_android.h.in
xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp
xbmc/cores/VideoRenderers/LinuxRendererGLES.h
xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h
xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecStageFright.cpp
xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecStageFright.h
xbmc/cores/dvdplayer/DVDCodecs/Video/DllLibStageFrightCodec.h [new file with mode: 0644]
xbmc/cores/dvdplayer/DVDCodecs/Video/Makefile.in
xbmc/cores/dvdplayer/DVDCodecs/Video/StageFrightVideo.cpp [deleted file]
xbmc/cores/dvdplayer/DVDCodecs/Video/StageFrightVideo.h [deleted file]
xbmc/cores/dvdplayer/DVDCodecs/Video/StageFrightVideoPrivate.cpp [deleted file]
xbmc/cores/dvdplayer/DVDCodecs/Video/StageFrightVideoPrivate.h [deleted file]
xbmc/cores/dvdplayer/DVDCodecs/Video/libstagefrightICS/Makefile.in [new file with mode: 0644]
xbmc/cores/dvdplayer/DVDCodecs/Video/libstagefrightICS/StageFrightInterface.cpp [new file with mode: 0644]
xbmc/cores/dvdplayer/DVDCodecs/Video/libstagefrightICS/StageFrightInterface.h [new file with mode: 0644]
xbmc/cores/dvdplayer/DVDCodecs/Video/libstagefrightICS/StageFrightVideo.cpp [new file with mode: 0644]
xbmc/cores/dvdplayer/DVDCodecs/Video/libstagefrightICS/StageFrightVideo.h [new file with mode: 0644]
xbmc/cores/dvdplayer/DVDCodecs/Video/libstagefrightICS/StageFrightVideoPrivate.cpp [new file with mode: 0644]
xbmc/cores/dvdplayer/DVDCodecs/Video/libstagefrightICS/StageFrightVideoPrivate.h [new file with mode: 0644]

index 72acd89..76d6396 100644 (file)
@@ -14,7 +14,11 @@ XBMCTEX_DIRS= \
 
 DVDPCODECS_DIRS= \
        lib \
-       lib/libdvd
+       lib/libdvd 
+
+ifeq (@USE_LIBSTAGEFRIGHT@,1)
+DVDPCODECS_DIRS += xbmc/cores/dvdplayer/DVDCodecs/Video/libstagefrightICS
+endif
 
 DVDPLAYER_ARCHIVES=xbmc/cores/dvdplayer/DVDPlayer.a \
                    xbmc/cores/dvdplayer/DVDCodecs/DVDCodecs.a \
@@ -329,7 +333,7 @@ all : $(FINAL_TARGETS)
 include Makefile.include
 
 .PHONY : dllloader exports visualizations screensavers eventclients papcodecs \
-       dvdpcodecs imagelib codecs externals force skins libaddon check \
+       dvdpcodecs dvdpextcodecs imagelib codecs externals force skins libaddon check \
        testframework testsuite
 
 # hack targets to keep build system up to date
@@ -402,6 +406,14 @@ libaddon: exports
 dvdpcodecs: dllloader
        $(MAKE) -C lib
        $(MAKE) -C lib/libdvd
+
+ifeq (@USE_LIBSTAGEFRIGHT@,1)
+dvdpextcodecs: libxbmc.so 
+       $(MAKE) -C xbmc/cores/dvdplayer/DVDCodecs/Video/libstagefrightICS
+else
+dvdpextcodecs:
+endif
+
 eventclients:
 ifeq ($(findstring osx,@ARCH@), osx)
 ifneq ($(findstring arm,@ARCH@), arm)
@@ -442,7 +454,7 @@ ifeq (@USE_PVR_ADDONS@,1)
        $(MAKE) -C pvr-addons
 endif
 
-codecs: papcodecs dvdpcodecs
+codecs: papcodecs dvdpcodecs dvdpextcodecs
 
 libs: libhdhomerun imagelib libexif system/libcpluff-@ARCH@.so $(CMYTH)
 
index 9b7c7dc..8af09f9 100644 (file)
@@ -39,6 +39,7 @@ AC_DEFUN([XB_ADD_CODEC],
   AC_MSG_CHECKING([for $2])
   case $add_codecs in
     *$2*)
+      use_codec_$2="yes"
       AC_SUBST([USE_$1], 1)
       AC_DEFINE([HAS_$1], 1, [using $2])
       AC_MSG_RESULT([enabling $2])
@@ -1966,7 +1967,6 @@ case $add_codecs in
       XB_ADD_CODEC([LIBAMCODEC], [amcodec])
       ;;
   *libstagefright*)
-      LIBS+="-L${prefix}/opt/android-libs -lstdc++ -lutils -lcutils -lstagefright -lbinder -lui -lgui"
       XB_ADD_CODEC([LIBSTAGEFRIGHT], [libstagefright])
       ;;
   *)
@@ -2564,6 +2564,10 @@ if test "$use_skin_touched" = "yes"; then
 OUTPUT_FILES="$OUTPUT_FILES addons/skin.touched/media/Makefile"
 fi
 
+if test "$use_codec_libstagefright" = "yes"; then
+OUTPUT_FILES="$OUTPUT_FILES xbmc/cores/dvdplayer/DVDCodecs/Video/libstagefrightICS/Makefile"
+fi
+
 OUTPUT_FILES="$OUTPUT_FILES \
   xbmc/interfaces/python/Makefile \
   xbmc/interfaces/python/test/Makefile"
index 4754b5e..e77c1bc 100644 (file)
@@ -73,6 +73,7 @@
 #define DLL_PATH_LIBDVDNAV     "libdvdnav-@ARCH@.so"
 #define DLL_PATH_LIBMPEG2      "@MPEG2_SONAME@"
 #define DLL_PATH_LIBMAD        "@MAD_SONAME@"
+#define DLL_PATH_LIBSTAGEFRIGHTICS    "libXBMCvcodec_stagefrightICS-@ARCH@.so"
 
 /* ffmpeg */
 #define DLL_PATH_LIBAVCODEC    "libavcodec-54-@ARCH@.so"
index 196e460..46f4442 100644 (file)
@@ -68,7 +68,7 @@
 #include <EGL/eglext.h>
 #include "windowing/egl/EGLWrapper.h"
 #include "android/activity/XBMCApp.h"
-#include "DVDCodecs/Video/StageFrightVideo.h"
+#include "DVDCodecs/Video/DVDVideoCodecStageFright.h"
 
 // EGL extension functions
 static PFNEGLCREATEIMAGEKHRPROC eglCreateImageKHR;
@@ -2605,7 +2605,7 @@ void CLinuxRendererGLES::AddProcessor(struct __CVBuffer *cvBufferRef, int index)
 }
 #endif
 #ifdef HAS_LIBSTAGEFRIGHT
-void CLinuxRendererGLES::AddProcessor(CStageFrightVideo* stf, EGLImageKHR eglimg, int index)
+void CLinuxRendererGLES::AddProcessor(CDVDVideoCodecStageFright* stf, EGLImageKHR eglimg, int index)
 {
 #ifdef DEBUG_VERBOSE
   unsigned int time = XbmcThreads::SystemClockMillis();
index 687b7c9..15f7d7b 100644 (file)
@@ -40,7 +40,7 @@ class CBaseTexture;
 namespace Shaders { class BaseYUV2RGBShader; }
 namespace Shaders { class BaseVideoFilterShader; }
 class COpenMaxVideo;
-class CStageFrightVideo;
+class CDVDVideoCodecStageFright;
 class CDVDMediaCodecInfo;
 typedef std::vector<int>     Features;
 
@@ -167,7 +167,7 @@ public:
   virtual void         AddProcessor(struct __CVBuffer *cvBufferRef, int index);
 #endif
 #ifdef HAS_LIBSTAGEFRIGHT
-  virtual void         AddProcessor(CStageFrightVideo* stf, EGLImageKHR eglimg, int index);
+  virtual void         AddProcessor(CDVDVideoCodecStageFright* stf, EGLImageKHR eglimg, int index);
 #endif
 #if defined(TARGET_ANDROID)
   // mediaCodec
@@ -278,7 +278,7 @@ protected:
     struct __CVBuffer *cvBufferRef;
 #endif
 #ifdef HAS_LIBSTAGEFRIGHT
-    CStageFrightVideo* stf;
+    CDVDVideoCodecStageFright* stf;
     EGLImageKHR eglimg;
 #endif
 #if defined(TARGET_ANDROID)
index baee6e0..b78f779 100644 (file)
@@ -38,7 +38,7 @@ namespace VDPAU { class CVdpauRenderPicture; }
 class COpenMax;
 class COpenMaxVideo;
 struct OpenMaxVideoBuffer;
-class CStageFrightVideo;
+class CDVDVideoCodecStageFright;
 class CDVDMediaCodecInfo;
 typedef void* EGLImageKHR;
 
@@ -75,7 +75,7 @@ struct DVDVideoPicture
     };
 
     struct {
-      CStageFrightVideo* stf;
+      CDVDVideoCodecStageFright* stf;
       EGLImageKHR eglimg;
     };
 
index a5d9b17..ee7fbe0 100644 (file)
 #include "settings/Settings.h"
 #include "DVDStreamInfo.h"
 #include "DVDVideoCodecStageFright.h"
-#include "StageFrightVideo.h"
 #include "utils/log.h"
+#include "windowing/WindowingFactory.h"
+#include "settings/AdvancedSettings.h"
+
+#include "DllLibStageFrightCodec.h"
 
 #define CLASSNAME "CDVDVideoCodecStageFright"
 ////////////////////////////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////////////////////////////
+
+DllLibStageFrightCodec*     CDVDVideoCodecStageFright::m_stf_dll = NULL;
+
 CDVDVideoCodecStageFright::CDVDVideoCodecStageFright()
   : CDVDVideoCodec()
-  , m_stf_decoder(NULL), m_converter(NULL), m_convert_bitstream(false)
+  , m_convert_bitstream(false),  m_converter(NULL)
+  , m_stf_handle(NULL)
 {
   m_pFormatName = "stf-xxxx";
+
+  if (!m_stf_dll)
+    m_stf_dll = new DllLibStageFrightCodec;
 }
 
 CDVDVideoCodecStageFright::~CDVDVideoCodecStageFright()
@@ -94,21 +104,18 @@ bool CDVDVideoCodecStageFright::Open(CDVDStreamInfo &hints, CDVDCodecOptions &op
         break;
     }
 
-    m_stf_decoder = new CStageFrightVideo;
-    if (!m_stf_decoder->Open(hints))
+    if (!(m_stf_dll && m_stf_dll->Load()))
+      return false;
+    m_stf_dll->EnableDelayedUnload(false);
+
+    m_stf_handle = m_stf_dll->create_stf(&g_Windowing, &g_advancedSettings);
+
+    if (!m_stf_dll->stf_Open(m_stf_handle, hints))
     {
       CLog::Log(LOGERROR,
           "%s::%s - failed to open, codec(%d), profile(%d), level(%d)",
           CLASSNAME, __func__, hints.codec, hints.profile, hints.level);
-      delete m_stf_decoder;
-      m_stf_decoder = NULL;
-
-      if (m_converter)
-      {
-        m_converter->Close();
-        delete m_converter;
-        m_converter = NULL;
-      }
+      Dispose();
       return false;
     }
 
@@ -126,17 +133,17 @@ void CDVDVideoCodecStageFright::Dispose()
     delete m_converter;
     m_converter = NULL;
   }
-  if (m_stf_decoder)
+  if (m_stf_handle)
   {
-    m_stf_decoder->Close();
-    delete m_stf_decoder;
-    m_stf_decoder = NULL;
+    m_stf_dll->stf_Close(m_stf_handle);
+    m_stf_dll->destroy_stf(m_stf_handle);
+    m_stf_handle = NULL;
   }
 }
 
 void CDVDVideoCodecStageFright::SetDropState(bool bDrop)
 {
-  m_stf_decoder->SetDropState(bDrop);
+  m_stf_dll->stf_SetDropState(m_stf_handle, bDrop);
 }
 
 int CDVDVideoCodecStageFright::Decode(uint8_t *pData, int iSize, double dts, double pts)
@@ -163,29 +170,30 @@ int CDVDVideoCodecStageFright::Decode(uint8_t *pData, int iSize, double dts, dou
   CLog::Log(LOGDEBUG, ">>> decode conversion - tm:%d\n", XbmcThreads::SystemClockMillis() - time);
 #endif
 
-  rtn = m_stf_decoder->Decode(demuxer_content, demuxer_bytes, dts, pts);
+  rtn = m_stf_dll->stf_Decode(m_stf_handle, demuxer_content, demuxer_bytes, dts, pts);
 
   return rtn;
 }
 
 void CDVDVideoCodecStageFright::Reset(void)
 {
-  m_stf_decoder->Reset();
+  m_stf_dll->stf_Reset(m_stf_handle);
 }
 
 bool CDVDVideoCodecStageFright::GetPicture(DVDVideoPicture* pDvdVideoPicture)
 {
-  return m_stf_decoder->GetPicture(pDvdVideoPicture);
+  pDvdVideoPicture->stf = this;
+  return m_stf_dll->stf_GetPicture(m_stf_handle, pDvdVideoPicture);
 }
 
 bool CDVDVideoCodecStageFright::ClearPicture(DVDVideoPicture* pDvdVideoPicture)
 {
-  return m_stf_decoder->ClearPicture(pDvdVideoPicture);
+  return m_stf_dll->stf_ClearPicture(m_stf_handle, pDvdVideoPicture);
 }
 
 void CDVDVideoCodecStageFright::SetSpeed(int iSpeed)
 {
-  m_stf_decoder->SetSpeed(iSpeed);
+  m_stf_dll->stf_SetSpeed(m_stf_handle, iSpeed);
 }
 
 int CDVDVideoCodecStageFright::GetDataSize(void)
@@ -198,4 +206,14 @@ double CDVDVideoCodecStageFright::GetTimeSize(void)
   return 0;
 }
 
+void CDVDVideoCodecStageFright::LockBuffer(EGLImageKHR eglimg)
+{
+  m_stf_dll->stf_LockBuffer(m_stf_handle, eglimg);
+}
+
+void CDVDVideoCodecStageFright::ReleaseBuffer(EGLImageKHR eglimg)
+{
+  m_stf_dll->stf_ReleaseBuffer(m_stf_handle, eglimg);
+}
+
 #endif
index 95e32c6..5289651 100644 (file)
@@ -24,7 +24,8 @@
 #include "DVDVideoCodec.h"
 #include "utils/BitstreamConverter.h"
 
-class CStageFrightVideo;
+class DllLibStageFrightCodec;
+
 class CDVDVideoCodecStageFright : public CDVDVideoCodec
 {
 public:
@@ -45,12 +46,16 @@ public:
   virtual int GetDataSize(void);
   virtual double GetTimeSize(void);
 
+  virtual void LockBuffer(EGLImageKHR eglimg);
+  virtual void ReleaseBuffer(EGLImageKHR eglimg);
+
 protected:
   const char        *m_pFormatName;
-  CStageFrightVideo     *m_stf_decoder;
-
   bool              m_convert_bitstream;
   CBitstreamConverter   *m_converter;
+  
+  static DllLibStageFrightCodec*     m_stf_dll;
+  void *            m_stf_handle;  
 };
 
 #endif
diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DllLibStageFrightCodec.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/DllLibStageFrightCodec.h
new file mode 100644 (file)
index 0000000..442746b
--- /dev/null
@@ -0,0 +1,83 @@
+#pragma once
+
+/*
+ *      Copyright (C) 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
+ *  <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#if (defined HAVE_CONFIG_H) && (!defined TARGET_WINDOWS)
+#include "config.h"
+#endif
+
+#include "DynamicDll.h"
+#include "DVDVideoCodec.h"
+
+class CWinSystemEGL;
+class CAdvancedSettings;
+
+class DllLibStageFrightCodecInterface
+{
+public:
+  virtual ~DllLibStageFrightCodecInterface() {}
+
+  virtual void* create_stf(CWinSystemEGL* windowing, CAdvancedSettings* advsettings)=0;
+  virtual void destroy_stf(void*)=0;
+  
+  virtual bool stf_Open(void*, CDVDStreamInfo &hints) = 0;
+  virtual void stf_Close(void*) = 0;
+  virtual int  stf_Decode(void*, uint8_t *pData, int iSize, double dts, double pts) = 0;
+  virtual void stf_Reset(void*) = 0;
+  virtual bool stf_GetPicture(void*, DVDVideoPicture *pDvdVideoPicture) = 0;
+  virtual bool stf_ClearPicture(void*, DVDVideoPicture* pDvdVideoPicture) = 0;
+  virtual void stf_SetDropState(void*, bool bDrop) = 0;
+  virtual void stf_SetSpeed(void*, int iSpeed) = 0;
+
+  virtual void stf_LockBuffer(void*, EGLImageKHR eglimg) = 0;
+  virtual void stf_ReleaseBuffer(void*, EGLImageKHR eglimg) = 0;
+};
+
+class DllLibStageFrightCodec : public DllDynamic, DllLibStageFrightCodecInterface
+{
+  DECLARE_DLL_WRAPPER(DllLibStageFrightCodec, DLL_PATH_LIBSTAGEFRIGHTICS)
+  DEFINE_METHOD2(void*, create_stf, (CWinSystemEGL* p1, CAdvancedSettings* p2))
+  DEFINE_METHOD1(void, destroy_stf, (void* p1))
+  DEFINE_METHOD2(bool, stf_Open, (void* p1, CDVDStreamInfo &p2))
+  DEFINE_METHOD1(void, stf_Close, (void* p1))
+  DEFINE_METHOD5(int, stf_Decode, (void* p1, uint8_t *p2, int p3, double p4, double p5))
+  DEFINE_METHOD1(void, stf_Reset, (void* p1))
+  DEFINE_METHOD2(bool, stf_GetPicture, (void* p1, DVDVideoPicture * p2))
+  DEFINE_METHOD2(bool, stf_ClearPicture, (void* p1, DVDVideoPicture * p2))
+  DEFINE_METHOD2(void, stf_SetDropState, (void* p1, bool p2))
+  DEFINE_METHOD2(void, stf_SetSpeed, (void* p1, int p2))
+  DEFINE_METHOD2(void, stf_LockBuffer, (void* p1, EGLImageKHR p2))
+  DEFINE_METHOD2(void, stf_ReleaseBuffer, (void* p1, EGLImageKHR p2))
+  BEGIN_METHOD_RESOLVE()
+    RESOLVE_METHOD(create_stf)
+    RESOLVE_METHOD(destroy_stf)
+    RESOLVE_METHOD(stf_Open)
+    RESOLVE_METHOD(stf_Close)
+    RESOLVE_METHOD(stf_Decode)
+    RESOLVE_METHOD(stf_Reset)
+    RESOLVE_METHOD(stf_GetPicture)
+    RESOLVE_METHOD(stf_ClearPicture)
+    RESOLVE_METHOD(stf_SetDropState)
+    RESOLVE_METHOD(stf_SetSpeed)
+    RESOLVE_METHOD(stf_LockBuffer)
+    RESOLVE_METHOD(stf_ReleaseBuffer)
+  END_METHOD_RESOLVE()
+};
index b0819a8..23261f1 100644 (file)
@@ -22,18 +22,6 @@ SRCS += OpenMax.cpp
 SRCS += OpenMaxVideo.cpp
 SRCS += DVDVideoCodecOpenMax.cpp
 endif
-ifeq (@USE_LIBSTAGEFRIGHT@,1)
-SRCS += StageFrightVideo.cpp
-SRCS += StageFrightVideoPrivate.cpp
-SRCS += DVDVideoCodecStageFright.cpp
-INCLUDES += -I${prefix}/opt/android-source/frameworks/base/include
-INCLUDES += -I${prefix}/opt/android-source/frameworks/base/native/include
-INCLUDES += -I${prefix}/opt/android-source/frameworks/base/include/media/stagefright
-INCLUDES += -I${prefix}/opt/android-source/frameworks/base/include/media/stagefright/openmax
-INCLUDES += -I${prefix}/opt/android-source/system/core/include
-INCLUDES += -I${prefix}/opt/android-source/libhardware/include
-endif
-
 ifeq (@USE_LIBAMCODEC@,1)
 SRCS += AMLCodec.cpp
 SRCS += DVDVideoCodecAmlogic.cpp
@@ -44,13 +32,12 @@ endif
 ifeq (@USE_ANDROID@,1)
 SRCS += DVDVideoCodecAndroidMediaCodec.cpp
 endif
+ifeq (@USE_LIBSTAGEFRIGHT@,1)
+SRCS += DVDVideoCodecStageFright.cpp
+endif
 
 LIB=Video.a
 
 include @abs_top_srcdir@/Makefile.include
 -include $(patsubst %.cpp,%.P,$(patsubst %.c,%.P,$(SRCS)))
 
-ifeq (@USE_LIBSTAGEFRIGHT@,1)
-CXXFLAGS += -Wno-multichar -fno-rtti
-endif
-
diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/StageFrightVideo.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/StageFrightVideo.cpp
deleted file mode 100644 (file)
index 4060f3b..0000000
+++ /dev/null
@@ -1,967 +0,0 @@
-/*
- *      Copyright (C) 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
- *  <http://www.gnu.org/licenses/>.
- *
- */
-/***************************************************************************/
-
-//#define DEBUG_VERBOSE 1
-
-#include "system.h"
-#include "system_gl.h"
-
-#include "StageFrightVideo.h"
-#include "StageFrightVideoPrivate.h"
-
-#include "guilib/GraphicContext.h"
-#include "DVDClock.h"
-#include "utils/log.h"
-#include "utils/fastmemcpy.h"
-#include "threads/Thread.h"
-#include "threads/Event.h"
-#include "settings/AdvancedSettings.h"
-
-#include "xbmc/guilib/FrameBufferObject.h"
-
-#include <EGL/egl.h>
-#include <EGL/eglext.h>
-#include "windowing/egl/EGLWrapper.h"
-
-#include <new>
-
-#define OMX_QCOM_COLOR_FormatYVU420SemiPlanar 0x7FA30C00
-#define OMX_TI_COLOR_FormatYUV420PackedSemiPlanar 0x7F000100
-
-#define CLASSNAME "CStageFrightVideo"
-
-#define EGL_NATIVE_BUFFER_ANDROID 0x3140
-#define EGL_IMAGE_PRESERVED_KHR   0x30D2
-
-const char *MEDIA_MIMETYPE_VIDEO_WMV  = "video/x-ms-wmv";
-
-using namespace android;
-
-static int64_t pts_dtoi(double pts)
-{
-  return (int64_t)(pts);
-}
-
-static double pts_itod(int64_t pts)
-{
-  return (double)pts;
-}
-
-/***********************************************************/
-
-class CStageFrightMediaSource : public MediaSource
-{
-public:
-  CStageFrightMediaSource(CStageFrightVideoPrivate *priv, sp<MetaData> meta)
-  {
-    p = priv;
-    source_meta = meta;
-  }
-
-  virtual sp<MetaData> getFormat()
-  {
-    return source_meta;
-  }
-
-  virtual status_t start(MetaData *params)
-  {
-    return OK;
-  }
-
-  virtual status_t stop()
-  {
-    return OK;
-  }
-
-  virtual status_t read(MediaBuffer **buffer,
-                        const MediaSource::ReadOptions *options)
-  {
-    Frame *frame;
-    status_t ret;
-    *buffer = NULL;
-    int64_t time_us = -1;
-    MediaSource::ReadOptions::SeekMode mode;
-
-    if (options && options->getSeekTo(&time_us, &mode))
-    {
-#if defined(DEBUG_VERBOSE)
-      CLog::Log(LOGDEBUG, "%s: reading source(%d): seek:%llu\n", CLASSNAME,p->in_queue.size(), time_us);
-#endif
-    }
-    else
-    {
-#if defined(DEBUG_VERBOSE)
-      CLog::Log(LOGDEBUG, "%s: reading source(%d)\n", CLASSNAME,p->in_queue.size());
-#endif
-    }
-
-    p->in_mutex.lock();
-    while (p->in_queue.empty() && p->decode_thread)
-      p->in_condition.wait(p->in_mutex);
-
-    if (p->in_queue.empty())
-    {
-      p->in_mutex.unlock();
-      return VC_ERROR;
-    }
-
-    std::map<int64_t,Frame*>::iterator it = p->in_queue.begin();
-    frame = it->second;
-    ret = frame->status;
-    *buffer = frame->medbuf;
-
-    p->in_queue.erase(it);
-    p->in_mutex.unlock();
-
-#if defined(DEBUG_VERBOSE)
-    CLog::Log(LOGDEBUG, ">>> exiting reading source(%d); pts:%llu\n", p->in_queue.size(),frame->pts);
-#endif
-
-    free(frame);
-
-    return ret;
-  }
-
-private:
-  sp<MetaData> source_meta;
-  CStageFrightVideoPrivate *p;
-};
-
-/********************************************/
-
-class CStageFrightDecodeThread : public CThread
-{
-protected:
-  CStageFrightVideoPrivate *p;
-
-public:
-  CStageFrightDecodeThread(CStageFrightVideoPrivate *priv)
-  : CThread("CStageFrightDecodeThread")
-  , p(priv)
-  {}
-
-  void OnStartup()
-  {
-  #if defined(DEBUG_VERBOSE)
-    CLog::Log(LOGDEBUG, "%s: entering decode thread\n", CLASSNAME);
-  #endif
-  }
-
-  void OnExit()
-  {
-  #if defined(DEBUG_VERBOSE)
-    CLog::Log(LOGDEBUG, "%s: exited decode thread\n", CLASSNAME);
-  #endif
-  }
-
-  void Process()
-  {
-    Frame* frame;
-    int32_t w, h, dw, dh;
-    int decode_done = 0;
-    int32_t keyframe = 0;
-    int32_t unreadable = 0;
-    MediaSource::ReadOptions readopt;
-    // GLuint texid;
-
-    //SetPriority(THREAD_PRIORITY_ABOVE_NORMAL);
-    do
-    {
-      #if defined(DEBUG_VERBOSE)
-      unsigned int time = XbmcThreads::SystemClockMillis();
-      CLog::Log(LOGDEBUG, "%s: >>> Handling frame\n", CLASSNAME);
-      #endif
-      p->cur_frame = NULL;
-      frame = (Frame*)malloc(sizeof(Frame));
-      if (!frame)
-      {
-        decode_done   = 1;
-        continue;
-      }
-
-      frame->eglimg = EGL_NO_IMAGE_KHR;
-      frame->medbuf = NULL;
-      if (p->resetting)
-      {
-        readopt.setSeekTo(0);
-        p->resetting = false;
-      }
-      frame->status = p->decoder->read(&frame->medbuf, &readopt);
-      readopt.clearSeekTo();
-
-      if (frame->status == OK)
-      {
-        if (!frame->medbuf->graphicBuffer().get())  // hw buffers
-        {
-          if (frame->medbuf->range_length() == 0)
-          {
-            CLog::Log(LOGERROR, "%s - Invalid buffer\n", CLASSNAME);
-            frame->status = VC_ERROR;
-            decode_done   = 1;
-            frame->medbuf->release();
-            frame->medbuf = NULL;
-          }
-          else
-            frame->format = RENDER_FMT_YUV420P;
-        }
-        else
-          frame->format = RENDER_FMT_EGLIMG;
-      }
-
-      if (frame->status == OK)
-      {
-        sp<MetaData> outFormat = p->decoder->getFormat();
-        outFormat->findInt32(kKeyWidth , &w);
-        outFormat->findInt32(kKeyHeight, &h);
-
-        if (!outFormat->findInt32(kKeyDisplayWidth , &dw))
-          dw = w;
-        if (!outFormat->findInt32(kKeyDisplayHeight, &dh))
-          dh = h;
-
-        if (!outFormat->findInt32(kKeyIsSyncFrame, &keyframe))
-          keyframe = 0;
-        if (!outFormat->findInt32(kKeyIsUnreadable, &unreadable))
-          unreadable = 0;
-
-        frame->pts = 0;
-
-        // The OMX.SEC decoder doesn't signal the modified width/height
-        if (p->decoder_component && !strncmp(p->decoder_component, "OMX.SEC", 7) &&
-          (w & 15 || h & 15))
-        {
-          if (((w + 15)&~15) * ((h + 15)&~15) * 3/2 == frame->medbuf->range_length())
-          {
-            w = (w + 15)&~15;
-            h = (h + 15)&~15;
-          }
-        }
-        frame->width = w;
-        frame->height = h;
-        frame->medbuf->meta_data()->findInt64(kKeyTime, &(frame->pts));
-      }
-      else if (frame->status == INFO_FORMAT_CHANGED)
-      {
-        int32_t cropLeft, cropTop, cropRight, cropBottom;
-        sp<MetaData> outFormat = p->decoder->getFormat();
-
-        outFormat->findInt32(kKeyWidth , &p->width);
-        outFormat->findInt32(kKeyHeight, &p->height);
-
-        cropLeft = cropTop = cropRight = cropBottom = 0;
-       if (!outFormat->findRect(kKeyCropRect, &cropLeft, &cropTop, &cropRight, &cropBottom))
-        {
-          p->x = 0;
-          p->y = 0;
-        }
-        else
-        {
-          p->x = cropLeft;
-          p->y = cropTop;
-          p->width = cropRight - cropLeft + 1;
-          p->height = cropBottom - cropTop + 1;
-        }
-        outFormat->findInt32(kKeyColorFormat, &p->videoColorFormat);
-        if (!outFormat->findInt32(kKeyStride, &p->videoStride))
-          p->videoStride = p->width;
-        if (!outFormat->findInt32(kKeySliceHeight, &p->videoSliceHeight))
-          p->videoSliceHeight = p->height;
-
-#if defined(DEBUG_VERBOSE)
-        CLog::Log(LOGDEBUG, ">>> new format col:%d, w:%d, h:%d, sw:%d, sh:%d, ctl:%d,%d; cbr:%d,%d\n", p->videoColorFormat, p->width, p->height, p->videoStride, p->videoSliceHeight, cropTop, cropLeft, cropBottom, cropRight);
-#endif
-
-        if (frame->medbuf)
-          frame->medbuf->release();
-        frame->medbuf = NULL;
-        free(frame);
-        continue;
-      }
-      else
-      {
-        CLog::Log(LOGERROR, "%s - decoding error (%d)\n", CLASSNAME,frame->status);
-        if (frame->medbuf)
-          frame->medbuf->release();
-        frame->medbuf = NULL;
-        free(frame);
-        continue;
-      }
-
-      if (frame->format == RENDER_FMT_EGLIMG)
-      {
-        if (!p->eglInitialized)
-        {
-          p->InitializeEGL(frame->width, frame->height);
-        }
-        else if (p->texwidth != frame->width || p->texheight != frame->height)
-        {
-          p->UninitializeEGL();
-          p->InitializeEGL(frame->width, frame->height);
-        }
-
-        if (p->free_queue.empty())
-        {
-          CLog::Log(LOGERROR, "%s::%s - Error: No free output buffers\n", CLASSNAME, __func__);
-          if (frame->medbuf)
-            frame->medbuf->release();
-          free(frame);
-          continue;
-        }
-
-        ANativeWindowBuffer* graphicBuffer = frame->medbuf->graphicBuffer()->getNativeBuffer();
-        native_window_set_buffers_timestamp(p->mVideoNativeWindow.get(), frame->pts * 1000);
-        int err = p->mVideoNativeWindow.get()->queueBuffer(p->mVideoNativeWindow.get(), graphicBuffer);
-        if (err == 0)
-          frame->medbuf->meta_data()->setInt32(kKeyRendered, 1);
-        frame->medbuf->release();
-        frame->medbuf = NULL;
-        p->UpdateStagefrightTexture();
-
-        if (!p->drop_state)
-        {
-          p->free_mutex.lock();
-          while (!p->free_queue.size())
-            usleep(10000);
-          std::list<std::pair<EGLImageKHR, int> >::iterator itfree = p->free_queue.begin();
-          int cur_slot = itfree->second;
-          p->fbo.BindToTexture(GL_TEXTURE_2D, p->slots[cur_slot].texid);
-          p->fbo.BeginRender();
-
-          glDisable(GL_DEPTH_TEST);
-          //glClear(GL_COLOR_BUFFER_BIT);
-
-          const GLfloat triangleVertices[] = {
-          -1.0f, 1.0f,
-          -1.0f, -1.0f,
-          1.0f, -1.0f,
-          1.0f, 1.0f,
-          };
-
-          glVertexAttribPointer(p->mPositionHandle, 2, GL_FLOAT, GL_FALSE, 0, triangleVertices);
-          glEnableVertexAttribArray(p->mPositionHandle);
-
-          glUseProgram(p->mPgm);
-          glUniform1i(p->mTexSamplerHandle, 0);
-
-          glBindTexture(GL_TEXTURE_EXTERNAL_OES, p->mVideoTextureId);
-
-          GLfloat texMatrix[16];
-          // const GLfloat texMatrix[] = {
-            // 1, 0, 0, 0,
-            // 0, -1, 0, 0,
-            // 0, 0, 1, 0,
-            // 0, 1, 0, 1
-          // };
-          p->GetStagefrightTransformMatrix(texMatrix);
-          glUniformMatrix4fv(p->mTexMatrixHandle, 1, GL_FALSE, texMatrix);
-
-          glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
-
-          glBindTexture(GL_TEXTURE_EXTERNAL_OES, 0);
-          // glDeleteTextures(1, &texid);
-          // eglDestroyImageKHR(p->eglDisplay, img);
-          p->fbo.EndRender();
-
-          glBindTexture(GL_TEXTURE_2D, 0);
-
-          frame->eglimg = p->slots[cur_slot].eglimg;
-          p->busy_queue.push_back(std::pair<EGLImageKHR, int>(*itfree));
-          p->free_queue.erase(itfree);
-          p->free_mutex.unlock();
-        }
-      }
-
-    #if defined(DEBUG_VERBOSE)
-      CLog::Log(LOGDEBUG, "%s: >>> pushed OUT frame; w:%d, h:%d, dw:%d, dh:%d, kf:%d, ur:%d, img:%p, tm:%d\n", CLASSNAME, frame->width, frame->height, dw, dh, keyframe, unreadable, frame->eglimg, XbmcThreads::SystemClockMillis() - time);
-    #endif
-
-      p->out_mutex.lock();
-      p->cur_frame = frame;
-      while (p->cur_frame)
-        p->out_condition.wait(p->out_mutex);
-      p->out_mutex.unlock();
-    }
-    while (!decode_done && !m_bStop);
-
-    if (p->eglInitialized)
-      p->UninitializeEGL();
-
-  }
-};
-
-/***********************************************************/
-
-bool CStageFrightVideo::Open(CDVDStreamInfo &hints)
-{
-#if defined(DEBUG_VERBOSE)
-  CLog::Log(LOGDEBUG, "%s::Open\n", CLASSNAME);
-#endif
-
-  CSingleLock lock(g_graphicsContext);
-
-  // stagefright crashes with null size. Trap this...
-  if (!hints.width || !hints.height)
-  {
-    CLog::Log(LOGERROR, "%s::%s - %s\n", CLASSNAME, __func__,"null size, cannot handle");
-    return false;
-  }
-
-  p = new CStageFrightVideoPrivate;
-  p->width     = hints.width;
-  p->height    = hints.height;
-
-  if (g_advancedSettings.m_stagefrightConfig.useSwRenderer)
-    p->quirks |= QuirkSWRender;
-
-  sp<MetaData> outFormat;
-  int32_t cropLeft, cropTop, cropRight, cropBottom;
-  //Vector<String8> matchingCodecs;
-
-  p->meta = new MetaData;
-  if (p->meta == NULL)
-  {
-    goto fail;
-  }
-
-  const char* mimetype;
-  switch (hints.codec)
-  {
-  case CODEC_ID_H264:
-    if (g_advancedSettings.m_stagefrightConfig.useAVCcodec == 0)
-      return false;
-    mimetype = MEDIA_MIMETYPE_VIDEO_AVC;
-    if ( *(char*)hints.extradata == 1 )
-      p->meta->setData(kKeyAVCC, kTypeAVCC, hints.extradata, hints.extrasize);
-    break;
-  case CODEC_ID_MPEG4:
-    if (g_advancedSettings.m_stagefrightConfig.useMP4codec == 0)
-      return false;
-    mimetype = MEDIA_MIMETYPE_VIDEO_MPEG4;
-    break;
-  case CODEC_ID_MPEG2VIDEO:
-    if (g_advancedSettings.m_stagefrightConfig.useMPEG2codec == 0)
-      return false;
-    mimetype = MEDIA_MIMETYPE_VIDEO_MPEG2;
-    break;
-  case CODEC_ID_VP3:
-  case CODEC_ID_VP6:
-  case CODEC_ID_VP6F:
-  case CODEC_ID_VP8:
-    if (g_advancedSettings.m_stagefrightConfig.useVPXcodec == 0)
-      return false;
-    mimetype = MEDIA_MIMETYPE_VIDEO_VPX;
-    break;
-  case CODEC_ID_VC1:
-  case CODEC_ID_WMV3:
-    if (g_advancedSettings.m_stagefrightConfig.useVC1codec == 0)
-      return false;
-    mimetype = MEDIA_MIMETYPE_VIDEO_WMV;
-    break;
-  default:
-    return false;
-    break;
-  }
-
-  p->meta->setCString(kKeyMIMEType, mimetype);
-  p->meta->setInt32(kKeyWidth, p->width);
-  p->meta->setInt32(kKeyHeight, p->height);
-
-  android::ProcessState::self()->startThreadPool();
-
-  p->source    = new CStageFrightMediaSource(p, p->meta);
-  p->client    = new OMXClient;
-
-  if (p->source == NULL || p->client == NULL)
-  {
-    goto fail;
-  }
-
-  if (p->client->connect() !=  OK)
-  {
-    delete p->client;
-    p->client = NULL;
-    CLog::Log(LOGERROR, "%s::%s - %s\n", CLASSNAME, __func__,"Cannot connect OMX client");
-    goto fail;
-  }
-
-  if ((p->quirks & QuirkSWRender) == 0)
-    p->InitStagefrightSurface();
-
-  p->decoder  = OMXCodec::Create(p->client->interface(), p->meta,
-                                         false, p->source, NULL,
-                                         OMXCodec::kHardwareCodecsOnly | (p->quirks & QuirkSWRender ? OMXCodec::kClientNeedsFramebuffer : 0),
-                                         p->mVideoNativeWindow
-                                         );
-
-  if (!(p->decoder != NULL && p->decoder->start() ==  OK))
-  {
-    p->decoder = NULL;
-    goto fail;
-  }
-
-  outFormat = p->decoder->getFormat();
-
-  if (!outFormat->findInt32(kKeyWidth, &p->width) || !outFormat->findInt32(kKeyHeight, &p->height)
-        || !outFormat->findInt32(kKeyColorFormat, &p->videoColorFormat))
-    goto fail;
-
-  const char *component;
-  if (outFormat->findCString(kKeyDecoderComponent, &component))
-  {
-    CLog::Log(LOGDEBUG, "%s::%s - component: %s\n", CLASSNAME, __func__, component);
-
-    //Blacklist
-    if (!strncmp(component, "OMX.google", 10))
-    {
-      // On some platforms, software decoders are returned anyway
-      CLog::Log(LOGERROR, "%s::%s - %s\n", CLASSNAME, __func__,"Blacklisted component (software)");
-      goto fail;
-    }
-    else if (!strncmp(component, "OMX.Nvidia.mp4.decode", 21) && g_advancedSettings.m_stagefrightConfig.useMP4codec != 1)
-    {
-      // Has issues with some XVID encoded MP4. Only fails after actual decoding starts...
-      CLog::Log(LOGERROR, "%s::%s - %s\n", CLASSNAME, __func__,"Blacklisted component (MP4)");
-      goto fail;
-    }
-  }
-
-  cropLeft = cropTop = cropRight = cropBottom = 0;
-  if (!outFormat->findRect(kKeyCropRect, &cropLeft, &cropTop, &cropRight, &cropBottom))
-  {
-    p->x = 0;
-    p->y = 0;
-  }
-  else
-  {
-    p->x = cropLeft;
-    p->y = cropTop;
-    p->width = cropRight - cropLeft + 1;
-    p->height = cropBottom - cropTop + 1;
-  }
-
-  if (!outFormat->findInt32(kKeyStride, &p->videoStride))
-    p->videoStride = p->width;
-  if (!outFormat->findInt32(kKeySliceHeight, &p->videoSliceHeight))
-    p->videoSliceHeight = p->height;
-
-  for (int i=0; i<INBUFCOUNT; ++i)
-  {
-    p->inbuf[i] = new MediaBuffer(300000);
-    p->inbuf[i]->setObserver(p);
-  }
-
-  p->decode_thread = new CStageFrightDecodeThread(p);
-  p->decode_thread->Create(true /*autodelete*/);
-
-#if defined(DEBUG_VERBOSE)
-  CLog::Log(LOGDEBUG, ">>> format col:%d, w:%d, h:%d, sw:%d, sh:%d, ctl:%d,%d; cbr:%d,%d\n", p->videoColorFormat, p->width, p->height, p->videoStride, p->videoSliceHeight, cropTop, cropLeft, cropBottom, cropRight);
-#endif
-
-  return true;
-
-fail:
-  if (p->decoder != 0)
-    p->decoder->stop();
-  if (p->client)
-  {
-    p->client->disconnect();
-    delete p->client;
-  }
-  if (p->decoder_component)
-    free(&p->decoder_component);
-  if ((p->quirks & QuirkSWRender) == 0)
-    p->UninitStagefrightSurface();
-  return false;
-}
-
-/*** Decode ***/
-int  CStageFrightVideo::Decode(uint8_t *pData, int iSize, double dts, double pts)
-{
-#if defined(DEBUG_VERBOSE)
-  unsigned int time = XbmcThreads::SystemClockMillis();
-  CLog::Log(LOGDEBUG, "%s::Decode - d:%p; s:%d; dts:%f; pts:%f\n", CLASSNAME, pData, iSize, dts, pts);
-#endif
-
-  Frame *frame;
-  int demuxer_bytes = iSize;
-  uint8_t *demuxer_content = pData;
-  int ret = 0;
-
-  if (demuxer_content)
-  {
-    frame = (Frame*)malloc(sizeof(Frame));
-    if (!frame)
-      return VC_ERROR;
-
-    frame->status  = OK;
-    if (g_advancedSettings.m_stagefrightConfig.useInputDTS)
-      frame->pts = (dts != DVD_NOPTS_VALUE) ? pts_dtoi(dts) : ((pts != DVD_NOPTS_VALUE) ? pts_dtoi(pts) : 0);
-    else
-      frame->pts = (pts != DVD_NOPTS_VALUE) ? pts_dtoi(pts) : ((dts != DVD_NOPTS_VALUE) ? pts_dtoi(dts) : 0);
-
-    // No valid pts? libstagefright asserts on this.
-    if (frame->pts < 0)
-    {
-      free(frame);
-      return ret;
-    }
-
-    frame->medbuf = p->getBuffer(demuxer_bytes);
-    if (!frame->medbuf)
-    {
-      free(frame);
-      return VC_ERROR;
-    }
-
-    fast_memcpy(frame->medbuf->data(), demuxer_content, demuxer_bytes);
-    frame->medbuf->meta_data()->clear();
-    frame->medbuf->meta_data()->setInt64(kKeyTime, frame->pts);
-
-    p->in_mutex.lock();
-    p->framecount++;
-    p->in_queue.insert(std::pair<int64_t, Frame*>(p->framecount, frame));
-    p->in_condition.notify();
-    p->in_mutex.unlock();
-  }
-
-  if (p->inputBufferAvailable() && p->in_queue.size() < INBUFCOUNT)
-    ret |= VC_BUFFER;
-  else
-    usleep(1000);
-  if (p->cur_frame != NULL)
-    ret |= VC_PICTURE;
-#if defined(DEBUG_VERBOSE)
-  CLog::Log(LOGDEBUG, "%s::Decode: pushed IN frame (%d); tm:%d\n", CLASSNAME,p->in_queue.size(), XbmcThreads::SystemClockMillis() - time);
-#endif
-
-  return ret;
-}
-
-bool CStageFrightVideo::ClearPicture(DVDVideoPicture* pDvdVideoPicture)
-{
- #if defined(DEBUG_VERBOSE)
-  unsigned int time = XbmcThreads::SystemClockMillis();
-#endif
-  if (pDvdVideoPicture->format == RENDER_FMT_EGLIMG && pDvdVideoPicture->eglimg != EGL_NO_IMAGE_KHR)
-    ReleaseBuffer(pDvdVideoPicture->eglimg);
-
-  if (p->prev_frame) {
-    if (p->prev_frame->medbuf)
-      p->prev_frame->medbuf->release();
-    free(p->prev_frame);
-    p->prev_frame = NULL;
-  }
-#if defined(DEBUG_VERBOSE)
-  CLog::Log(LOGDEBUG, "%s::ClearPicture (%d)\n", CLASSNAME, XbmcThreads::SystemClockMillis() - time);
-#endif
-
-  return true;
-}
-
-bool CStageFrightVideo::GetPicture(DVDVideoPicture* pDvdVideoPicture)
-{
-#if defined(DEBUG_VERBOSE)
-  unsigned int time = XbmcThreads::SystemClockMillis();
-  CLog::Log(LOGDEBUG, "%s::GetPicture\n", CLASSNAME);
-  if (p->cycle_time != 0)
-    CLog::Log(LOGDEBUG, ">>> cycle dur:%d\n", XbmcThreads::SystemClockMillis() - p->cycle_time);
-  p->cycle_time = time;
-#endif
-
-  status_t status;
-
-  p->out_mutex.lock();
-  if (!p->cur_frame)
-  {
-    CLog::Log(LOGERROR, "%s::%s - Error getting frame\n", CLASSNAME, __func__);
-    p->out_condition.notify();
-    p->out_mutex.unlock();
-    return false;
-  }
-
-  Frame *frame = p->cur_frame;
-  status  = frame->status;
-
-  pDvdVideoPicture->format = frame->format;
-  pDvdVideoPicture->dts = DVD_NOPTS_VALUE;
-  pDvdVideoPicture->pts = frame->pts;
-  pDvdVideoPicture->iWidth  = frame->width;
-  pDvdVideoPicture->iHeight = frame->height;
-  pDvdVideoPicture->iDisplayWidth = frame->width;
-  pDvdVideoPicture->iDisplayHeight = frame->height;
-  pDvdVideoPicture->iFlags  = DVP_FLAG_ALLOCATED;
-  pDvdVideoPicture->stf = this;
-  pDvdVideoPicture->eglimg = EGL_NO_IMAGE_KHR;
-
-  if (status != OK)
-  {
-    CLog::Log(LOGERROR, "%s::%s - Error getting picture from frame(%d)\n", CLASSNAME, __func__,status);
-    if (frame->medbuf) {
-      frame->medbuf->release();
-    }
-    free(frame);
-    p->cur_frame = NULL;
-    p->out_condition.notify();
-    p->out_mutex.unlock();
-    return false;
-  }
-
-  if (pDvdVideoPicture->format == RENDER_FMT_EGLIMG)
-  {
-    pDvdVideoPicture->eglimg = frame->eglimg;
-  #if defined(DEBUG_VERBOSE)
-    CLog::Log(LOGDEBUG, ">>> pic dts:%f, pts:%llu, img:%p, tm:%d\n", pDvdVideoPicture->dts, frame->pts, pDvdVideoPicture->eglimg, XbmcThreads::SystemClockMillis() - time);
-  #endif
-  }
-  else if (pDvdVideoPicture->format == RENDER_FMT_YUV420P)
-  {
-    pDvdVideoPicture->color_range  = 0;
-    pDvdVideoPicture->color_matrix = 4;
-
-    unsigned int luma_pixels = frame->width  * frame->height;
-    unsigned int chroma_pixels = luma_pixels/4;
-    uint8_t* data = NULL;
-    if (frame->medbuf && !p->drop_state)
-    {
-      data = (uint8_t*)((long)frame->medbuf->data() + frame->medbuf->range_offset());
-    }
-    switch (p->videoColorFormat)
-    {
-      case OMX_COLOR_FormatYUV420Planar:
-        pDvdVideoPicture->iLineSize[0] = frame->width;
-        pDvdVideoPicture->iLineSize[1] = frame->width / 2;
-        pDvdVideoPicture->iLineSize[2] = frame->width / 2;
-        pDvdVideoPicture->iLineSize[3] = 0;
-        pDvdVideoPicture->data[0] = data;
-        pDvdVideoPicture->data[1] = pDvdVideoPicture->data[0] + luma_pixels;
-        pDvdVideoPicture->data[2] = pDvdVideoPicture->data[1] + chroma_pixels;
-        pDvdVideoPicture->data[3] = 0;
-        break;
-      case OMX_COLOR_FormatYUV420SemiPlanar:
-      case OMX_QCOM_COLOR_FormatYVU420SemiPlanar:
-      case OMX_TI_COLOR_FormatYUV420PackedSemiPlanar:
-        pDvdVideoPicture->iLineSize[0] = frame->width;
-        pDvdVideoPicture->iLineSize[1] = frame->width;
-        pDvdVideoPicture->iLineSize[2] = 0;
-        pDvdVideoPicture->iLineSize[3] = 0;
-        pDvdVideoPicture->data[0] = data;
-        pDvdVideoPicture->data[1] = pDvdVideoPicture->data[0] + luma_pixels;
-        pDvdVideoPicture->data[2] = pDvdVideoPicture->data[1] + chroma_pixels;
-        pDvdVideoPicture->data[3] = 0;
-        break;
-      default:
-        CLog::Log(LOGERROR, "%s::%s - Unsupported color format(%d)\n", CLASSNAME, __func__,p->videoColorFormat);
-    }
-  #if defined(DEBUG_VERBOSE)
-    CLog::Log(LOGDEBUG, ">>> pic pts:%f, data:%p, col:%d, w:%d, h:%d, tm:%d\n", pDvdVideoPicture->pts, data, p->videoColorFormat, frame->width, frame->height, XbmcThreads::SystemClockMillis() - time);
-  #endif
-  }
-
-  if (p->drop_state)
-    pDvdVideoPicture->iFlags |= DVP_FLAG_DROPPED;
-
-  p->prev_frame = p->cur_frame;
-  p->cur_frame = NULL;
-  p->out_condition.notify();
-  p->out_mutex.unlock();
-
-  return true;
-}
-
-void CStageFrightVideo::Close()
-{
-#if defined(DEBUG_VERBOSE)
-  CLog::Log(LOGDEBUG, "%s::Close\n", CLASSNAME);
-#endif
-
-  Frame *frame;
-
-  if (p->decode_thread && p->decode_thread->IsRunning())
-    p->decode_thread->StopThread(false);
-  p->decode_thread = NULL;
-  p->in_condition.notify();
-
-  // Give decoder_thread time to process EOS, if stuck on reading
-  usleep(50000);
-
-#if defined(DEBUG_VERBOSE)
-  CLog::Log(LOGDEBUG, "Cleaning OUT\n");
-#endif
-  p->out_mutex.lock();
-  if (p->cur_frame)
-  {
-    if (p->cur_frame->medbuf)
-      p->cur_frame->medbuf->release();
-    free(p->cur_frame);
-    p->cur_frame = NULL;
-  }
-  p->out_condition.notify();
-  p->out_mutex.unlock();
-
-  if (p->prev_frame)
-  {
-    if (p->prev_frame->medbuf)
-      p->prev_frame->medbuf->release();
-    free(p->prev_frame);
-    p->prev_frame = NULL;
-  }
-
-#if defined(DEBUG_VERBOSE)
-  CLog::Log(LOGDEBUG, "Stopping omxcodec\n");
-#endif
-  p->decoder->stop();
-  p->client->disconnect();
-
-#if defined(DEBUG_VERBOSE)
-  CLog::Log(LOGDEBUG, "Cleaning IN(%d)\n", p->in_queue.size());
-#endif
-  std::map<int64_t,Frame*>::iterator it;
-  while (!p->in_queue.empty())
-  {
-    it = p->in_queue.begin();
-    frame = it->second;
-    p->in_queue.erase(it);
-    if (frame->medbuf)
-      frame->medbuf->release();
-    free(frame);
-  }
-
-  if (p->decoder_component)
-    free(&p->decoder_component);
-
-  delete p->client;
-
-  if ((p->quirks & QuirkSWRender) == 0)
-    p->UninitStagefrightSurface();
-
-  for (int i=0; i<INBUFCOUNT; ++i)
-  {
-    p->inbuf[i]->setObserver(NULL);
-    p->inbuf[i]->release();
-  }
-
-  delete p;
-}
-
-void CStageFrightVideo::Reset(void)
-{
-#if defined(DEBUG_VERBOSE)
-  CLog::Log(LOGDEBUG, "%s::Reset\n", CLASSNAME);
-#endif
-  Frame* frame;
-  p->in_mutex.lock();
-  std::map<int64_t,Frame*>::iterator it;
-  while (!p->in_queue.empty())
-  {
-    it = p->in_queue.begin();
-    frame = it->second;
-    p->in_queue.erase(it);
-    if (frame->medbuf)
-      frame->medbuf->release();
-    free(frame);
-  }
-  p->resetting = true;
-  p->framecount = 0;
-
-  p->in_mutex.unlock();
-}
-
-void CStageFrightVideo::SetDropState(bool bDrop)
-{
-  if (bDrop == p->drop_state)
-    return;
-
-#if defined(DEBUG_VERBOSE)
-  CLog::Log(LOGDEBUG, "%s::SetDropState (%d->%d)\n", CLASSNAME,p->drop_state,bDrop);
-#endif
-
-  p->drop_state = bDrop;
-}
-
-void CStageFrightVideo::SetSpeed(int iSpeed)
-{
-}
-
-/***************/
-
-void CStageFrightVideo::LockBuffer(EGLImageKHR eglimg)
-{
- #if defined(DEBUG_VERBOSE)
-  unsigned int time = XbmcThreads::SystemClockMillis();
-#endif
-  p->free_mutex.lock();
-  std::list<std::pair<EGLImageKHR, int> >::iterator it = p->free_queue.begin();
-  for(;it != p->free_queue.end(); ++it)
-  {
-    if ((*it).first == eglimg)
-      break;
-  }
-  if (it == p->free_queue.end())
-  {
-    p->busy_queue.push_back(std::pair<EGLImageKHR, int>(*it));
-    p->free_mutex.unlock();
-    return;
-  }
-#if defined(DEBUG_VERBOSE)
-  CLog::Log(LOGDEBUG, "Locking %p: tm:%d\n", eglimg, XbmcThreads::SystemClockMillis() - time);
-#endif
-
-  p->busy_queue.push_back(std::pair<EGLImageKHR, int>(*it));
-  p->free_queue.erase(it);
-  p->free_mutex.unlock();
-}
-
-void CStageFrightVideo::ReleaseBuffer(EGLImageKHR eglimg)
-{
- #if defined(DEBUG_VERBOSE)
-  unsigned int time = XbmcThreads::SystemClockMillis();
-#endif
-  p->free_mutex.lock();
-  int cnt = 0;
-  std::list<std::pair<EGLImageKHR, int> >::iterator it = p->busy_queue.begin();
-  std::list<std::pair<EGLImageKHR, int> >::iterator itfree;
-  for(;it != p->busy_queue.end(); ++it)
-  {
-    if ((*it).first == eglimg)
-    {
-      cnt++;
-      if (cnt==1)
-        itfree = it;
-      else
-        break;
-    }
-  }
-  if (it == p->busy_queue.end() && !cnt)
-  {
-    p->free_mutex.unlock();
-    return;
-  }
-#if defined(DEBUG_VERBOSE)
-  CLog::Log(LOGDEBUG, "Unlocking %p: tm:%d\n", eglimg, XbmcThreads::SystemClockMillis() - time);
-#endif
-
-  if (cnt==1)
-  {
-    p->free_queue.push_back(std::pair<EGLImageKHR, int>(*itfree));
-    p->busy_queue.erase(itfree);
-  }
-  p->free_mutex.unlock();
-}
diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/StageFrightVideo.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/StageFrightVideo.h
deleted file mode 100644 (file)
index 7e3cfd5..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-#pragma once
-/*
- *      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
- *  <http://www.gnu.org/licenses/>.
- *
- */
-
-#if defined(HAS_LIBSTAGEFRIGHT)
-
-#include "cores/dvdplayer/DVDStreamInfo.h"
-#include "DVDVideoCodec.h"
-
-class CStageFrightVideoPrivate;
-
-namespace android { class MediaBuffer; }
-
-class CStageFrightVideo
-{
-public:
-  CStageFrightVideo() {};
-  virtual ~CStageFrightVideo() {};
-
-  bool Open(CDVDStreamInfo &hints);
-  void Close(void);
-  int  Decode(uint8_t *pData, int iSize, double dts, double pts);
-  void Reset(void);
-  bool GetPicture(DVDVideoPicture *pDvdVideoPicture);
-  bool ClearPicture(DVDVideoPicture* pDvdVideoPicture);
-  void SetDropState(bool bDrop);
-  virtual void SetSpeed(int iSpeed);
-
-  void LockBuffer(EGLImageKHR eglimg);
-  void ReleaseBuffer(EGLImageKHR eglimg);
-
-private:
-  CStageFrightVideoPrivate* p;
-};
-
-// defined(HAS_LIBSTAGEFRIGHT)
-#endif
diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/StageFrightVideoPrivate.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/StageFrightVideoPrivate.cpp
deleted file mode 100644 (file)
index 996a38d..0000000
+++ /dev/null
@@ -1,356 +0,0 @@
-/*
- *      Copyright (C) 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
- *  <http://www.gnu.org/licenses/>.
- *
- */
-/***************************************************************************/
-
-#include "StageFrightVideoPrivate.h"
-
-#include <EGL/egl.h>
-#include <EGL/eglext.h>
-#include <GLES2/gl2.h>
-#include <GLES2/gl2ext.h>
-#include "windowing/egl/EGLWrapper.h"
-#include "windowing/WindowingFactory.h"
-#include "utils/log.h"
-
-#include "android/jni/Surface.h"
-#include "android/jni/SurfaceTexture.h"
-
-GLint glerror;
-#define CheckEglError(x) while((glerror = eglGetError()) != EGL_SUCCESS) CLog::Log(LOGERROR, "EGL error in %s: %x",x, glerror);
-#define CheckGlError(x)  while((glerror = glGetError()) != GL_NO_ERROR) CLog::Log(LOGERROR, "GL error in %s: %x",x, glerror);
-
-// EGL extension functions
-static PFNEGLCREATEIMAGEKHRPROC eglCreateImageKHR;
-static PFNEGLDESTROYIMAGEKHRPROC eglDestroyImageKHR;
-static PFNGLEGLIMAGETARGETTEXTURE2DOESPROC glEGLImageTargetTexture2DOES;
-
-int NP2( unsigned x ) {
-  --x;
-  x |= x >> 1;
-  x |= x >> 2;
-  x |= x >> 4;
-  x |= x >> 8;
-  x |= x >> 16;
-  return ++x;
-}
-
-CStageFrightVideoPrivate::CStageFrightVideoPrivate()
-    : decode_thread(NULL), source(NULL)
-    , eglDisplay(EGL_NO_DISPLAY), eglSurface(EGL_NO_SURFACE), eglContext(EGL_NO_CONTEXT)
-    , eglInitialized(false)
-    , framecount(0)
-    , quirks(QuirkNone), cur_frame(NULL), prev_frame(NULL)
-    , width(-1), height(-1)
-    , texwidth(-1), texheight(-1)
-    , client(NULL), decoder(NULL), decoder_component(NULL)
-    , drop_state(false), resetting(false)
-    , mVideoNativeWindow(NULL)
-{
-  if (!eglCreateImageKHR)
-    eglCreateImageKHR = (PFNEGLCREATEIMAGEKHRPROC) CEGLWrapper::GetProcAddress("eglCreateImageKHR");
-  if (!eglDestroyImageKHR)
-    eglDestroyImageKHR = (PFNEGLDESTROYIMAGEKHRPROC) CEGLWrapper::GetProcAddress("eglDestroyImageKHR");
-  if (!glEGLImageTargetTexture2DOES)
-    glEGLImageTargetTexture2DOES = (PFNGLEGLIMAGETARGETTEXTURE2DOESPROC) CEGLWrapper::GetProcAddress("glEGLImageTargetTexture2DOES");
-}
-
-void CStageFrightVideoPrivate::signalBufferReturned(MediaBuffer *buffer)
-{
-}
-
-MediaBuffer* CStageFrightVideoPrivate::getBuffer(size_t size)
-{
-  int i=0;
-  for (; i<INBUFCOUNT; ++i)
-    if (inbuf[i]->refcount() == 0 && inbuf[i]->size() >= size)
-      break;
-  if (i == INBUFCOUNT)
-  {
-    i = 0;
-    for (; i<INBUFCOUNT; ++i)
-      if (inbuf[i]->refcount() == 0)
-        break;
-    if (i == INBUFCOUNT)
-      return NULL;
-    inbuf[i]->setObserver(NULL);
-    inbuf[i]->release();
-    inbuf[i] = new MediaBuffer(size);
-    inbuf[i]->setObserver(this);
-  }
-
-  inbuf[i]->add_ref();
-  inbuf[i]->set_range(0, size);
-  return inbuf[i];
-}
-
-bool CStageFrightVideoPrivate::inputBufferAvailable()
-{
-  for (int i=0; i<INBUFCOUNT; ++i)
-    if (inbuf[i]->refcount() == 0)
-      return true;
-
-  return false;
-}
-
-void CStageFrightVideoPrivate::loadOESShader(GLenum shaderType, const char* pSource, GLuint* outShader)
-{
-#if defined(DEBUG_VERBOSE)
-  CLog::Log(LOGDEBUG, ">>loadOESShader\n");
-#endif
-
-  GLuint shader = glCreateShader(shaderType);
-  CheckGlError("loadOESShader");
-  if (shader) {
-    glShaderSource(shader, 1, &pSource, NULL);
-    glCompileShader(shader);
-    GLint compiled = 0;
-    glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
-    if (!compiled) {
-      GLint infoLen = 0;
-      glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen);
-      if (infoLen) {
-        char* buf = (char*) malloc(infoLen);
-        if (buf) {
-          glGetShaderInfoLog(shader, infoLen, NULL, buf);
-          printf("Shader compile log:\n%s\n", buf);
-          free(buf);
-        }
-      } else {
-        char* buf = (char*) malloc(0x1000);
-        if (buf) {
-          glGetShaderInfoLog(shader, 0x1000, NULL, buf);
-          printf("Shader compile log:\n%s\n", buf);
-          free(buf);
-        }
-      }
-      glDeleteShader(shader);
-      shader = 0;
-    }
-  }
-  *outShader = shader;
-}
-
-void CStageFrightVideoPrivate::createOESProgram(const char* pVertexSource, const char* pFragmentSource, GLuint* outPgm)
-{
-#if defined(DEBUG_VERBOSE)
-  CLog::Log(LOGDEBUG, ">>createOESProgram\n");
-#endif
-  GLuint vertexShader, fragmentShader;
-  {
-    loadOESShader(GL_VERTEX_SHADER, pVertexSource, &vertexShader);
-  }
-  {
-    loadOESShader(GL_FRAGMENT_SHADER, pFragmentSource, &fragmentShader);
-  }
-
-  GLuint program = glCreateProgram();
-  if (program) {
-    glAttachShader(program, vertexShader);
-    glAttachShader(program, fragmentShader);
-    glLinkProgram(program);
-    GLint linkStatus = GL_FALSE;
-    glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
-    if (linkStatus != GL_TRUE) {
-      GLint bufLength = 0;
-      glGetProgramiv(program, GL_INFO_LOG_LENGTH, &bufLength);
-      if (bufLength) {
-        char* buf = (char*) malloc(bufLength);
-        if (buf) {
-          glGetProgramInfoLog(program, bufLength, NULL, buf);
-          printf("Program link log:\n%s\n", buf);
-          free(buf);
-        }
-      }
-      glDeleteProgram(program);
-      program = 0;
-    }
-  }
-  glDeleteShader(vertexShader);
-  glDeleteShader(fragmentShader);
-  *outPgm = program;
-}
-
-void CStageFrightVideoPrivate::OES_shader_setUp()
-{
-
-  const char vsrc[] =
-  "attribute vec4 vPosition;\n"
-  "varying vec2 texCoords;\n"
-  "uniform mat4 texMatrix;\n"
-  "void main() {\n"
-  "  vec2 vTexCoords = 0.5 * (vPosition.xy + vec2(1.0, 1.0));\n"
-  "  texCoords = (texMatrix * vec4(vTexCoords, 0.0, 1.0)).xy;\n"
-  "  gl_Position = vPosition;\n"
-  "}\n";
-
-  const char fsrc[] =
-  "#extension GL_OES_EGL_image_external : require\n"
-  "precision mediump float;\n"
-  "uniform samplerExternalOES texSampler;\n"
-  "varying vec2 texCoords;\n"
-  "void main() {\n"
-  "  gl_FragColor = texture2D(texSampler, texCoords);\n"
-  "}\n";
-
-  {
-  #if defined(DEBUG_VERBOSE)
-    CLog::Log(LOGDEBUG, ">>OES_shader_setUp\n");
-  #endif
-    CheckGlError("OES_shader_setUp");
-    createOESProgram(vsrc, fsrc, &mPgm);
-  }
-
-  mPositionHandle = glGetAttribLocation(mPgm, "vPosition");
-  mTexSamplerHandle = glGetUniformLocation(mPgm, "texSampler");
-  mTexMatrixHandle = glGetUniformLocation(mPgm, "texMatrix");
-}
-
-void CStageFrightVideoPrivate::InitializeEGL(int w, int h)
-{
-  texwidth = w;
-  texheight = h;
-  if (!g_Windowing.IsExtSupported("GL_TEXTURE_NPOT"))
-  {
-    texwidth  = NP2(texwidth);
-    texheight = NP2(texheight);
-  }
-
-  eglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
-  eglBindAPI(EGL_OPENGL_ES_API);
-  EGLint contextAttributes[] = {
-    EGL_CONTEXT_CLIENT_VERSION, 2,
-    EGL_NONE
-  };
-  eglContext = eglCreateContext(eglDisplay, g_Windowing.GetEGLConfig(), EGL_NO_CONTEXT, contextAttributes);
-  EGLint pbufferAttribs[] = {
-    EGL_WIDTH, texwidth,
-    EGL_HEIGHT, texheight,
-    EGL_NONE
-  };
-  eglSurface = eglCreatePbufferSurface(eglDisplay, g_Windowing.GetEGLConfig(), pbufferAttribs);
-  eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglContext);
-  CheckGlError("stf init");
-
-  static const EGLint imageAttributes[] = {
-    EGL_IMAGE_PRESERVED_KHR, EGL_FALSE,
-    EGL_GL_TEXTURE_LEVEL_KHR, 0,
-    EGL_NONE
-  };
-
-  for (int i=0; i<NUMFBOTEX; ++i)
-  {
-    glGenTextures(1, &(slots[i].texid));
-    glBindTexture(GL_TEXTURE_2D,  slots[i].texid);
-
-    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texwidth, texheight, 0,
-           GL_RGBA, GL_UNSIGNED_BYTE, 0);
-
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-    // This is necessary for non-power-of-two textures
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-
-    slots[i].eglimg = eglCreateImageKHR(eglDisplay, eglContext, EGL_GL_TEXTURE_2D_KHR, (EGLClientBuffer)(slots[i].texid),imageAttributes);
-    free_queue.push_back(std::pair<EGLImageKHR, int>(slots[i].eglimg, i));
-
-  }
-  glBindTexture(GL_TEXTURE_2D,  0);
-
-  fbo.Initialize();
-  OES_shader_setUp();
-
-  eglInitialized = true;
-#if defined(DEBUG_VERBOSE)
-  CLog::Log(LOGDEBUG, "%s: >>> Initialized EGL: w:%d; h:%d\n", CLASSNAME, texwidth, texheight);
-#endif
-}
-
-void CStageFrightVideoPrivate::UninitializeEGL()
-{
-  fbo.Cleanup();
-  for (int i=0; i<NUMFBOTEX; ++i)
-  {
-    glDeleteTextures(1, &(slots[i].texid));
-    eglDestroyImageKHR(eglDisplay, slots[i].eglimg);
-  }
-
-  if (eglContext != EGL_NO_CONTEXT)
-    eglDestroyContext(eglDisplay, eglContext);
-  eglContext = EGL_NO_CONTEXT;
-
-  if (eglSurface != EGL_NO_SURFACE)
-    eglDestroySurface(eglDisplay, eglSurface);
-  eglSurface = EGL_NO_SURFACE;
-
-  eglInitialized = false;
-}
-
-bool CStageFrightVideoPrivate::InitStagefrightSurface()
-{
-   if (mVideoNativeWindow != NULL)
-    return true;
-
-  JNIEnv* env = xbmc_jnienv();
-
-  mVideoTextureId = -1;
-
-  glGenTextures(1, &mVideoTextureId);
-  glBindTexture(GL_TEXTURE_EXTERNAL_OES, mVideoTextureId);
-  glTexParameterf(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-  glTexParameterf(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-  glTexParameterf(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
-  glTexParameterf(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-  glBindTexture(GL_TEXTURE_EXTERNAL_OES, 0);
-
-  mSurfTexture = new CJNISurfaceTexture(mVideoTextureId);
-  mSurface = new CJNISurface(*mSurfTexture);
-
-  mVideoNativeWindow = ANativeWindow_fromSurface(env, mSurface->get_raw());
-  native_window_api_connect(mVideoNativeWindow.get(), NATIVE_WINDOW_API_MEDIA);
-
-  return true;
-}
-
-void CStageFrightVideoPrivate::UninitStagefrightSurface()
-{
-  if (mVideoNativeWindow == NULL)
-    return;
-
-  native_window_api_disconnect(mVideoNativeWindow.get(), NATIVE_WINDOW_API_MEDIA);
-  ANativeWindow_release(mVideoNativeWindow.get());
-  mVideoNativeWindow = NULL;
-
-  delete mSurface;
-  delete mSurfTexture;
-
-  glDeleteTextures(1, &mVideoTextureId);
-}
-
-void CStageFrightVideoPrivate::UpdateStagefrightTexture()
-{
-  mSurfTexture->updateTexImage();
-}
-
-void CStageFrightVideoPrivate::GetStagefrightTransformMatrix(float* transformMatrix)
-{
-    mSurfTexture->getTransformMatrix(transformMatrix);
-}
-
diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/StageFrightVideoPrivate.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/StageFrightVideoPrivate.h
deleted file mode 100644 (file)
index 2f9886f..0000000
+++ /dev/null
@@ -1,160 +0,0 @@
-#pragma once
-/*
- *      Copyright (C) 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
- *  <http://www.gnu.org/licenses/>.
- *
- */
-/***************************************************************************/
-
-#include "threads/Thread.h"
-#include "xbmc/guilib/FrameBufferObject.h"
-#include "cores/VideoRenderers/RenderFormats.h"
-
-#include <android/native_window.h>
-#include <android/native_window_jni.h>
-
-#include <media/stagefright/MetaData.h>
-#include <media/stagefright/MediaBuffer.h>
-#include <media/stagefright/MediaBufferGroup.h>
-#include <media/stagefright/MediaDefs.h>
-#include <media/stagefright/MediaSource.h>
-
-#include <binder/ProcessState.h>
-#include <media/stagefright/OMXClient.h>
-#include <media/stagefright/OMXCodec.h>
-#include <media/stagefright/foundation/ABuffer.h>
-#include <utils/List.h>
-#include <utils/RefBase.h>
-#include <ui/GraphicBuffer.h>
-#include <ui/PixelFormat.h>
-#include <gui/SurfaceTexture.h>
-
-#include "system_gl.h"
-
-#include <map>
-#include <list>
-
-#define NUMFBOTEX 4
-#define INBUFCOUNT 16
-
-class CStageFrightDecodeThread;
-class CJNISurface;
-class CJNISurfaceTexture;
-
-using namespace android;
-
-struct tex_slot
-{
-  GLuint texid;
-  EGLImageKHR eglimg;
-};
-
-struct Frame
-{
-  status_t status;
-  int32_t width, height;
-  int64_t pts;
-  ERenderFormat format;
-  EGLImageKHR eglimg;
-  MediaBuffer* medbuf;
-};
-
-enum StageFrightQuirks
-{
-  QuirkNone = 0,
-  QuirkSWRender = 0x01,
-};
-
-class CStageFrightVideoPrivate : public MediaBufferObserver
-{
-public:
-  CStageFrightVideoPrivate();
-
-  virtual void signalBufferReturned(MediaBuffer *buffer);
-
-  MediaBuffer* getBuffer(size_t size);
-  bool inputBufferAvailable();
-
-  void loadOESShader(GLenum shaderType, const char* pSource, GLuint* outShader);
-  void createOESProgram(const char* pVertexSource, const char* pFragmentSource, GLuint* outPgm);
-  void OES_shader_setUp();
-  void InitializeEGL(int w, int h);
-  void UninitializeEGL();
-
-public:
-  CStageFrightDecodeThread* decode_thread;
-
-  sp<MediaSource> source;
-
-  MediaBuffer* inbuf[INBUFCOUNT];
-
-  GLuint mPgm;
-  GLint mPositionHandle;
-  GLint mTexSamplerHandle;
-  GLint mTexMatrixHandle;
-
-  CFrameBufferObject fbo;
-  EGLDisplay eglDisplay;
-  EGLSurface eglSurface;
-  EGLContext eglContext;
-  bool eglInitialized;
-
-  tex_slot slots[NUMFBOTEX];
-  std::list< std::pair<EGLImageKHR, int> > free_queue;
-  std::list< std::pair<EGLImageKHR, int> > busy_queue;
-
-  sp<MetaData> meta;
-  int64_t framecount;
-  std::map<int64_t, Frame*> in_queue;
-  std::map<int64_t, Frame*> out_queue;
-  CCriticalSection in_mutex;
-  CCriticalSection out_mutex;
-  CCriticalSection free_mutex;
-  XbmcThreads::ConditionVariable in_condition;
-  XbmcThreads::ConditionVariable out_condition;
-
-  int quirks;
-  Frame *cur_frame;
-  Frame *prev_frame;
-  bool source_done;
-  int x, y;
-  int width, height;
-  int texwidth, texheight;
-
-  OMXClient *client;
-  sp<MediaSource> decoder;
-  const char *decoder_component;
-  int videoColorFormat;
-  int videoStride;
-  int videoSliceHeight;
-
-  bool drop_state;
-  bool resetting;
-#if defined(DEBUG_VERBOSE)
-  unsigned int cycle_time;
-#endif
-
-  unsigned int mVideoTextureId;
-  CJNISurfaceTexture* mSurfTexture;
-  CJNISurface* mSurface;
-  sp<ANativeWindow> mVideoNativeWindow;
-
-  bool InitStagefrightSurface();
-  void UninitStagefrightSurface();
-  void UpdateStagefrightTexture();
-  void GetStagefrightTransformMatrix(float* transformMatrix);
-};
diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/libstagefrightICS/Makefile.in b/xbmc/cores/dvdplayer/DVDCodecs/Video/libstagefrightICS/Makefile.in
new file mode 100644 (file)
index 0000000..81d7b6e
--- /dev/null
@@ -0,0 +1,49 @@
+ARCH=@ARCH@
+
+INCLUDES+=-I@abs_top_srcdir@/xbmc/cores/dvdplayer
+INCLUDES+=-I..
+
+SRCS += StageFrightInterface.cpp
+SRCS += StageFrightVideo.cpp
+SRCS += StageFrightVideoPrivate.cpp
+INCLUDES += -I${prefix}/opt/android-source/frameworks/base/include
+INCLUDES += -I${prefix}/opt/android-source/frameworks/base/native/include
+INCLUDES += -I${prefix}/opt/android-source/frameworks/base/include/media/stagefright
+INCLUDES += -I${prefix}/opt/android-source/frameworks/base/include/media/stagefright/openmax
+INCLUDES += -I${prefix}/opt/android-source/system/core/include
+INCLUDES += -I${prefix}/opt/android-source/libhardware/include
+
+LIBNAME=libXBMCvcodec_stagefrightICS
+LIB_SHARED=@abs_top_srcdir@/system/players/dvdplayer/$(LIBNAME)-$(ARCH).so
+
+LIBS += -landroid -lEGL -lGLESv2 -L${prefix}/opt/android-libs -lstdc++ -lutils -lcutils -lstagefright -lbinder -lui -lgui -L@abs_top_srcdir@ -lxbmc
+
+all: $(LIB_SHARED)
+
+include @abs_top_srcdir@/Makefile.include
+-include $(patsubst %.cpp,%.P,$(patsubst %.c,%.P,$(SRCS)))
+
+JNICXXFLAGS = $(CXXFLAGS) -std=gnu++0x -Wextra
+STFCXXFLAGS = $(CXXFLAGS) -Wno-multichar -fno-rtti -fPIC
+
+$(LIB_SHARED): $(OBJS)
+       $(CXX) $(STFCXXFLAGS) $(LDFLAGS) -shared -Wl,-no-undefined -g -o $(LIB_SHARED) $(OBJS) $(LIBS)
+
+StageFrightVideo.o: StageFrightVideo.cpp
+       $(CXX) -MF $*.d -MD -c $(STFCXXFLAGS) $(DEFINES) $(INCLUDES) $< -o $@
+
+StageFrightVideoPrivate.o: StageFrightVideoPrivate.cpp
+       $(CXX) -MF $*.d -MD -c $(STFCXXFLAGS) $(DEFINES) $(INCLUDES) $< -o $@
+
+Surface.o: Surface.cpp
+       $(CXX) -MF $*.d -MD -c $(JNICXXFLAGS) $(DEFINES) $(INCLUDES) $< -o $@
+
+SurfaceTexture.o: SurfaceTexture.cpp
+       $(CXX) -MF $*.d -MD -c $(JNICXXFLAGS) $(DEFINES) $(INCLUDES) $< -o $@
+
+CLEAN_FILES = \
+       $(LIB_SHARED) \
+
+DISTCLEAN_FILES= \
+       Makefile \
+
diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/libstagefrightICS/StageFrightInterface.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/libstagefrightICS/StageFrightInterface.cpp
new file mode 100644 (file)
index 0000000..b2305d7
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ *      Copyright (C) 2013 Team XBMC
+ *      http://xbmc.org
+ *
+ *  This Program is free software; you can redistfribute 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 distfributed 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
+ *  <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "StageFrightInterface.h"
+#include "StageFrightVideo.h"
+
+#include "windowing/WindowingFactory.h"
+#include "settings/AdvancedSettings.h"
+
+void* create_stf(CWinSystemEGL* windowing, CAdvancedSettings* advsettings)
+{
+  return (void*)new CStageFrightVideo(windowing, advsettings);
+}
+
+void destroy_stf(void* stf)
+{
+  delete (CStageFrightVideo*)stf;
+}
+
+bool stf_Open(void* stf, CDVDStreamInfo &hints)
+{
+  return ((CStageFrightVideo*)stf)->Open(hints);
+}
+
+void stf_Close(void* stf)
+{
+  ((CStageFrightVideo*)stf)->Close();
+}
+
+int  stf_Decode(void* stf, uint8_t *pData, int iSize, double dts, double pts)
+{
+  return ((CStageFrightVideo*)stf)->Decode(pData, iSize, dts, pts);
+}
+
+void stf_Reset(void* stf)
+{
+  ((CStageFrightVideo*)stf)->Reset();
+}
+
+bool stf_GetPicture(void* stf, DVDVideoPicture *pDvdVideoPicture)
+{
+  return ((CStageFrightVideo*)stf)->GetPicture(pDvdVideoPicture);
+}
+
+bool stf_ClearPicture(void* stf, DVDVideoPicture* pDvdVideoPicture)
+{
+  return ((CStageFrightVideo*)stf)->ClearPicture(pDvdVideoPicture);
+}
+
+void stf_SetDropState(void* stf, bool bDrop)
+{
+  ((CStageFrightVideo*)stf)->SetDropState(bDrop);
+}
+
+void stf_SetSpeed(void* stf, int iSpeed)
+{
+  ((CStageFrightVideo*)stf)->SetSpeed(iSpeed);
+}
+
+void stf_LockBuffer(void* stf, EGLImageKHR eglimg)
+{
+  ((CStageFrightVideo*)stf)->LockBuffer(eglimg);
+}
+
+void stf_ReleaseBuffer(void* stf, EGLImageKHR eglimg)
+{
+  ((CStageFrightVideo*)stf)->ReleaseBuffer(eglimg);
+}
+
diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/libstagefrightICS/StageFrightInterface.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/libstagefrightICS/StageFrightInterface.h
new file mode 100644 (file)
index 0000000..6c4eebf
--- /dev/null
@@ -0,0 +1,45 @@
+#pragma once
+
+/*
+ *      Copyright (C) 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
+ *  <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "DVDVideoCodec.h"
+
+class CStageFrightVideo;
+class CWinSystemEGL;
+class CAdvancedSettings;
+
+extern "C"
+{
+  void* create_stf(CWinSystemEGL* windowing, CAdvancedSettings* advsettings);
+  void destroy_stf(void*);
+
+  bool stf_Open(void*, CDVDStreamInfo &hints);
+  void stf_Close(void*);
+  int  stf_Decode(void*, uint8_t *pData, int iSize, double dts, double pts);
+  void stf_Reset(void*);
+  bool stf_GetPicture(void*, DVDVideoPicture *pDvdVideoPicture);
+  bool stf_ClearPicture(void*, DVDVideoPicture* pDvdVideoPicture);
+  void stf_SetDropState(void*, bool bDrop);
+  void stf_SetSpeed(void*, int iSpeed);
+
+  void stf_LockBuffer(void*, EGLImageKHR eglimg);
+  void stf_ReleaseBuffer(void*, EGLImageKHR eglimg);
+}
diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/libstagefrightICS/StageFrightVideo.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/libstagefrightICS/StageFrightVideo.cpp
new file mode 100644 (file)
index 0000000..1165525
--- /dev/null
@@ -0,0 +1,969 @@
+/*
+ *      Copyright (C) 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
+ *  <http://www.gnu.org/licenses/>.
+ *
+ */
+/***************************************************************************/
+
+//#define DEBUG_VERBOSE 1
+
+#include "system.h"
+#include "system_gl.h"
+
+#include "StageFrightVideo.h"
+#include "StageFrightVideoPrivate.h"
+
+#include "guilib/GraphicContext.h"
+#include "DVDClock.h"
+#include "utils/log.h"
+#include "utils/fastmemcpy.h"
+#include "threads/Thread.h"
+#include "threads/Event.h"
+#include "settings/AdvancedSettings.h"
+
+#include "xbmc/guilib/FrameBufferObject.h"
+
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+#include "windowing/egl/EGLWrapper.h"
+#include "windowing/WindowingFactory.h"
+
+#include <new>
+
+#define OMX_QCOM_COLOR_FormatYVU420SemiPlanar 0x7FA30C00
+#define OMX_TI_COLOR_FormatYUV420PackedSemiPlanar 0x7F000100
+
+#define CLASSNAME "CStageFrightVideo"
+
+#define EGL_NATIVE_BUFFER_ANDROID 0x3140
+#define EGL_IMAGE_PRESERVED_KHR   0x30D2
+
+const char *MEDIA_MIMETYPE_VIDEO_WMV  = "video/x-ms-wmv";
+
+using namespace android;
+
+static int64_t pts_dtoi(double pts)
+{
+  return (int64_t)(pts);
+}
+
+static double pts_itod(int64_t pts)
+{
+  return (double)pts;
+}
+
+/***********************************************************/
+
+class CStageFrightMediaSource : public MediaSource
+{
+public:
+  CStageFrightMediaSource(CStageFrightVideoPrivate *priv, sp<MetaData> meta)
+  {
+    p = priv;
+    source_meta = meta;
+  }
+
+  virtual sp<MetaData> getFormat()
+  {
+    return source_meta;
+  }
+
+  virtual status_t start(MetaData *params)
+  {
+    return OK;
+  }
+
+  virtual status_t stop()
+  {
+    return OK;
+  }
+
+  virtual status_t read(MediaBuffer **buffer,
+                        const MediaSource::ReadOptions *options)
+  {
+    Frame *frame;
+    status_t ret;
+    *buffer = NULL;
+    int64_t time_us = -1;
+    MediaSource::ReadOptions::SeekMode mode;
+
+    if (options && options->getSeekTo(&time_us, &mode))
+    {
+#if defined(DEBUG_VERBOSE)
+      CLog::Log(LOGDEBUG, "%s: reading source(%d): seek:%llu\n", CLASSNAME,p->in_queue.size(), time_us);
+#endif
+    }
+    else
+    {
+#if defined(DEBUG_VERBOSE)
+      CLog::Log(LOGDEBUG, "%s: reading source(%d)\n", CLASSNAME,p->in_queue.size());
+#endif
+    }
+
+    p->in_mutex.lock();
+    while (p->in_queue.empty() && p->decode_thread)
+      p->in_condition.wait(p->in_mutex);
+
+    if (p->in_queue.empty())
+    {
+      p->in_mutex.unlock();
+      return VC_ERROR;
+    }
+
+    std::map<int64_t,Frame*>::iterator it = p->in_queue.begin();
+    frame = it->second;
+    ret = frame->status;
+    *buffer = frame->medbuf;
+
+    p->in_queue.erase(it);
+    p->in_mutex.unlock();
+
+#if defined(DEBUG_VERBOSE)
+    CLog::Log(LOGDEBUG, ">>> exiting reading source(%d); pts:%llu\n", p->in_queue.size(),frame->pts);
+#endif
+
+    free(frame);
+
+    return ret;
+  }
+
+private:
+  sp<MetaData> source_meta;
+  CStageFrightVideoPrivate *p;
+};
+
+/********************************************/
+
+class CStageFrightDecodeThread : public CThread
+{
+protected:
+  CStageFrightVideoPrivate *p;
+
+public:
+  CStageFrightDecodeThread(CStageFrightVideoPrivate *priv)
+  : CThread("CStageFrightDecodeThread")
+  , p(priv)
+  {}
+
+  void OnStartup()
+  {
+  #if defined(DEBUG_VERBOSE)
+    CLog::Log(LOGDEBUG, "%s: entering decode thread\n", CLASSNAME);
+  #endif
+  }
+
+  void OnExit()
+  {
+  #if defined(DEBUG_VERBOSE)
+    CLog::Log(LOGDEBUG, "%s: exited decode thread\n", CLASSNAME);
+  #endif
+  }
+
+  void Process()
+  {
+    Frame* frame;
+    int32_t w, h, dw, dh;
+    int decode_done = 0;
+    int32_t keyframe = 0;
+    int32_t unreadable = 0;
+    MediaSource::ReadOptions readopt;
+    // GLuint texid;
+
+    //SetPriority(THREAD_PRIORITY_ABOVE_NORMAL);
+    do
+    {
+      #if defined(DEBUG_VERBOSE)
+      unsigned int time = XbmcThreads::SystemClockMillis();
+      CLog::Log(LOGDEBUG, "%s: >>> Handling frame\n", CLASSNAME);
+      #endif
+      p->cur_frame = NULL;
+      frame = (Frame*)malloc(sizeof(Frame));
+      if (!frame)
+      {
+        decode_done   = 1;
+        continue;
+      }
+
+      frame->eglimg = EGL_NO_IMAGE_KHR;
+      frame->medbuf = NULL;
+      if (p->resetting)
+      {
+        readopt.setSeekTo(0);
+        p->resetting = false;
+      }
+      frame->status = p->decoder->read(&frame->medbuf, &readopt);
+      readopt.clearSeekTo();
+
+      if (frame->status == OK)
+      {
+        if (!frame->medbuf->graphicBuffer().get())  // hw buffers
+        {
+          if (frame->medbuf->range_length() == 0)
+          {
+            CLog::Log(LOGERROR, "%s - Invalid buffer\n", CLASSNAME);
+            frame->status = VC_ERROR;
+            decode_done   = 1;
+            frame->medbuf->release();
+            frame->medbuf = NULL;
+          }
+          else
+            frame->format = RENDER_FMT_YUV420P;
+        }
+        else
+          frame->format = RENDER_FMT_EGLIMG;
+      }
+
+      if (frame->status == OK)
+      {
+        frame->width = p->width;
+        frame->height = p->height;
+        frame->pts = 0;
+
+        sp<MetaData> outFormat = p->decoder->getFormat();
+        outFormat->findInt32(kKeyWidth , &w);
+        outFormat->findInt32(kKeyHeight, &h);
+
+        // The OMX.SEC decoder doesn't signal the modified width/height
+        if (p->decoder_component && (w & 15 || h & 15) && !strncmp(p->decoder_component, "OMX.SEC", 7))
+        {
+          if (((w + 15)&~15) * ((h + 15)&~15) * 3/2 == frame->medbuf->range_length())
+          {
+            w = (w + 15)&~15;
+            h = (h + 15)&~15;
+            frame->width = w;
+            frame->height = h;
+          }
+        }
+        frame->medbuf->meta_data()->findInt64(kKeyTime, &(frame->pts));
+      }
+      else if (frame->status == INFO_FORMAT_CHANGED)
+      {
+        int32_t cropLeft, cropTop, cropRight, cropBottom;
+        sp<MetaData> outFormat = p->decoder->getFormat();
+
+        outFormat->findInt32(kKeyWidth , &p->width);
+        outFormat->findInt32(kKeyHeight, &p->height);
+
+        cropLeft = cropTop = cropRight = cropBottom = 0;
+        if (!outFormat->findRect(kKeyCropRect, &cropLeft, &cropTop, &cropRight, &cropBottom))
+        {
+          p->x = 0;
+          p->y = 0;
+        }
+        else
+        {
+          p->x = cropLeft;
+          p->y = cropTop;
+          p->width = cropRight - cropLeft + 1;
+          p->height = cropBottom - cropTop + 1;
+        }
+        outFormat->findInt32(kKeyColorFormat, &p->videoColorFormat);
+        if (!outFormat->findInt32(kKeyStride, &p->videoStride))
+          p->videoStride = p->width;
+        if (!outFormat->findInt32(kKeySliceHeight, &p->videoSliceHeight))
+          p->videoSliceHeight = p->height;
+
+#if defined(DEBUG_VERBOSE)
+        CLog::Log(LOGDEBUG, ">>> new format col:%d, w:%d, h:%d, sw:%d, sh:%d, ctl:%d,%d; cbr:%d,%d\n", p->videoColorFormat, p->width, p->height, p->videoStride, p->videoSliceHeight, cropTop, cropLeft, cropBottom, cropRight);
+#endif
+
+        if (frame->medbuf)
+          frame->medbuf->release();
+        frame->medbuf = NULL;
+        free(frame);
+        continue;
+      }
+      else
+      {
+        CLog::Log(LOGERROR, "%s - decoding error (%d)\n", CLASSNAME,frame->status);
+        if (frame->medbuf)
+          frame->medbuf->release();
+        frame->medbuf = NULL;
+        free(frame);
+        continue;
+      }
+
+      if (frame->format == RENDER_FMT_EGLIMG)
+      {
+        if (!p->eglInitialized)
+        {
+          p->InitializeEGL(frame->width, frame->height);
+        }
+        else if (p->texwidth != frame->width || p->texheight != frame->height)
+        {
+          p->UninitializeEGL();
+          p->InitializeEGL(frame->width, frame->height);
+        }
+
+        if (p->free_queue.empty())
+        {
+          CLog::Log(LOGERROR, "%s::%s - Error: No free output buffers\n", CLASSNAME, __func__);
+          if (frame->medbuf)
+            frame->medbuf->release();
+          free(frame);
+          continue;
+        }
+
+        ANativeWindowBuffer* graphicBuffer = frame->medbuf->graphicBuffer()->getNativeBuffer();
+        native_window_set_buffers_timestamp(p->mVideoNativeWindow.get(), frame->pts * 1000);
+        int err = p->mVideoNativeWindow.get()->queueBuffer(p->mVideoNativeWindow.get(), graphicBuffer);
+        if (err == 0)
+          frame->medbuf->meta_data()->setInt32(kKeyRendered, 1);
+        frame->medbuf->release();
+        frame->medbuf = NULL;
+        p->UpdateStagefrightTexture();
+
+        if (!p->drop_state)
+        {
+          p->free_mutex.lock();
+          while (!p->free_queue.size())
+            usleep(10000);
+          std::list<std::pair<EGLImageKHR, int> >::iterator itfree = p->free_queue.begin();
+          int cur_slot = itfree->second;
+          p->fbo.BindToTexture(GL_TEXTURE_2D, p->slots[cur_slot].texid);
+          p->fbo.BeginRender();
+
+          glDisable(GL_DEPTH_TEST);
+          //glClear(GL_COLOR_BUFFER_BIT);
+
+          const GLfloat triangleVertices[] = {
+          -1.0f, 1.0f,
+          -1.0f, -1.0f,
+          1.0f, -1.0f,
+          1.0f, 1.0f,
+          };
+
+          glVertexAttribPointer(p->mPositionHandle, 2, GL_FLOAT, GL_FALSE, 0, triangleVertices);
+          glEnableVertexAttribArray(p->mPositionHandle);
+
+          glUseProgram(p->mPgm);
+          glUniform1i(p->mTexSamplerHandle, 0);
+
+          glBindTexture(GL_TEXTURE_EXTERNAL_OES, p->mVideoTextureId);
+
+          GLfloat texMatrix[16];
+          // const GLfloat texMatrix[] = {
+            // 1, 0, 0, 0,
+            // 0, -1, 0, 0,
+            // 0, 0, 1, 0,
+            // 0, 1, 0, 1
+          // };
+          p->GetStagefrightTransformMatrix(texMatrix);
+          glUniformMatrix4fv(p->mTexMatrixHandle, 1, GL_FALSE, texMatrix);
+
+          glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
+
+          glBindTexture(GL_TEXTURE_EXTERNAL_OES, 0);
+          // glDeleteTextures(1, &texid);
+          // eglDestroyImageKHR(p->eglDisplay, img);
+          p->fbo.EndRender();
+
+          glBindTexture(GL_TEXTURE_2D, 0);
+
+          frame->eglimg = p->slots[cur_slot].eglimg;
+          p->busy_queue.push_back(std::pair<EGLImageKHR, int>(*itfree));
+          p->free_queue.erase(itfree);
+          p->free_mutex.unlock();
+        }
+      }
+
+    #if defined(DEBUG_VERBOSE)
+      CLog::Log(LOGDEBUG, "%s: >>> pushed OUT frame; w:%d, h:%d, dw:%d, dh:%d, kf:%d, ur:%d, img:%p, tm:%d\n", CLASSNAME, frame->width, frame->height, dw, dh, keyframe, unreadable, frame->eglimg, XbmcThreads::SystemClockMillis() - time);
+    #endif
+
+      p->out_mutex.lock();
+      p->cur_frame = frame;
+      while (p->cur_frame)
+        p->out_condition.wait(p->out_mutex);
+      p->out_mutex.unlock();
+    }
+    while (!decode_done && !m_bStop);
+
+    if (p->eglInitialized)
+      p->UninitializeEGL();
+
+  }
+};
+
+/***********************************************************/
+
+CStageFrightVideo::CStageFrightVideo(CWinSystemEGL* windowing, CAdvancedSettings* advsettings)
+{
+#if defined(DEBUG_VERBOSE)
+  CLog::Log(LOGDEBUG, "%s::ctor: %d\n", CLASSNAME, sizeof(CStageFrightVideo));
+#endif
+  p = new CStageFrightVideoPrivate;
+  p->m_g_Windowing = windowing;
+  p->m_g_advancedSettings = advsettings;
+}
+
+CStageFrightVideo::~CStageFrightVideo()
+{
+  delete p;
+}
+
+bool CStageFrightVideo::Open(CDVDStreamInfo &hints)
+{
+#if defined(DEBUG_VERBOSE)
+  CLog::Log(LOGDEBUG, "%s::Open\n", CLASSNAME);
+#endif
+
+  CSingleLock lock(g_graphicsContext);
+
+  // stagefright crashes with null size. Trap this...
+  if (!hints.width || !hints.height)
+  {
+    CLog::Log(LOGERROR, "%s::%s - %s\n", CLASSNAME, __func__,"null size, cannot handle");
+    return false;
+  }
+  p->width     = hints.width;
+  p->height    = hints.height;
+
+  if (p->m_g_advancedSettings->m_stagefrightConfig.useSwRenderer)
+    p->quirks |= QuirkSWRender;
+
+  sp<MetaData> outFormat;
+  int32_t cropLeft, cropTop, cropRight, cropBottom;
+  //Vector<String8> matchingCodecs;
+
+  p->meta = new MetaData;
+  if (p->meta == NULL)
+  {
+    CLog::Log(LOGERROR, "%s::%s - %s\n", CLASSNAME, __func__,"cannot allocate MetaData");
+    return false;
+  }
+
+  const char* mimetype;
+  switch (hints.codec)
+  {
+  case CODEC_ID_H264:
+    if (p->m_g_advancedSettings->m_stagefrightConfig.useAVCcodec == 0)
+      return false;
+    mimetype = MEDIA_MIMETYPE_VIDEO_AVC;
+    if ( *(char*)hints.extradata == 1 )
+      p->meta->setData(kKeyAVCC, kTypeAVCC, hints.extradata, hints.extrasize);
+    break;
+  case CODEC_ID_MPEG4:
+    if (p->m_g_advancedSettings->m_stagefrightConfig.useMP4codec == 0)
+      return false;
+    mimetype = MEDIA_MIMETYPE_VIDEO_MPEG4;
+    break;
+  case CODEC_ID_MPEG2VIDEO:
+    if (p->m_g_advancedSettings->m_stagefrightConfig.useMPEG2codec == 0)
+      return false;
+    mimetype = MEDIA_MIMETYPE_VIDEO_MPEG2;
+    break;
+  case CODEC_ID_VP3:
+  case CODEC_ID_VP6:
+  case CODEC_ID_VP6F:
+  case CODEC_ID_VP8:
+    if (p->m_g_advancedSettings->m_stagefrightConfig.useVPXcodec == 0)
+      return false;
+    mimetype = MEDIA_MIMETYPE_VIDEO_VPX;
+    break;
+  case CODEC_ID_VC1:
+  case CODEC_ID_WMV3:
+    if (p->m_g_advancedSettings->m_stagefrightConfig.useVC1codec == 0)
+      return false;
+    mimetype = MEDIA_MIMETYPE_VIDEO_WMV;
+    break;
+  default:
+    return false;
+    break;
+  }
+
+  p->meta->setCString(kKeyMIMEType, mimetype);
+  p->meta->setInt32(kKeyWidth, p->width);
+  p->meta->setInt32(kKeyHeight, p->height);
+
+  android::ProcessState::self()->startThreadPool();
+
+  p->source    = new CStageFrightMediaSource(p, p->meta);
+  p->client    = new OMXClient;
+
+  if (p->source == NULL || p->client == NULL)
+  {
+    CLog::Log(LOGERROR, "%s::%s - %s\n", CLASSNAME, __func__,"Cannot obtain source / client");
+    return false;
+  }
+
+  if (p->client->connect() !=  OK)
+  {
+    delete p->client;
+    p->client = NULL;
+    CLog::Log(LOGERROR, "%s::%s - %s\n", CLASSNAME, __func__,"Cannot connect OMX client");
+    return false;
+  }
+
+  if ((p->quirks & QuirkSWRender) == 0)
+    p->InitStagefrightSurface();
+
+  p->decoder  = OMXCodec::Create(p->client->interface(), p->meta,
+                                         false, p->source, NULL,
+                                         OMXCodec::kHardwareCodecsOnly | (p->quirks & QuirkSWRender ? OMXCodec::kClientNeedsFramebuffer : 0),
+                                         p->mVideoNativeWindow
+                                         );
+
+  if (!(p->decoder != NULL && p->decoder->start() ==  OK))
+  {
+    p->decoder = NULL;
+    return false;
+  }
+
+  outFormat = p->decoder->getFormat();
+
+  if (!outFormat->findInt32(kKeyWidth, &p->width) || !outFormat->findInt32(kKeyHeight, &p->height)
+        || !outFormat->findInt32(kKeyColorFormat, &p->videoColorFormat))
+    return false;
+
+  const char *component;
+  if (outFormat->findCString(kKeyDecoderComponent, &component))
+  {
+    CLog::Log(LOGDEBUG, "%s::%s - component: %s\n", CLASSNAME, __func__, component);
+
+    //Blacklist
+    if (!strncmp(component, "OMX.google", 10))
+    {
+      // On some platforms, software decoders are returned anyway
+      CLog::Log(LOGERROR, "%s::%s - %s\n", CLASSNAME, __func__,"Blacklisted component (software)");
+      return false;
+    }
+    else if (!strncmp(component, "OMX.Nvidia.mp4.decode", 21) && p->m_g_advancedSettings->m_stagefrightConfig.useMP4codec != 1)
+    {
+      // Has issues with some XVID encoded MP4. Only fails after actual decoding starts...
+      CLog::Log(LOGERROR, "%s::%s - %s\n", CLASSNAME, __func__,"Blacklisted component (MP4)");
+      return false;
+    }
+  }
+
+  cropLeft = cropTop = cropRight = cropBottom = 0;
+  if (!outFormat->findRect(kKeyCropRect, &cropLeft, &cropTop, &cropRight, &cropBottom))
+  {
+    p->x = 0;
+    p->y = 0;
+  }
+  else
+  {
+    p->x = cropLeft;
+    p->y = cropTop;
+    p->width = cropRight - cropLeft + 1;
+    p->height = cropBottom - cropTop + 1;
+  }
+
+  if (!outFormat->findInt32(kKeyStride, &p->videoStride))
+    p->videoStride = p->width;
+  if (!outFormat->findInt32(kKeySliceHeight, &p->videoSliceHeight))
+    p->videoSliceHeight = p->height;
+
+  for (int i=0; i<INBUFCOUNT; ++i)
+  {
+    p->inbuf[i] = new MediaBuffer(300000);
+    p->inbuf[i]->setObserver(p);
+  }
+
+  p->decode_thread = new CStageFrightDecodeThread(p);
+  p->decode_thread->Create(true /*autodelete*/);
+
+#if defined(DEBUG_VERBOSE)
+  CLog::Log(LOGDEBUG, ">>> format col:%d, w:%d, h:%d, sw:%d, sh:%d, ctl:%d,%d; cbr:%d,%d\n", p->videoColorFormat, p->width, p->height, p->videoStride, p->videoSliceHeight, cropTop, cropLeft, cropBottom, cropRight);
+#endif
+
+  return true;
+}
+
+/*** Decode ***/
+int  CStageFrightVideo::Decode(uint8_t *pData, int iSize, double dts, double pts)
+{
+#if defined(DEBUG_VERBOSE)
+  unsigned int time = XbmcThreads::SystemClockMillis();
+  CLog::Log(LOGDEBUG, "%s::Decode - d:%p; s:%d; dts:%f; pts:%f\n", CLASSNAME, pData, iSize, dts, pts);
+#endif
+
+  Frame *frame;
+  int demuxer_bytes = iSize;
+  uint8_t *demuxer_content = pData;
+  int ret = 0;
+
+  if (demuxer_content)
+  {
+    frame = (Frame*)malloc(sizeof(Frame));
+    if (!frame)
+      return VC_ERROR;
+
+    frame->status  = OK;
+    if (p->m_g_advancedSettings->m_stagefrightConfig.useInputDTS)
+      frame->pts = (dts != DVD_NOPTS_VALUE) ? pts_dtoi(dts) : ((pts != DVD_NOPTS_VALUE) ? pts_dtoi(pts) : 0);
+    else
+      frame->pts = (pts != DVD_NOPTS_VALUE) ? pts_dtoi(pts) : ((dts != DVD_NOPTS_VALUE) ? pts_dtoi(dts) : 0);
+
+    // No valid pts? libstagefright asserts on this.
+    if (frame->pts < 0)
+    {
+      free(frame);
+      return ret;
+    }
+
+    frame->medbuf = p->getBuffer(demuxer_bytes);
+    if (!frame->medbuf)
+    {
+      free(frame);
+      return VC_ERROR;
+    }
+
+    fast_memcpy(frame->medbuf->data(), demuxer_content, demuxer_bytes);
+    frame->medbuf->meta_data()->clear();
+    frame->medbuf->meta_data()->setInt64(kKeyTime, frame->pts);
+
+    p->in_mutex.lock();
+    p->framecount++;
+    p->in_queue.insert(std::pair<int64_t, Frame*>(p->framecount, frame));
+    p->in_condition.notify();
+    p->in_mutex.unlock();
+  }
+
+  if (p->inputBufferAvailable() && p->in_queue.size() < INBUFCOUNT)
+    ret |= VC_BUFFER;
+  else
+    usleep(1000);
+  if (p->cur_frame != NULL)
+    ret |= VC_PICTURE;
+#if defined(DEBUG_VERBOSE)
+  CLog::Log(LOGDEBUG, "%s::Decode: pushed IN frame (%d); tm:%d\n", CLASSNAME,p->in_queue.size(), XbmcThreads::SystemClockMillis() - time);
+#endif
+
+  return ret;
+}
+
+bool CStageFrightVideo::ClearPicture(DVDVideoPicture* pDvdVideoPicture)
+{
+ #if defined(DEBUG_VERBOSE)
+  unsigned int time = XbmcThreads::SystemClockMillis();
+#endif
+  if (pDvdVideoPicture->format == RENDER_FMT_EGLIMG && pDvdVideoPicture->eglimg != EGL_NO_IMAGE_KHR)
+    ReleaseBuffer(pDvdVideoPicture->eglimg);
+
+  if (p->prev_frame) {
+    if (p->prev_frame->medbuf)
+      p->prev_frame->medbuf->release();
+    free(p->prev_frame);
+    p->prev_frame = NULL;
+  }
+#if defined(DEBUG_VERBOSE)
+  CLog::Log(LOGDEBUG, "%s::ClearPicture (%d)\n", CLASSNAME, XbmcThreads::SystemClockMillis() - time);
+#endif
+
+  return true;
+}
+
+bool CStageFrightVideo::GetPicture(DVDVideoPicture* pDvdVideoPicture)
+{
+#if defined(DEBUG_VERBOSE)
+  unsigned int time = XbmcThreads::SystemClockMillis();
+  CLog::Log(LOGDEBUG, "%s::GetPicture\n", CLASSNAME);
+  if (p->cycle_time != 0)
+    CLog::Log(LOGDEBUG, ">>> cycle dur:%d\n", XbmcThreads::SystemClockMillis() - p->cycle_time);
+  p->cycle_time = time;
+#endif
+
+  status_t status;
+
+  p->out_mutex.lock();
+  if (!p->cur_frame)
+  {
+    CLog::Log(LOGERROR, "%s::%s - Error getting frame\n", CLASSNAME, __func__);
+    p->out_condition.notify();
+    p->out_mutex.unlock();
+    return false;
+  }
+
+  Frame *frame = p->cur_frame;
+  status  = frame->status;
+
+  pDvdVideoPicture->format = frame->format;
+  pDvdVideoPicture->dts = DVD_NOPTS_VALUE;
+  pDvdVideoPicture->pts = frame->pts;
+  pDvdVideoPicture->iWidth  = frame->width;
+  pDvdVideoPicture->iHeight = frame->height;
+  pDvdVideoPicture->iDisplayWidth = frame->width;
+  pDvdVideoPicture->iDisplayHeight = frame->height;
+  pDvdVideoPicture->iFlags  = DVP_FLAG_ALLOCATED;
+  pDvdVideoPicture->eglimg = EGL_NO_IMAGE_KHR;
+
+  if (status != OK)
+  {
+    CLog::Log(LOGERROR, "%s::%s - Error getting picture from frame(%d)\n", CLASSNAME, __func__,status);
+    if (frame->medbuf) {
+      frame->medbuf->release();
+    }
+    free(frame);
+    p->cur_frame = NULL;
+    p->out_condition.notify();
+    p->out_mutex.unlock();
+    return false;
+  }
+
+  if (pDvdVideoPicture->format == RENDER_FMT_EGLIMG)
+  {
+    pDvdVideoPicture->eglimg = frame->eglimg;
+  #if defined(DEBUG_VERBOSE)
+    CLog::Log(LOGDEBUG, ">>> pic dts:%f, pts:%llu, img:%p, tm:%d\n", pDvdVideoPicture->dts, frame->pts, pDvdVideoPicture->eglimg, XbmcThreads::SystemClockMillis() - time);
+  #endif
+  }
+  else if (pDvdVideoPicture->format == RENDER_FMT_YUV420P)
+  {
+    pDvdVideoPicture->color_range  = 0;
+    pDvdVideoPicture->color_matrix = 4;
+
+    unsigned int luma_pixels = frame->width  * frame->height;
+    unsigned int chroma_pixels = luma_pixels/4;
+    uint8_t* data = NULL;
+    if (frame->medbuf && !p->drop_state)
+    {
+      data = (uint8_t*)((long)frame->medbuf->data() + frame->medbuf->range_offset());
+    }
+    switch (p->videoColorFormat)
+    {
+      case OMX_COLOR_FormatYUV420Planar:
+        pDvdVideoPicture->iLineSize[0] = frame->width;
+        pDvdVideoPicture->iLineSize[1] = frame->width / 2;
+        pDvdVideoPicture->iLineSize[2] = frame->width / 2;
+        pDvdVideoPicture->iLineSize[3] = 0;
+        pDvdVideoPicture->data[0] = data;
+        pDvdVideoPicture->data[1] = pDvdVideoPicture->data[0] + luma_pixels;
+        pDvdVideoPicture->data[2] = pDvdVideoPicture->data[1] + chroma_pixels;
+        pDvdVideoPicture->data[3] = 0;
+        break;
+      case OMX_COLOR_FormatYUV420SemiPlanar:
+      case OMX_QCOM_COLOR_FormatYVU420SemiPlanar:
+      case OMX_TI_COLOR_FormatYUV420PackedSemiPlanar:
+        pDvdVideoPicture->iLineSize[0] = frame->width;
+        pDvdVideoPicture->iLineSize[1] = frame->width;
+        pDvdVideoPicture->iLineSize[2] = 0;
+        pDvdVideoPicture->iLineSize[3] = 0;
+        pDvdVideoPicture->data[0] = data;
+        pDvdVideoPicture->data[1] = pDvdVideoPicture->data[0] + luma_pixels;
+        pDvdVideoPicture->data[2] = pDvdVideoPicture->data[1] + chroma_pixels;
+        pDvdVideoPicture->data[3] = 0;
+        break;
+      default:
+        CLog::Log(LOGERROR, "%s::%s - Unsupported color format(%d)\n", CLASSNAME, __func__,p->videoColorFormat);
+    }
+  #if defined(DEBUG_VERBOSE)
+    CLog::Log(LOGDEBUG, ">>> pic pts:%f, data:%p, col:%d, w:%d, h:%d, tm:%d\n", pDvdVideoPicture->pts, data, p->videoColorFormat, frame->width, frame->height, XbmcThreads::SystemClockMillis() - time);
+  #endif
+  }
+
+  if (p->drop_state)
+    pDvdVideoPicture->iFlags |= DVP_FLAG_DROPPED;
+
+  p->prev_frame = p->cur_frame;
+  p->cur_frame = NULL;
+  p->out_condition.notify();
+  p->out_mutex.unlock();
+
+  return true;
+}
+
+void CStageFrightVideo::Close()
+{
+#if defined(DEBUG_VERBOSE)
+  CLog::Log(LOGDEBUG, "%s::Close\n", CLASSNAME);
+#endif
+
+  Frame *frame;
+
+  if (p->decode_thread && p->decode_thread->IsRunning())
+    p->decode_thread->StopThread(false);
+  p->decode_thread = NULL;
+  p->in_condition.notify();
+
+  // Give decoder_thread time to process EOS, if stuck on reading
+  usleep(50000);
+
+#if defined(DEBUG_VERBOSE)
+  CLog::Log(LOGDEBUG, "Cleaning OUT\n");
+#endif
+  p->out_mutex.lock();
+  if (p->cur_frame)
+  {
+    if (p->cur_frame->medbuf)
+      p->cur_frame->medbuf->release();
+    free(p->cur_frame);
+    p->cur_frame = NULL;
+  }
+  p->out_condition.notify();
+  p->out_mutex.unlock();
+
+  if (p->prev_frame)
+  {
+    if (p->prev_frame->medbuf)
+      p->prev_frame->medbuf->release();
+    free(p->prev_frame);
+    p->prev_frame = NULL;
+  }
+
+#if defined(DEBUG_VERBOSE)
+  CLog::Log(LOGDEBUG, "Stopping omxcodec\n");
+#endif
+  if (p->decoder != NULL)
+    p->decoder->stop();
+  if (p->client)
+    p->client->disconnect();
+
+#if defined(DEBUG_VERBOSE)
+  CLog::Log(LOGDEBUG, "Cleaning IN(%d)\n", p->in_queue.size());
+#endif
+  std::map<int64_t,Frame*>::iterator it;
+  while (!p->in_queue.empty())
+  {
+    it = p->in_queue.begin();
+    frame = it->second;
+    p->in_queue.erase(it);
+    if (frame->medbuf)
+      frame->medbuf->release();
+    free(frame);
+  }
+  
+#if defined(DEBUG_VERBOSE)
+  CLog::Log(LOGDEBUG, "Cleaning libstagefright\n", p->in_queue.size());
+#endif
+  if ((p->quirks & QuirkSWRender) == 0)
+    p->UninitStagefrightSurface();
+
+#if defined(DEBUG_VERBOSE)
+  CLog::Log(LOGDEBUG, "Final Cleaning\n", p->in_queue.size());
+#endif
+  if (p->decoder_component)
+    free(&p->decoder_component);
+
+  delete p->client;
+
+  for (int i=0; i<INBUFCOUNT; ++i)
+  {
+    if (p->inbuf[i])
+    {
+      p->inbuf[i]->setObserver(NULL);
+      p->inbuf[i]->release();
+      p->inbuf[i] = NULL;
+    }
+  }
+}
+
+void CStageFrightVideo::Reset(void)
+{
+#if defined(DEBUG_VERBOSE)
+  CLog::Log(LOGDEBUG, "%s::Reset\n", CLASSNAME);
+#endif
+  Frame* frame;
+  p->in_mutex.lock();
+  std::map<int64_t,Frame*>::iterator it;
+  while (!p->in_queue.empty())
+  {
+    it = p->in_queue.begin();
+    frame = it->second;
+    p->in_queue.erase(it);
+    if (frame->medbuf)
+      frame->medbuf->release();
+    free(frame);
+  }
+  p->resetting = true;
+  p->framecount = 0;
+
+  p->in_mutex.unlock();
+}
+
+void CStageFrightVideo::SetDropState(bool bDrop)
+{
+  if (bDrop == p->drop_state)
+    return;
+
+#if defined(DEBUG_VERBOSE)
+  CLog::Log(LOGDEBUG, "%s::SetDropState (%d->%d)\n", CLASSNAME,p->drop_state,bDrop);
+#endif
+
+  p->drop_state = bDrop;
+}
+
+void CStageFrightVideo::SetSpeed(int iSpeed)
+{
+}
+
+/***************/
+
+void CStageFrightVideo::LockBuffer(EGLImageKHR eglimg)
+{
+ #if defined(DEBUG_VERBOSE)
+  unsigned int time = XbmcThreads::SystemClockMillis();
+#endif
+  p->free_mutex.lock();
+  std::list<std::pair<EGLImageKHR, int> >::iterator it = p->free_queue.begin();
+  for(;it != p->free_queue.end(); ++it)
+  {
+    if ((*it).first == eglimg)
+      break;
+  }
+  if (it == p->free_queue.end())
+  {
+    p->busy_queue.push_back(std::pair<EGLImageKHR, int>(*it));
+    p->free_mutex.unlock();
+    return;
+  }
+#if defined(DEBUG_VERBOSE)
+  CLog::Log(LOGDEBUG, "Locking %p: tm:%d\n", eglimg, XbmcThreads::SystemClockMillis() - time);
+#endif
+
+  p->busy_queue.push_back(std::pair<EGLImageKHR, int>(*it));
+  p->free_queue.erase(it);
+  p->free_mutex.unlock();
+}
+
+void CStageFrightVideo::ReleaseBuffer(EGLImageKHR eglimg)
+{
+ #if defined(DEBUG_VERBOSE)
+  unsigned int time = XbmcThreads::SystemClockMillis();
+#endif
+  p->free_mutex.lock();
+  int cnt = 0;
+  std::list<std::pair<EGLImageKHR, int> >::iterator it = p->busy_queue.begin();
+  std::list<std::pair<EGLImageKHR, int> >::iterator itfree;
+  for(;it != p->busy_queue.end(); ++it)
+  {
+    if ((*it).first == eglimg)
+    {
+      cnt++;
+      if (cnt==1)
+        itfree = it;
+      else
+        break;
+    }
+  }
+  if (it == p->busy_queue.end() && !cnt)
+  {
+    p->free_mutex.unlock();
+    return;
+  }
+#if defined(DEBUG_VERBOSE)
+  CLog::Log(LOGDEBUG, "Unlocking %p: tm:%d\n", eglimg, XbmcThreads::SystemClockMillis() - time);
+#endif
+
+  if (cnt==1)
+  {
+    p->free_queue.push_back(std::pair<EGLImageKHR, int>(*itfree));
+    p->busy_queue.erase(itfree);
+  }
+  p->free_mutex.unlock();
+}
diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/libstagefrightICS/StageFrightVideo.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/libstagefrightICS/StageFrightVideo.h
new file mode 100644 (file)
index 0000000..4ddc310
--- /dev/null
@@ -0,0 +1,56 @@
+#pragma once
+/*
+ *      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
+ *  <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#if defined(HAS_LIBSTAGEFRIGHT)
+
+#include "cores/dvdplayer/DVDStreamInfo.h"
+#include "DVDVideoCodec.h"
+
+class CWinSystemEGL;
+class CAdvancedSettings;
+class CStageFrightVideoPrivate;
+
+namespace android { class MediaBuffer; }
+
+class CStageFrightVideo
+{
+public:
+  CStageFrightVideo(CWinSystemEGL* windowing, CAdvancedSettings* advsettings);
+  virtual ~CStageFrightVideo();
+
+  bool Open(CDVDStreamInfo &hints);
+  void Close(void);
+  int  Decode(uint8_t *pData, int iSize, double dts, double pts);
+  void Reset(void);
+  bool GetPicture(DVDVideoPicture *pDvdVideoPicture);
+  bool ClearPicture(DVDVideoPicture* pDvdVideoPicture);
+  void SetDropState(bool bDrop);
+  virtual void SetSpeed(int iSpeed);
+
+  void LockBuffer(EGLImageKHR eglimg);
+  void ReleaseBuffer(EGLImageKHR eglimg);
+
+private:
+  CStageFrightVideoPrivate* p;
+};
+
+// defined(HAS_LIBSTAGEFRIGHT)
+#endif
diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/libstagefrightICS/StageFrightVideoPrivate.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/libstagefrightICS/StageFrightVideoPrivate.cpp
new file mode 100644 (file)
index 0000000..ab638a0
--- /dev/null
@@ -0,0 +1,385 @@
+/*
+ *      Copyright (C) 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
+ *  <http://www.gnu.org/licenses/>.
+ *
+ */
+/***************************************************************************/
+
+//#define DEBUG_VERBOSE 1
+
+#include "StageFrightVideoPrivate.h"
+
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
+#include "windowing/egl/EGLWrapper.h"
+#include "windowing/WindowingFactory.h"
+#include "settings/AdvancedSettings.h"
+#include "utils/log.h"
+
+#include "android/jni/Surface.h"
+#include "android/jni/SurfaceTexture.h"
+
+#define CLASSNAME "CStageFrightVideoPrivate"
+
+GLint glerror;
+#define CheckEglError(x) while((glerror = eglGetError()) != EGL_SUCCESS) CLog::Log(LOGERROR, "EGL error in %s: %x",x, glerror);
+#define CheckGlError(x)  while((glerror = glGetError()) != GL_NO_ERROR) CLog::Log(LOGERROR, "GL error in %s: %x",x, glerror);
+
+// EGL extension functions
+static PFNEGLCREATEIMAGEKHRPROC eglCreateImageKHR;
+static PFNEGLDESTROYIMAGEKHRPROC eglDestroyImageKHR;
+static PFNGLEGLIMAGETARGETTEXTURE2DOESPROC glEGLImageTargetTexture2DOES;
+
+int NP2( unsigned x ) {
+  --x;
+  x |= x >> 1;
+  x |= x >> 2;
+  x |= x >> 4;
+  x |= x >> 8;
+  x |= x >> 16;
+  return ++x;
+}
+
+CStageFrightVideoPrivate::CStageFrightVideoPrivate()
+    : decode_thread(NULL), source(NULL)
+    , eglDisplay(EGL_NO_DISPLAY), eglSurface(EGL_NO_SURFACE), eglContext(EGL_NO_CONTEXT)
+    , eglInitialized(false)
+    , framecount(0)
+    , quirks(QuirkNone), cur_frame(NULL), prev_frame(NULL)
+    , width(-1), height(-1)
+    , texwidth(-1), texheight(-1)
+    , client(NULL), decoder(NULL), decoder_component(NULL)
+    , drop_state(false), resetting(false)
+{
+  if (!eglCreateImageKHR)
+    eglCreateImageKHR = (PFNEGLCREATEIMAGEKHRPROC) CEGLWrapper::GetProcAddress("eglCreateImageKHR");
+  if (!eglDestroyImageKHR)
+    eglDestroyImageKHR = (PFNEGLDESTROYIMAGEKHRPROC) CEGLWrapper::GetProcAddress("eglDestroyImageKHR");
+  if (!glEGLImageTargetTexture2DOES)
+    glEGLImageTargetTexture2DOES = (PFNGLEGLIMAGETARGETTEXTURE2DOESPROC) CEGLWrapper::GetProcAddress("glEGLImageTargetTexture2DOES");
+
+  for (int i=0; i<INBUFCOUNT; ++i)
+    inbuf[i] = NULL;
+}
+
+void CStageFrightVideoPrivate::signalBufferReturned(MediaBuffer *buffer)
+{
+}
+
+MediaBuffer* CStageFrightVideoPrivate::getBuffer(size_t size)
+{
+  int i=0;
+  for (; i<INBUFCOUNT; ++i)
+    if (inbuf[i]->refcount() == 0 && inbuf[i]->size() >= size)
+      break;
+  if (i == INBUFCOUNT)
+  {
+    i = 0;
+    for (; i<INBUFCOUNT; ++i)
+      if (inbuf[i]->refcount() == 0)
+        break;
+    if (i == INBUFCOUNT)
+      return NULL;
+    inbuf[i]->setObserver(NULL);
+    inbuf[i]->release();
+    inbuf[i] = new MediaBuffer(size);
+    inbuf[i]->setObserver(this);
+  }
+
+  inbuf[i]->add_ref();
+  inbuf[i]->set_range(0, size);
+  return inbuf[i];
+}
+
+bool CStageFrightVideoPrivate::inputBufferAvailable()
+{
+  for (int i=0; i<INBUFCOUNT; ++i)
+    if (inbuf[i]->refcount() == 0)
+      return true;
+
+  return false;
+}
+
+void CStageFrightVideoPrivate::loadOESShader(GLenum shaderType, const char* pSource, GLuint* outShader)
+{
+#if defined(DEBUG_VERBOSE)
+  CLog::Log(LOGDEBUG, ">>loadOESShader\n");
+#endif
+
+  GLuint shader = glCreateShader(shaderType);
+  CheckGlError("loadOESShader");
+  if (shader) {
+    glShaderSource(shader, 1, &pSource, NULL);
+    glCompileShader(shader);
+    GLint compiled = 0;
+    glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
+    if (!compiled) {
+      GLint infoLen = 0;
+      glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen);
+      if (infoLen) {
+        char* buf = (char*) malloc(infoLen);
+        if (buf) {
+          glGetShaderInfoLog(shader, infoLen, NULL, buf);
+          printf("Shader compile log:\n%s\n", buf);
+          free(buf);
+        }
+      } else {
+        char* buf = (char*) malloc(0x1000);
+        if (buf) {
+          glGetShaderInfoLog(shader, 0x1000, NULL, buf);
+          printf("Shader compile log:\n%s\n", buf);
+          free(buf);
+        }
+      }
+      glDeleteShader(shader);
+      shader = 0;
+    }
+  }
+  *outShader = shader;
+}
+
+void CStageFrightVideoPrivate::createOESProgram(const char* pVertexSource, const char* pFragmentSource, GLuint* outPgm)
+{
+#if defined(DEBUG_VERBOSE)
+  CLog::Log(LOGDEBUG, ">>createOESProgram\n");
+#endif
+  GLuint vertexShader, fragmentShader;
+  {
+    loadOESShader(GL_VERTEX_SHADER, pVertexSource, &vertexShader);
+  }
+  {
+    loadOESShader(GL_FRAGMENT_SHADER, pFragmentSource, &fragmentShader);
+  }
+
+  GLuint program = glCreateProgram();
+  if (program) {
+    glAttachShader(program, vertexShader);
+    glAttachShader(program, fragmentShader);
+    glLinkProgram(program);
+    GLint linkStatus = GL_FALSE;
+    glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
+    if (linkStatus != GL_TRUE) {
+      GLint bufLength = 0;
+      glGetProgramiv(program, GL_INFO_LOG_LENGTH, &bufLength);
+      if (bufLength) {
+        char* buf = (char*) malloc(bufLength);
+        if (buf) {
+          glGetProgramInfoLog(program, bufLength, NULL, buf);
+          printf("Program link log:\n%s\n", buf);
+          free(buf);
+        }
+      }
+      glDeleteProgram(program);
+      program = 0;
+    }
+  }
+  glDeleteShader(vertexShader);
+  glDeleteShader(fragmentShader);
+  *outPgm = program;
+}
+
+void CStageFrightVideoPrivate::OES_shader_setUp()
+{
+
+  const char vsrc[] =
+  "attribute vec4 vPosition;\n"
+  "varying vec2 texCoords;\n"
+  "uniform mat4 texMatrix;\n"
+  "void main() {\n"
+  "  vec2 vTexCoords = 0.5 * (vPosition.xy + vec2(1.0, 1.0));\n"
+  "  texCoords = (texMatrix * vec4(vTexCoords, 0.0, 1.0)).xy;\n"
+  "  gl_Position = vPosition;\n"
+  "}\n";
+
+  const char fsrc[] =
+  "#extension GL_OES_EGL_image_external : require\n"
+  "precision mediump float;\n"
+  "uniform samplerExternalOES texSampler;\n"
+  "varying vec2 texCoords;\n"
+  "void main() {\n"
+  "  gl_FragColor = texture2D(texSampler, texCoords);\n"
+  "}\n";
+
+  {
+  #if defined(DEBUG_VERBOSE)
+    CLog::Log(LOGDEBUG, ">>OES_shader_setUp\n");
+  #endif
+    CheckGlError("OES_shader_setUp");
+    createOESProgram(vsrc, fsrc, &mPgm);
+  }
+
+  mPositionHandle = glGetAttribLocation(mPgm, "vPosition");
+  mTexSamplerHandle = glGetUniformLocation(mPgm, "texSampler");
+  mTexMatrixHandle = glGetUniformLocation(mPgm, "texMatrix");
+}
+
+void CStageFrightVideoPrivate::InitializeEGL(int w, int h)
+{
+#if defined(DEBUG_VERBOSE)
+  CLog::Log(LOGDEBUG, "%s: >>> InitializeEGL: w:%d; h:%d\n", CLASSNAME, w, h);
+#endif
+  texwidth = w;
+  texheight = h;
+  if (!m_g_Windowing->IsExtSupported("GL_TEXTURE_NPOT"))
+  {
+    texwidth  = NP2(texwidth);
+    texheight = NP2(texheight);
+  }
+
+  eglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+  if (eglDisplay == EGL_NO_DISPLAY)
+    CLog::Log(LOGERROR, "%s: InitializeEGL: no display\n", CLASSNAME);
+  eglBindAPI(EGL_OPENGL_ES_API);
+  EGLint contextAttributes[] = {
+    EGL_CONTEXT_CLIENT_VERSION, 2,
+    EGL_NONE
+  };
+  eglContext = eglCreateContext(eglDisplay, m_g_Windowing->GetEGLConfig(), EGL_NO_CONTEXT, contextAttributes);
+  EGLint pbufferAttribs[] = {
+    EGL_WIDTH, texwidth,
+    EGL_HEIGHT, texheight,
+    EGL_NONE
+  };
+  eglSurface = eglCreatePbufferSurface(eglDisplay, m_g_Windowing->GetEGLConfig(), pbufferAttribs);
+  eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglContext);
+  CheckGlError("stf init");
+
+  static const EGLint imageAttributes[] = {
+    EGL_IMAGE_PRESERVED_KHR, EGL_FALSE,
+    EGL_GL_TEXTURE_LEVEL_KHR, 0,
+    EGL_NONE
+  };
+
+  for (int i=0; i<NUMFBOTEX; ++i)
+  {
+    glGenTextures(1, &(slots[i].texid));
+    glBindTexture(GL_TEXTURE_2D,  slots[i].texid);
+
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texwidth, texheight, 0,
+           GL_RGBA, GL_UNSIGNED_BYTE, 0);
+
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+    // This is necessary for non-power-of-two textures
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+
+    slots[i].eglimg = eglCreateImageKHR(eglDisplay, eglContext, EGL_GL_TEXTURE_2D_KHR, (EGLClientBuffer)(slots[i].texid),imageAttributes);
+    free_queue.push_back(std::pair<EGLImageKHR, int>(slots[i].eglimg, i));
+
+  }
+  glBindTexture(GL_TEXTURE_2D,  0);
+
+  fbo.Initialize();
+  OES_shader_setUp();
+
+  eglInitialized = true;
+#if defined(DEBUG_VERBOSE)
+  CLog::Log(LOGDEBUG, "%s: <<< InitializeEGL: w:%d; h:%d\n", CLASSNAME, texwidth, texheight);
+#endif
+}
+
+void CStageFrightVideoPrivate::UninitializeEGL()
+{
+#if defined(DEBUG_VERBOSE)
+  CLog::Log(LOGDEBUG, "%s: >>> UninitializeEGL\n", CLASSNAME);
+#endif
+  fbo.Cleanup();
+  for (int i=0; i<NUMFBOTEX; ++i)
+  {
+    glDeleteTextures(1, &(slots[i].texid));
+    eglDestroyImageKHR(eglDisplay, slots[i].eglimg);
+  }
+
+  if (eglContext != EGL_NO_CONTEXT)
+    eglDestroyContext(eglDisplay, eglContext);
+  eglContext = EGL_NO_CONTEXT;
+
+  if (eglSurface != EGL_NO_SURFACE)
+    eglDestroySurface(eglDisplay, eglSurface);
+  eglSurface = EGL_NO_SURFACE;
+
+  eglInitialized = false;
+}
+
+bool CStageFrightVideoPrivate::InitStagefrightSurface()
+{
+#if defined(DEBUG_VERBOSE)
+  CLog::Log(LOGDEBUG, "%s: >>> InitStagefrightSurface\n", CLASSNAME);
+#endif
+   if (mVideoNativeWindow != NULL)
+    return true;
+
+  mVideoTextureId = -1;
+
+  glGenTextures(1, &mVideoTextureId);
+  glBindTexture(GL_TEXTURE_EXTERNAL_OES, mVideoTextureId);
+  glTexParameterf(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+  glTexParameterf(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+  glTexParameterf(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+  glTexParameterf(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+  glBindTexture(GL_TEXTURE_EXTERNAL_OES, 0);
+
+  mSurfTexture = new CJNISurfaceTexture(mVideoTextureId);
+  mSurface = new CJNISurface(*mSurfTexture);
+
+  JNIEnv* env = xbmc_jnienv();
+  mVideoNativeWindow = ANativeWindow_fromSurface(env, mSurface->get_raw());
+  native_window_api_connect(mVideoNativeWindow.get(), NATIVE_WINDOW_API_MEDIA);
+
+#if defined(DEBUG_VERBOSE)
+  CLog::Log(LOGDEBUG, "%s: <<< InitStagefrightSurface\n", CLASSNAME);
+#endif
+  return true;
+}
+
+void CStageFrightVideoPrivate::UninitStagefrightSurface()
+{
+#if defined(DEBUG_VERBOSE)
+  CLog::Log(LOGDEBUG, "%s: >>> UninitStagefrightSurface\n", CLASSNAME);
+#endif
+  if (mVideoNativeWindow == NULL)
+    return;
+
+  native_window_api_disconnect(mVideoNativeWindow.get(), NATIVE_WINDOW_API_MEDIA);
+  ANativeWindow_release(mVideoNativeWindow.get());
+  mVideoNativeWindow = NULL;
+
+  mSurface->release();
+  mSurfTexture->release();
+
+  delete mSurface;
+  delete mSurfTexture;
+
+  glDeleteTextures(1, &mVideoTextureId);
+#if defined(DEBUG_VERBOSE)
+  CLog::Log(LOGDEBUG, "%s: <<< UninitStagefrightSurface\n", CLASSNAME);
+#endif
+}
+
+void CStageFrightVideoPrivate::UpdateStagefrightTexture()
+{
+  mSurfTexture->updateTexImage();
+}
+
+void CStageFrightVideoPrivate::GetStagefrightTransformMatrix(float* transformMatrix)
+{
+  mSurfTexture->getTransformMatrix(transformMatrix);
+}
+
diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/libstagefrightICS/StageFrightVideoPrivate.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/libstagefrightICS/StageFrightVideoPrivate.h
new file mode 100644 (file)
index 0000000..d10ef41
--- /dev/null
@@ -0,0 +1,165 @@
+#pragma once
+/*
+ *      Copyright (C) 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
+ *  <http://www.gnu.org/licenses/>.
+ *
+ */
+/***************************************************************************/
+
+#include "threads/Thread.h"
+#include "xbmc/guilib/FrameBufferObject.h"
+#include "cores/VideoRenderers/RenderFormats.h"
+
+#include <android/native_window.h>
+#include <android/native_window_jni.h>
+
+#include <media/stagefright/MetaData.h>
+#include <media/stagefright/MediaBuffer.h>
+#include <media/stagefright/MediaBufferGroup.h>
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MediaSource.h>
+
+#include <binder/ProcessState.h>
+#include <media/stagefright/OMXClient.h>
+#include <media/stagefright/OMXCodec.h>
+#include <media/stagefright/foundation/ABuffer.h>
+#include <utils/List.h>
+#include <utils/RefBase.h>
+#include <ui/GraphicBuffer.h>
+#include <ui/PixelFormat.h>
+#include <gui/SurfaceTexture.h>
+
+#include "system_gl.h"
+
+#include <map>
+#include <list>
+
+#define NUMFBOTEX 4
+#define INBUFCOUNT 16
+
+class CStageFrightDecodeThread;
+class CJNISurface;
+class CJNISurfaceTexture;
+class CWinSystemEGL;
+class CAdvancedSettings;
+
+using namespace android;
+
+struct tex_slot
+{
+  GLuint texid;
+  EGLImageKHR eglimg;
+};
+
+struct Frame
+{
+  status_t status;
+  int32_t width, height;
+  int64_t pts;
+  ERenderFormat format;
+  EGLImageKHR eglimg;
+  MediaBuffer* medbuf;
+};
+
+enum StageFrightQuirks
+{
+  QuirkNone = 0,
+  QuirkSWRender = 0x01,
+};
+
+class CStageFrightVideoPrivate : public MediaBufferObserver
+{
+public:
+  CStageFrightVideoPrivate();
+
+  virtual void signalBufferReturned(MediaBuffer *buffer);
+
+  MediaBuffer* getBuffer(size_t size);
+  bool inputBufferAvailable();
+
+  void loadOESShader(GLenum shaderType, const char* pSource, GLuint* outShader);
+  void createOESProgram(const char* pVertexSource, const char* pFragmentSource, GLuint* outPgm);
+  void OES_shader_setUp();
+  void InitializeEGL(int w, int h);
+  void UninitializeEGL();
+
+public:
+  CStageFrightDecodeThread* decode_thread;
+
+  sp<MediaSource> source;
+
+  MediaBuffer* inbuf[INBUFCOUNT];
+
+  GLuint mPgm;
+  GLint mPositionHandle;
+  GLint mTexSamplerHandle;
+  GLint mTexMatrixHandle;
+
+  CWinSystemEGL* m_g_Windowing;
+  CAdvancedSettings* m_g_advancedSettings;
+
+  CFrameBufferObject fbo;
+  EGLDisplay eglDisplay;
+  EGLSurface eglSurface;
+  EGLContext eglContext;
+  bool eglInitialized;
+
+  tex_slot slots[NUMFBOTEX];
+  std::list< std::pair<EGLImageKHR, int> > free_queue;
+  std::list< std::pair<EGLImageKHR, int> > busy_queue;
+
+  sp<MetaData> meta;
+  int64_t framecount;
+  std::map<int64_t, Frame*> in_queue;
+  std::map<int64_t, Frame*> out_queue;
+  CCriticalSection in_mutex;
+  CCriticalSection out_mutex;
+  CCriticalSection free_mutex;
+  XbmcThreads::ConditionVariable in_condition;
+  XbmcThreads::ConditionVariable out_condition;
+
+  int quirks;
+  Frame *cur_frame;
+  Frame *prev_frame;
+  bool source_done;
+  int x, y;
+  int width, height;
+  int texwidth, texheight;
+
+  OMXClient *client;
+  sp<MediaSource> decoder;
+  const char *decoder_component;
+  int videoColorFormat;
+  int videoStride;
+  int videoSliceHeight;
+
+  bool drop_state;
+  bool resetting;
+#if defined(DEBUG_VERBOSE)
+  unsigned int cycle_time;
+#endif
+
+  unsigned int mVideoTextureId;
+  CJNISurfaceTexture* mSurfTexture;
+  CJNISurface* mSurface;
+  sp<ANativeWindow> mVideoNativeWindow;
+
+  bool InitStagefrightSurface();
+  void UninitStagefrightSurface();
+  void UpdateStagefrightTexture();
+  void GetStagefrightTransformMatrix(float* transformMatrix);
+};