Skip to content

Commit

Permalink
Merge pull request Doikki#790 from Doikki/dev
Browse files Browse the repository at this point in the history
视频滤镜功能
  • Loading branch information
Doikki authored Aug 17, 2022
2 parents fe01896 + fc642a0 commit 5203b55
Show file tree
Hide file tree
Showing 56 changed files with 3,917 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package xyz.doikki.dkplayer.activity.api

import android.content.Context
import android.content.Intent
import android.graphics.BitmapFactory
import android.text.TextUtils
import android.view.View
import android.widget.EditText
Expand All @@ -13,11 +14,17 @@ import xyz.doikki.dkplayer.util.IntentKeys
import xyz.doikki.dkplayer.util.Utils
import xyz.doikki.dkplayer.widget.component.DebugInfoView
import xyz.doikki.dkplayer.widget.component.PlayerMonitor
import xyz.doikki.dkplayer.widget.render.gl.GLSurfaceRenderViewFactory
import xyz.doikki.dkplayer.widget.render.gl2.GLSurfaceRenderView2
import xyz.doikki.dkplayer.widget.render.gl2.filter.GlFilterGroup
import xyz.doikki.dkplayer.widget.render.gl2.filter.GlSepiaFilter
import xyz.doikki.dkplayer.widget.render.gl2.filter.GlSharpenFilter
import xyz.doikki.dkplayer.widget.render.gl2.filter.GlWatermarkFilter
import xyz.doikki.videocontroller.StandardVideoController
import xyz.doikki.videocontroller.component.*
import xyz.doikki.videoplayer.player.BaseVideoView
import xyz.doikki.videoplayer.player.VideoView
import xyz.doikki.videoplayer.render.IRenderView
import xyz.doikki.videoplayer.render.RenderViewFactory
import xyz.doikki.videoplayer.util.L

