Skip to content

关于取得美颜数据的效率问题 #340

@a483210

Description

@a483210

我看您是通过glReadPixels获得像素的
GLES20.glViewport(0, 0, mInputWidth, mInputHeight);
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, mGLFboId[0]);
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
GLES20.glReadPixels(0, 0, mInputWidth, mInputHeight, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, mGLFboBuffer);
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0);
GLES20.glViewport(0, 0, mOutputWidth, mOutputHeight);

但是在有些机子上效率还是不够,尽管我已经用了beautify_fragment_low
目前只有发现grafika的方法效率可以,但是我又发现MediaCodec的KEY_FRAME_RATE设置了无效,我查了google说它是由输入源确定的(比如摄像头),所以如果我想录制15帧视频,就只有2个方法
1、修改Camera的fps,但是当我设置成为15帧时会明显出现卡顿
2、先编码成h264然后在解码成yuvi420,最后在进行一次编码,这样做明显非常多余
请问您有什么好方法吗?

Activity

begeekmyfriend

begeekmyfriend commented on Feb 17, 2017

@begeekmyfriend
Owner

你说的没错,glReadPixels的效率问题,#324 已经吐槽过了,并没有太好的兼容性方法,估计只有魔改了~

  • 方法一是从native上gles动刀,这个可以试试,yasea就不考虑做了;
  • 方法二的确如你所说,用MediaCodec直接从surface读取编码,然后再解码,加特效(包括旋转翻转等),这种做法也很难看。

只能说一些机子上设备驱动太差了(glReadPixels也可以看做设备驱动读接口),不过建议你对比一下不开美颜时的帧率,美颜再怎么优化也不可能比原始帧率高。如果原始帧率就很低,那就不单单是glReadPixels的问题,估计只能考虑换机型了。

a483210

a483210 commented on Feb 20, 2017

@a483210
Author

谢谢您的回答,我用glReadPixels测试过一些机型,在索尼三星等机子上效率非常高,但是在国产机子上效率就非常差,这是不是因为国产的接口优化差呢?
还有从native上gles动刀大概怎么做?我不太理解您的意思。

notedit

notedit commented on Feb 20, 2017

@notedit

你可以google EGLImageKHR

begeekmyfriend

begeekmyfriend commented on Feb 20, 2017

@begeekmyfriend
Owner

建议你先跑一个non-gpuimage分支测试一下fps,如果还是太差就别浪费时间了。

a483210

a483210 commented on Feb 20, 2017

@a483210
Author

@notedit 事实上我查找过EGLImageKHR,但是我找不到GraphicBuffer.h,我看他好像在android的源码里面,我在ndk里面引用不到,然后有人说从源码里提取,事实上我觉得这不太靠谱。所以我最终放弃了EGLImageKHR。
http://stackoverflow.com/questions/23261662/how-to-use-graphicbuffer-in-android-ndk 例子
您有什么好方法可以解决该问题吗?
@begeekmyfriend 我测试过https://github.com/wuhaoyu1990/MagicCamera 项目采用low的情况下大部分机子都能保持流畅,如果实在没办法我只能用grafika的方法了。

begeekmyfriend

begeekmyfriend commented on Feb 20, 2017

@begeekmyfriend
Owner

Grafika用什么方式将GPU memory的数据拷贝到CPU memory的?

a483210

a483210 commented on Feb 20, 2017

@a483210
Author

它通过MediaCodec
format.setInteger(MediaFormat.KEY_COLOR_FORMAT,MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface)
将surface里的数据直接编码
https://github.com/wuhaoyu1990/MagicCamera/blob/master/Project-AndroidStudio/magicfilter/src/main/java/com/seu/magicfilter/encoder/video/VideoEncoderCore.java
详细做法

notedit

notedit commented on Feb 20, 2017

@notedit

Grafika 的做法必须4.3 以上

begeekmyfriend

begeekmyfriend commented on Feb 20, 2017

@begeekmyfriend
Owner

哦,就是上面第二种啊,多一道编解码,效果反而比glReadPixels好,太悲催了

notedit

