aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--addons/resource.language.en_gb/resources/strings.po5
-rw-r--r--configure.ac2
-rw-r--r--system/settings/android.xml9
-rw-r--r--tools/android/packaging/Makefile.in1
-rw-r--r--tools/android/packaging/xbmc/activity_main.xml.in14
-rw-r--r--tools/android/packaging/xbmc/src/org/xbmc/kodi/Main.java.in57
-rw-r--r--tools/android/packaging/xbmc/src/org/xbmc/kodi/XBMCVideoView.java.in120
-rw-r--r--xbmc/android/activity/JNIMainActivity.cpp17
-rw-r--r--xbmc/android/activity/JNIMainActivity.h4
-rw-r--r--xbmc/android/jni/Surface.cpp4
-rw-r--r--xbmc/android/jni/Surface.h1
-rw-r--r--xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp67
-rw-r--r--xbmc/cores/VideoRenderers/LinuxRendererGLES.h3
-rw-r--r--xbmc/cores/VideoRenderers/RenderFormats.h1
-rw-r--r--xbmc/cores/VideoRenderers/RenderManager.cpp2
-rw-r--r--xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.cpp18
-rw-r--r--xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecAndroidMediaCodec.cpp71
-rw-r--r--xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecAndroidMediaCodec.h11
-rw-r--r--xbmc/cores/dvdplayer/DVDPlayerVideo.cpp1
-rw-r--r--xbmc/settings/Settings.cpp2
-rw-r--r--xbmc/settings/Settings.h1
-rw-r--r--xbmc/windowing/egl/EGLNativeTypeAndroid.cpp44
-rw-r--r--xbmc/windowing/egl/EGLNativeTypeAndroid.h4
23 files changed, 387 insertions, 72 deletions
diff --git a/addons/resource.language.en_gb/resources/strings.po b/addons/resource.language.en_gb/resources/strings.po
index df3ed141a1..fa1f48432b 100644
--- a/addons/resource.language.en_gb/resources/strings.po
+++ b/addons/resource.language.en_gb/resources/strings.po
@@ -6530,7 +6530,10 @@ msgctxt "#13439"
msgid "Allow hardware acceleration - MediaCodec"
msgstr ""
-#empty string with id 13440
+#: system/settings/settings.xml
+msgctxt "#13440"
+msgid "Allow hardware acceleration - MediaCodec (Surface)"
+msgstr ""
#: system/settings/settings.xml
msgctxt "#13441"
diff --git a/configure.ac b/configure.ac
index fd5ab126ff..a86ddd94b7 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2429,6 +2429,8 @@ OUTPUT_FILES="Makefile \
tools/android/packaging/xbmc/src/org/xbmc/kodi/XBMCOnFrameAvailableListener.java \
tools/android/packaging/xbmc/src/org/xbmc/kodi/XBMCSettingsContentObserver.java \
tools/android/packaging/xbmc/src/org/xbmc/kodi/XBMCOnAudioFocusChangeListener.java \
+ tools/android/packaging/xbmc/src/org/xbmc/kodi/XBMCVideoView.java \
+ tools/android/packaging/xbmc/activity_main.xml \
tools/android/packaging/xbmc/strings.xml \
addons/xbmc.addon/addon.xml"
diff --git a/system/settings/android.xml b/system/settings/android.xml
index a3067620ce..1c5341b47b 100644
--- a/system/settings/android.xml
+++ b/system/settings/android.xml
@@ -19,6 +19,15 @@
</updates>
<control type="toggle" />
</setting>
+ <setting id="videoplayer.usemediacodecsurface" type="boolean" label="13440" help="36544">
+ <visible>HAS_MEDIACODEC</visible>
+ <level>2</level>
+ <default>true</default>
+ <updates>
+ <update type="change" />
+ </updates>
+ <control type="toggle" />
+ </setting>
<setting id="videoplayer.usemediacodec" type="boolean" label="13439" help="36544">
<visible>HAS_MEDIACODEC</visible>
<level>2</level>
diff --git a/tools/android/packaging/Makefile.in b/tools/android/packaging/Makefile.in
index 0effde17bd..2e6a78858c 100644
--- a/tools/android/packaging/Makefile.in
+++ b/tools/android/packaging/Makefile.in
@@ -113,6 +113,7 @@ res:
cp -fp media/drawable-xxhdpi/ic_launcher.png xbmc/res/drawable-xxhdpi/ic_launcher.png
cp -fp media/drawable-xhdpi/banner.png xbmc/res/drawable-xhdpi/banner.png
cp xbmc/strings.xml xbmc/res/values/
+ cp xbmc/activity_main.xml xbmc/res/layout/
mkdir -p tmp/res; $(AAPT) c -S xbmc/res -C tmp/res; cp -r -n xbmc/res tmp/ || true
$(AAPT) p -f -I $(SDKROOT)/platforms/$(SDK_PLATFORM)/android.jar -S tmp/res/ -M xbmc/AndroidManifest.xml -F images/@APP_NAME_LC@app-debug-skeleton.apk -J xbmc/src
@rm -rf tmp/
diff --git a/tools/android/packaging/xbmc/activity_main.xml.in b/tools/android/packaging/xbmc/activity_main.xml.in
new file mode 100644
index 0000000000..eb5003d519
--- /dev/null
+++ b/tools/android/packaging/xbmc/activity_main.xml.in
@@ -0,0 +1,14 @@
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/VideoLayout"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:background="@android:color/transparent" >
+
+ <org.xbmc.@APP_NAME_LC@.XBMCVideoView
+ android:id="@+id/VideoView1"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:background="@android:color/transparent" />
+
+</RelativeLayout>
+
diff --git a/tools/android/packaging/xbmc/src/org/xbmc/kodi/Main.java.in b/tools/android/packaging/xbmc/src/org/xbmc/kodi/Main.java.in
index 3ea0399452..8b1848396a 100644
--- a/tools/android/packaging/xbmc/src/org/xbmc/kodi/Main.java.in
+++ b/tools/android/packaging/xbmc/src/org/xbmc/kodi/Main.java.in
@@ -6,24 +6,64 @@ import android.media.AudioManager;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
+import android.view.Surface;
+import android.widget.RelativeLayout;
+import android.graphics.Color;
import android.graphics.PixelFormat;
import android.os.Handler;
+import org.xbmc.@APP_NAME_LC@.XBMCVideoView;
-public class Main extends NativeActivity
+public class Main extends NativeActivity
{
+ private static final String TAG = "@APP_NAME_LC@";
+
private XBMCSettingsContentObserver mSettingsContentObserver;
- private View thisView;
+ private XBMCVideoView mVideoView = null;
+ private RelativeLayout mVideoLayout = null;
+ private View thisView = null;
private Handler handler = new Handler();
native void _onNewIntent(Intent intent);
- public Main()
+ public Main()
{
super();
}
+ public Surface getVideoViewSurface()
+ {
+ return mVideoView.getSurface();
+ }
+
+ public void setVideoViewSurfaceRect(final int left, final int top, final int right, final int bottom)
+ {
+ runOnUiThread(new Runnable()
+ {
+ @Override
+ public void run()
+ {
+ android.widget.RelativeLayout.LayoutParams mp = new android.widget.RelativeLayout.LayoutParams(mVideoView.getLayoutParams());
+ mp.setMargins(left, top, mVideoLayout.getWidth() - right, mVideoLayout.getHeight() - bottom);
+ mVideoView.setLayoutParams(mp);
+ mVideoView.requestLayout();
+ }
+ });
+ }
+
+ public void clearVideoView()
+ {
+ runOnUiThread(new Runnable()
+ {
+ @Override
+ public void run()
+ {
+ mVideoView.clearSurface();
+ }
+ });
+ }
+
@Override
- public void onCreate(Bundle savedInstanceState)
+ public void onCreate(Bundle savedInstanceState)
{
// The dynamic linker on droid is a mess.
// Depending on version, it might not be able to properly resolve
@@ -36,8 +76,15 @@ public class Main extends NativeActivity
System.loadLibrary("@APP_NAME_LC@");
super.onCreate(savedInstanceState);
+ getWindow().setFormat(PixelFormat.TRANSPARENT);
+
+ setContentView(R.layout.activity_main);
+ mVideoView = (XBMCVideoView)findViewById(R.id.VideoView1);
+ mVideoView.getHolder().setFormat(PixelFormat.TRANSPARENT);
+ mVideoLayout = (RelativeLayout) findViewById(R.id.VideoLayout);
+
setVolumeControlStream(AudioManager.STREAM_MUSIC);
-
+
mSettingsContentObserver = new XBMCSettingsContentObserver(this, new Handler());
getApplicationContext().getContentResolver().registerContentObserver(android.provider.Settings.System.CONTENT_URI, true, mSettingsContentObserver );
diff --git a/tools/android/packaging/xbmc/src/org/xbmc/kodi/XBMCVideoView.java.in b/tools/android/packaging/xbmc/src/org/xbmc/kodi/XBMCVideoView.java.in
new file mode 100644
index 0000000000..432a7cdb01
--- /dev/null
+++ b/tools/android/packaging/xbmc/src/org/xbmc/kodi/XBMCVideoView.java.in
@@ -0,0 +1,120 @@
+package org.xbmc.@APP_NAME_LC@;
+
+import javax.microedition.khronos.egl.EGL10;
+import javax.microedition.khronos.egl.EGLConfig;
+import javax.microedition.khronos.egl.EGLContext;
+import javax.microedition.khronos.egl.EGLDisplay;
+import javax.microedition.khronos.egl.EGLSurface;
+
+import android.R.bool;
+import android.opengl.GLES20;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.Surface;
+import android.view.SurfaceHolder;
+import android.view.SurfaceView;
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Color;
+
+public class XBMCVideoView extends SurfaceView implements
+ SurfaceHolder.Callback
+{
+ private static final String TAG = "XBMCVideoPlayView";
+ public boolean mHasHolder = false;
+
+ public XBMCVideoView(Context context)
+ {
+ super(context);
+ getHolder().addCallback(this);
+ }
+
+ public XBMCVideoView(Context context, AttributeSet attrs)
+ {
+ this(context, attrs, 0);
+ getHolder().addCallback(this);
+ }
+
+ public XBMCVideoView(Context context, AttributeSet attrs, int defStyle)
+ {
+ super(context, attrs, defStyle);
+ getHolder().addCallback(this);
+ }
+
+ /**
+ * Clears the playback surface to black.
+ */
+ public void clearSurface()
+ {
+ // Have to go EGL to allow reuse of surface
+
+ final int EGL_OPENGL_ES2_BIT = 4;
+ final int EGL_CONTEXT_CLIENT_VERSION = 0x3098;
+
+ EGL10 egl = (EGL10) EGLContext.getEGL();
+ EGLDisplay display = egl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
+ egl.eglInitialize(display, null);
+
+ int[] attribList =
+ { EGL10.EGL_RED_SIZE, 8, EGL10.EGL_GREEN_SIZE, 8, EGL10.EGL_BLUE_SIZE, 8,
+ EGL10.EGL_ALPHA_SIZE, 8, EGL10.EGL_RENDERABLE_TYPE,
+ EGL_OPENGL_ES2_BIT, EGL10.EGL_NONE, 0, // placeholder for
+ // recordable [@-3]
+ EGL10.EGL_NONE };
+ EGLConfig[] configs = new EGLConfig[1];
+ int[] numConfigs = new int[1];
+ egl.eglChooseConfig(display, attribList, configs, configs.length,
+ numConfigs);
+ EGLConfig config = configs[0];
+ EGLContext context = egl.eglCreateContext(display, config,
+ EGL10.EGL_NO_CONTEXT, new int[]
+ { EGL_CONTEXT_CLIENT_VERSION, 2, EGL10.EGL_NONE });
+ EGLSurface eglSurface = egl.eglCreateWindowSurface(display, config,
+ this, new int[]
+ { EGL10.EGL_NONE });
+
+ egl.eglMakeCurrent(display, eglSurface, eglSurface, context);
+ GLES20.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+ GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
+ egl.eglSwapBuffers(display, eglSurface);
+ egl.eglDestroySurface(display, eglSurface);
+ egl.eglMakeCurrent(display, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_SURFACE,
+ EGL10.EGL_NO_CONTEXT);
+ egl.eglDestroyContext(display, context);
+ egl.eglTerminate(display);
+ }
+
+ public Surface getSurface()
+ {
+ if (!mHasHolder)
+ {
+ return null;
+ } else
+ {
+ Log.d(TAG, "getSurface() = " + getHolder().getSurface());
+ return getHolder().getSurface();
+ }
+ }
+
+ @Override
+ public void surfaceCreated(SurfaceHolder holder)
+ {
+ Log.d(TAG, "Created");
+ mHasHolder = true;
+ }
+
+ @Override
+ public void surfaceChanged(SurfaceHolder holder, int format, int width,
+ int height)
+ {
+ Log.d(TAG, "Changed, format:" + format + ", width:" + width
+ + ", height:" + height);
+ }
+
+ @Override
+ public void surfaceDestroyed(SurfaceHolder holder)
+ {
+ Log.d(TAG, "Destroyed");
+ mHasHolder = false;
+ }
+}
diff --git a/xbmc/android/activity/JNIMainActivity.cpp b/xbmc/android/activity/JNIMainActivity.cpp
index 322b2e4a22..1074d0124b 100644
--- a/xbmc/android/activity/JNIMainActivity.cpp
+++ b/xbmc/android/activity/JNIMainActivity.cpp
@@ -76,3 +76,20 @@ void CJNIMainActivity::_onAudioFocusChange(JNIEnv *env, jobject context, jint fo
m_appInstance->onAudioFocusChange(focusChange);
}
+CJNISurface CJNIMainActivity::getVideoViewSurface()
+{
+ return call_method<jhobject>(m_context,
+ "getVideoViewSurface", "()Landroid/view/Surface;");
+}
+
+void CJNIMainActivity::clearVideoView()
+{
+ call_method<void>(m_context,
+ "clearVideoView", "()V");
+}
+
+void CJNIMainActivity::setVideoViewSurfaceRect(int l, int t, int r, int b)
+{
+ call_method<void>(m_context,
+ "setVideoViewSurfaceRect", "(IIII)V", l, t, r, b);
+}
diff --git a/xbmc/android/activity/JNIMainActivity.h b/xbmc/android/activity/JNIMainActivity.h
index 848b354800..300ea81af7 100644
--- a/xbmc/android/activity/JNIMainActivity.h
+++ b/xbmc/android/activity/JNIMainActivity.h
@@ -37,6 +37,10 @@ public:
static void _callNative(JNIEnv *env, jobject context, jlong funcAddr, jlong variantAddr);
static void runNativeOnUiThread(void (*callback)(CVariant *), CVariant *variant);
+ CJNISurface getVideoViewSurface();
+ void clearVideoView();
+ void setVideoViewSurfaceRect(int l, int t, int r, int b);
+
private:
static CJNIMainActivity *m_appInstance;
diff --git a/xbmc/android/jni/Surface.cpp b/xbmc/android/jni/Surface.cpp
index 59a8a253e4..c91b0d8a47 100644
--- a/xbmc/android/jni/Surface.cpp
+++ b/xbmc/android/jni/Surface.cpp
@@ -41,6 +41,10 @@ void CJNISurface::PopulateStaticFields()
ROTATION_270= get_static_field<int>(clazz, "ROTATION_270");
}
+CJNISurface::CJNISurface()
+ : CJNIBase(CJNISurface::m_classname)
+{
+}
CJNISurface::CJNISurface(const CJNISurfaceTexture &surfaceTexture) : CJNIBase(m_classname)
{
diff --git a/xbmc/android/jni/Surface.h b/xbmc/android/jni/Surface.h
index 2259807405..85fc1b8efb 100644
--- a/xbmc/android/jni/Surface.h
+++ b/xbmc/android/jni/Surface.h
@@ -25,6 +25,7 @@ class CJNISurfaceTexture;
class CJNISurface : public CJNIBase
{
public:
+ CJNISurface();
CJNISurface(const CJNISurfaceTexture &surfaceTexture);
CJNISurface(const jni::jhobject &object) : CJNIBase(object) {};
~CJNISurface() {};
diff --git a/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp b/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp
index d398d13b8a..af063416a8 100644
--- a/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp
+++ b/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp
@@ -594,6 +594,44 @@ void CLinuxRendererGLES::RenderUpdateVideo(bool clear, DWORD flags, DWORD alpha)
return;
}
+#ifdef TARGET_ANDROID
+ else if (m_renderMethod & RENDER_MEDIACODECSURFACE)
+ {
+ CDVDMediaCodecInfo *mci = m_buffers[m_iYV12RenderBuffer].mediacodec;
+ if (mci)
+ {
+ // this hack is needed to get the 2D mode of a 3D movie going
+ RENDER_STEREO_MODE stereo_mode = g_graphicsContext.GetStereoMode();
+ if (stereo_mode)
+ g_graphicsContext.SetStereoView(RENDER_STEREO_VIEW_LEFT);
+
+ ManageDisplay();
+
+ if (stereo_mode)
+ g_graphicsContext.SetStereoView(RENDER_STEREO_VIEW_OFF);
+
+ CRect dstRect(m_destRect);
+ CRect srcRect(m_sourceRect);
+ switch (stereo_mode)
+ {
+ case RENDER_STEREO_MODE_SPLIT_HORIZONTAL:
+ dstRect.y2 *= 2.0;
+ srcRect.y2 *= 2.0;
+ break;
+
+ case RENDER_STEREO_MODE_SPLIT_VERTICAL:
+ dstRect.x2 *= 2.0;
+ srcRect.x2 *= 2.0;
+ break;
+
+ default:
+ break;
+ }
+
+ mci->RenderUpdate(srcRect, dstRect);
+ }
+ }
+#endif
#ifdef HAS_IMXVPU
else if (m_renderMethod & RENDER_IMXMAP)
{
@@ -722,6 +760,7 @@ unsigned int CLinuxRendererGLES::PreInit()
#endif
#if defined(TARGET_ANDROID)
m_formats.push_back(RENDER_FMT_MEDIACODEC);
+ m_formats.push_back(RENDER_FMT_MEDIACODECSURFACE);
#endif
#ifdef HAS_IMXVPU
m_formats.push_back(RENDER_FMT_IMXMAP);
@@ -828,6 +867,12 @@ void CLinuxRendererGLES::LoadShaders(int field)
m_renderMethod = RENDER_MEDIACODEC;
break;
}
+ else if (m_format == RENDER_FMT_MEDIACODECSURFACE)
+ {
+ CLog::Log(LOGNOTICE, "GL: Using MediaCodec (Surface) render method");
+ m_renderMethod = RENDER_MEDIACODECSURFACE;
+ break;
+ }
else if (m_format == RENDER_FMT_IMXMAP)
{
CLog::Log(LOGNOTICE, "GL: Using IMXMAP render method");
@@ -902,7 +947,7 @@ void CLinuxRendererGLES::LoadShaders(int field)
m_textureCreate = &CLinuxRendererGLES::CreateCVRefTexture;
m_textureDelete = &CLinuxRendererGLES::DeleteCVRefTexture;
}
- else if (m_format == RENDER_FMT_BYPASS)
+ else if (m_format == RENDER_FMT_BYPASS || m_format == RENDER_FMT_MEDIACODECSURFACE)
{
m_textureUpload = &CLinuxRendererGLES::UploadBYPASSTexture;
m_textureCreate = &CLinuxRendererGLES::CreateBYPASSTexture;
@@ -1043,6 +1088,8 @@ void CLinuxRendererGLES::ReleaseBuffer(int idx)
SAFE_RELEASE(buf.mediacodec);
}
}
+ if ( m_renderMethod & RENDER_MEDIACODECSURFACE )
+ SAFE_RELEASE(buf.mediacodec);
#endif
#ifdef HAS_IMXVPU
if (m_renderMethod & RENDER_IMXMAP)
@@ -1053,7 +1100,7 @@ void CLinuxRendererGLES::ReleaseBuffer(int idx)
void CLinuxRendererGLES::Render(DWORD flags, int index)
{
// If rendered directly by the hardware
- if (m_renderMethod & RENDER_BYPASS)
+ if (m_renderMethod & RENDER_BYPASS || m_renderMethod & RENDER_MEDIACODECSURFACE)
return;
// obtain current field, if interlaced
@@ -1836,7 +1883,7 @@ bool CLinuxRendererGLES::RenderCapture(CRenderCapture* capture)
return false;
// If rendered directly by the hardware
- if (m_renderMethod & RENDER_BYPASS)
+ if (m_renderMethod & RENDER_BYPASS || m_renderMethod & RENDER_MEDIACODECSURFACE)
{
capture->BeginRender();
capture->EndRender();
@@ -2926,6 +2973,9 @@ bool CLinuxRendererGLES::Supports(EINTERLACEMETHOD method)
return false;
}
+ if(m_renderMethod & RENDER_MEDIACODECSURFACE)
+ return false;
+
if(m_renderMethod & RENDER_CVREF)
return false;
@@ -2967,6 +3017,9 @@ bool CLinuxRendererGLES::Supports(ESCALINGMETHOD method)
if(m_renderMethod & RENDER_IMXMAP)
return false;
+ if (m_renderMethod & RENDER_MEDIACODECSURFACE)
+ return false;
+
if(method == VS_SCALINGMETHOD_NEAREST
|| method == VS_SCALINGMETHOD_LINEAR)
return true;
@@ -2994,6 +3047,9 @@ EINTERLACEMETHOD CLinuxRendererGLES::AutoInterlaceMethod()
if(m_renderMethod & RENDER_MEDIACODEC)
return VS_INTERLACEMETHOD_RENDER_BOB_INVERTED;
+ if(m_renderMethod & RENDER_MEDIACODECSURFACE)
+ return VS_INTERLACEMETHOD_NONE;
+
if(m_renderMethod & RENDER_CVREF)
return VS_INTERLACEMETHOD_NONE;
@@ -3015,7 +3071,8 @@ CRenderInfo CLinuxRendererGLES::GetRenderInfo()
if(m_format == RENDER_FMT_OMXEGL ||
m_format == RENDER_FMT_CVBREF ||
m_format == RENDER_FMT_EGLIMG ||
- m_format == RENDER_FMT_MEDIACODEC)
+ m_format == RENDER_FMT_MEDIACODEC ||
+ m_format == RENDER_FMT_MEDIACODECSURFACE)
info.optimal_buffer_size = 2;
else if(m_format == RENDER_FMT_IMXMAP)
{
@@ -3114,7 +3171,7 @@ void CLinuxRendererGLES::AddProcessor(CDVDVideoCodecIMXBuffer *buffer, int index
bool CLinuxRendererGLES::IsGuiLayer()
{
- if (m_format == RENDER_FMT_BYPASS || m_format == RENDER_FMT_IMXMAP)
+ if (m_format == RENDER_FMT_BYPASS || m_format == RENDER_FMT_IMXMAP || m_format == RENDER_FMT_MEDIACODECSURFACE)
return false;
else
return true;
diff --git a/xbmc/cores/VideoRenderers/LinuxRendererGLES.h b/xbmc/cores/VideoRenderers/LinuxRendererGLES.h
index 2d803d5f44..77bbb579f3 100644
--- a/xbmc/cores/VideoRenderers/LinuxRendererGLES.h
+++ b/xbmc/cores/VideoRenderers/LinuxRendererGLES.h
@@ -93,7 +93,8 @@ enum RenderMethod
RENDER_BYPASS = 0x100,
RENDER_EGLIMG = 0x200,
RENDER_MEDIACODEC = 0x400,
- RENDER_IMXMAP = 0x800
+ RENDER_MEDIACODECSURFACE = 0x800,
+ RENDER_IMXMAP = 0x1000
};
enum RenderQuality
diff --git a/xbmc/cores/VideoRenderers/RenderFormats.h b/xbmc/cores/VideoRenderers/RenderFormats.h
index 97634c278c..c6329ff7f6 100644
--- a/xbmc/cores/VideoRenderers/RenderFormats.h
+++ b/xbmc/cores/VideoRenderers/RenderFormats.h
@@ -40,6 +40,7 @@ enum ERenderFormat {
RENDER_FMT_BYPASS,
RENDER_FMT_EGLIMG,
RENDER_FMT_MEDIACODEC,
+ RENDER_FMT_MEDIACODECSURFACE,
RENDER_FMT_IMXMAP,
RENDER_FMT_MMAL,
};
diff --git a/xbmc/cores/VideoRenderers/RenderManager.cpp b/xbmc/cores/VideoRenderers/RenderManager.cpp
index 24edf5a92e..7a99ac4beb 100644
--- a/xbmc/cores/VideoRenderers/RenderManager.cpp
+++ b/xbmc/cores/VideoRenderers/RenderManager.cpp
@@ -1018,7 +1018,7 @@ int CXBMCRenderManager::AddVideoPicture(DVDVideoPicture& pic)
m_pRenderer->AddProcessor(pic.stf, pic.eglimg, index);
#endif
#if defined(TARGET_ANDROID)
- else if(pic.format == RENDER_FMT_MEDIACODEC)
+ else if(pic.format == RENDER_FMT_MEDIACODEC || pic.format == RENDER_FMT_MEDIACODECSURFACE)
m_pRenderer->AddProcessor(pic.mediacodec, index);
#endif
#ifdef HAS_IMXVPU
diff --git a/xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.cpp b/xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.cpp
index 3c16ec349a..84e9ef1700 100644
--- a/xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.cpp
+++ b/xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.cpp
@@ -263,6 +263,22 @@ CDVDVideoCodec* CDVDFactoryCodec::CreateVideoCodec(CDVDStreamInfo &hint, const C
#endif
#if defined(TARGET_ANDROID)
+ if (!hint.software && CSettings::GetInstance().GetBool(CSettings::SETTING_VIDEOPLAYER_USEMEDIACODECSURFACE))
+ {
+ switch(hint.codec)
+ {
+ case AV_CODEC_ID_MPEG4:
+ case AV_CODEC_ID_MSMPEG4V2:
+ case AV_CODEC_ID_MSMPEG4V3:
+ // Avoid h/w decoder for SD; Those files might use features
+ // not supported and can easily be soft-decoded
+ if (hint.width <= 800)
+ break;
+ default:
+ CLog::Log(LOGINFO, "MediaCodec (Surface) Video Decoder...");
+ if ( (pCodec = OpenCodec(new CDVDVideoCodecAndroidMediaCodec(true), hint, options)) ) return pCodec;
+ }
+ }
if (!hint.software && CSettings::GetInstance().GetBool(CSettings::SETTING_VIDEOPLAYER_USEMEDIACODEC))
{
switch(hint.codec)
@@ -276,7 +292,7 @@ CDVDVideoCodec* CDVDFactoryCodec::CreateVideoCodec(CDVDStreamInfo &hint, const C
break;
default:
CLog::Log(LOGINFO, "MediaCodec Video Decoder...");
- if ( (pCodec = OpenCodec(new CDVDVideoCodecAndroidMediaCodec(), hint, options)) ) return pCodec;
+ if ( (pCodec = OpenCodec(new CDVDVideoCodecAndroidMediaCodec(false), hint, options)) ) return pCodec;
}
}
#endif
diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecAndroidMediaCodec.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecAndroidMediaCodec.cpp
index 7953d66df2..3ef826550a 100644
--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecAndroidMediaCodec.cpp
+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecAndroidMediaCodec.cpp
@@ -36,6 +36,9 @@
#include "utils/CPUInfo.h"
#include "utils/log.h"
#include "settings/AdvancedSettings.h"
+#include "android/activity/XBMCApp.h"
+#include "cores/VideoRenderers/RenderManager.h"
+#include "cores/VideoRenderers/RenderFlags.h"
#include "android/jni/ByteBuffer.h"
#include "android/jni/MediaCodec.h"
@@ -172,10 +175,7 @@ CDVDMediaCodecInfo::CDVDMediaCodecInfo(
{
// paranoid checks
assert(m_index >= 0);
- assert(m_texture > 0);
assert(m_codec != NULL);
- assert(m_surfacetexture != NULL);
- assert(m_frameready != NULL);
}
CDVDMediaCodecInfo::~CDVDMediaCodecInfo()
@@ -220,7 +220,8 @@ void CDVDMediaCodecInfo::ReleaseOutputBuffer(bool render)
// then wait for rendered frame to become avaliable.
if (render)
- m_frameready->Reset();
+ if (m_frameready)
+ m_frameready->Reset();
m_codec->releaseOutputBuffer(m_index, render);
m_isReleased = true;
@@ -295,15 +296,35 @@ void CDVDMediaCodecInfo::UpdateTexImage()
}
}
+void CDVDMediaCodecInfo::RenderUpdate(const CRect &SrcRect, const CRect &DestRect)
+{
+ CSingleLock lock(m_section);
+
+ static CRect cur_rect;
+
+ if (!m_valid)
+ return;
+
+ if (DestRect != cur_rect)
+ {
+ CXBMCApp::get()->setVideoViewSurfaceRect(DestRect.x1, DestRect.y1, DestRect.x2, DestRect.y2);
+ cur_rect = DestRect;
+ }
+
+ ReleaseOutputBuffer(true);
+}
+
+
/*****************************************************************************/
/*****************************************************************************/
-CDVDVideoCodecAndroidMediaCodec::CDVDVideoCodecAndroidMediaCodec()
+CDVDVideoCodecAndroidMediaCodec::CDVDVideoCodecAndroidMediaCodec(bool surface_render)
: m_formatname("mediacodec")
, m_opened(false)
, m_surface(NULL)
, m_textureId(0)
, m_bitstream(NULL)
, m_render_sw(false)
+, m_render_surface(surface_render)
{
memset(&m_videobuffer, 0x00, sizeof(DVDVideoPicture));
memset(&m_demux_pkt, 0, sizeof(m_demux_pkt));
@@ -450,6 +471,9 @@ bool CDVDVideoCodecAndroidMediaCodec::Open(CDVDStreamInfo &hints, CDVDCodecOptio
break;
}
+ if (m_render_surface)
+ m_formatname += "(S)";
+
// CJNIMediaCodec::createDecoderByXXX doesn't handle errors nicely,
// it crashes if the codec isn't found. This is fixed in latest AOSP,
// but not in current 4.1 devices. So 1st search for a matching codec, then create it.
@@ -522,6 +546,7 @@ bool CDVDVideoCodecAndroidMediaCodec::Open(CDVDStreamInfo &hints, CDVDCodecOptio
SAFE_DELETE(m_bitstream);
return false;
}
+ m_render_surface = false;
}
// setup a YUV420P DVDVideoPicture buffer.
@@ -562,6 +587,8 @@ void CDVDVideoCodecAndroidMediaCodec::Dispose()
m_opened = false;
+ g_renderManager.RegisterRenderUpdateCallBack((const void*)NULL, NULL);
+
// release any retained demux packets
if (m_demux_pkt.pData)
free(m_demux_pkt.pData);
@@ -593,6 +620,8 @@ void CDVDVideoCodecAndroidMediaCodec::Dispose()
xbmc_jnienv()->ExceptionClear();
}
ReleaseSurfaceTexture();
+ if (m_render_surface)
+ CXBMCApp::get()->clearVideoView();
SAFE_DELETE(m_bitstream);
}
@@ -801,7 +830,7 @@ bool CDVDVideoCodecAndroidMediaCodec::GetPicture(DVDVideoPicture* pDvdVideoPictu
bool CDVDVideoCodecAndroidMediaCodec::ClearPicture(DVDVideoPicture* pDvdVideoPicture)
{
- if (pDvdVideoPicture->format == RENDER_FMT_MEDIACODEC)
+ if (pDvdVideoPicture->format == RENDER_FMT_MEDIACODEC || pDvdVideoPicture->format == RENDER_FMT_MEDIACODECSURFACE)
SAFE_RELEASE(pDvdVideoPicture->mediacodec);
memset(pDvdVideoPicture, 0x00, sizeof(DVDVideoPicture));
@@ -843,7 +872,10 @@ void CDVDVideoCodecAndroidMediaCodec::FlushInternal()
return;
for (size_t i = 0; i < m_inflight.size(); i++)
+ {
m_inflight[i]->Validate(false);
+ m_inflight[i]->Release();
+ }
m_inflight.clear();
for (size_t i = 0; i < m_output.size(); i++)
@@ -885,6 +917,8 @@ bool CDVDVideoCodecAndroidMediaCodec::ConfigureMediaCodec(void)
}
InitSurfaceTexture();
+ if (m_render_surface)
+ m_videosurface = CXBMCApp::get()->getVideoViewSurface();
// configure and start the codec.
// use the MediaFormat that we have setup.
@@ -901,12 +935,16 @@ bool CDVDVideoCodecAndroidMediaCodec::ConfigureMediaCodec(void)
}
else
{
- m_codec->configure(mediaformat, *m_surface, crypto, flags);
+ if (m_render_surface)
+ m_codec->configure(mediaformat, m_videosurface, crypto, flags);
+ else
+ m_codec->configure(mediaformat, *m_surface, crypto, flags);
}
// always, check/clear jni exceptions.
if (xbmc_jnienv()->ExceptionCheck())
{
CLog::Log(LOGERROR, "CDVDVideoCodecAndroidMediaCodec::ExceptionCheck: configure");
+ xbmc_jnienv()->ExceptionDescribe();
xbmc_jnienv()->ExceptionClear();
return false;
}
@@ -917,6 +955,7 @@ bool CDVDVideoCodecAndroidMediaCodec::ConfigureMediaCodec(void)
if (xbmc_jnienv()->ExceptionCheck())
{
CLog::Log(LOGERROR, "CDVDVideoCodecAndroidMediaCodec::ExceptionCheck: start");
+ xbmc_jnienv()->ExceptionDescribe();
xbmc_jnienv()->ExceptionClear();
return false;
}
@@ -932,7 +971,7 @@ int CDVDVideoCodecAndroidMediaCodec::GetOutputPicture(void)
{
int rtn = 0;
- int64_t timeout_us = 1000;
+ int64_t timeout_us = 10000;
CJNIMediaCodecBufferInfo bufferInfo;
int index = m_codec->dequeueOutputBuffer(bufferInfo, timeout_us);
if (xbmc_jnienv()->ExceptionCheck())
@@ -1137,8 +1176,16 @@ void CDVDVideoCodecAndroidMediaCodec::ConfigureOutputFormat(CJNIMediaFormat* med
if (!m_render_sw)
{
- CLog::Log(LOGDEBUG, "CDVDVideoCodecAndroidMediaCodec:: Direct Surface Rendering");
- m_videobuffer.format = RENDER_FMT_MEDIACODEC;
+ if (m_render_surface)
+ {
+ CLog::Log(LOGDEBUG, "CDVDVideoCodecAndroidMediaCodec:: Multi-Surface Rendering");
+ m_videobuffer.format = RENDER_FMT_MEDIACODECSURFACE;
+ }
+ else
+ {
+ CLog::Log(LOGDEBUG, "CDVDVideoCodecAndroidMediaCodec:: Direct Surface Rendering");
+ m_videobuffer.format = RENDER_FMT_MEDIACODEC;
+ }
}
else
{
@@ -1305,7 +1352,7 @@ void CDVDVideoCodecAndroidMediaCodec::CallbackInitSurfaceTexture(void *userdata)
void CDVDVideoCodecAndroidMediaCodec::InitSurfaceTexture(void)
{
- if (m_render_sw)
+ if (m_render_sw || m_render_surface)
return;
// We MUST create the GLES texture on the main thread
@@ -1348,7 +1395,7 @@ void CDVDVideoCodecAndroidMediaCodec::InitSurfaceTexture(void)
void CDVDVideoCodecAndroidMediaCodec::ReleaseSurfaceTexture(void)
{
- if (m_render_sw)
+ if (m_render_sw || m_render_surface)
return;
// it is safe to delete here even though these items
diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecAndroidMediaCodec.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecAndroidMediaCodec.h
index 82da3f9c72..c320a84495 100644
--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecAndroidMediaCodec.h
+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecAndroidMediaCodec.h
@@ -28,6 +28,8 @@
#include "DVDStreamInfo.h"
#include "threads/Thread.h"
#include "threads/SingleLock.h"
+#include "android/jni/Surface.h"
+#include "guilib/Geometry.h"
class CJNISurface;
class CJNISurfaceTexture;
@@ -66,6 +68,7 @@ public:
int GetTextureID() const;
void GetTransformMatrix(float *textureMatrix);
void UpdateTexImage();
+ void RenderUpdate(const CRect &SrcRect, const CRect &DestRect);
private:
// private because we are reference counted
@@ -88,7 +91,7 @@ private:
class CDVDVideoCodecAndroidMediaCodec : public CDVDVideoCodec
{
public:
- CDVDVideoCodecAndroidMediaCodec();
+ CDVDVideoCodecAndroidMediaCodec(bool surface_render = false);
virtual ~CDVDVideoCodecAndroidMediaCodec();
// required overrides
@@ -101,7 +104,7 @@ public:
virtual void SetDropState(bool bDrop);
virtual int GetDataSize(void);
virtual double GetTimeSize(void);
- virtual const char* GetName(void) { return m_formatname; }
+ virtual const char* GetName(void) { return m_formatname.c_str(); }
virtual unsigned GetAllowedReferences();
protected:
@@ -119,12 +122,13 @@ protected:
std::string m_mime;
std::string m_codecname;
int m_colorFormat;
- const char *m_formatname;
+ std::string m_formatname;
bool m_opened;
bool m_drop;
CJNISurface *m_surface;
unsigned int m_textureId;
+ CJNISurface m_videosurface;
// we need these as shared_ptr because CDVDVideoCodecAndroidMediaCodec
// will get deleted before CLinuxRendererGLES is shut down and
// CLinuxRendererGLES refs them via CDVDMediaCodecInfo.
@@ -141,6 +145,7 @@ protected:
DVDVideoPicture m_videobuffer;
bool m_render_sw;
+ bool m_render_surface;
int m_src_offset[4];
int m_src_stride[4];
};
diff --git a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp
index 87cfb78158..379c54153c 100644
--- a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp
+++ b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp
@@ -928,6 +928,7 @@ static std::string GetRenderFormatName(ERenderFormat format)
case RENDER_FMT_EGLIMG: return "EGLIMG";
case RENDER_FMT_BYPASS: return "BYPASS";
case RENDER_FMT_MEDIACODEC:return "MEDIACODEC";
+ case RENDER_FMT_MEDIACODECSURFACE:return "MEDIACODECSURFACE";
case RENDER_FMT_IMXMAP: return "IMXMAP";
case RENDER_FMT_MMAL: return "MMAL";
case RENDER_FMT_NONE: return "NONE";
diff --git a/xbmc/settings/Settings.cpp b/xbmc/settings/Settings.cpp
index 904c54bbab..aeed0b17d2 100644
--- a/xbmc/settings/Settings.cpp
+++ b/xbmc/settings/Settings.cpp
@@ -161,6 +161,7 @@ const std::string CSettings::SETTING_VIDEOPLAYER_RENDERMETHOD = "videoplayer.ren
const std::string CSettings::SETTING_VIDEOPLAYER_HQSCALERS = "videoplayer.hqscalers";
const std::string CSettings::SETTING_VIDEOPLAYER_USEAMCODEC = "videoplayer.useamcodec";
const std::string CSettings::SETTING_VIDEOPLAYER_USEMEDIACODEC = "videoplayer.usemediacodec";
+const std::string CSettings::SETTING_VIDEOPLAYER_USEMEDIACODECSURFACE = "videoplayer.usemediacodecsurface";
const std::string CSettings::SETTING_VIDEOPLAYER_USEVDPAU = "videoplayer.usevdpau";
const std::string CSettings::SETTING_VIDEOPLAYER_USEVDPAUMIXER = "videoplayer.usevdpaumixer";
const std::string CSettings::SETTING_VIDEOPLAYER_USEVDPAUMPEG2 = "videoplayer.usevdpaumpeg2";
@@ -1098,6 +1099,7 @@ void CSettings::InitializeISettingCallbacks()
settingSet.insert(CSettings::SETTING_VIDEOSCREEN_TESTPATTERN);
settingSet.insert(CSettings::SETTING_VIDEOPLAYER_USEAMCODEC);
settingSet.insert(CSettings::SETTING_VIDEOPLAYER_USEMEDIACODEC);
+ settingSet.insert(CSettings::SETTING_VIDEOPLAYER_USEMEDIACODECSURFACE);
m_settingsManager->RegisterCallback(&g_application, settingSet);
settingSet.clear();
diff --git a/xbmc/settings/Settings.h b/xbmc/settings/Settings.h
index c1f09e0eae..415ed3b869 100644
--- a/xbmc/settings/Settings.h
+++ b/xbmc/settings/Settings.h
@@ -117,6 +117,7 @@ public:
static const std::string SETTING_VIDEOPLAYER_HQSCALERS;
static const std::string SETTING_VIDEOPLAYER_USEAMCODEC;
static const std::string SETTING_VIDEOPLAYER_USEMEDIACODEC;
+ static const std::string SETTING_VIDEOPLAYER_USEMEDIACODECSURFACE;
static const std::string SETTING_VIDEOPLAYER_USEVDPAU;
static const std::string SETTING_VIDEOPLAYER_USEVDPAUMIXER;
static const std::string SETTING_VIDEOPLAYER_USEVDPAUMPEG2;
diff --git a/xbmc/windowing/egl/EGLNativeTypeAndroid.cpp b/xbmc/windowing/egl/EGLNativeTypeAndroid.cpp
index b90d4fbfa6..5f9de94972 100644
--- a/xbmc/windowing/egl/EGLNativeTypeAndroid.cpp
+++ b/xbmc/windowing/egl/EGLNativeTypeAndroid.cpp
@@ -35,7 +35,6 @@
#include "android/jni/System.h"
CEGLNativeTypeAndroid::CEGLNativeTypeAndroid()
- : m_width(0), m_height(0)
{
}
@@ -67,29 +66,6 @@ static bool DeviceCanUseDisplaysize(const std::string &name)
void CEGLNativeTypeAndroid::Initialize()
{
std::string displaySize;
- m_width = m_height = 0;
-
- // FIXME: Temporary shield specific hack to obtain HDMI resolution
- // Remove and use New Android M API
- if (DeviceCanUseDisplaysize(CJNIBuild::DEVICE))
- displaySize = CJNISystemProperties::get("sys.display-size", "");
-
- // Override with xmbc_properties if present
- std::string customdisplaySize = CJNISystem::getProperty("xbmc.display-size", "");
- if (!customdisplaySize.empty())
- displaySize = customdisplaySize;
-
- if (!displaySize.empty())
- {
- CLog::Log(LOGDEBUG, "CEGLNativeTypeAndroid: display-size: %s", displaySize.c_str());
- std::vector<std::string> aSize = StringUtils::Split(displaySize, "x");
- if (aSize.size() == 2)
- {
- m_width = StringUtils::IsInteger(aSize[0]) ? atoi(aSize[0].c_str()) : 0;
- m_height = StringUtils::IsInteger(aSize[1]) ? atoi(aSize[1].c_str()) : 0;
- }
- }
-
return;
}
void CEGLNativeTypeAndroid::Destroy()
@@ -170,18 +146,10 @@ bool CEGLNativeTypeAndroid::GetNativeResolution(RESOLUTION_INFO *res) const
if (!nativeWindow)
return false;
- if (!m_width || !m_height)
- {
- ANativeWindow_acquire(*nativeWindow);
- res->iWidth = ANativeWindow_getWidth(*nativeWindow);
- res->iHeight= ANativeWindow_getHeight(*nativeWindow);
- ANativeWindow_release(*nativeWindow);
- }
- else
- {
- res->iWidth = m_width;
- res->iHeight = m_height;
- }
+ ANativeWindow_acquire(*nativeWindow);
+ res->iWidth = ANativeWindow_getWidth(*nativeWindow);
+ res->iHeight= ANativeWindow_getHeight(*nativeWindow);
+ ANativeWindow_release(*nativeWindow);
res->fRefreshRate = currentRefreshRate();
res->dwFlags= D3DPRESENTFLAG_PROGRESSIVE;
@@ -199,9 +167,7 @@ bool CEGLNativeTypeAndroid::GetNativeResolution(RESOLUTION_INFO *res) const
bool CEGLNativeTypeAndroid::SetNativeResolution(const RESOLUTION_INFO &res)
{
- CLog::Log(LOGDEBUG, "CEGLNativeTypeAndroid: SetNativeResolution: %dx%d", m_width, m_height);
- if (m_width && m_height)
- CXBMCApp::SetBuffersGeometry(m_width, m_height, 0);
+ CLog::Log(LOGNOTICE, "CEGLNativeTypeAndroid: Switching to resolution: %s", res.strMode.c_str());
if (abs(currentRefreshRate() - res.fRefreshRate) > 0.0001)
CXBMCApp::SetRefreshRate(res.fRefreshRate);
diff --git a/xbmc/windowing/egl/EGLNativeTypeAndroid.h b/xbmc/windowing/egl/EGLNativeTypeAndroid.h
index 8c99c1df23..f26215d8cd 100644
--- a/xbmc/windowing/egl/EGLNativeTypeAndroid.h
+++ b/xbmc/windowing/egl/EGLNativeTypeAndroid.h
@@ -46,8 +46,4 @@ public:
virtual bool GetPreferredResolution(RESOLUTION_INFO *res) const;
virtual bool ShowWindow(bool show);
-
-protected:
- int m_width;
- int m_height;
};