/**
Expand All @@ -26,6 +33,10 @@ import xyz.doikki.videoplayer.util.L
*/
class PlayerActivity : BaseActivity<VideoView>() {

private val renderView by lazy {
GLSurfaceRenderView2(this)
}

override fun getLayoutResId() = R.layout.activity_player

override fun initView() {
Expand Down Expand Up @@ -107,7 +118,19 @@ class PlayerActivity : BaseActivity<VideoView>() {

// 临时切换RenderView, 如需全局请通过VideoConfig配置,详见MyApplication
if (intent.getBooleanExtra(IntentKeys.CUSTOM_RENDER, false)) {
mVideoView.setRenderViewFactory(GLSurfaceRenderViewFactory.create())
// mVideoView.setRenderViewFactory(GLSurfaceRenderViewFactory.create())
mVideoView.setRenderViewFactory(object : RenderViewFactory() {
override fun createRenderView(context: Context?): IRenderView {
return renderView
}
})
// 设置滤镜
renderView.setGlFilter(GlFilterGroup(
// 水印
GlWatermarkFilter(BitmapFactory.decodeResource(resources, R.mipmap.ic_launcher)),
GlSepiaFilter(),
GlSharpenFilter()
))
}
//临时切换播放核心,如需全局请通过VideoConfig配置,详见MyApplication
//使用IjkPlayer解码
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,6 @@ public void onCreate() {
.setPlayerFactory(ExoMediaPlayerFactory.create())
// 设置自己的渲染view,内部默认TextureView实现
// .setRenderViewFactory(SurfaceRenderViewFactory.create())
// GLSurfaceView 可对视频加滤镜
// .setRenderViewFactory(GLSurfaceRenderViewFactory.create())
// 根据手机重力感应自动切换横竖屏,默认false
// .setEnableOrientation(true)
// 监听系统中其他播放器是否获取音频焦点,实现不与其他播放器同时播放的效果,默认true
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
package xyz.doikki.dkplayer.widget.render.gl2;

import static android.opengl.GLES20.GL_ARRAY_BUFFER;
import static android.opengl.GLES20.GL_CLAMP_TO_EDGE;
import static android.opengl.GLES20.GL_LINK_STATUS;
import static android.opengl.GLES20.GL_STATIC_DRAW;
import static android.opengl.GLES20.GL_TEXTURE_MAG_FILTER;
import static android.opengl.GLES20.GL_TEXTURE_MIN_FILTER;
import static android.opengl.GLES20.GL_TEXTURE_WRAP_S;
import static android.opengl.GLES20.GL_TEXTURE_WRAP_T;
import static android.opengl.GLES20.GL_TRUE;
import static android.opengl.GLES20.glCreateProgram;

import android.graphics.Bitmap;
import android.opengl.GLES20;
import android.opengl.GLException;
import android.opengl.GLUtils;
import android.util.Log;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;

import xyz.doikki.dkplayer.BuildConfig;


public class EglUtil {

public static final int NO_TEXTURE = -1;

private static final int FLOAT_SIZE_BYTES = 4;

public static int loadShader(final String strSource, final int iType) {
int[] compiled = new int[1];
int iShader = GLES20.glCreateShader(iType);
GLES20.glShaderSource(iShader, strSource);
GLES20.glCompileShader(iShader);
GLES20.glGetShaderiv(iShader, GLES20.GL_COMPILE_STATUS, compiled, 0);
if (compiled[0] == 0) {
Log.d("Load Shader Failed", "Compilation\n" + GLES20.glGetShaderInfoLog(iShader));
return 0;
}
return iShader;
}

public static int createProgram(final int vertexShader, final int pixelShader) throws GLException {
final int program = glCreateProgram();
if (program == 0) {
throw new RuntimeException("Could not create program");
}

GLES20.glAttachShader(program, vertexShader);
GLES20.glAttachShader(program, pixelShader);

GLES20.glLinkProgram(program);
final int[] linkStatus = new int[1];
GLES20.glGetProgramiv(program, GL_LINK_STATUS, linkStatus, 0);
if (linkStatus[0] != GL_TRUE) {
GLES20.glDeleteProgram(program);
throw new RuntimeException("Could not link program");
}
return program;
}

public static void checkEglError(String operation) {
if (!BuildConfig.DEBUG) return;
int error;
while ((error = GLES20.glGetError()) != GLES20.GL_NO_ERROR) {
throw new RuntimeException(operation + ": glError " + error);
}
}

public static void setupSampler(final int target, final int mag, final int min) {
GLES20.glTexParameterf(target, GL_TEXTURE_MAG_FILTER, mag);
GLES20.glTexParameterf(target, GL_TEXTURE_MIN_FILTER, min);
GLES20.glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
GLES20.glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
}


public static int createBuffer(final float[] data) {
return createBuffer(toFloatBuffer(data));
}

public static int createBuffer(final FloatBuffer data) {
final int[] buffers = new int[1];
GLES20.glGenBuffers(buffers.length, buffers, 0);
updateBufferData(buffers[0], data);
return buffers[0];
}

public static FloatBuffer toFloatBuffer(final float[] data) {
final FloatBuffer buffer = ByteBuffer
.allocateDirect(data.length * FLOAT_SIZE_BYTES)
.order(ByteOrder.nativeOrder())
.asFloatBuffer();
buffer.put(data).position(0);
return buffer;
}


public static void updateBufferData(final int bufferName, final FloatBuffer data) {
GLES20.glBindBuffer(GL_ARRAY_BUFFER, bufferName);
GLES20.glBufferData(GL_ARRAY_BUFFER, data.capacity() * FLOAT_SIZE_BYTES, data, GL_STATIC_DRAW);
GLES20.glBindBuffer(GL_ARRAY_BUFFER, 0);
}

public static int loadTexture(final Bitmap img, final int usedTexId, final boolean recycle) {
int[] textures = new int[1];
if (usedTexId == NO_TEXTURE) {
GLES20.glGenTextures(1, textures, 0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textures[0]);
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,
GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,
GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,
GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,
GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);

GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, img, 0);
} else {
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, usedTexId);
GLUtils.texSubImage2D(GLES20.GL_TEXTURE_2D, 0, 0, 0, img);
textures[0] = usedTexId;
}
if (recycle) {
img.recycle();
}
return textures[0];
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package xyz.doikki.dkplayer.widget.render.gl2;

import static android.opengl.GLES20.GL_COLOR_BUFFER_BIT;
import static android.opengl.GLES20.GL_DEPTH_BUFFER_BIT;
import static android.opengl.GLES20.GL_FRAMEBUFFER;

import android.opengl.GLES20;
import android.opengl.GLSurfaceView;

import java.util.LinkedList;
import java.util.Queue;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;

import xyz.doikki.dkplayer.widget.render.gl2.filter.GlFilter;


abstract class GLFrameBufferObjectRenderer implements GLSurfaceView.Renderer {

private GLFramebufferObject framebufferObject;
private GlFilter normalShader;

private final Queue<Runnable> runOnDraw;


GLFrameBufferObjectRenderer() {
runOnDraw = new LinkedList<Runnable>();
}


@Override
public final void onSurfaceCreated(final GL10 gl, final EGLConfig config) {
framebufferObject = new GLFramebufferObject();
normalShader = new GlFilter();
normalShader.setup();
onSurfaceCreated(config);
}

@Override
public final void onSurfaceChanged(final GL10 gl, final int width, final int height) {
framebufferObject.setup(width, height);
normalShader.setFrameSize(width, height);
onSurfaceChanged(width, height);
}

@Override
public final void onDrawFrame(final GL10 gl) {
synchronized (runOnDraw) {
while (!runOnDraw.isEmpty()) {
runOnDraw.poll().run();
}
}
framebufferObject.enable();
GLES20.glViewport(0, 0, framebufferObject.getWidth(), framebufferObject.getHeight());

onDrawFrame(framebufferObject);

GLES20.glBindFramebuffer(GL_FRAMEBUFFER, 0);
GLES20.glViewport(0, 0, framebufferObject.getWidth(), framebufferObject.getHeight());

GLES20.glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
normalShader.draw(framebufferObject.getTexName(), null);

}

@Override
protected void finalize() throws Throwable {

}

public abstract void onSurfaceCreated(EGLConfig config);

public abstract void onSurfaceChanged(int width, int height);

public abstract void onDrawFrame(GLFramebufferObject fbo);
}
Loading

0 comments on commit 5203b55

Please sign in to comment.