notedit commented on Feb 20, 2017

@notedit

EGLImageKHR 为什么不靠谱 我身边认识的公司 就有用的

begeekmyfriend

begeekmyfriend commented on Feb 20, 2017

@begeekmyfriend
Owner

@notedit Grafika的方式要解码一遍,加特效后还要再编码一遍,这种效率反而好也是没谁了

a483210

a483210 commented on Feb 20, 2017

@a483210
Author

@notedit 您知道使用EGLImageKHR 具体应该怎么做吗?我对这里不是十分了解

notedit

notedit commented on Feb 20, 2017

@notedit

知道 @a483210

a483210

a483210 commented on Feb 20, 2017

@a483210
Author

@notedit 额,能教下我吗?拜托了!

notedit

notedit commented on Feb 20, 2017

@notedit

不是几行代码可以搞定的 之前搞了很长时间才搞定

4.3 以下的机器可以不支持了, 直接渲染到Surface 上 然后用Mediacodec 就可以

4 remaining items

begeekmyfriend

begeekmyfriend commented on Feb 20, 2017

@begeekmyfriend
Owner

试试修改摄像头的帧率设置

a483210

a483210 commented on Feb 20, 2017

@a483210
Author

我试过了,的确可以,但是如果我修改为低于24帧,就会感到明显的卡顿,所以这里我非常纠结

notedit

notedit commented on Feb 20, 2017

@notedit

我这边设置15帧 也没感觉卡

a483210

a483210 commented on Feb 20, 2017

@a483210
Author

@notedit 额,您把摄像头浏览的fps设置成15帧不会感觉稍微有些卡顿么

notedit

notedit commented on Feb 20, 2017

@notedit

不会 在音视频通话里面15帧 很正常

a483210

a483210 commented on Feb 20, 2017

@a483210
Author

@notedit 好的,我明天实验下,非常感谢

a483210

a483210 commented on Feb 21, 2017

@a483210
Author

@notedit 我测试了下设置摄像头为15帧,但是从MediaCodec得到sps pps显示还是30帧,用FFmpeg检测出来的是24帧,也就是说当我放这个h264时是快进的

begeekmyfriend

begeekmyfriend commented on Feb 21, 2017

@begeekmyfriend
Owner

你的设备是手机?报上名来

a483210

a483210 commented on Feb 21, 2017

@a483210
Author

索尼z2 应该说我没理解MediaCodec的sps pps是靠什么确定的

begeekmyfriend

begeekmyfriend commented on Feb 21, 2017

@begeekmyfriend
Owner

摄像头和编码器都设成15吗?

a483210

a483210 commented on Feb 21, 2017

@a483210
Author

对,我也试过低于15帧的,也一样没用

jtyang

jtyang commented on Apr 8, 2017

@jtyang

请问下MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface具体要咋改呢?试了下@begeekmyfriend说的,“这段代码不要了”,貌似预览都有问题。

a483210

a483210 commented on Apr 8, 2017

@a483210
Author

@jtyang 你可以看下我写的《Android 关于美颜/滤镜 从OpenGl录制视频的一种方案》希望能对你有所帮助

hirudo-zy

hirudo-zy commented on Jul 6, 2017

@hirudo-zy

@notedit 您好,想向您请教下EGLImageKHR获取数据的问题。当我使用
buffer->lock(GraphicBuffer::USAGE_SW_READ_OFTEN, &ptr);
memcpy(pixels, ptr, wh4);
buffer->unlock();
获取数据时,我只能得到一个数据为空的ptr(有地址),不知道您遇到过这个问题吗?有什么好的建议吗?
Stack Overflow上类似的问题https://stackoverflow.com/questions/21151259/replacing-glreadpixels-with-egl-khr-image-base-for-faster-pixel-copy?noredirect=1&lq=1

liouvilles

liouvilles commented on Nov 21, 2023

@liouvilles

23年再回一句用ImageReader读合适吗

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @notedit@begeekmyfriend@a483210@jtyang@liouvilles

        Issue actions

          关于取得美颜数据的效率问题 · Issue #340 · begeekmyfriend/yasea