MasayukiSuda / GPUVideo-android

This library apply video filter on generate an Mp4 and on ExoPlayer video and Video Recording with Camera2.
MIT License
658 stars 179 forks source link

how to apply new GPUvideo #22

Closed Rehamgalal closed 5 years ago

Rehamgalal commented 5 years ago

the same library for images is applying Instagram video i"m trying to apply them on the library like these 👍 https://github.com/imrunning/android-instagram-image-filter/tree/master/instagramfilter/src/main/java/jp/co/cyberagent/android/gpuimage/sample/filter

I'm trying to apply the IFImageFilter class for video like here

public class IFVideoFilter extends GlFilter {

    private int filterInputTextureUniform2;
    private int filterInputTextureUniform3;
    private int filterInputTextureUniform4;
    private int filterInputTextureUniform5;
    private int filterInputTextureUniform6;
    public int filterSourceTexture2 = EglUtil.NO_TEXTURE;
    public int filterSourceTexture3 = EglUtil.NO_TEXTURE;
    public int filterSourceTexture4 = EglUtil.NO_TEXTURE;
    public int filterSourceTexture5 = EglUtil.NO_TEXTURE;
    public int filterSourceTexture6 = EglUtil.NO_TEXTURE;
    private final LinkedList<Runnable> runOnDraw;
    private List<Integer> mResIds;
    private Context mContext;
    public IFVideoFilter(Context context,String fragmentShaderString){
        super(DEFAULT_VERTEX_SHADER,fragmentShaderString);
        mContext=context;
        runOnDraw = new LinkedList<>();
    }

    public void setup() {
        super.setup();
        filterInputTextureUniform2 = GLES20.glGetUniformLocation(getProgram(), "sTexture2");
        filterInputTextureUniform3 = GLES20.glGetUniformLocation(getProgram(), "sTexture3");
        filterInputTextureUniform4 = GLES20.glGetUniformLocation(getProgram(), "sTexture4");
        filterInputTextureUniform5 = GLES20.glGetUniformLocation(getProgram(), "sTexture5");
        filterInputTextureUniform6 = GLES20.glGetUniformLocation(getProgram(), "sTexture6");
        while (!runOnDraw.isEmpty()) {
            runOnDraw.removeFirst().run();
        }
        initInputTexture();

    }
    private void runOnDraw(final Runnable runnable) {
        synchronized (runOnDraw) {
            runOnDraw.addLast(runnable);
        }
    }
    public void onDestroy() {
        super.onDestroy();

        if (filterSourceTexture2 != EglUtil.NO_TEXTURE) {
            int[] arrayOfInt1 = new int[1];
            arrayOfInt1[0] = this.filterSourceTexture2;
            GLES20.glDeleteTextures(1, arrayOfInt1, 0);
            this.filterSourceTexture2 = EglUtil.NO_TEXTURE;
        }

        if (filterSourceTexture3 != EglUtil.NO_TEXTURE) {
            int[] arrayOfInt2 = new int[1];
            arrayOfInt2[0] = this.filterSourceTexture3;
            GLES20.glDeleteTextures(1, arrayOfInt2, 0);
            this.filterSourceTexture3 = EglUtil.NO_TEXTURE;
        }

        if (filterSourceTexture4 != EglUtil.NO_TEXTURE) {
            int[] arrayOfInt3 = new int[1];
            arrayOfInt3[0] = this.filterSourceTexture4;
            GLES20.glDeleteTextures(1, arrayOfInt3, 0);
            this.filterSourceTexture4 = EglUtil.NO_TEXTURE;
        }

        if (filterSourceTexture5 != EglUtil.NO_TEXTURE) {
            int[] arrayOfInt4 = new int[1];
            arrayOfInt4[0] = this.filterSourceTexture5;
            GLES20.glDeleteTextures(1, arrayOfInt4, 0);
            this.filterSourceTexture5 = EglUtil.NO_TEXTURE;
        }

        if (filterSourceTexture6 != EglUtil.NO_TEXTURE) {
            int[] arrayOfInt5 = new int[1];
            arrayOfInt5[0] = this.filterSourceTexture6;
            GLES20.glDeleteTextures(1, arrayOfInt5, 0);
            this.filterSourceTexture6 = EglUtil.NO_TEXTURE;
        }

    }
    @Override
    protected void onDrawArraysPre() {
        super.onDrawArraysPre();

        if (filterSourceTexture2 != EglUtil.NO_TEXTURE) {
            GLES20.glActiveTexture(GLES20.GL_TEXTURE3);
            GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, filterSourceTexture2);
            GLES20.glUniform1i(filterInputTextureUniform2, 3);
        }

