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);