0°

Android利用硬解硬编和OpenGLES来高效的处理MP4视频

内容预览:
  • 理论上就能一举解决上面的两个问题~
  • 视频流处理完毕后,利用MediaExtractor读取音频流,并利用MediaMuxer混...~
  • “ 视频流解码并混合 在第四步的代码中,已经出现了视频流编码的方法了,...~

始发于微信公众号: 程序员小乐

分享编程技能、互联网技术、生活感悟、打造干货分享平台,将总结的技术、心得、经验分享给大家,这里不只限于技术!学无止境,不求尽如人意,但求问心无愧。让学习成为一种美、一种习惯。值得爱学习的你去关注,感觉有帮助转发分享让更多的人去关注!点击上方 蓝字 关注!



作者:湖广午王

链接:http://blog.csdn.net/junzia/article/details/77924629
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

Android利用硬解硬编和OpenGLES来高效的处理MP4视频—– 由   分享


每日英语

Life is full of trial and error. One failure doesn’t mean you’re out of the picture. 

人生充满了尝试与错误。一次失败不代表你就出局了。



最近工作中遇到一个问题,就是要对视频增加视频特效,实现类似于抖音的效果,抖音的效果由其他同事实现,我的工作重心在视频的处理,特效的集成。按照之前的思路很快就实现了这个功能,但是实际应用到项目中时却遇到各种问题。于是就有了这篇博客。


遇到的问题



说是各种问题,特效方便的不管,我所遇到的视频处理的问题主要为以下两个方面:


  1. 处理过程耗时较长。因为处理的时候是按照之前的思路,用MediaCodec解码,取出ByteBuffer,然后用OpenGLES处理,处理完毕后readPixels,得到图像数据,然后将图像数据推入MediaCodec编码。 在这里readPixels非常耗时。480*840的视频,一帧耗时基本是40ms+。

  2. 手机兼容性很成问题。虽然不需要考虑低版本兼容,只需要考虑4.4+的手机。但是Android手机市场的情况,开发者朋友们应该也都知道,各家有各家的小动作,混乱不堪。解码出来的视频数据,并不是固定的格式,虽然大多数手机都支持YUV420P或者YUV420SP,但是也有些奇葩手机,只能解码出OMX_QCOM_COLOR_FormatYUV420PackedSemiPlanar32m这类的格式,总不能都去判断然后根据格式去转换吧。


之前看官方文档的时候,有看到MediaCodec解码视频支持直接解码到Surface上,编码也可以直接从Surface采集数据,这样的话,视频数据可以直接解码到Surface上,然后通过OpenGLES处理,再又通过Surface进行编码,就无需关注解码出来的数据的格式了,而且应用层也不必自己去将原始数据导入GPU以及将处理后的数据导出GPU了,这些工作可以都丢给Android SDK去做。理论上就能一举解决上面的两个问题。那么具体应该如何做呢?


处理流程



有了理论,剩下的就是实现了。不卖关子,根据以上的方案,直接列出处理的流程:


  1. 利用MediaExtractor获取Mp4的音轨和视轨,获取音频视频的MediaFormat.

  2. 根据音视频信息,创建视频解码器,视频编码器,音频暂时不处理就不创建编解码器了。其中视频解码器的Surface是通过先创建一个SurfaceTexture,然后将这个SurfaceTexture作为参数创建的,这样的话,视频流就可以通过这个SurfaceTexture提供给OpenGL环境作为输出。视频编码器的Surface可直接调用createInputSurface()方法创建,这个Surface后续传递给OpenGL环境作为输出

  3. 创建MediaMuxer,用于后面合成处理后的视频和音频。

  4. 创建OpenGL环境,用于处理视频图像,这个OpenGL环境由EGL创建,EGLSurface为WindowSurface,并以编码器创建的Surface作为参数。

  5. MediaExtractor读取原始Mp4中的视频流,交由解码器解码到Surface上。

  6. SurfaceTexture监听有视频帧时,通知OpenGL线程工作,处理视频图像,并渲染。

  7. OpenGL线程每次渲染完毕,通知编码线程进行编码,编码后的数据通过MediaMuxer混合。

  8. 视频流处理完毕后,利用MediaExtractor读取音频流,并利用MediaMuxer混合到新的视频文件中。

  9. 处理完毕后调用MediaMuxer的stop方法,处理后的视频就生成成功了。


