diff --git a/android/ijkplayer/build.gradle b/android/ijkplayer/build.gradle
index abc1270f52..a9f95ddeeb 100644
--- a/android/ijkplayer/build.gradle
+++ b/android/ijkplayer/build.gradle
@@ -2,10 +2,11 @@
buildscript {
repositories {
+ google()
jcenter()
}
dependencies {
- classpath 'com.android.tools.build:gradle:2.1.3'
+ classpath 'com.android.tools.build:gradle:3.2.1'
classpath 'com.github.dcendents:android-maven-gradle-plugin:1.4.1'
classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.7'
@@ -16,20 +17,21 @@ buildscript {
allprojects {
repositories {
+ google()
jcenter()
}
}
ext {
- compileSdkVersion = 25
- buildToolsVersion = "25.0.3"
+ compileSdkVersion = 28
+ buildToolsVersion = "28.0.3"
- targetSdkVersion = 25
+ targetSdkVersion = 28
versionCode = 800800
versionName = "0.8.8"
}
wrapper {
- gradleVersion = '2.14.1'
+ gradleVersion = '4.6'
}
diff --git a/android/ijkplayer/gradle/wrapper/gradle-wrapper.properties b/android/ijkplayer/gradle/wrapper/gradle-wrapper.properties
index f47ae66616..225518ccc2 100644
--- a/android/ijkplayer/gradle/wrapper/gradle-wrapper.properties
+++ b/android/ijkplayer/gradle/wrapper/gradle-wrapper.properties
@@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-all.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip
diff --git a/android/ijkplayer/ijkplayer-arm64/src/main/AndroidManifest.xml b/android/ijkplayer/ijkplayer-arm64/src/main/AndroidManifest.xml
index f075c28515..88a4fb0d68 100644
--- a/android/ijkplayer/ijkplayer-arm64/src/main/AndroidManifest.xml
+++ b/android/ijkplayer/ijkplayer-arm64/src/main/AndroidManifest.xml
@@ -1,7 +1,4 @@
-
-
diff --git a/android/ijkplayer/ijkplayer-armv5/src/main/AndroidManifest.xml b/android/ijkplayer/ijkplayer-armv5/src/main/AndroidManifest.xml
index 5d35eadf2a..2975659e0f 100644
--- a/android/ijkplayer/ijkplayer-armv5/src/main/AndroidManifest.xml
+++ b/android/ijkplayer/ijkplayer-armv5/src/main/AndroidManifest.xml
@@ -1,7 +1,4 @@
-
-
\ No newline at end of file
diff --git a/android/ijkplayer/ijkplayer-armv7a/src/main/AndroidManifest.xml b/android/ijkplayer/ijkplayer-armv7a/src/main/AndroidManifest.xml
index f3727da39c..64e550b80c 100644
--- a/android/ijkplayer/ijkplayer-armv7a/src/main/AndroidManifest.xml
+++ b/android/ijkplayer/ijkplayer-armv7a/src/main/AndroidManifest.xml
@@ -1,7 +1,4 @@
-
-
\ No newline at end of file
diff --git a/android/ijkplayer/ijkplayer-example/build.gradle b/android/ijkplayer/ijkplayer-example/build.gradle
index ae4a0c6589..b9d14b2b80 100644
--- a/android/ijkplayer/ijkplayer-example/build.gradle
+++ b/android/ijkplayer/ijkplayer-example/build.gradle
@@ -16,6 +16,8 @@ android {
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode rootProject.ext.versionCode
versionName rootProject.ext.versionName
+
+ flavorDimensions "versionCode"
}
buildTypes {
release {
@@ -24,7 +26,7 @@ android {
}
}
productFlavors {
- all32 { minSdkVersion 9 }
+// all32 { minSdkVersion 9 }
all64 { minSdkVersion 21 }
// armv5 {}
// armv7a {}
@@ -44,9 +46,9 @@ dependencies {
compile project(':ijkplayer-java')
compile project(':ijkplayer-exo')
- all32Compile project(':ijkplayer-armv5')
- all32Compile project(':ijkplayer-armv7a')
- all32Compile project(':ijkplayer-x86')
+// all32Compile project(':ijkplayer-armv5')
+// all32Compile project(':ijkplayer-armv7a')
+// all32Compile project(':ijkplayer-x86')
all64Compile project(':ijkplayer-armv5')
all64Compile project(':ijkplayer-armv7a')
diff --git a/android/ijkplayer/ijkplayer-example/src/main/AndroidManifest.xml b/android/ijkplayer/ijkplayer-example/src/main/AndroidManifest.xml
index dd3a3af123..13eab76b5e 100644
--- a/android/ijkplayer/ijkplayer-example/src/main/AndroidManifest.xml
+++ b/android/ijkplayer/ijkplayer-example/src/main/AndroidManifest.xml
@@ -2,9 +2,7 @@
-
+
diff --git a/android/ijkplayer/ijkplayer-example/src/main/java/tv/danmaku/ijk/media/example/widget/filter/AbsIjkRender.java b/android/ijkplayer/ijkplayer-example/src/main/java/tv/danmaku/ijk/media/example/widget/filter/AbsIjkRender.java
new file mode 100644
index 0000000000..0d2edea3a4
--- /dev/null
+++ b/android/ijkplayer/ijkplayer-example/src/main/java/tv/danmaku/ijk/media/example/widget/filter/AbsIjkRender.java
@@ -0,0 +1,137 @@
+package tv.danmaku.ijk.media.example.widget.filter;
+
+import android.opengl.GLES20;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.FloatBuffer;
+
+import tv.danmaku.ijk.media.player.IIjkFilter;
+
+
+/**
+ * base renderer
+ * Created by xrealm on 2019/2/21.
+ */
+public abstract class AbsIjkRender implements IIjkFilter {
+
+ protected FloatBuffer renderVertices;
+ protected FloatBuffer textureVertices;
+
+ protected int width, height;
+
+ protected int programHandle;
+ protected int textureHandle;
+ protected int positionHandle;
+ protected int texCoordHandle;
+ protected int textureIn;
+
+ public AbsIjkRender() {
+ float[] vertices = new float[]{
+ -1f, -1f,
+ 1f, -1f,
+ -1f, 1f,
+ 1f, 1f
+ };
+ renderVertices = ByteBuffer.allocateDirect(vertices.length * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();
+ renderVertices.put(vertices).position(0);
+
+ float[] texData = new float[]{
+ 0.0f, 0.0f,
+ 1.0f, 0.0f,
+ 0.0f, 1.0f,
+ 1.0f, 1.0f,
+ };
+
+ textureVertices = ByteBuffer.allocateDirect(texData.length * 4)
+ .order(ByteOrder.nativeOrder())
+ .asFloatBuffer()
+ .put(texData);
+ textureVertices.position(0);
+ }
+
+ @Override
+ public void onCreated() {
+ programHandle = ShaderHelper.buildProgram(getVertexShader(), getFragmentShader());
+ bindShaderAttributes();
+ initShaderHandles();
+ }
+
+ @Override
+ public void onSizeChanged(int width, int height) {
+ this.width = width;
+ this.height = height;
+ }
+
+ @Override
+ public void onDrawFrame(int textureId) {
+ if (programHandle == 0) {
+ onCreated();
+ }
+ textureIn = textureId;
+ GLES20.glViewport(0, 0, width, height);
+ GLES20.glClearColor(0, 0, 0, 0);
+ GLES20.glClear(GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);
+
+ GLES20.glUseProgram(programHandle);
+ passShaderValues();
+ GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
+ disableDrawArray();
+ }
+
+ protected String getVertexShader() {
+ return "attribute vec4 position;\n"
+ + "attribute vec2 inputTextureCoordinate;\n"
+ + "varying vec2 textureCoordinate;\n"
+ + "void main() {\n"
+ + " textureCoordinate = inputTextureCoordinate;\n"
+ + " gl_Position = position;\n"
+ + "}\n";
+ }
+
+ protected String getFragmentShader() {
+ return "precision mediump float;\n"
+ + "uniform sampler2D inputImageTexture0;\n"
+ + "varying vec2 textureCoordinate;\n"
+ + "void main() {\n"
+ + " gl_FragColor = texture2D(inputImageTexture0, uv);\n"
+ + "}";
+ }
+
+ protected void bindShaderAttributes() {
+ GLES20.glBindAttribLocation(programHandle, 0, "position");
+ GLES20.glBindAttribLocation(programHandle, 1, "inputTextureCoordinate");
+ }
+
+ protected void initShaderHandles() {
+ positionHandle = GLES20.glGetAttribLocation(programHandle, "position");
+ texCoordHandle = GLES20.glGetAttribLocation(programHandle, "inputTextureCoordinate");
+ textureHandle = GLES20.glGetUniformLocation(programHandle, "inputImageTexture0");
+ }
+
+ protected void passShaderValues() {
+ GLES20.glEnableVertexAttribArray(positionHandle);
+ GLES20.glVertexAttribPointer(positionHandle, 2, GLES20.GL_FLOAT, false, 8, renderVertices);
+
+ GLES20.glEnableVertexAttribArray(texCoordHandle);
+ GLES20.glVertexAttribPointer(texCoordHandle, 2, GLES20.GL_FLOAT, false, 8, textureVertices);
+
+ GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
+ GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureIn);
+ GLES20.glUniform1i(textureHandle, 0);
+ }
+
+ protected void disableDrawArray() {
+ GLES20.glDisableVertexAttribArray(positionHandle);
+ GLES20.glDisableVertexAttribArray(texCoordHandle);
+ GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0);
+ }
+
+ public int getWidth() {
+ return width;
+ }
+
+ public int getHeight() {
+ return height;
+ }
+}
diff --git a/android/ijkplayer/ijkplayer-example/src/main/java/tv/danmaku/ijk/media/example/widget/filter/GrayFilter.java b/android/ijkplayer/ijkplayer-example/src/main/java/tv/danmaku/ijk/media/example/widget/filter/GrayFilter.java
new file mode 100644
index 0000000000..220922395e
--- /dev/null
+++ b/android/ijkplayer/ijkplayer-example/src/main/java/tv/danmaku/ijk/media/example/widget/filter/GrayFilter.java
@@ -0,0 +1,22 @@
+package tv.danmaku.ijk.media.example.widget.filter;
+
+/**
+ * Created by xrealm on 2019/2/21.
+ */
+public class GrayFilter extends AbsIjkRender {
+
+ @Override
+ protected String getFragmentShader() {
+ return "precision highp float;\n" +
+ "\n" +
+ "varying vec2 textureCoordinate;\n" +
+ "uniform sampler2D inputImageTexture0;\n" +
+ "\n" +
+ "void main() {\n" +
+ " vec2 uv = textureCoordinate;\n" +
+ " vec4 color = texture2D(inputImageTexture0, uv);\n" +
+ " float gray = color.r * 0.6 + color.g * 0.3 + color.b * 0.1;\n" +
+ " gl_FragColor = vec4(gray, gray, gray, 1.0);\n" +
+ "}";
+ }
+}
diff --git a/android/ijkplayer/ijkplayer-example/src/main/java/tv/danmaku/ijk/media/example/widget/filter/ShaderHelper.java b/android/ijkplayer/ijkplayer-example/src/main/java/tv/danmaku/ijk/media/example/widget/filter/ShaderHelper.java
new file mode 100644
index 0000000000..c83a6fd89e
--- /dev/null
+++ b/android/ijkplayer/ijkplayer-example/src/main/java/tv/danmaku/ijk/media/example/widget/filter/ShaderHelper.java
@@ -0,0 +1,75 @@
+package tv.danmaku.ijk.media.example.widget.filter;
+
+import android.opengl.GLES20;
+import android.util.Log;
+
+/**
+ * Created by xrealm on 2017/9/5.
+ */
+
+public class ShaderHelper {
+
+ private static final String TAG = "ShaderHelper";
+
+ public static int buildProgram(String vertexSourceCode, String fragmentSourceCode) {
+ int program;
+ //compile
+ int vertexShader = compileVertexShader(vertexSourceCode);
+ int fragmentShader = compileFragmentShader(fragmentSourceCode);
+ //link
+ program = linkProgram(vertexShader, fragmentShader);
+ validateProgram(program);
+ return program;
+ }
+
+ private static void validateProgram(int program) {
+ GLES20.glValidateProgram(program);
+ int[] validateStatus = new int[1];
+ GLES20.glGetProgramiv(program, GLES20.GL_VALIDATE_STATUS, validateStatus, 0);
+ if (validateStatus[0] == 0) {
+ Log.e(TAG, "Results of validating program : " + validateStatus[0]
+ + "\n Log : " + GLES20.glGetProgramInfoLog(program));
+ }
+ }
+
+ private static int linkProgram(int vertexShader, int fragmentShader) {
+ int program = GLES20.glCreateProgram();
+ GLES20.glAttachShader(program, vertexShader);
+ GLES20.glAttachShader(program, fragmentShader);
+ GLES20.glLinkProgram(program);
+ int[] linkStatus = new int[1];
+ GLES20.glGetProgramiv(program, GLES20.GL_LINK_STATUS, linkStatus, 0);
+ if (linkStatus[0] == 0) {
+ GLES20.glDeleteProgram(program);
+ Log.e(TAG, "Linking of program failed. Reason : \n" + GLES20.glGetProgramInfoLog(program));
+ }
+ return program;
+ }
+
+ private static int compileVertexShader(String shaderCode) {
+ return compileShader(GLES20.GL_VERTEX_SHADER, shaderCode);
+ }
+
+ private static int compileFragmentShader(String shaderCode) {
+ return compileShader(GLES20.GL_FRAGMENT_SHADER, shaderCode);
+ }
+
+ private static int compileShader(int type, String shaderSourceCode) {
+ int shaderId = GLES20.glCreateShader(type);
+ String errInfo = "none";
+ if (shaderId != 0) {
+ GLES20.glShaderSource(shaderId, shaderSourceCode);
+ GLES20.glCompileShader(shaderId);
+ int[] compileStatus = new int[1];
+ GLES20.glGetShaderiv(shaderId, GLES20.GL_COMPILE_STATUS, compileStatus, 0);
+ if (compileStatus[0] == 0) {
+ errInfo = GLES20.glGetShaderInfoLog(shaderId);
+ GLES20.glDeleteShader(shaderId);
+ }
+ }
+ if (shaderId == 0) {
+ Log.e(TAG, "could not create new shader. Reason : \n" + errInfo);
+ }
+ return shaderId;
+ }
+}
diff --git a/android/ijkplayer/ijkplayer-example/src/main/java/tv/danmaku/ijk/media/example/widget/media/IjkVideoView.java b/android/ijkplayer/ijkplayer-example/src/main/java/tv/danmaku/ijk/media/example/widget/media/IjkVideoView.java
index cc3f002d82..0524cc237a 100755
--- a/android/ijkplayer/ijkplayer-example/src/main/java/tv/danmaku/ijk/media/example/widget/media/IjkVideoView.java
+++ b/android/ijkplayer/ijkplayer-example/src/main/java/tv/danmaku/ijk/media/example/widget/media/IjkVideoView.java
@@ -48,8 +48,10 @@
import java.util.regex.Matcher;
import java.util.regex.Pattern;
+import tv.danmaku.ijk.media.example.widget.filter.GrayFilter;
import tv.danmaku.ijk.media.exo.IjkExoMediaPlayer;
import tv.danmaku.ijk.media.player.AndroidMediaPlayer;
+import tv.danmaku.ijk.media.player.IIjkFilter;
import tv.danmaku.ijk.media.player.IMediaPlayer;
import tv.danmaku.ijk.media.player.IjkMediaPlayer;
import tv.danmaku.ijk.media.player.IjkTimedText;
@@ -1071,6 +1073,10 @@ public IMediaPlayer createPlayer(int playerType) {
ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "http-detect-range-support", 0);
ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_CODEC, "skip_loop_filter", 48);
+
+ ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "overlay-format", IjkMediaPlayer.SDL_OPENGL);
+ IIjkFilter imageFilter = new GrayFilter();
+ ijkMediaPlayer.setGLFilter(imageFilter);
}
mediaPlayer = ijkMediaPlayer;
}
diff --git a/android/ijkplayer/ijkplayer-java/src/main/AndroidManifest.xml b/android/ijkplayer/ijkplayer-java/src/main/AndroidManifest.xml
index c87fe47051..e45a047395 100644
--- a/android/ijkplayer/ijkplayer-java/src/main/AndroidManifest.xml
+++ b/android/ijkplayer/ijkplayer-java/src/main/AndroidManifest.xml
@@ -1,7 +1,4 @@
-
-
\ No newline at end of file
diff --git a/android/ijkplayer/ijkplayer-java/src/main/java/tv/danmaku/ijk/media/player/IIjkFilter.java b/android/ijkplayer/ijkplayer-java/src/main/java/tv/danmaku/ijk/media/player/IIjkFilter.java
new file mode 100644
index 0000000000..3fd08ea728
--- /dev/null
+++ b/android/ijkplayer/ijkplayer-java/src/main/java/tv/danmaku/ijk/media/player/IIjkFilter.java
@@ -0,0 +1,12 @@
+package tv.danmaku.ijk.media.player;
+
+/**
+ * Created by xrealm on 17/11/18.
+ */
+public interface IIjkFilter {
+ void onCreated();
+
+ void onSizeChanged(int width, int height);
+
+ void onDrawFrame(int textureId);
+}
diff --git a/android/ijkplayer/ijkplayer-java/src/main/java/tv/danmaku/ijk/media/player/IjkMediaPlayer.java b/android/ijkplayer/ijkplayer-java/src/main/java/tv/danmaku/ijk/media/player/IjkMediaPlayer.java
index beb73f76e8..b8448558c2 100755
--- a/android/ijkplayer/ijkplayer-java/src/main/java/tv/danmaku/ijk/media/player/IjkMediaPlayer.java
+++ b/android/ijkplayer/ijkplayer-java/src/main/java/tv/danmaku/ijk/media/player/IjkMediaPlayer.java
@@ -101,6 +101,7 @@ public final class IjkMediaPlayer extends AbstractMediaPlayer {
public static final int SDL_FCC_YV12 = 0x32315659; // YV12
public static final int SDL_FCC_RV16 = 0x36315652; // RGB565
public static final int SDL_FCC_RV32 = 0x32335652; // RGBX8888
+ public static final String SDL_OPENGL = "fcc-_es2";
//----------------------------------------
//----------------------------------------
@@ -937,6 +938,10 @@ public void setKeepInBackground(boolean keepInBackground) {
// do nothing
}
+ public void setGLFilter(IIjkFilter filter) {
+ native_setGLFilter(filter);
+ }
+
private static native void native_init();
private native void native_setup(Object IjkMediaPlayer_this);
@@ -1284,4 +1289,6 @@ public String onMediaCodecSelect(IMediaPlayer mp, String mimeType, int profile,
public static native void native_profileBegin(String libName);
public static native void native_profileEnd();
public static native void native_setLogLevel(int level);
+
+ public native void native_setGLFilter(IIjkFilter filter);
}
diff --git a/android/ijkplayer/ijkplayer-x86/src/main/AndroidManifest.xml b/android/ijkplayer/ijkplayer-x86/src/main/AndroidManifest.xml
index 68a12d04a8..01dd7f8702 100644
--- a/android/ijkplayer/ijkplayer-x86/src/main/AndroidManifest.xml
+++ b/android/ijkplayer/ijkplayer-x86/src/main/AndroidManifest.xml
@@ -1,7 +1,4 @@
-
-
diff --git a/android/ijkplayer/ijkplayer-x86_64/src/main/AndroidManifest.xml b/android/ijkplayer/ijkplayer-x86_64/src/main/AndroidManifest.xml
index 9ff26a79ea..d5691663a0 100644
--- a/android/ijkplayer/ijkplayer-x86_64/src/main/AndroidManifest.xml
+++ b/android/ijkplayer/ijkplayer-x86_64/src/main/AndroidManifest.xml
@@ -1,7 +1,4 @@
-
-
diff --git a/ijkmedia/ijkplayer/android/ijkplayer_android.c b/ijkmedia/ijkplayer/android/ijkplayer_android.c
index da4de8a37a..374648e942 100644
--- a/ijkmedia/ijkplayer/android/ijkplayer_android.c
+++ b/ijkmedia/ijkplayer/android/ijkplayer_android.c
@@ -30,6 +30,7 @@
#include "../ijkplayer_internal.h"
#include "../pipeline/ffpipeline_ffplay.h"
#include "pipeline/ffpipeline_android.h"
+#include
IjkMediaPlayer *ijkmp_android_create(int(*msg_loop)(void*))
{
@@ -125,3 +126,18 @@ void ijkmp_android_set_mediacodec_select_callback(IjkMediaPlayer *mp, bool (*cal
pthread_mutex_unlock(&mp->mutex);
MPTRACE("ijkmp_android_set_mediacodec_select_callback()=void");
}
+
+void ijkmp_android_set_filter(IjkMediaPlayer *mp,int hasFilter,void *onCreated,void *onSizeChanged,void *onDrawFrame, void* filterObject) {
+
+ if(!mp || !(mp->ffplayer)|| !(mp->ffplayer->vout)){
+ return ;
+ }
+
+ mp->ffplayer->vout->hasFilter = hasFilter;
+ if(hasFilter == 1) {
+ mp->ffplayer->vout->filterObject = filterObject;
+ mp->ffplayer->vout->func_onCreated=onCreated;
+ mp->ffplayer->vout->func_onSizeChanged=onSizeChanged;
+ mp->ffplayer->vout->func_onDrawFrame=onDrawFrame;
+ }
+}
\ No newline at end of file
diff --git a/ijkmedia/ijkplayer/android/ijkplayer_android.h b/ijkmedia/ijkplayer/android/ijkplayer_android.h
index f711b290fc..c20fc8c9d5 100644
--- a/ijkmedia/ijkplayer/android/ijkplayer_android.h
+++ b/ijkmedia/ijkplayer/android/ijkplayer_android.h
@@ -42,4 +42,5 @@ void ijkmp_android_set_volume(JNIEnv *env, IjkMediaPlayer *mp, float left, float
int ijkmp_android_get_audio_session_id(JNIEnv *env, IjkMediaPlayer *mp);
void ijkmp_android_set_mediacodec_select_callback(IjkMediaPlayer *mp, bool (*callback)(void *opaque, ijkmp_mediacodecinfo_context *mcc), void *opaque);
+void ijkmp_android_set_filter(IjkMediaPlayer *mp,int has_filter,void *onCreated,void *onSizeChanged,void *onDrawFrame, void* filterObject);
#endif
diff --git a/ijkmedia/ijkplayer/android/ijkplayer_jni.c b/ijkmedia/ijkplayer/android/ijkplayer_jni.c
index b5a50e7d6a..232565f075 100755
--- a/ijkmedia/ijkplayer/android/ijkplayer_jni.c
+++ b/ijkmedia/ijkplayer/android/ijkplayer_jni.c
@@ -1127,8 +1127,72 @@ IjkMediaPlayer_setFrameAtTime(JNIEnv *env, jobject thiz, jstring path, jlong sta
return;
}
+static jmethodID onCreatedMethod;
+static jmethodID onSizeChangedMethod;
+static jmethodID onDrawFrameMethod;
+void onCreated(void* object){
+ ALOGE("%s: SetupThreadEnv \n", __func__);
+
+ JNIEnv* env;
+ jobject filter = object;
+ if (JNI_OK != SDL_JNI_SetupThreadEnv(&env)) {
+ ALOGE("%s: SetupThreadEnv failed\n", __func__);
+ return ;
+ }
+ if(onCreatedMethod){
+ (*env)->CallVoidMethod(env,filter,onCreatedMethod);
+ }
+}
+//
+void onSizeChanged(int width,int height, void* object){
+ ALOGE("%s: SetupThreadEnv width %d, height %d\n", __func__, width, height);
+
+ JNIEnv* env;
+ jobject filter = object;
+ if (JNI_OK != SDL_JNI_SetupThreadEnv(&env)) {
+ ALOGE("%s: SetupThreadEnv failed\n", __func__);
+ return ;
+ }
+ if(onSizeChangedMethod){
+ (*env)->CallVoidMethod(env,filter,onSizeChangedMethod,width,height);
+ }
+}
+//
+void onDrawFrame(int textureId, void* object){
+ ALOGE("%s: SetupThreadEnv \n", __func__);
+
+ JNIEnv* env;
+ jobject filter = object;
+ if (JNI_OK != SDL_JNI_SetupThreadEnv(&env)) {
+ ALOGE("%s: SetupThreadEnv failed\n", __func__);
+ return ;
+ }
+ if(onDrawFrameMethod){
+ (*env)->CallVoidMethod(env,filter,onDrawFrameMethod,textureId);
+ }
+}
+
+static void
+IjkMediaPlayer_native_setGLFilter(JNIEnv *env, jobject thiz, jobject filter)
+{
+
+ IjkMediaPlayer *mp = jni_get_media_player(env, thiz);
+ jobject filterObject;
+ if(filter != NULL){
+ filterObject=(*env)->NewGlobalRef(env,filter);
+ jclass filterClass=(*env)->GetObjectClass(env,filterObject);
+ onCreatedMethod=(*env)->GetMethodID(env,filterClass,"onCreated","()V");
+ onSizeChangedMethod=(*env)->GetMethodID(env,filterClass,"onSizeChanged","(II)V");
+ onDrawFrameMethod=(*env)->GetMethodID(env,filterClass,"onDrawFrame","(I)V");
+ ALOGE("IjkMediaPlayer_native_setGLFilter mp %p mFilter %p, onCreate %p, onSize %p, onDraw %p", mp, filterObject, onCreatedMethod, onSizeChangedMethod, onDrawFrameMethod);
+ ijkmp_android_set_filter(mp, 1, onCreated, onSizeChanged, onDrawFrame, filterObject);
+ }else{
+ ijkmp_android_set_filter(mp, 0, NULL, NULL, NULL, NULL);
+ }
+}
+
// ----------------------------------------------------------------------------
@@ -1180,6 +1244,7 @@ static JNINativeMethod g_methods[] = {
{ "native_setLogLevel", "(I)V", (void *) IjkMediaPlayer_native_setLogLevel },
{ "_setFrameAtTime", "(Ljava/lang/String;JJII)V", (void *) IjkMediaPlayer_setFrameAtTime },
+ { "native_setGLFilter", "(Ltv/danmaku/ijk/media/player/IIjkFilter;)V", (void *) IjkMediaPlayer_native_setGLFilter },
};
JNIEXPORT jint JNI_OnLoad(JavaVM *vm, void *reserved)
diff --git a/ijkmedia/ijksdl/android/ijksdl_vout_android_nativewindow.c b/ijkmedia/ijksdl/android/ijksdl_vout_android_nativewindow.c
index e2a2e90317..3d6cb4f177 100644
--- a/ijkmedia/ijksdl/android/ijksdl_vout_android_nativewindow.c
+++ b/ijkmedia/ijksdl/android/ijksdl_vout_android_nativewindow.c
@@ -26,6 +26,7 @@
#include
#include
+#include
#include "ijksdl/ijksdl_vout.h"
#include "ijksdl/ijksdl_vout_internal.h"
#include "ijksdl/ijksdl_container.h"
@@ -107,6 +108,12 @@ static SDL_VoutOverlay *func_create_overlay(int width, int height, int frame_for
{
SDL_LockMutex(vout->mutex);
SDL_VoutOverlay *overlay = func_create_overlay_l(width, height, frame_format, vout);
+
+ overlay->hasFilter=vout->hasFilter;
+ overlay->filterObject = vout->filterObject;
+ overlay->func_onCreated=vout->func_onCreated;
+ overlay->func_onSizeChanged=vout->func_onSizeChanged;
+ overlay->func_onDrawFrame=vout->func_onDrawFrame;
SDL_UnlockMutex(vout->mutex);
return overlay;
}
diff --git a/ijkmedia/ijksdl/gles2/internal.h b/ijkmedia/ijksdl/gles2/internal.h
index edafc1daaf..93347c9e79 100644
--- a/ijkmedia/ijksdl/gles2/internal.h
+++ b/ijkmedia/ijksdl/gles2/internal.h
@@ -57,6 +57,15 @@ typedef struct IJK_GLES2_Renderer
GLboolean (*func_uploadTexture)(IJK_GLES2_Renderer *renderer, SDL_VoutOverlay *overlay);
GLvoid (*func_destroy)(IJK_GLES2_Renderer *renderer);
+ GLuint frame_buffers[1];
+ GLuint frame_textures[1];
+
+ void* filterObject;
+ int hasFilter;
+ void (* func_onCreated)(void* object);
+ void (* func_onSizeChanged)(int width, int height, void* object);
+ void (* func_onDrawFrame)(int textureId, void*object);
+
GLsizei buffer_width;
GLsizei visible_width;
diff --git a/ijkmedia/ijksdl/gles2/renderer.c b/ijkmedia/ijksdl/gles2/renderer.c
index 76c61273a2..c53169298b 100644
--- a/ijkmedia/ijksdl/gles2/renderer.c
+++ b/ijkmedia/ijksdl/gles2/renderer.c
@@ -180,6 +180,13 @@ IJK_GLES2_Renderer *IJK_GLES2_Renderer_create(SDL_VoutOverlay *overlay)
}
renderer->format = overlay->format;
+
+ renderer->filterObject = overlay->filterObject;
+ renderer->hasFilter=overlay->hasFilter;
+ renderer->func_onCreated=overlay->func_onCreated;
+ renderer->func_onSizeChanged=overlay->func_onSizeChanged;
+ renderer->func_onDrawFrame=overlay->func_onDrawFrame;
+
return renderer;
}
@@ -407,6 +414,12 @@ GLboolean IJK_GLES2_Renderer_renderOverlay(IJK_GLES2_Renderer *renderer, SDL_Vou
buffer_width != renderer->buffer_width &&
visible_width != renderer->visible_width)){
+ ALOGE("mao: size changed size changed :%d",renderer->frame_buffers[0]);
+ //size changed
+ if(renderer->hasFilter && renderer->frame_buffers[0]) {
+ renderer->func_onSizeChanged(renderer->frame_width, renderer->frame_height, renderer->filterObject);
+ }
+
renderer->vertices_changed = 0;
IJK_GLES2_Renderer_Vertices_apply(renderer);
@@ -423,7 +436,67 @@ GLboolean IJK_GLES2_Renderer_renderOverlay(IJK_GLES2_Renderer *renderer, SDL_Vou
IJK_GLES2_Renderer_TexCoords_reloadVertex(renderer);
}
+ if(renderer->hasFilter && !renderer->frame_buffers[0] && renderer->frame_width > 0 && renderer->frame_height > 0) {
+ glGenTextures(1,renderer->frame_textures);
+ glBindTexture(GL_TEXTURE_2D,renderer->frame_textures[0]);
+ glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,renderer->frame_width,renderer->frame_height,0,GL_RGBA,GL_UNSIGNED_BYTE,NULL);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ glBindTexture(GL_TEXTURE_2D,0);
+
+ //创建framebuffer
+ glGenFramebuffers(1,renderer->frame_buffers);
+ glBindFramebuffer(GL_FRAMEBUFFER,renderer->frame_buffers[0]);
+ glFramebufferTexture2D(GL_FRAMEBUFFER,GL_COLOR_ATTACHMENT0,GL_TEXTURE_2D,renderer->frame_textures[0],0);
+
+ glBindFramebuffer(GL_FRAMEBUFFER,0);
+
+ renderer->func_onCreated(renderer->filterObject);
+ renderer->func_onSizeChanged(renderer->frame_width,renderer->frame_height, renderer->filterObject);
+ ALOGE("mao: create framebuffer and textureid %d, %d", renderer->frame_width, renderer->frame_height);
+ }
+
+
+ if(renderer->hasFilter && renderer->frame_buffers[0]){
+ GLint bindFrame;
+ glGetIntegerv(GL_FRAMEBUFFER_BINDING,&bindFrame);
+ IJK_GLES2_checkError_TRACE("glGetIntegerv");
+ ALOGE("mao: default frame binding %d",bindFrame);
+ glBindFramebuffer(GL_FRAMEBUFFER,renderer->frame_buffers[0]);
+ IJK_GLES2_checkError_TRACE("glBindFramebuffer");
+ //glFramebufferTexture2D(GL_FRAMEBUFFER,GL_COLOR_ATTACHMENT0,GL_TEXTURE_2D,renderer->frame_textures[0],0);
+ IJK_GLES2_Renderer_use(renderer);
+ IJK_GLES2_checkError_TRACE("IJK_GLES2_Renderer_use");
+ // glBindFramebuffer(GL_FRAMEBUFFER, renderer->frame_buffers[0]);
+ }
+
+ //renderer->func_use(renderer);
+ //glViewport(0, 0, renderer->frame_width, renderer->frame_height); IJK_GLES2_checkError_TRACE("glViewport");
+ //glClear(GL_COLOR_BUFFER_BIT); IJK_GLES2_checkError_TRACE("glClear");
+
+ //IJK_GLES_Matrix modelViewProj;
+ //IJK_GLES2_loadOrtho(&modelViewProj, -1.0f, 1.0f, -1.0f, 1.0f, -1.0f, 1.0f);
+ //glUniformMatrix4fv(renderer->um4_mvp, 1, GL_FALSE, modelViewProj.m); IJK_GLES2_checkError_TRACE("glUniformMatrix4fv(um4_mvp)");
+
+ GLsizei padding_pixels = buffer_width - visible_width + 1;
+ GLfloat padding_normalized = ((GLfloat)padding_pixels) / buffer_width;
+
+ IJK_GLES2_Renderer_TexCoords_reset(renderer);
+ IJK_GLES2_Renderer_TexCoords_cropRight(renderer, padding_normalized);
+ IJK_GLES2_Renderer_TexCoords_reloadVertex(renderer);
+ IJK_GLES2_Renderer_Vertices_reloadVertex(renderer);
+
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); IJK_GLES2_checkError_TRACE("glDrawArrays");
+ IJK_GLES2_checkError_TRACE("glDrawArrays");
+ ALOGE("[GLES2 render] draw frame width=%d, height=%d!!", renderer->frame_width, renderer->frame_height);
+
+ //调用Filter onDrawFrame
+ if(renderer->hasFilter && renderer->frame_buffers[0]) {
+ glBindFramebuffer(GL_FRAMEBUFFER,0);
+ renderer->func_onDrawFrame(renderer->frame_textures[0], renderer->filterObject);
+ }
return GL_TRUE;
}
diff --git a/ijkmedia/ijksdl/ijksdl_vout.h b/ijkmedia/ijksdl/ijksdl_vout.h
index 8f0f63b67b..8d78034a4f 100644
--- a/ijkmedia/ijksdl/ijksdl_vout.h
+++ b/ijkmedia/ijksdl/ijksdl_vout.h
@@ -49,6 +49,12 @@ struct SDL_VoutOverlay {
SDL_Class *opaque_class;
SDL_VoutOverlay_Opaque *opaque;
+ void* filterObject;
+ int hasFilter;
+ void (* func_onCreated)(void* object);
+ void (* func_onSizeChanged)(int width,int height, void* object);
+ void (* func_onDrawFrame)(int textureId, void* object);
+
void (*free_l)(SDL_VoutOverlay *overlay);
int (*lock)(SDL_VoutOverlay *overlay);
int (*unlock)(SDL_VoutOverlay *overlay);
@@ -69,6 +75,12 @@ struct SDL_Vout {
int (*display_overlay)(SDL_Vout *vout, SDL_VoutOverlay *overlay);
Uint32 overlay_format;
+
+ void* filterObject;
+ int hasFilter;
+ void (* func_onCreated)(void* object);
+ void (* func_onSizeChanged)(int width,int height, void* object);
+ void (* func_onDrawFrame)(int textureId, void* object);
};
void SDL_VoutFree(SDL_Vout *vout);