        if (filterSourceTexture3 != EglUtil.NO_TEXTURE) {
            GLES20.glActiveTexture(GLES20.GL_TEXTURE4);
            GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, filterSourceTexture3);
            GLES20.glUniform1i(filterInputTextureUniform3, 4);
        }

        if (filterSourceTexture4 != EglUtil.NO_TEXTURE) {
            GLES20.glActiveTexture(GLES20.GL_TEXTURE5);
            GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, filterSourceTexture4);
            GLES20.glUniform1i(filterInputTextureUniform4, 5);
        }

        if (filterSourceTexture5 != EglUtil.NO_TEXTURE) {
            GLES20.glActiveTexture(GLES20.GL_TEXTURE6);
            GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, filterSourceTexture5);
            GLES20.glUniform1i(filterInputTextureUniform5, 6);
        }

        if (filterSourceTexture6 != EglUtil.NO_TEXTURE) {
            GLES20.glActiveTexture(GLES20.GL_TEXTURE7);
            GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, filterSourceTexture6);
            GLES20.glUniform1i(filterInputTextureUniform6, 7);
        }

    }

    public void addInputTexture(int resId) {
        if (mResIds == null) {
            mResIds = new ArrayList<Integer>();
        }
        mResIds.add(resId);
    }

    public void initInputTexture() {
        if (mResIds == null) {
            return;
        }
        if (mResIds.size() > 0) {
            runOnDraw(new Runnable() {
                @Override
                public void run() {
                    Bitmap b = BitmapFactory.decodeResource(mContext.getResources(), mResIds.get(0));
                    filterSourceTexture2 = EglUtil.loadTexture(b, EglUtil.NO_TEXTURE, true);
                }
            });
        }

        if (mResIds.size() > 1) {
            runOnDraw(new Runnable() {
                @Override
                public void run() {
                    Bitmap b = BitmapFactory.decodeResource(mContext.getResources(), mResIds.get(1));
                    filterSourceTexture3 = EglUtil.loadTexture(b, EglUtil.NO_TEXTURE, true);
                }
            });
        }

        if (mResIds.size() > 2) {
            runOnDraw(new Runnable() {
                @Override
                public void run() {
                    Bitmap b = BitmapFactory.decodeResource(mContext.getResources(), mResIds.get(2));
                    filterSourceTexture4 = EglUtil.loadTexture(b, EglUtil.NO_TEXTURE, true);
                }
            });
        }

        if (mResIds.size() > 3) {
            runOnDraw(new Runnable() {
                @Override
                public void run() {
                    Bitmap b = BitmapFactory.decodeResource(mContext.getResources(), mResIds.get(3));
                    filterSourceTexture5 = EglUtil.loadTexture(b, EglUtil.NO_TEXTURE, true);
                }
            });
        }

        if (mResIds.size() > 4) {
            runOnDraw(new Runnable() {
                @Override
                public void run() {
                    Bitmap b = BitmapFactory.decodeResource(mContext.getResources(), mResIds.get(4));
                    filterSourceTexture6 = EglUtil.loadTexture(b, EglUtil.NO_TEXTURE, true);
                }
            });
        }
    }

}

i get error java.lang.RuntimeException: Could not link program Player is accessed on the wrong thread.

seanghay commented 5 years ago

In your case, the error may be caused by the incompatibility of Vertex Shader and Fragment Shader. To solve this kind of problem, you should check each varying field name carefully (Probably change from textureCoordinate to vTextureCoord) and make sure it's the same in both Vertex and Fragment shader. Another thing is that GlFilter texture uniform field is sTexture make sure you changed to everywhere in your new shader, and replace all inputImageTexture to sTexture.

seanghay commented 5 years ago