具体实现



流程一捋,道理到家都懂,具体怎么实现呢。根据以上流程上代码了。


创建需要的编解码工具



这里是直接把1、2、3步的事情,在一个方法中完成了:

Android利用硬解硬编和OpenGLES来高效的处理MP4视频


创建OpenGl环境



第4步,创建OpenGL环境,用来处理视频图像,先直接贴个工具类,用于创建OpenGL环境


Android利用硬解硬编和OpenGLES来高效的处理MP4视频

Android利用硬解硬编和OpenGLES来高效的处理MP4视频

Android利用硬解硬编和OpenGLES来高效的处理MP4视频

Android利用硬解硬编和OpenGLES来高效的处理MP4视频

Android利用硬解硬编和OpenGLES来高效的处理MP4视频

Android利用硬解硬编和OpenGLES来高效的处理MP4视频


借助上面的工具类创建OpenGL环境。可以看到里面使用了信号量,是用于当有新的视频图像时由SurfaceTexture的监听器通知GL线程执行渲染,没有的话就等待新的视频图像解码完后再执行处理工作。


Android利用硬解硬编和OpenGLES来高效的处理MP4视频


第6步就是用于通知这个GL线程执行渲染工作,只需要在监听器中,发出信号就可以了。


Android利用硬解硬编和OpenGLES来高效的处理MP4视频


视频流解码



第5步,需要将视频解码,解码的方法如下。在解码的线程中循环调用此方法,其返回值为true时结束循环,也就是视频帧解码完毕。


Android利用硬解硬编和OpenGLES来高效的处理MP4视频


视频流解码并混合



在第四步的代码中,已经出现了视频流编码的方法了,也就是videoEncodeStep(boolean),其实现如下:


Android利用硬解硬编和OpenGLES来高效的处理MP4视频


音频流处理



因为现在暂时不需要对视音频处理,所以直接从原始MP4中读取音频流混合到新的Mp4中即可,与解码相同,这个方法也是在线程中循环调用,返回true时终止循环,最后调用MediaMuxer的stop方法,新的视频就生成好了。


Android利用硬解硬编和OpenGLES来高效的处理MP4视频


为了不阻塞主线程,音视频的处理单独开一个线程处理为好。


Android利用硬解硬编和OpenGLES来高效的处理MP4视频


其它



源码在github上(https://github.com/doggycoder/AudioVideo),有需要的朋友可自行下载,如有帮助欢迎fock和start。如果对于硬编硬解不太理解的,可以查阅官方文档,我的另外一篇博客也有编码的示例,可以参考——

Android硬编码——音频编码、视频编码及音视频混合

(http://blog.csdn.net/junzia/article/details/54018671)

对于OpenGLES不太熟悉的朋友,可以参考我前面的OpenGLES系列的博客。

每日掏心话

没有走不通的路,没有过不去的坎。相信自己,我们都有可能创造奇迹!

Android利用硬解硬编和OpenGLES来高效的处理MP4视频


推荐阅读





小密圈
这里聚集了业界内的大牛,值得各位大牛的加入!

Android利用硬解硬编和OpenGLES来高效的处理MP4视频

看完本文有收获?请转发分享给更多人
关注「杨守乐」,提升编程技能

【QQ技术群】279126311 []
【QQ技术群】484572225 [未]

以上就是:Android利用硬解硬编和OpenGLES来高效的处理MP4视频 的全部内容。

本站部分内容来源于互联网和用户投稿,如有侵权请联系我们删除,谢谢。
Email:[email protected]


0 条回复 A 作者 M 管理员
    所有的伟大,都源于一个勇敢的开始!
欢迎您,新朋友,感谢参与互动!欢迎您 {{author}},您在本站有{{commentsCount}}条评论