Как уменьшить или исправить объем графической памяти, используемой GlSurfaceView при применении эффектов мультимедиа Android к изображениям в Android? - PullRequest
0 голосов
/ 21 января 2019

Я делаю приложение для Android, которое использует GLSurfaceView и мультимедийные эффекты Android для применения фильтров к изображениям. Реализация работает нормально, за исключением того, что в приложении возникает утечка памяти. При каждом добавлении эффекта в графическую память использование приложения значительно увеличивается, и эта память никогда не освобождается.

Кто-нибудь знает, как уменьшить объем памяти в этом классе, или, по крайней мере, знает, что вызывает интенсивное использование памяти, и указывает мне верное направление для решения этой проблемы?

Я пытался дозвониться до GLES20.glDeleteTextures(2, mTextures, 0) как раз перед GLES20.glGenTextures(2, mTextures, 0), но это не помогло. Я также экспериментировал с GLES20.glFinish() и GLES20.glFlush() и mEffectContext.release() безуспешно или без каких-либо заметных изменений.

Я приложил скриншот из выполненного профилирования, а также соответствующие фрагменты самого класса ниже.

Это мой первый вопрос о переполнении стека, поэтому не стесняйтесь поправлять меня, если я нарушил все правила сообщества.

class ImageFilterView extends GLSurfaceView implements GLSurfaceView.Renderer {

 private int[] mTextures = new int[2];

    private void init() {

        setEGLContextClientVersion(2);
        setRenderer(this);
        setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
        setFilterEffect(NONE);

    }

    @Override
    public void onSurfaceChanged(GL10 gl, int width, int height) {
        if (mTexRenderer != null) {
            mTexRenderer.updateViewSize(width, height);
        }
    }

    @Override
    public void onDrawFrame(GL10 gl) {

        if (!mInitialized) {
            //Only need to do this once
            mEffectContext = EffectContext.createWithCurrentGlContext();
            mTexRenderer.init();
            loadTextures();
            mInitialized = true;
        }
        if (mCurrentEffect != NONE || mCustomEffect != null) {
            //if an effect is chosen initialize it and apply it to the texture
            initEffect();
            applyEffect();
        }
        renderResult();
        if (isSaveImage) {
            final Bitmap mFilterBitmap = BitmapUtil.createBitmapFromGLSurface(this, gl);
            Log.e(TAG, "onDrawFrame: " + mFilterBitmap);
            isSaveImage = false;
            if (mOnSaveBitmap != null) {
                new Handler(Looper.getMainLooper()).post(new Runnable() {
                    @Override
                    public void run() {
                        mOnSaveBitmap.onBitmapReady(mFilterBitmap);
                    }
                });
            }
        }
    }

    void setFilterEffect(PhotoFilter effect) {
        mCurrentEffect = effect;
        mCustomEffect = null;
        requestRender();
    }



    void saveBitmap(OnSaveBitmap onSaveBitmap) {
        mOnSaveBitmap = onSaveBitmap;
        isSaveImage = true;
        requestRender();
    }

    private void loadTextures() {

        GLES20.glGenTextures(2, mTextures, 0);
        // Load input bitmap
        if (mSourceBitmap != null) {
            mImageWidth = mSourceBitmap.getWidth();
            mImageHeight = mSourceBitmap.getHeight();  
            mTexRenderer.updateTextureSize(mImageWidth, mImageHeight);

            // Upload to texture
            GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextures[0]);
            GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, mSourceBitmap, 0);

            // Set texture parameters
            GLToolbox.initTexParams();
        }
    }

    private void initEffect() {
        EffectFactory effectFactory = mEffectContext.getFactory();
        if (mEffect != null) {
            mEffect.release();

        }
        if (mCustomEffect != null) {
            mEffect = effectFactory.createEffect(mCustomEffect.getEffectName());
            Map<String, Object> parameters = mCustomEffect.getParameters();
            for (Map.Entry<String, Object> param : parameters.entrySet()) {
                mEffect.setParameter(param.getKey(), param.getValue());
            }
        } else {
            // Initialize the correct effect based on the selected menu/action item
            switch (mCurrentEffect) {

                case VIGNETTE:
                    mEffect = effectFactory.createEffect(EFFECT_VIGNETTE);
                    mEffect.setParameter("scale", .5f);
                    break;
            }
        }
    }

    private void applyEffect() {
        mEffect.apply(mTextures[0], mImageWidth, mImageHeight, mTextures[1]);
    }

    private void renderResult() {
        if (mCurrentEffect != NONE || mCustomEffect != null) {
            // if no effect is chosen, just render the original bitmap
            mTexRenderer.renderTexture(mTextures[1]);
        } else {
            // render the result of applyEffect()
            mTexRenderer.renderTexture(mTextures[0]);
        }

    }


}

Снимок экрана профилирования: память увеличивается при каждом добавлении фильтра

...