I wrote and changed quite a few stuff here. Please take a look that might help you!

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.opengl.GLES20;
import android.util.SparseIntArray;

import com.daasuu.mp4compose.filter.GlFilter;
import com.daasuu.mp4compose.utils.EglUtil;

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

abstract class IFVideoFilter extends GlFilter {

    private final String[] textureHandleNames = new String[] {
            "inputImageTexture2",
            "inputImageTexture3",
            "inputImageTexture4",
            "inputImageTexture5",
            "inputImageTexture6"
    };

    protected final Context context;
    protected final ArrayList<Integer> textureResourceIds = new ArrayList<>();
    protected final SparseIntArray texturesMap = new SparseIntArray();
    protected final Queue<Runnable> preDrawRunnables = new LinkedList<>();

    public IFVideoFilter(
            final Context context,
            final String fragmentShaderSource)
    {
        super(GlFilter.DEFAULT_VERTEX_SHADER, fragmentShaderSource);
        this.context = context;
        preDrawRunnables.add(this::initTextures);
    }

    @Override
    protected void onDraw() {
        while (!preDrawRunnables.isEmpty()) preDrawRunnables.poll().run();
        for (int i = 0; i < texturesMap.size(); i++) {
            final int uniformLocation = texturesMap.keyAt(i);
            final int textureId = texturesMap.get(uniformLocation);
            if (textureId != EglUtil.NO_TEXTURE) {
                GLES20.glActiveTexture(GLES20.GL_TEXTURE3 + i);
                GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureId);
                GLES20.glUniform1i(uniformLocation, 3 + i);
            }
        }
    }

    private void initTextures() {
        for (int i = 0; i < textureHandleNames.length; i++) {
            if (textureResourceIds.size() > i) {
                int textureId;
                final int textureLocation = getHandle(textureHandleNames[i]);
                final Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(),
                        textureResourceIds.get(i));
                textureId = EglUtil.loadTexture(bitmap, EglUtil.NO_TEXTURE, true);
                texturesMap.put(textureLocation, textureId);
            }
        }
    }
}

Implementation Example of IFLomoFilter

import android.content.Context;

public class IFLomoFilter extends IFVideoFilter {
    private static final String SHADER = "precision lowp float;\n" +
            " \n" +
            " varying highp vec2 vTextureCoord;\n" +
            " \n" +
            " uniform sampler2D sTexture;\n" +
            " uniform sampler2D inputImageTexture2;\n" +
            " uniform sampler2D inputImageTexture3;\n" +
            " \n" +
            " void main()\n" +
            " {\n" +
            "     \n" +
            "     vec3 texel = texture2D(sTexture, vTextureCoord).rgb;\n" +
            "     \n" +
            "     vec2 red = vec2(texel.r, 0.16666);\n" +
            "     vec2 green = vec2(texel.g, 0.5);\n" +
            "     vec2 blue = vec2(texel.b, 0.83333);\n" +
            "     \n" +
            "     texel.rgb = vec3(\n" +
            "                      texture2D(inputImageTexture2, red).r,\n" +
            "                      texture2D(inputImageTexture2, green).g,\n" +
            "                      texture2D(inputImageTexture2, blue).b);\n" +
            "     \n" +
            "     vec2 tc = (2.0 * vTextureCoord) - 1.0;\n" +
            "     float d = dot(tc, tc);\n" +
            "     vec2 lookup = vec2(d, texel.r);\n" +
            "     texel.r = texture2D(inputImageTexture3, lookup).r;\n" +
            "     lookup.y = texel.g;\n" +
            "     texel.g = texture2D(inputImageTexture3, lookup).g;\n" +
            "     lookup.y = texel.b;\n" +
            "     texel.b\t= texture2D(inputImageTexture3, lookup).b;\n" +
            "     \n" +
            "     gl_FragColor = vec4(texel,1.0);\n" +
            " }\n";

    public IFLomoFilter(Context context) {
        super(context, SHADER);
        textureResourceIds.add(R.drawable.lomo_map);
        textureResourceIds.add(R.drawable.vignette_map);
    }
}
Rehamgalal commented 5 years ago

@seanghay thank you it's working you saved my time