Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
a483210 opened this issue Feb 17, 2017 · 34 comments
Open

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

a483210 opened this issue Feb 17, 2017 · 34 comments

Comments

@a483210
Copy link

a483210 commented Feb 17, 2017

我看您是通过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,最后在进行一次编码,这样做明显非常多余
请问您有什么好方法吗?

@begeekmyfriend
Copy link
Owner

begeekmyfriend commented Feb 17, 2017

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

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

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

@a483210
Copy link
Author

a483210 commented Feb 20, 2017

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

@notedit
Copy link

notedit commented Feb 20, 2017

你可以google EGLImageKHR

@begeekmyfriend
Copy link
Owner

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

@a483210
Copy link
Author

a483210 commented Feb 20, 2017

@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
Copy link
Owner

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

@a483210
Copy link
Author

a483210 commented Feb 20, 2017

它通过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
Copy link

notedit commented Feb 20, 2017

Grafika 的做法必须4.3 以上

@begeekmyfriend
Copy link
Owner

begeekmyfriend commented Feb 20, 2017

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

@notedit
Copy link

notedit commented Feb 20, 2017

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

@begeekmyfriend
Copy link
Owner

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

@a483210
Copy link
Author

a483210 commented Feb 20, 2017

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

@notedit
Copy link

notedit commented Feb 20, 2017

知道 @a483210

@a483210
Copy link
Author

a483210 commented Feb 20, 2017

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

@notedit
Copy link

notedit commented Feb 20, 2017

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

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

@begeekmyfriend
Copy link
Owner

@a483210 意思就是放弃glReadPixels使用MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface

@a483210
Copy link
Author

a483210 commented Feb 20, 2017

谢谢2位,我现在已经在用Mediacodec 写了,除了做法难看点,o(╯□╰)o

@begeekmyfriend
Copy link
Owner

@a483210 你理解错了,这段代码不要了,FBO去掉,直接读取surface,一次编码即可,不需要再解码

@a483210
Copy link
Author

a483210 commented Feb 20, 2017

我知道可以直接编码,但是我不知道怎么控制fps,设置成15帧它依然会编码出30帧的h264。
我之前google过好像是fps会根据输入源来确定,所以我才会再次解码,然后自己去过滤多余的帧

@begeekmyfriend
Copy link
Owner

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

@a483210
Copy link
Author

a483210 commented Feb 20, 2017

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

@notedit
Copy link

notedit commented Feb 20, 2017

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

@a483210
Copy link
Author

a483210 commented Feb 20, 2017

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

@notedit
Copy link

notedit commented Feb 20, 2017

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

@a483210
Copy link
Author

a483210 commented Feb 20, 2017

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

@a483210
Copy link
Author

a483210 commented Feb 21, 2017

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

@begeekmyfriend
Copy link
Owner

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

@a483210
Copy link
Author

a483210 commented Feb 21, 2017

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

@begeekmyfriend
Copy link
Owner

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

@a483210
Copy link
Author

a483210 commented Feb 21, 2017

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

@jtyang
Copy link

jtyang commented Apr 8, 2017

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

@a483210
Copy link
Author

a483210 commented Apr 8, 2017

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

@hirudo-zy
Copy link

@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
Copy link

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants