提交 8aaa4be3 编写于 作者: S shuyu

增加了滤镜功能 (2017-09-16)

上级 863e0a0c
......@@ -28,5 +28,6 @@ public class GSYApplication extends Application {
//GSYVideoType.setShowType(GSYVideoType.SCREEN_MATCH_FULL);
//GSYVideoType.setShowType(GSYVideoType.SCREEN_TYPE_FULL);
//GSYVideoType.setRenderType(GSYVideoType.SUFRACE);
GSYVideoType.setRenderType(GSYVideoType.GLSURFACE);
}
}
......@@ -29,7 +29,8 @@ public class GSYRenderView {
}
public void requestLayout() {
mShowView.requestLayout();
if (mShowView != null)
mShowView.requestLayout();
}
public float getRotation() {
......@@ -37,7 +38,8 @@ public class GSYRenderView {
}
public void setRotation(float rotation) {
mShowView.setRotation(rotation);
if (mShowView != null)
mShowView.setRotation(rotation);
}
public void invalidate() {
......@@ -52,6 +54,10 @@ public class GSYRenderView {
return mShowView.getHeight();
}
public View getShowView() {
return mShowView;
}
/**
* 暂停时初始化位图
*/
......@@ -70,7 +76,24 @@ public class GSYRenderView {
}
public void setLayoutParams(ViewGroup.LayoutParams layoutParams) {
mShowView.setLayoutParams(layoutParams);
if (mShowView != null)
mShowView.setLayoutParams(layoutParams);
}
public void onResume() {
if (mShowView instanceof GSYVideoGLView) {
GSYVideoGLView gsyVideoGLView = (GSYVideoGLView) mShowView;
gsyVideoGLView.requestLayout();
gsyVideoGLView.onResume();
}
}
public void onPause() {
if (mShowView instanceof GSYVideoGLView) {
GSYVideoGLView gsyVideoGLView = (GSYVideoGLView) mShowView;
gsyVideoGLView.requestLayout();
gsyVideoGLView.onPause();
}
}
/**
......@@ -126,6 +149,33 @@ public class GSYRenderView {
}
}
/**
* 添加播放的view
*/
public void addGLView(Context context, ViewGroup textureViewContainer, int rotate, GSYVideoGLView.onGSYSurfaceListener gsySurfaceListener, GSYVideoGLView.ShaderInterface effect) {
if (textureViewContainer.getChildCount() > 0) {
textureViewContainer.removeAllViews();
}
GSYVideoGLView gsyVideoGLView = new GSYVideoGLView(context);
gsyVideoGLView.setEffect(effect);
gsyVideoGLView.setGSYSurfaceListener(gsySurfaceListener);
gsyVideoGLView.setRotation(rotate);
mShowView = gsyVideoGLView;
int params = getTextureParams();
if (textureViewContainer instanceof RelativeLayout) {
RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(params, params);
layoutParams.addRule(RelativeLayout.CENTER_IN_PARENT);
textureViewContainer.addView(gsyVideoGLView, layoutParams);
} else if (textureViewContainer instanceof FrameLayout) {
FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(params, params);
layoutParams.gravity = Gravity.CENTER;
textureViewContainer.addView(gsyVideoGLView, layoutParams);
}
}
/**
* 获取布局参数
*
......
package com.shuyu.gsyvideoplayer;
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.SurfaceTexture;
import android.opengl.GLES20;
import android.opengl.GLSurfaceView;
import android.opengl.Matrix;
import android.util.AttributeSet;
import android.util.Log;
import android.view.Surface;
import com.shuyu.gsyvideoplayer.utils.MeasureHelper;
import com.shuyu.gsyvideoplayer.effect.NoEffect;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
/**
* 原 @author sheraz.khilji
*/
@SuppressLint("ViewConstructor")
public class GSYVideoGLView extends GLSurfaceView {
private static final String TAG = GSYVideoGLView.class.getName();
private VideoRender mRenderer;
private Context mContext;
private ShaderInterface mEffect = new NoEffect();
private MeasureHelper measureHelper;
private onGSYSurfaceListener mGSYSurfaceListener;
public interface onGSYSurfaceListener {
void onSurfaceAvailable(Surface surface);
}
public interface ShaderInterface {
String getShader(GLSurfaceView mGlSurfaceView);
}
public GSYVideoGLView(Context context) {
super(context);
init(context);
}
public GSYVideoGLView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
private void init(Context context) {
mContext = context;
setEGLContextClientVersion(2);
mRenderer = new VideoRender();
measureHelper = new MeasureHelper(this);
setRenderer(mRenderer);
mRenderer.setSurfaceView(GSYVideoGLView.this);
}
public void setGSYSurfaceListener(onGSYSurfaceListener mGSYSurfaceListener) {
this.mGSYSurfaceListener = mGSYSurfaceListener;
mRenderer.setGSYSurfaceListener(this.mGSYSurfaceListener);
}
public void setEffect(ShaderInterface shaderEffect) {
if (shaderEffect != null) {
mEffect = shaderEffect;
mRenderer.setEffect(mEffect);
}
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
if (GSYVideoManager.instance().getMediaPlayer() != null) {
try {
int videoWidth = GSYVideoManager.instance().getCurrentVideoWidth();
int videoHeight = GSYVideoManager.instance().getCurrentVideoHeight();
int videoSarNum = GSYVideoManager.instance().getMediaPlayer().getVideoSarNum();
int videoSarDen = GSYVideoManager.instance().getMediaPlayer().getVideoSarDen();
if (videoWidth > 0 && videoHeight > 0) {
measureHelper.setVideoSampleAspectRatio(videoSarNum, videoSarDen);
measureHelper.setVideoSize(videoWidth, videoHeight);
}
measureHelper.setVideoRotation((int) getRotation());
measureHelper.doMeasure(widthMeasureSpec, heightMeasureSpec);
} catch (Exception e) {
e.printStackTrace();
}
}
setMeasuredDimension(measureHelper.getMeasuredWidth(), measureHelper.getMeasuredHeight());
}
public int getSizeH() {
return measureHelper.getMeasuredHeight();
}
public int getSizeW() {
return measureHelper.getMeasuredWidth();
}
private static class VideoRender implements Renderer, SurfaceTexture.OnFrameAvailableListener {
private static String TAG = VideoRender.class.getName();
private static final int FLOAT_SIZE_BYTES = 4;
private static final int TRIANGLE_VERTICES_DATA_STRIDE_BYTES = 5 * FLOAT_SIZE_BYTES;
private static final int TRIANGLE_VERTICES_DATA_POS_OFFSET = 0;
private static final int TRIANGLE_VERTICES_DATA_UV_OFFSET = 3;
private static final int GL_TEXTURE_EXTERNAL_OES = 0x8D65;
private final float[] mTriangleVerticesData = {
// X, Y, Z, U, V
-1.0f, -1.0f, 0, 0.f, 0.f, 1.0f, -1.0f, 0, 1.f, 0.f, -1.0f,
1.0f, 0, 0.f, 1.f, 1.0f, 1.0f, 0, 1.f, 1.f,};
private FloatBuffer mTriangleVertices;
private final String mVertexShader = "uniform mat4 uMVPMatrix;\n"
+ "uniform mat4 uSTMatrix;\n"
+ "attribute vec4 aPosition;\n"
+ "attribute vec4 aTextureCoord;\n"
+ "varying vec2 vTextureCoord;\n"
+ "void main() {\n"
+ " gl_Position = uMVPMatrix * aPosition;\n"
+ " vTextureCoord = (uSTMatrix * aTextureCoord).xy;\n"
+ "}\n";
private float[] mMVPMatrix = new float[16];
private float[] mSTMatrix = new float[16];
private int mProgram;
private int mTextureID[] = new int[2];
private int muMVPMatrixHandle;
private int muSTMatrixHandle;
private int maPositionHandle;
private int maTextureHandle;
private boolean updateSurface = false;
private SurfaceTexture mSurface;
private onGSYSurfaceListener mGSYSurfaceListener;
private ShaderInterface mEffect = new NoEffect();
private GLSurfaceView mSurfaceView;
public void setEffect(ShaderInterface shaderEffect) {
if (shaderEffect != null)
mEffect = shaderEffect;
}
public VideoRender() {
mTriangleVertices = ByteBuffer
.allocateDirect(
mTriangleVerticesData.length * FLOAT_SIZE_BYTES)
.order(ByteOrder.nativeOrder()).asFloatBuffer();
mTriangleVertices.put(mTriangleVerticesData).position(0);
Matrix.setIdentityM(mSTMatrix, 0);
}
public void setGSYSurfaceListener(onGSYSurfaceListener onSurfaceListener) {
this.mGSYSurfaceListener = onSurfaceListener;
}
public void setSurfaceView(GLSurfaceView surfaceView) {
this.mSurfaceView = surfaceView;
}
@Override
public void onDrawFrame(GL10 glUnused) {
synchronized (this) {
if (updateSurface) {
mSurface.updateTexImage();
mSurface.getTransformMatrix(mSTMatrix);
updateSurface = false;
}
}
mProgram = createProgram(mVertexShader, mEffect.getShader(mSurfaceView));
GLES20.glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
GLES20.glClear(GLES20.GL_DEPTH_BUFFER_BIT
| GLES20.GL_COLOR_BUFFER_BIT);
GLES20.glUseProgram(mProgram);
checkGlError("glUseProgram");
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GL_TEXTURE_EXTERNAL_OES, mTextureID[0]);
mTriangleVertices.position(TRIANGLE_VERTICES_DATA_POS_OFFSET);
GLES20.glVertexAttribPointer(maPositionHandle, 3, GLES20.GL_FLOAT,
false, TRIANGLE_VERTICES_DATA_STRIDE_BYTES,
mTriangleVertices);
checkGlError("glVertexAttribPointer maPosition");
GLES20.glEnableVertexAttribArray(maPositionHandle);
checkGlError("glEnableVertexAttribArray maPositionHandle");
mTriangleVertices.position(TRIANGLE_VERTICES_DATA_UV_OFFSET);
GLES20.glVertexAttribPointer(maTextureHandle, 3, GLES20.GL_FLOAT,
false, TRIANGLE_VERTICES_DATA_STRIDE_BYTES,
mTriangleVertices);
checkGlError("glVertexAttribPointer maTextureHandle");
GLES20.glEnableVertexAttribArray(maTextureHandle);
checkGlError("glEnableVertexAttribArray maTextureHandle");
Matrix.setIdentityM(mMVPMatrix, 0);
GLES20.glUniformMatrix4fv(muMVPMatrixHandle, 1, false, mMVPMatrix,
0);
GLES20.glUniformMatrix4fv(muSTMatrixHandle, 1, false, mSTMatrix, 0);
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
checkGlError("glDrawArrays");
GLES20.glFinish();
}
@Override
public void onSurfaceChanged(GL10 glUnused, int width, int height) {
GLES20.glViewport(0, 0, width, height);
}
@Override
public void onSurfaceCreated(GL10 glUnused, EGLConfig config) {
mProgram = createProgram(mVertexShader, mEffect.getShader(mSurfaceView));
if (mProgram == 0) {
return;
}
maPositionHandle = GLES20
.glGetAttribLocation(mProgram, "aPosition");
checkGlError("glGetAttribLocation aPosition");
if (maPositionHandle == -1) {
throw new RuntimeException(
"Could not get attrib location for aPosition");
}
maTextureHandle = GLES20.glGetAttribLocation(mProgram,
"aTextureCoord");
checkGlError("glGetAttribLocation aTextureCoord");
if (maTextureHandle == -1) {
throw new RuntimeException(
"Could not get attrib location for aTextureCoord");
}
muMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram,
"uMVPMatrix");
checkGlError("glGetUniformLocation uMVPMatrix");
if (muMVPMatrixHandle == -1) {
throw new RuntimeException(
"Could not get attrib location for uMVPMatrix");
}
muSTMatrixHandle = GLES20.glGetUniformLocation(mProgram,
"uSTMatrix");
checkGlError("glGetUniformLocation uSTMatrix");
if (muSTMatrixHandle == -1) {
throw new RuntimeException(
"Could not get attrib location for uSTMatrix");
}
// int[] textures = new int[1];
GLES20.glGenTextures(2, mTextureID, 0);
// GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureID[0]);
// mTextureID = textures[0];
GLES20.glBindTexture(GL_TEXTURE_EXTERNAL_OES, mTextureID[0]);
checkGlError("glBindTexture mTextureID");
// GLES20.glTexParameterf(GL_TEXTURE_EXTERNAL_OES,
// GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST);
// GLES20.glTexParameterf(GL_TEXTURE_EXTERNAL_OES,
// GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D,
GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D,
GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D,
GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D,
GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);
/*
* Create the SurfaceTexture that will feed this textureID, and pass
* it to the MediaPlayer
*/
mSurface = new SurfaceTexture(mTextureID[0]);
mSurface.setOnFrameAvailableListener(this);
Surface surface = new Surface(mSurface);
if (mGSYSurfaceListener != null) {
mGSYSurfaceListener.onSurfaceAvailable(surface);
}
//surface.release();
}
@Override
synchronized public void onFrameAvailable(SurfaceTexture surface) {
updateSurface = true;
}
private int loadShader(int shaderType, String source) {
int shader = GLES20.glCreateShader(shaderType);
if (shader != 0) {
GLES20.glShaderSource(shader, source);
GLES20.glCompileShader(shader);
int[] compiled = new int[1];
GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS,
compiled, 0);
if (compiled[0] == 0) {
Log.e(TAG, "Could not compile shader " + shaderType + ":");
Log.e(TAG, GLES20.glGetShaderInfoLog(shader));
GLES20.glDeleteShader(shader);
shader = 0;
}
}
return shader;
}
private int createProgram(String vertexSource, String fragmentSource) {
int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertexSource);
if (vertexShader == 0) {
return 0;
}
int pixelShader = loadShader(GLES20.GL_FRAGMENT_SHADER,
fragmentSource);
if (pixelShader == 0) {
return 0;
}
int program = GLES20.glCreateProgram();
if (program != 0) {
GLES20.glAttachShader(program, vertexShader);
checkGlError("glAttachShader");
GLES20.glAttachShader(program, pixelShader);
checkGlError("glAttachShader");
GLES20.glLinkProgram(program);
int[] linkStatus = new int[1];
GLES20.glGetProgramiv(program, GLES20.GL_LINK_STATUS,
linkStatus, 0);
if (linkStatus[0] != GLES20.GL_TRUE) {
Log.e(TAG, "Could not link program: ");
Log.e(TAG, GLES20.glGetProgramInfoLog(program));
GLES20.glDeleteProgram(program);
program = 0;
}
}
return program;
}
private void checkGlError(String op) {
int error;
while ((error = GLES20.glGetError()) != GLES20.GL_NO_ERROR) {
Log.e(TAG, op + ": glError " + error);
throw new RuntimeException(op + ": glError " + error);
}
}
}
}
......@@ -3,6 +3,8 @@ package com.shuyu.gsyvideoplayer.builder;
import android.graphics.drawable.Drawable;
import android.view.View;
import com.shuyu.gsyvideoplayer.GSYVideoGLView;
import com.shuyu.gsyvideoplayer.effect.NoEffect;
import com.shuyu.gsyvideoplayer.listener.LockClickListener;
import com.shuyu.gsyvideoplayer.listener.StandardVideoAllCallBack;
import com.shuyu.gsyvideoplayer.listener.VideoAllCallBack;
......@@ -135,6 +137,9 @@ public class GSYVideoOptionBuilder {
//滑动dialog进度条样式
protected Drawable mDialogProgressBarDrawable;
//滤镜
protected GSYVideoGLView.ShaderInterface mEffectFilter = new NoEffect();
/**
* 全屏动画
*
......@@ -460,6 +465,14 @@ public class GSYVideoOptionBuilder {
return this;
}
/**
* 设置滤镜效果
*/
public GSYVideoOptionBuilder setEffectFilter(GSYVideoGLView.ShaderInterface effectFilter) {
this.mEffectFilter = effectFilter;
return this;
}
public void build(StandardGSYVideoPlayer gsyVideoPlayer) {
if (mStandardVideoAllCallBack != null) {
gsyVideoPlayer.setStandardVideoAllCallBack(mStandardVideoAllCallBack);
......@@ -521,6 +534,7 @@ public class GSYVideoOptionBuilder {
gsyVideoPlayer.setIsTouchWiget(mIsTouchWiget);
gsyVideoPlayer.setIsTouchWigetFull(mIsTouchWigetFull);
gsyVideoPlayer.setNeedShowWifiTip(mNeedShowWifiTip);
gsyVideoPlayer.setEffectFilter(mEffectFilter);
if (mEnlargeImageRes > 0) {
gsyVideoPlayer.setEnlargeImageRes(mEnlargeImageRes);
}
......
package com.shuyu.gsyvideoplayer.effect;
import android.opengl.GLSurfaceView;
import com.shuyu.gsyvideoplayer.GSYVideoGLView.ShaderInterface;
/**
* Attempts to auto-fix the video based on histogram equalization.
*
* @author sheraz.khilji
*/
public class AutoFixEffect implements ShaderInterface {
private float scale;
/**
* Initialize Effect
*
* @param scale Float, between 0 and 1. Zero means no adjustment, while 1
* indicates the maximum amount of adjustment.
*/
public AutoFixEffect(float scale) {
if (scale < 0.0f)
scale = 0.0f;
if (scale > 1.0f)
scale = 1.0f;
this.scale = scale;
}
@Override
public String getShader(GLSurfaceView mGlSurfaceView) {
String shader = "#extension GL_OES_EGL_image_external : require\n"
+ "precision mediump float;\n"
+ "uniform samplerExternalOES tex_sampler_0;\n"
+ "uniform samplerExternalOES tex_sampler_1;\n"
+ "uniform samplerExternalOES tex_sampler_2;\n"
+ " float scale;\n" + " float shift_scale;\n"
+ " float hist_offset;\n" + " float hist_scale;\n"
+ " float density_offset;\n" + " float density_scale;\n"
+ "varying vec2 vTextureCoord;\n" + "void main() {\n"
+ " shift_scale = "
+ (1.0f / 256f)
+ ";\n"
+ " hist_offset = "
+ (0.5f / 766f)
+ ";\n"
+ " hist_scale = "
+ (765f / 766f)
+ ";\n"
+ " density_offset = "
+ (0.5f / 1024f)
+ ";\n"
+ " density_scale = "
+ (1023f / 1024f)
+ ";\n"
+ " scale = "
+ scale
+ ";\n"
+ " const vec3 weights = vec3(0.33333, 0.33333, 0.33333);\n"
+ " vec4 color = texture2D(tex_sampler_0, vTextureCoord);\n"
+ " float energy = dot(color.rgb, weights);\n"
+ " float mask_value = energy - 0.5;\n"
+ " float alpha;\n"
+ " if (mask_value > 0.0) {\n"
+ " alpha = (pow(2.0 * mask_value, 1.5) - 1.0) * scale + 1.0;\n"
+ " } else { \n"
+ " alpha = (pow(2.0 * mask_value, 2.0) - 1.0) * scale + 1.0;\n"
+ " }\n"
+ " float index = energy * hist_scale + hist_offset;\n"
+ " vec4 temp = texture2D(tex_sampler_1, vec2(index, 0.5));\n"
+ " float value = temp.g + temp.r * shift_scale;\n"
+ " index = value * density_scale + density_offset;\n"
+ " temp = texture2D(tex_sampler_2, vec2(index, 0.5));\n"
+ " value = temp.g + temp.r * shift_scale;\n"
+ " float dst_energy = energy * alpha + value * (1.0 - alpha);\n"
+ " float max_energy = energy / max(color.r, max(color.g, color.b));\n"
+ " if (dst_energy > max_energy) {\n"
+ " dst_energy = max_energy;\n"
+ " }\n"
+ " if (energy == 0.0) {\n"
+ " gl_FragColor = color;\n"
+ " } else {\n"
+ " gl_FragColor = vec4(color.rgb * dst_energy / energy, color.a);\n"
+ " }\n" + "}\n";
return shader;
}
}
package com.shuyu.gsyvideoplayer.effect;
import android.opengl.GLSurfaceView;
import com.shuyu.gsyvideoplayer.GSYVideoGLView.ShaderInterface;
/**
* Converts the video into black and white colors
*
* @author sheraz.khilji
*/
public class BlackAndWhiteEffect implements ShaderInterface {
/**
* Initialize Effect
*/
public BlackAndWhiteEffect() {
}
@Override
public String getShader(GLSurfaceView mGlSurfaceView) {
String shader = "#extension GL_OES_EGL_image_external : require\n"
+ "precision mediump float;\n"
+ "varying vec2 vTextureCoord;\n"
+ "uniform samplerExternalOES sTexture;\n" + "void main() {\n"
+ " vec4 color = texture2D(sTexture, vTextureCoord);\n"
+ " float colorR = (color.r + color.g + color.b) / 3.0;\n"
+ " float colorG = (color.r + color.g + color.b) / 3.0;\n"
+ " float colorB = (color.r + color.g + color.b) / 3.0;\n"
+ " gl_FragColor = vec4(colorR, colorG, colorB, color.a);\n"
+ "}\n";
return shader;
}
}
package com.shuyu.gsyvideoplayer.effect;
import android.opengl.GLSurfaceView;
import com.shuyu.gsyvideoplayer.GSYVideoGLView.ShaderInterface;
/**
* Adjusts the brightness of the video.
*
* @author sheraz.khilji
*/
public class BrightnessEffect implements ShaderInterface {
private float brightnessValue;
/**
* Initialize Effect
*
* @param brightnessvalue Range should be between 0.1- 2.0 with 1.0 being normal.
*/
public BrightnessEffect(float brightnessvalue) {
if (brightnessvalue < 0.1f)
brightnessvalue = 0.1f;
if (brightnessvalue > 2.0f)
brightnessvalue = 2.0f;
this.brightnessValue = brightnessvalue;
}
@Override
public String getShader(GLSurfaceView mGlSurfaceView) {
String shader = "#extension GL_OES_EGL_image_external : require\n"
+ "precision mediump float;\n"
+ "uniform samplerExternalOES sTexture;\n"
+ "float brightness ;\n" + "varying vec2 vTextureCoord;\n"
+ "void main() {\n" + " brightness =" + brightnessValue
+ ";\n"
+ " vec4 color = texture2D(sTexture, vTextureCoord);\n"
+ " gl_FragColor = brightness * color;\n" + "}\n";
return shader;
}
}
package com.shuyu.gsyvideoplayer.effect;
import android.opengl.GLSurfaceView;
import com.shuyu.gsyvideoplayer.GSYVideoGLView.ShaderInterface;
/**
* Adjusts the contrast of the video.
*
* @author sheraz.khilji
*/
public class ContrastEffect implements ShaderInterface {
private float contrast;
/**
* Initialize Effect
*
* @param contrast Range should be between 0.1- 2.0 with 1.0 being normal.
*/
public ContrastEffect(float contrast) {
if (contrast < 0.1f)
contrast = 0.1f;
if (contrast > 2.0f)
contrast = 2.0f;
this.contrast = contrast;
}
@Override
public String getShader(GLSurfaceView mGlSurfaceView) {
String shader = "#extension GL_OES_EGL_image_external : require\n"
+ "precision mediump float;\n"
+ "uniform samplerExternalOES sTexture;\n"
+ " float contrast;\n" + "varying vec2 vTextureCoord;\n"
+ "void main() {\n" + " contrast =" + contrast + ";\n"
+ " vec4 color = texture2D(sTexture, vTextureCoord);\n"
+ " color -= 0.5;\n" + " color *= contrast;\n"
+ " color += 0.5;\n" + " gl_FragColor = color;\n" + "}\n";
return shader;
}
}
package com.shuyu.gsyvideoplayer.effect;
import android.opengl.GLSurfaceView;
import com.shuyu.gsyvideoplayer.GSYVideoGLView.ShaderInterface;
/**
* Applies a cross process effect on video, in which the red and green channels
* are enhanced while the blue channel is restricted.
*
* @author sheraz.khilji
*/
public class CrossProcessEffect implements ShaderInterface {
/**
* Initialize Effect
*/
public CrossProcessEffect() {
}
@Override
public String getShader(GLSurfaceView mGlSurfaceView) {
String shader = "#extension GL_OES_EGL_image_external : require\n"
+ "precision mediump float;\n"
+ "uniform samplerExternalOES sTexture;\n"
+ "varying vec2 vTextureCoord;\n" + "void main() {\n"
+ " vec4 color = texture2D(sTexture, vTextureCoord);\n"
+ " vec3 ncolor = vec3(0.0, 0.0, 0.0);\n" + " float value;\n"
+ " if (color.r < 0.5) {\n" + " value = color.r;\n"
+ " } else {\n" + " value = 1.0 - color.r;\n" + " }\n"
+ " float red = 4.0 * value * value * value;\n"
+ " if (color.r < 0.5) {\n" + " ncolor.r = red;\n"
+ " } else {\n" + " ncolor.r = 1.0 - red;\n" + " }\n"
+ " if (color.g < 0.5) {\n" + " value = color.g;\n"
+ " } else {\n" + " value = 1.0 - color.g;\n" + " }\n"
+ " float green = 2.0 * value * value;\n"
+ " if (color.g < 0.5) {\n" + " ncolor.g = green;\n"
+ " } else {\n" + " ncolor.g = 1.0 - green;\n" + " }\n"
+ " ncolor.b = color.b * 0.5 + 0.25;\n"
+ " gl_FragColor = vec4(ncolor.rgb, color.a);\n" + "}\n";
return shader;
}
}
package com.shuyu.gsyvideoplayer.effect;
import android.opengl.GLSurfaceView;
import com.shuyu.gsyvideoplayer.GSYVideoGLView.ShaderInterface;
import java.util.Date;
import java.util.Random;
/**
* Applies black and white documentary style effect on video..
*
* @author sheraz.khilji
*/
public class DocumentaryEffect implements ShaderInterface {
private int mWidth;
private int mHeight;
private Random mRandom;
/**
* Initialize Effect
*/
public DocumentaryEffect() {
}
/**
* Init all values that will be used by this shader.
*
* @param mGlSurfaceView which is responsible for displaying your video
*/
private void initValues(GLSurfaceView mGlSurfaceView) {
mWidth = mGlSurfaceView.getWidth();
mHeight = mGlSurfaceView.getHeight();
mRandom = new Random(new Date().getTime());
}
@Override
public String getShader(GLSurfaceView mGlSurfaceView) {
initValues(mGlSurfaceView);
float scale[] = new float[2];
if (mWidth > mHeight) {
scale[0] = 1f;
scale[1] = ((float) mHeight) / mWidth;
} else {
scale[0] = ((float) mWidth) / mHeight;
scale[1] = 1f;
}
float max_dist = ((float) Math.sqrt(scale[0] * scale[0] + scale[1]
* scale[1])) * 0.5f;
float seed[] = {mRandom.nextFloat(), mRandom.nextFloat()};
String scaleString[] = new String[2];
String seedString[] = new String[2];
scaleString[0] = "scale[0] = " + scale[0] + ";\n";
scaleString[1] = "scale[1] = " + scale[1] + ";\n";
seedString[0] = "seed[0] = " + seed[0] + ";\n";
seedString[1] = "seed[1] = " + seed[1] + ";\n";
String inv_max_distString = "inv_max_dist = " + 1.0f / max_dist + ";\n";
String stepsizeString = "stepsize = " + 1.0f / 255.0f + ";\n";
String shader = "#extension GL_OES_EGL_image_external : require\n"
+ "precision mediump float;\n"
+ "uniform samplerExternalOES sTexture;\n"
+ " vec2 seed;\n"
+ " float stepsize;\n"
+ " float inv_max_dist;\n"
+ " vec2 scale;\n"
+ "varying vec2 vTextureCoord;\n"
+ "float rand(vec2 loc) {\n"
+ " float theta1 = dot(loc, vec2(0.9898, 0.233));\n"
+ " float theta2 = dot(loc, vec2(12.0, 78.0));\n"
+ " float value = cos(theta1) * sin(theta2) + sin(theta1) * cos(theta2);\n"
+
// keep value of part1 in range: (2^-14 to 2^14).
" float temp = mod(197.0 * value, 1.0) + value;\n"
+ " float part1 = mod(220.0 * temp, 1.0) + temp;\n"
+ " float part2 = value * 0.5453;\n"
+ " float part3 = cos(theta1 + theta2) * 0.43758;\n"
+ " return fract(part1 + part2 + part3);\n"
+ "}\n"
+ "void main() {\n"
// Parameters that were created above
+ scaleString[0]
+ scaleString[1]
+ seedString[0]
+ seedString[1]
+ inv_max_distString
+ stepsizeString
// black white
+ " vec4 color = texture2D(sTexture, vTextureCoord);\n"
+ " float dither = rand(vTextureCoord + seed);\n"
+ " vec3 xform = clamp(2.0 * color.rgb, 0.0, 1.0);\n"
+ " vec3 temp = clamp(2.0 * (color.rgb + stepsize), 0.0, 1.0);\n"
+ " vec3 new_color = clamp(xform + (temp - xform) * (dither - 0.5), 0.0, 1.0);\n"
+
// grayscale
" float gray = dot(new_color, vec3(0.299, 0.587, 0.114));\n"
+ " new_color = vec3(gray, gray, gray);\n"
+
// vignette
" vec2 coord = vTextureCoord - vec2(0.5, 0.5);\n"
+ " float dist = length(coord * scale);\n"
+ " float lumen = 0.85 / (1.0 + exp((dist * inv_max_dist - 0.83) * 20.0)) + 0.15;\n"
+ " gl_FragColor = vec4(new_color * lumen, color.a);\n"
+ "}\n";
return shader;
}
}
package com.shuyu.gsyvideoplayer.effect;
import android.graphics.Color;
import android.opengl.GLSurfaceView;
import com.shuyu.gsyvideoplayer.GSYVideoGLView.ShaderInterface;
/**
* Representation of video using only two color tones.
*
* @author sheraz.khilji
*/
public class DuotoneEffect implements ShaderInterface {
// Default values
private int mFirstColor = Color.MAGENTA;
private int mSecondColor = Color.YELLOW;
/**
* Initialize effect
*
* @param mFirstColor Integer, representing an ARGB color with 8 bits per channel.
* May be created using Color class.
* @param mSecondColor Integer, representing an ARGB color with 8 bits per channel.
* May be created using Color class.
*/
public DuotoneEffect(int mFirstColor, int mSecondColor) {
this.mFirstColor = mFirstColor;
this.mSecondColor = mSecondColor;
}
@Override
public String getShader(GLSurfaceView mGlSurfaceView) {
float first[] = {Color.red(mFirstColor) / 255f,
Color.green(mFirstColor) / 255f, Color.blue(mFirstColor) / 255f};
float second[] = {Color.red(mSecondColor) / 255f,
Color.green(mSecondColor) / 255f,
Color.blue(mSecondColor) / 255f};
String firstColorString[] = new String[3];
String secondColorString[] = new String[3];
firstColorString[0] = "first[0] = " + first[0] + ";\n";
firstColorString[1] = "first[1] = " + first[1] + ";\n";
firstColorString[2] = "first[2] = " + first[2] + ";\n";
secondColorString[0] = "second[0] = " + second[0] + ";\n";
secondColorString[1] = "second[1] = " + second[1] + ";\n";
secondColorString[2] = "second[2] = " + second[2] + ";\n";
String shader = "#extension GL_OES_EGL_image_external : require\n"
+ "precision mediump float;\n"
+ "uniform samplerExternalOES sTexture;\n"
+ " vec3 first;\n"
+ " vec3 second;\n"
+ "varying vec2 vTextureCoord;\n"
+ "void main() {\n"
// Parameters that were created above
+ firstColorString[0]
+ firstColorString[1]
+ firstColorString[2]
+ secondColorString[0]
+ secondColorString[1]
+ secondColorString[2]
+ " vec4 color = texture2D(sTexture, vTextureCoord);\n"
+ " float energy = (color.r + color.g + color.b) * 0.3333;\n"
+ " vec3 new_color = (1.0 - energy) * first + energy * second;\n"
+ " gl_FragColor = vec4(new_color.rgb, color.a);\n" + "}\n";
return shader;
}
}
package com.shuyu.gsyvideoplayer.effect;
import android.opengl.GLSurfaceView;
import com.shuyu.gsyvideoplayer.GSYVideoGLView.ShaderInterface;
/**
* Applies back-light filling to the video.
*
* @author sheraz.khilji
*/
public class FillLightEffect implements ShaderInterface {
private float strength = 0f;
/**
* Initialize Effect
*
* @param strength Float, between 0 and 1. 0 means no change.
*/
public FillLightEffect(float strength) {
if (strength < 0.0f)
strength = 0f;
if (strength > 1.0f)
strength = 1f;
this.strength = strength;
}
@Override
public String getShader(GLSurfaceView mGlSurfaceView) {
float fade_gamma = 0.3f;
float amt = 1.0f - strength;
float mult = 1.0f / (amt * 0.7f + 0.3f);
float faded = fade_gamma + (1.0f - fade_gamma) * mult;
float igamma = 1.0f / faded;
String multString = "mult = " + mult + ";\n";
String igammaString = "igamma = " + igamma + ";\n";
String shader = "#extension GL_OES_EGL_image_external : require\n"
+ "precision mediump float;\n"
+ "uniform samplerExternalOES sTexture;\n"
+ " float mult;\n"
+ " float igamma;\n"
+ "varying vec2 vTextureCoord;\n"
+ "void main()\n"
+ "{\n"
// Parameters that were created above
+ multString
+ igammaString
+ " const vec3 color_weights = vec3(0.25, 0.5, 0.25);\n"
+ " vec4 color = texture2D(sTexture, vTextureCoord);\n"
+ " float lightmask = dot(color.rgb, color_weights);\n"
+ " float backmask = (1.0 - lightmask);\n"
+ " vec3 ones = vec3(1.0, 1.0, 1.0);\n"
+ " vec3 diff = pow(mult * color.rgb, igamma * ones) - color.rgb;\n"
+ " diff = min(diff, 1.0);\n"
+ " vec3 new_color = min(color.rgb + diff * backmask, 1.0);\n"
+ " gl_FragColor = vec4(new_color, color.a);\n" + "}\n";
return shader;
}
}
package com.shuyu.gsyvideoplayer.effect;
import android.opengl.GLSurfaceView;
import com.shuyu.gsyvideoplayer.GSYVideoGLView.ShaderInterface;
/**
* Apply Gamma Effect on Video being played
*/
public class GammaEffect implements ShaderInterface {
private float gammaValue;
/**
* Initialize Effect
*
* @param gammaValue Range should be between 0.0 - 2.0 with 1.0 being normal.
*/
public GammaEffect(float gammaValue) {
if (gammaValue < 0.0f)
gammaValue = 0.0f;
if (gammaValue > 2.0f)
gammaValue = 2.0f;
this.gammaValue = gammaValue;
}
@Override
public String getShader(GLSurfaceView mGlSurfaceView) {
String shader = "#extension GL_OES_EGL_image_external : require\n"
+ "precision mediump float;\n"
+ "varying vec2 vTextureCoord;\n"
+ "uniform samplerExternalOES sTexture;\n"
+ "float gamma=" + gammaValue + ";\n"
+ "void main() {\n"
+ "vec4 textureColor = texture2D(sTexture, vTextureCoord);\n"
+ "gl_FragColor = vec4(pow(textureColor.rgb, vec3(gamma)), textureColor.w);\n"
+ "}\n";
return shader;
}
}
\ No newline at end of file
package com.shuyu.gsyvideoplayer.effect;
import android.opengl.GLSurfaceView;
import com.shuyu.gsyvideoplayer.GSYVideoGLView.ShaderInterface;
import java.util.Date;
import java.util.Random;
/**
* Applies film grain effect to video.
*
* @author sheraz.khilji
*/
public class GrainEffect implements ShaderInterface {
private int mWidth;
private int mHeight;
private float strength;
private Random mRandom;
/**
* Initialize Effect
*
* @param strength Float, between 0 and 1. Zero means no distortion, while 1
* indicates the maximum amount of adjustment.
*/
public GrainEffect(float strength) {
if (strength < 0.0f)
strength = 0.0f;
if (strength > 1.0f)
strength = 1.0f;
this.strength = strength;
}
/**
* Init all values that will be used by this shader.
*
* @param mGlSurfaceView which is responsible for displaying your video
*/
private void initValues(GLSurfaceView mGlSurfaceView) {
mWidth = mGlSurfaceView.getWidth();
mHeight = mGlSurfaceView.getHeight();
mRandom = new Random(new Date().getTime());
}
@Override
public String getShader(GLSurfaceView mGlSurfaceView) {
initValues(mGlSurfaceView);
float seed[] = {mRandom.nextFloat(), mRandom.nextFloat()};
String scaleString = "scale = " + strength + ";\n";
String seedString[] = new String[2];
seedString[0] = "seed[0] = " + seed[0] + ";\n";
seedString[1] = "seed[1] = " + seed[1] + ";\n";
String stepX = "stepX = " + 0.5f / mWidth + ";\n";
String stepY = "stepY = " + 0.5f / mHeight + ";\n";
// locString[1] = "loc[1] = loc[1]+" + seedString[1] + ";\n";
String shader = "#extension GL_OES_EGL_image_external : require\n"
+ "precision mediump float;\n"
+ " vec2 seed;\n"
+ "varying vec2 vTextureCoord;\n"
+ "uniform samplerExternalOES tex_sampler_0;\n"
+ "uniform samplerExternalOES tex_sampler_1;\n"
+ "float scale;\n"
+ " float stepX;\n"
+ " float stepY;\n"
+ "float rand(vec2 loc) {\n"
+ " float theta1 = dot(loc, vec2(0.9898, 0.233));\n"
+ " float theta2 = dot(loc, vec2(12.0, 78.0));\n"
+ " float value = cos(theta1) * sin(theta2) + sin(theta1) * cos(theta2);\n"
+
// keep value of part1 in range: (2^-14 to 2^14).
" float temp = mod(197.0 * value, 1.0) + value;\n"
+ " float part1 = mod(220.0 * temp, 1.0) + temp;\n"
+ " float part2 = value * 0.5453;\n"
+ " float part3 = cos(theta1 + theta2) * 0.43758;\n"
+ " float sum = (part1 + part2 + part3);\n"
+ " return fract(sum)*scale;\n"
+ "}\n"
+ "void main() {\n"
// Parameters that were created above
+ seedString[0]
+ seedString[1]
+ scaleString
+ stepX
+ stepY
+ " float noise = texture2D(tex_sampler_1, vTextureCoord + vec2(-stepX, -stepY)).r * 0.224;\n"
+ " noise += texture2D(tex_sampler_1, vTextureCoord + vec2(-stepX, stepY)).r * 0.224;\n"
+ " noise += texture2D(tex_sampler_1, vTextureCoord + vec2(stepX, -stepY)).r * 0.224;\n"
+ " noise += texture2D(tex_sampler_1, vTextureCoord + vec2(stepX, stepY)).r * 0.224;\n"
+ " noise += 0.4448;\n"
+ " noise *= scale;\n"
+ " vec4 color = texture2D(tex_sampler_0, vTextureCoord);\n"
+ " float energy = 0.33333 * color.r + 0.33333 * color.g + 0.33333 * color.b;\n"
+ " float mask = (1.0 - sqrt(energy));\n"
+ " float weight = 1.0 - 1.333 * mask * noise;\n"
+ " gl_FragColor = vec4(color.rgb * weight, color.a);\n"
+ " gl_FragColor = gl_FragColor+vec4(rand(vTextureCoord + seed), rand(vTextureCoord + seed),rand(vTextureCoord + seed),1);\n"
+ "}\n";
return shader;
}
}
package com.shuyu.gsyvideoplayer.effect;
import android.opengl.GLSurfaceView;
import com.shuyu.gsyvideoplayer.GSYVideoGLView.ShaderInterface;
/**
* Converts video to GreyScale.
*
* @author sheraz.khilji
*/
public class GreyScaleEffect implements ShaderInterface {
/**
* Initialize Effect
*/
public GreyScaleEffect() {
}
@Override
public String getShader(GLSurfaceView mGlSurfaceView) {
String shader = "#extension GL_OES_EGL_image_external : require\n"
+ "precision mediump float;\n"
+ "uniform samplerExternalOES sTexture;\n"
+ "varying vec2 vTextureCoord;\n" + "void main() {\n"
+ " vec4 color = texture2D(sTexture, vTextureCoord);\n"
+ " float y = dot(color, vec4(0.299, 0.587, 0.114, 0));\n"
+ " gl_FragColor = vec4(y, y, y, color.a);\n" + "}\n";
;
return shader;
}
}
package com.shuyu.gsyvideoplayer.effect;
import android.opengl.GLSurfaceView;
import com.shuyu.gsyvideoplayer.GSYVideoGLView.ShaderInterface;
/**
* Apply Hue effect on the video being played
*/
public class HueEffect implements ShaderInterface {
float hueValue;
/**
* Initialize Effect
* <p>
* <img alt="Hue value chart" width="400" height="350" src="https://cloud.githubusercontent.com/assets/2201511/21810115/b99ac22a-d74a-11e6-9f6c-ef74d15c88c7.jpg" >
*
* @param hueDegrees Range of value should be between 0 to 360 degrees as described in the image above
*/
public HueEffect(float hueDegrees) {
// manipulating input value so that we can map it on 360 degree circle
hueValue = ((hueDegrees - 45) / 45f + 0.5f) * -1;
}
@Override
public String getShader(GLSurfaceView mGlSurfaceView) {
String shader = "#extension GL_OES_EGL_image_external : require\n"
+ "precision mediump float;\n"
+ "varying vec2 vTextureCoord;\n"
+ "uniform samplerExternalOES sTexture;\n"
+ "float hue=" + hueValue + ";\n"
+ "void main() {\n"
+ "vec4 kRGBToYPrime = vec4 (0.299, 0.587, 0.114, 0.0);\n"
+ "vec4 kRGBToI = vec4 (0.595716, -0.274453, -0.321263, 0.0);\n"
+ "vec4 kRGBToQ = vec4 (0.211456, -0.522591, 0.31135, 0.0);\n"
+ "vec4 kYIQToR = vec4 (1.0, 0.9563, 0.6210, 0.0);\n"
+ "vec4 kYIQToG = vec4 (1.0, -0.2721, -0.6474, 0.0);\n"
+ "vec4 kYIQToB = vec4 (1.0, -1.1070, 1.7046, 0.0);\n"
+ "vec4 color = texture2D(sTexture, vTextureCoord);\n"
+ "float YPrime = dot(color, kRGBToYPrime);\n"
+ "float I = dot(color, kRGBToI);\n"
+ "float Q = dot(color, kRGBToQ);\n"
+ "float chroma = sqrt (I * I + Q * Q);\n"
+ "Q = chroma * sin (hue);\n"
+ "I = chroma * cos (hue);\n"
+ "vec4 yIQ = vec4 (YPrime, I, Q, 0.0);\n"
+ "color.r = dot (yIQ, kYIQToR);\n"
+ "color.g = dot (yIQ, kYIQToG);\n"
+ "color.b = dot (yIQ, kYIQToB);\n"
+ "gl_FragColor = color;\n"
+ "}\n";
return shader;
}
}
\ No newline at end of file
package com.shuyu.gsyvideoplayer.effect;
import android.opengl.GLSurfaceView;
import com.shuyu.gsyvideoplayer.GSYVideoGLView.ShaderInterface;
/**
* Inverts the video colors. This can also be known as negative Effect.
*
* @author sheraz.khilji
*/
public class InvertColorsEffect implements ShaderInterface {
/**
* Initialize Effect
*/
public InvertColorsEffect() {
}
@Override
public String getShader(GLSurfaceView mGlSurfaceView) {
String shader = "#extension GL_OES_EGL_image_external : require\n"
+ "precision mediump float;\n"
+ "varying vec2 vTextureCoord;\n"
+ "uniform samplerExternalOES sTexture;\n" + "void main() {\n"
+ " vec4 color = texture2D(sTexture, vTextureCoord);\n"
+ " float colorR = (1.0 - color.r) / 1.0;\n"
+ " float colorG = (1.0 - color.g) / 1.0;\n"
+ " float colorB = (1.0 - color.b) / 1.0;\n"
+ " gl_FragColor = vec4(colorR, colorG, colorB, color.a);\n"
+ "}\n";
return shader;
}
}
package com.shuyu.gsyvideoplayer.effect;
import android.opengl.GLSurfaceView;
import com.shuyu.gsyvideoplayer.GSYVideoGLView.ShaderInterface;
import java.util.Date;
import java.util.Random;
/**
* Applies lomo-camera style effect to video.
*
* @author sheraz.khilji
*/
public class LamoishEffect implements ShaderInterface {
private int mWidth;
private int mHeight;
private Random mRandom;
/**
* Initialize Effect
*/
public LamoishEffect() {
}
/**
* Init all values that will be used by this shader.
*
* @param mGlSurfaceView which is responsible for displaying your video
*/
private void initValues(GLSurfaceView mGlSurfaceView) {
mWidth = mGlSurfaceView.getWidth();
mHeight = mGlSurfaceView.getHeight();
mRandom = new Random(new Date().getTime());
}
@Override
public String getShader(GLSurfaceView mGlSurfaceView) {
initValues(mGlSurfaceView);
float scale[] = new float[2];
if (mWidth > mHeight) {
scale[0] = 1f;
scale[1] = ((float) mHeight) / mWidth;
} else {
scale[0] = ((float) mWidth) / mHeight;
scale[1] = 1f;
}
float max_dist = ((float) Math.sqrt(scale[0] * scale[0] + scale[1]
* scale[1])) * 0.5f;
float seed[] = {mRandom.nextFloat(), mRandom.nextFloat()};
String scaleString[] = new String[2];
String seedString[] = new String[2];
scaleString[0] = "scale[0] = " + scale[0] + ";\n";
scaleString[1] = "scale[1] = " + scale[1] + ";\n";
seedString[0] = "seed[0] = " + seed[0] + ";\n";
seedString[1] = "seed[1] = " + seed[1] + ";\n";
String inv_max_distString = "inv_max_dist = " + 1.0f / max_dist + ";\n";
String stepsizeString = "stepsize = " + 1.0f / 255.0f + ";\n";
String stepsizeXString = "stepsizeX = " + 1.0f / mWidth + ";\n";
String stepsizeYString = "stepsizeY = " + 1.0f / mHeight + ";\n";
String shader = "#extension GL_OES_EGL_image_external : require\n"
+ "precision mediump float;\n"
+ "uniform samplerExternalOES sTexture;\n"
+ " vec2 seed;\n"
+ " float stepsizeX;\n"
+ " float stepsizeY;\n"
+ " float stepsize;\n"
+ " vec2 scale;\n"
+ " float inv_max_dist;\n"
+ "varying vec2 vTextureCoord;\n"
+ "float rand(vec2 loc) {\n"
+ " float theta1 = dot(loc, vec2(0.9898, 0.233));\n"
+ " float theta2 = dot(loc, vec2(12.0, 78.0));\n"
+ " float value = cos(theta1) * sin(theta2) + sin(theta1) * cos(theta2);\n"
+
// keep value of part1 in range: (2^-14 to 2^14).
" float temp = mod(197.0 * value, 1.0) + value;\n"
+ " float part1 = mod(220.0 * temp, 1.0) + temp;\n"
+ " float part2 = value * 0.5453;\n"
+ " float part3 = cos(theta1 + theta2) * 0.43758;\n"
+ " return fract(part1 + part2 + part3);\n" + "}\n"
+ "void main() {\n"
// Parameters that were created above
+ scaleString[0]
+ scaleString[1]
+ seedString[0]
+ seedString[1]
+ inv_max_distString
+ stepsizeString
+ stepsizeXString
+ stepsizeYString
// sharpen
+ " vec3 nbr_color = vec3(0.0, 0.0, 0.0);\n"
+ " vec2 coord;\n"
+ " vec4 color = texture2D(sTexture, vTextureCoord);\n"
+ " coord.x = vTextureCoord.x - 0.5 * stepsizeX;\n"
+ " coord.y = vTextureCoord.y - stepsizeY;\n"
+ " nbr_color += texture2D(sTexture, coord).rgb - color.rgb;\n"
+ " coord.x = vTextureCoord.x - stepsizeX;\n"
+ " coord.y = vTextureCoord.y + 0.5 * stepsizeY;\n"
+ " nbr_color += texture2D(sTexture, coord).rgb - color.rgb;\n"
+ " coord.x = vTextureCoord.x + stepsizeX;\n"
+ " coord.y = vTextureCoord.y - 0.5 * stepsizeY;\n"
+ " nbr_color += texture2D(sTexture, coord).rgb - color.rgb;\n"
+ " coord.x = vTextureCoord.x + stepsizeX;\n"
+ " coord.y = vTextureCoord.y + 0.5 * stepsizeY;\n"
+ " nbr_color += texture2D(sTexture, coord).rgb - color.rgb;\n"
+ " vec3 s_color = vec3(color.rgb + 0.3 * nbr_color);\n"
+
// cross process
" vec3 c_color = vec3(0.0, 0.0, 0.0);\n"
+ " float value;\n"
+ " if (s_color.r < 0.5) {\n"
+ " value = s_color.r;\n"
+ " } else {\n"
+ " value = 1.0 - s_color.r;\n"
+ " }\n"
+ " float red = 4.0 * value * value * value;\n"
+ " if (s_color.r < 0.5) {\n"
+ " c_color.r = red;\n"
+ " } else {\n"
+ " c_color.r = 1.0 - red;\n"
+ " }\n"
+ " if (s_color.g < 0.5) {\n"
+ " value = s_color.g;\n"
+ " } else {\n"
+ " value = 1.0 - s_color.g;\n"
+ " }\n"
+ " float green = 2.0 * value * value;\n"
+ " if (s_color.g < 0.5) {\n"
+ " c_color.g = green;\n"
+ " } else {\n"
+ " c_color.g = 1.0 - green;\n"
+ " }\n"
+ " c_color.b = s_color.b * 0.5 + 0.25;\n"
+
// blackwhite
" float dither = rand(vTextureCoord + seed);\n"
+ " vec3 xform = clamp((c_color.rgb - 0.15) * 1.53846, 0.0, 1.0);\n"
+ " vec3 temp = clamp((color.rgb + stepsize - 0.15) * 1.53846, 0.0, 1.0);\n"
+ " vec3 bw_color = clamp(xform + (temp - xform) * (dither - 0.5), 0.0, 1.0);\n"
+
// vignette
" coord = vTextureCoord - vec2(0.5, 0.5);\n"
+ " float dist = length(coord * scale);\n"
+ " float lumen = 0.85 / (1.0 + exp((dist * inv_max_dist - 0.73) * 20.0)) + 0.15;\n"
+ " gl_FragColor = vec4(bw_color * lumen, color.a);\n" + "}\n";
;
return shader;
}
}
package com.shuyu.gsyvideoplayer.effect;
import android.opengl.GLSurfaceView;
import com.shuyu.gsyvideoplayer.GSYVideoGLView.ShaderInterface;
/**
* Displays the normal video without any effect.
*
* @author sheraz.khilji
*/
public class NoEffect implements ShaderInterface {
/**
* Initialize
*/
public NoEffect() {
}
@Override
public String getShader(GLSurfaceView mGlSurfaceView) {
String shader = "#extension GL_OES_EGL_image_external : require\n"
+ "precision mediump float;\n"
+ "varying vec2 vTextureCoord;\n"
+ "uniform samplerExternalOES sTexture;\n" + "void main() {\n"
+ " gl_FragColor = texture2D(sTexture, vTextureCoord);\n"
+ "}\n";
return shader;
}
}
\ No newline at end of file
package com.shuyu.gsyvideoplayer.effect;
import android.opengl.GLSurfaceView;
import com.shuyu.gsyvideoplayer.GSYVideoGLView.ShaderInterface;
/**
* Applies Posterization effect to video.
*
* @author sheraz.khilji
*/
public class PosterizeEffect implements ShaderInterface {
/**
* Initialize Effect
*/
public PosterizeEffect() {
}
@Override
public String getShader(GLSurfaceView mGlSurfaceView) {
String shader = "#extension GL_OES_EGL_image_external : require\n"
+ "precision mediump float;\n"
+ "uniform samplerExternalOES sTexture;\n"
+ "varying vec2 vTextureCoord;\n" + "void main() {\n"
+ " vec4 color = texture2D(sTexture, vTextureCoord);\n"
+ " vec3 pcolor;\n"
+ " pcolor.r = (color.r >= 0.5) ? 0.75 : 0.25;\n"
+ " pcolor.g = (color.g >= 0.5) ? 0.75 : 0.25;\n"
+ " pcolor.b = (color.b >= 0.5) ? 0.75 : 0.25;\n"
+ " gl_FragColor = vec4(pcolor, color.a);\n" + "}\n";
return shader;
}
}
package com.shuyu.gsyvideoplayer.effect;
import android.opengl.GLSurfaceView;
import com.shuyu.gsyvideoplayer.GSYVideoGLView.ShaderInterface;
/**
* Adjusts color saturation of video. There is still some issue with this
* effect.
*
* @author sheraz.khilji
*/
public class SaturationEffect implements ShaderInterface {
private float scale = 0f;
/**
* Initialize Effect
*
* @param scale Float, between -1 and 1. 0 means no change, while -1 indicates
* full desaturation, i.e. grayscale.
*/
public SaturationEffect(float scale) {
this.scale = scale;
}
@Override
public String getShader(GLSurfaceView mGlSurfaceView) {
float shift = 1.0f / 255.0f;
float weights[] = {2f / 8f, 5f / 8f, 1f / 8f};
float exponents[] = new float[3];
String weightsString[] = new String[3];
String exponentsString[] = new String[3];
exponentsString[0] = "";
exponentsString[1] = "";
exponentsString[2] = "";
String scaleString = "";
if (scale > 0.0f) {
exponents[0] = (0.9f * scale) + 1.0f;
exponents[1] = (2.1f * scale) + 1.0f;
exponents[2] = (2.7f * scale) + 1.0f;
exponentsString[0] = "exponents[0] = " + exponents[0] + ";\n";
exponentsString[1] = "exponents[1] = " + exponents[1] + ";\n";
exponentsString[2] = "exponents[2] = " + exponents[2] + ";\n";
} else
scaleString = "scale = " + (1.0f + scale) + ";\n";
weightsString[0] = "weights[0] = " + weights[0] + ";\n";
weightsString[1] = "weights[1] = " + weights[1] + ";\n";
weightsString[2] = "weights[2] = " + weights[2] + ";\n";
String shiftString = "shift = " + shift + ";\n";
String shader = "#extension GL_OES_EGL_image_external : require\n"
+ "precision mediump float;\n"
+ "uniform samplerExternalOES sTexture;\n" + " float scale;\n"
+ " float shift;\n" + " vec3 weights;\n" + " vec3 exponents;\n"
+ "varying vec2 vTextureCoord;\n" + "void main() {\n"
// Parameters that were created above
+ weightsString[0]
+ weightsString[1]
+ weightsString[2]
+ shiftString
+ scaleString
+ " vec4 oldcolor = texture2D(sTexture, vTextureCoord);\n"
+ " float kv = dot(oldcolor.rgb, weights) + shift;\n"
+ " vec3 new_color = scale * oldcolor.rgb + (1.0 - scale) * kv;\n"
+ " gl_FragColor= vec4(new_color, oldcolor.a);\n"
// Parameters that were created above
+ weightsString[0]
+ weightsString[1]
+ weightsString[2]
+ exponentsString[0]
+ exponentsString[1]
+ exponentsString[2]
+ " vec4 color = texture2D(sTexture, vTextureCoord);\n"
+ " float de = dot(color.rgb, weights);\n"
+ " float inv_de = 1.0 / de;\n"
+ " vec3 verynew_color = de * pow(color.rgb * inv_de, exponents);\n"
+ " float max_color = max(max(max(verynew_color.r, verynew_color.g), verynew_color.b), 1.0);\n"
+ " gl_FragColor = gl_FragColor+vec4(verynew_color / max_color, color.a);\n"
+ "}\n";
return shader;
}
}
package com.shuyu.gsyvideoplayer.effect;
import android.opengl.GLSurfaceView;
import com.shuyu.gsyvideoplayer.GSYVideoGLView.ShaderInterface;
/**
* Converts video to Sepia tone.
*
* @author sheraz.khilji
*/
public class SepiaEffect implements ShaderInterface {
/**
* Initialize Effect
*/
public SepiaEffect() {
}
@Override
public String getShader(GLSurfaceView mGlSurfaceView) {
float weights[] = {805.0f / 2048.0f, 715.0f / 2048.0f,
557.0f / 2048.0f, 1575.0f / 2048.0f, 1405.0f / 2048.0f,
1097.0f / 2048.0f, 387.0f / 2048.0f, 344.0f / 2048.0f,
268.0f / 2048.0f};
String matrixString[] = new String[9];
matrixString[0] = " matrix[0][0]=" + weights[0] + ";\n";
matrixString[1] = " matrix[0][1]=" + weights[1] + ";\n";
matrixString[2] = " matrix[0][2]=" + weights[2] + ";\n";
matrixString[3] = " matrix[1][0]=" + weights[3] + ";\n";
matrixString[4] = " matrix[1][1]=" + weights[4] + ";\n";
matrixString[5] = " matrix[1][2]=" + weights[5] + ";\n";
matrixString[6] = " matrix[2][0]=" + weights[6] + ";\n";
matrixString[7] = " matrix[2][1]=" + weights[7] + ";\n";
matrixString[8] = " matrix[2][2]=" + weights[8] + ";\n";
String shader = "#extension GL_OES_EGL_image_external : require\n"
+ "precision mediump float;\n"
+ "uniform samplerExternalOES sTexture;\n" + " mat3 matrix;\n"
+ "varying vec2 vTextureCoord;\n" + "void main() {\n"
+ matrixString[0] + matrixString[1] + matrixString[2]
+ matrixString[3] + matrixString[4] + matrixString[5]
+ matrixString[6] + matrixString[7] + matrixString[8]
+ " vec4 color = texture2D(sTexture, vTextureCoord);\n"
+ " vec3 new_color = min(matrix * color.rgb, 1.0);\n"
+ " gl_FragColor = vec4(new_color.rgb, color.a);\n" + "}\n";
return shader;
}
}
package com.shuyu.gsyvideoplayer.effect;
import android.opengl.GLSurfaceView;
import com.shuyu.gsyvideoplayer.GSYVideoGLView.ShaderInterface;
/**
* Sharpens the video.
*
* @author sheraz.khilji
*/
public class SharpnessEffect implements ShaderInterface {
private int mWidth;
private int mHeight;
private float scale = 0f;
/**
* Initialize Effect
*
* @param scale Float, between 0 and 1. 0 means no change.
*/
public SharpnessEffect(float scale) {
if (scale < 0.0f)
scale = 0.0f;
if (scale > 1.0f)
scale = 1.0f;
this.scale = scale;
}
/**
* Init all values that will be used by this shader.
*
* @param mGlSurfaceView which is responsible for displaying your video
*/
private void initValues(GLSurfaceView mGlSurfaceView) {
mWidth = mGlSurfaceView.getWidth();
mHeight = mGlSurfaceView.getHeight();
}
@Override
public String getShader(GLSurfaceView mGlSurfaceView) {
initValues(mGlSurfaceView);
String stepsizeXString = "stepsizeX = " + 1.0f / mWidth + ";\n";
String stepsizeYString = "stepsizeY = " + 1.0f / mHeight + ";\n";
String scaleString = "scale = " + scale + ";\n";
String shader = "#extension GL_OES_EGL_image_external : require\n"
+ "precision mediump float;\n"
+ "uniform samplerExternalOES sTexture;\n"
+ " float scale;\n"
+ " float stepsizeX;\n"
+ " float stepsizeY;\n"
+ "varying vec2 vTextureCoord;\n"
+ "void main() {\n"
// Parameters that were created above
+ stepsizeXString
+ stepsizeYString
+ scaleString
+ " vec3 nbr_color = vec3(0.0, 0.0, 0.0);\n"
+ " vec2 coord;\n"
+ " vec4 color = texture2D(sTexture, vTextureCoord);\n"
+ " coord.x = vTextureCoord.x - 0.5 * stepsizeX;\n"
+ " coord.y = vTextureCoord.y - stepsizeY;\n"
+ " nbr_color += texture2D(sTexture, coord).rgb - color.rgb;\n"
+ " coord.x = vTextureCoord.x - stepsizeX;\n"
+ " coord.y = vTextureCoord.y + 0.5 * stepsizeY;\n"
+ " nbr_color += texture2D(sTexture, coord).rgb - color.rgb;\n"
+ " coord.x = vTextureCoord.x + stepsizeX;\n"
+ " coord.y = vTextureCoord.y - 0.5 * stepsizeY;\n"
+ " nbr_color += texture2D(sTexture, coord).rgb - color.rgb;\n"
+ " coord.x = vTextureCoord.x + stepsizeX;\n"
+ " coord.y = vTextureCoord.y + 0.5 * stepsizeY;\n"
+ " nbr_color += texture2D(sTexture, coord).rgb - color.rgb;\n"
+ " gl_FragColor = vec4(color.rgb - 2.0 * scale * nbr_color, color.a);\n"
+ "}\n";
return shader;
}
}
package com.shuyu.gsyvideoplayer.effect;
import android.opengl.GLSurfaceView;
import com.shuyu.gsyvideoplayer.GSYVideoGLView.ShaderInterface;
/**
* Adjusts color temperature of the video.
*
* @author sheraz.khilji
*/
public class TemperatureEffect implements ShaderInterface {
private float scale = 0f;
/**
* Initialize Effect
*
* @param scale Float, between 0 and 1, with 0 indicating cool, and 1
* indicating warm. A value of of 0.5 indicates no change.
*/
public TemperatureEffect(float scale) {
if (scale < 0.0f)
scale = 0.0f;
if (scale > 1.0f)
scale = 1.0f;
this.scale = scale;
}
@Override
public String getShader(GLSurfaceView mGlSurfaceView) {
String scaleString = "scale = " + (2.0f * scale - 1.0f) + ";\n";
String shader = "#extension GL_OES_EGL_image_external : require\n"
+ "precision mediump float;\n"
+ "uniform samplerExternalOES sTexture;\n"
+ " float scale;\n"
+ "varying vec2 vTextureCoord;\n"
+ "void main() {\n" // Parameters that were created above
+ scaleString
+ " vec4 color = texture2D(sTexture, vTextureCoord);\n"
+ " vec3 new_color = color.rgb;\n"
+ " new_color.r = color.r + color.r * ( 1.0 - color.r) * scale;\n"
+ " new_color.b = color.b - color.b * ( 1.0 - color.b) * scale;\n"
+ " if (scale > 0.0) { \n"
+ " new_color.g = color.g + color.g * ( 1.0 - color.g) * scale * 0.25;\n"
+ " }\n"
+ " float max_value = max(new_color.r, max(new_color.g, new_color.b));\n"
+ " if (max_value > 1.0) { \n"
+ " new_color /= max_value;\n" + " } \n"
+ " gl_FragColor = vec4(new_color, color.a);\n" + "}\n";
return shader;
}
}
package com.shuyu.gsyvideoplayer.effect;
import android.graphics.Color;
import android.opengl.GLSurfaceView;
import com.shuyu.gsyvideoplayer.GSYVideoGLView.ShaderInterface;
/**
* Tints the video with specified color..
*
* @author sheraz.khilji
*/
public class TintEffect implements ShaderInterface {
private int mTint = 0xFF0000FF;
/**
* Initialize Effect
*
* @param color Integer, representing an ARGB color with 8 bits per channel.
* May be created using Color class.
*/
public TintEffect(int color) {
this.mTint = color;
}
@Override
public String getShader(GLSurfaceView mGlSurfaceView) {
float color_ratio[] = {0.21f, 0.71f, 0.07f};
String color_ratioString[] = new String[3];
color_ratioString[0] = "color_ratio[0] = " + color_ratio[0] + ";\n";
color_ratioString[1] = "color_ratio[1] = " + color_ratio[1] + ";\n";
color_ratioString[2] = "color_ratio[2] = " + color_ratio[2] + ";\n";
float tint_color[] = {Color.red(mTint) / 255f,
Color.green(mTint) / 255f, Color.blue(mTint) / 255f};
String tintString[] = new String[3];
tintString[0] = "tint[0] = " + tint_color[0] + ";\n";
tintString[1] = "tint[1] = " + tint_color[1] + ";\n";
tintString[2] = "tint[2] = " + tint_color[2] + ";\n";
String shader = "#extension GL_OES_EGL_image_external : require\n"
+ "precision mediump float;\n"
+ "uniform samplerExternalOES sTexture;\n"
+ " vec3 tint;\n"
+ " vec3 color_ratio;\n"
+ "varying vec2 vTextureCoord;\n"
+ "void main() {\n"
// Parameters that were created above
+ color_ratioString[0]
+ color_ratioString[1]
+ color_ratioString[2]
+ tintString[0]
+ tintString[1]
+ tintString[2]
+ " vec4 color = texture2D(sTexture, vTextureCoord);\n"
+ " float avg_color = dot(color_ratio, color.rgb);\n"
+ " vec3 new_color = min(0.8 * avg_color + 0.2 * tint, 1.0);\n"
+ " gl_FragColor = vec4(new_color.rgb, color.a);\n" + "}\n";
return shader;
}
}
package com.shuyu.gsyvideoplayer.effect;
import android.opengl.GLSurfaceView;
import com.shuyu.gsyvideoplayer.GSYVideoGLView.ShaderInterface;
/**
* Applies lomo-camera style effect to video.
*
* @author sheraz.khilji
*/
public class VignetteEffect implements ShaderInterface {
private int mWidth = 0;
private int mHeight = 0;
private float mScale = 0f;
private final float mShade = 0.85f;
/**
* Initialize Effect
*
* @param scale Float, between 0 and 1. 0 means no change.
*/
public VignetteEffect(float scale) {
if (scale < 0.0f)
scale = 0.0f;
if (scale > 1.0f)
scale = 1.0f;
this.mScale = scale;
}
/**
* Init all values that will be used by this shader.
*
* @param mGlSurfaceView which is responsible for displaying your video
*/
private void initValues(GLSurfaceView mGlSurfaceView) {
mWidth = mGlSurfaceView.getWidth();
mHeight = mGlSurfaceView.getHeight();
}
@Override
public String getShader(GLSurfaceView mGlSurfaceView) {
initValues(mGlSurfaceView);
float scale[] = new float[2];
if (mWidth > mHeight) {
scale[0] = 1f;
scale[1] = ((float) mHeight) / mWidth;
} else {
scale[0] = ((float) mWidth) / mHeight;
scale[1] = 1f;
}
float max_dist = ((float) Math.sqrt(scale[0] * scale[0] + scale[1]
* scale[1])) * 0.5f;
String scaleString[] = new String[2];
scaleString[0] = "scale[0] = " + scale[0] + ";\n";
scaleString[1] = "scale[1] = " + scale[1] + ";\n";
String inv_max_distString = "inv_max_dist = " + 1.0f / max_dist + ";\n";
String shadeString = "shade = " + mShade + ";\n";
// The 'range' is between 1.3 to 0.6. When scale is zero then range is
// 1.3
// which means no vignette at all because the luminousity difference is
// less than 1/256 and will cause nothing.
String rangeString = "range = "
+ (1.30f - (float) Math.sqrt(mScale) * 0.7f) + ";\n";
String shader = "#extension GL_OES_EGL_image_external : require\n"
+ "precision mediump float;\n"
+ "uniform samplerExternalOES sTexture;\n"
+ " float range;\n"
+ " float inv_max_dist;\n"
+ " float shade;\n"
+ " vec2 scale;\n"
+ "varying vec2 vTextureCoord;\n"
+ "void main() {\n"
// Parameters that were created above
+ scaleString[0]
+ scaleString[1]
+ inv_max_distString
+ shadeString
+ rangeString
+ " const float slope = 20.0;\n"
+ " vec2 coord = vTextureCoord - vec2(0.5, 0.5);\n"
+ " float dist = length(coord * scale);\n"
+ " float lumen = shade / (1.0 + exp((dist * inv_max_dist - range) * slope)) + (1.0 - shade);\n"
+ " vec4 color = texture2D(sTexture, vTextureCoord);\n"
+ " gl_FragColor = vec4(color.rgb * lumen, color.a);\n"
+ "}\n";
return shader;
}
}
......@@ -26,6 +26,10 @@ public class GSYVideoType {
public final static int IJKEXOPLAYER = 1;
//gl
public final static int GLSURFACE = 2;
//surface
public final static int SUFRACE = 1;
......
......@@ -7,20 +7,16 @@ import android.support.annotation.AttrRes;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.TextureView;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.RelativeLayout;
import com.shuyu.gsyvideoplayer.GSYRenderView;
import com.shuyu.gsyvideoplayer.GSYSurfaceView;
import com.shuyu.gsyvideoplayer.GSYTextureView;
import com.shuyu.gsyvideoplayer.GSYVideoGLView;
import com.shuyu.gsyvideoplayer.GSYVideoManager;
import com.shuyu.gsyvideoplayer.effect.NoEffect;
import com.shuyu.gsyvideoplayer.utils.GSYVideoType;
/**
......@@ -28,7 +24,7 @@ import com.shuyu.gsyvideoplayer.utils.GSYVideoType;
* Created by guoshuyu on 2017/8/2.
*/
public abstract class GSYTextureRenderView extends FrameLayout implements TextureView.SurfaceTextureListener, SurfaceHolder.Callback2 {
public abstract class GSYTextureRenderView extends FrameLayout implements TextureView.SurfaceTextureListener, SurfaceHolder.Callback2, GSYVideoGLView.onGSYSurfaceListener {
//native绘制
protected Surface mSurface;
......@@ -42,6 +38,9 @@ public abstract class GSYTextureRenderView extends FrameLayout implements Textur
//满屏填充暂停为徒
protected Bitmap mFullPauseBitmap;
//滤镜
protected GSYVideoGLView.ShaderInterface mEffectFilter = new NoEffect();
//画面选择角度
protected int mRotate;
......@@ -106,6 +105,11 @@ public abstract class GSYTextureRenderView extends FrameLayout implements Textur
public void surfaceRedrawNeeded(SurfaceHolder holder) {
}
/******************** GLSurfaceView ****************************/
@Override
public void onSurfaceAvailable(Surface surface) {
pauseLogic(surface, false);
}
/**
* 暂停逻辑
......@@ -128,6 +132,9 @@ public abstract class GSYTextureRenderView extends FrameLayout implements Textur
if (GSYVideoType.getRenderType() == GSYVideoType.SUFRACE) {
mTextureView.addSurfaceView(getContext(), mTextureViewContainer, mRotate, this);
return;
} else if (GSYVideoType.getRenderType() == GSYVideoType.GLSURFACE) {
mTextureView.addGLView(getContext(), mTextureViewContainer, mRotate, this, mEffectFilter);
return;
}
mTextureView.addTextureView(getContext(), mTextureViewContainer, mRotate, this);
......@@ -171,6 +178,13 @@ public abstract class GSYTextureRenderView extends FrameLayout implements Textur
}
protected GSYVideoGLView getGSYVideoGLSView() {
if (mTextureView.getShowView() instanceof GSYVideoGLView) {
return (GSYVideoGLView)mTextureView.getShowView();
}
return null;
}
//暂停时使用绘制画面显示暂停、避免黑屏
protected abstract void showPauseCover();
......@@ -180,4 +194,15 @@ public abstract class GSYTextureRenderView extends FrameLayout implements Textur
//小屏幕绘制层
protected abstract void setSmallVideoTextureView();
public GSYVideoGLView.ShaderInterface getEffectFilter() {
return mEffectFilter;
}
/**
* 设置滤镜效果
*/
public void setEffectFilter(GSYVideoGLView.ShaderInterface effectFilter) {
this.mEffectFilter = effectFilter;
}
}
......@@ -495,6 +495,10 @@ public abstract class GSYVideoView extends GSYTextureRenderView implements GSYMe
listenerNetWorkState();
mHadPlay = true;
if (mTextureView != null) {
mTextureView.onResume();
}
}
@Override
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册