? ? ? 最近在做一个IOS与Android视频互发的软件,而两个平台提供的相关API中没有共通的视频编码格式。于是对微信视频做了一个简单分析,最后成功将微信Android客户端视频编码库剥离并调用。下面说下大概的分析过程。
? ? ? 首先从对微信录制的mp4视频做编码分析知道用的是H.264/AAC,而对AAC的支持Android是从2.3.3才开始的,所以2.3.3以下的版本必然要自己做编码。
? ? ? 接下就是对微信Android客户端反编并分析,用到的工具当然是apktool,为方面查看.so文件中的符号链接,当然得用下linux里的nm命令,同时配上vim编辑器对反编的smali文件做修改,大事可成。
? ? ? 微信jni调用共有4个so库,经过简单分析可以知道libvprotocal.so正是我们要找的库文件。自然通过其中的函数名可以定位到java中的vprotocal.java类。该类中共有4个native方法,分别是GetNowFrameCnt,?cancel,compress和pack。结合微信交互中的流程,首先是录制,录制结束后有一个压缩的过程,那么这四个方法应该比较自然的解释为:GetNowFrameCnt用户获取压缩的进度,cancel用于取消压缩过程,compress为压缩视频或音频,pack应该是将数据进一步打包的意思,具体作用可以做进一步分析。这四个函数中,compress是比较令人头痛的,因为其参数居然有11个。所以如果想把这个库用起来的话,下一步是分析出compress和pack中每个参数的含义。
? ? ? 由于对视频录制、压缩、转换或打包等等没有相关知识,所以本人决定获取微信运行时这些参数的具体值,以期有更多的提示。那么势必要写点dalvik代码了。
? ? ? 分析微信的log方式后发现在release版中将log关掉了,那么首先将log全部打印出来,这个改动还是比较简单的,修改完成后重新打包后安装运行。果然一堆log出现。于是赶紧再录一段视频,此时出现了跟视频相关的log,在录制和压缩过程中都周期性在打印log,看来有点希望了。
? ? ? 接下来就是打印上述compress和pack两个函数中的参数(这里需要费点功夫,刚开始写dalvik代码还有点不舒服,简单一句Log.d()要敲十几行的代码)。vprotocal.java中将这两个函数进一步做了封装,但还是在vprotocal类中调用,所以可以在调用前插入打印参数值的代码。经过几次崩溃后终于将打印log的代码搞定,于是迫不及待的再打包运行录视频,此时log中清晰的将这几个函数的调用顺序以及参数值打印出来。
? ? ? 进一步的分析每个参数的值,终于确定了这些参数的含义,其中compress的参数中包括视频转换前后的高和宽,帧率,原始视频数据文件,生成缩略图文件等,pack的参数包括生成的mp4文件路径,原始视频数据和原始音频数据。生成视频的过程为:生成视频缩略图,压缩原始视频数据,将压缩后的视频和音频数据打包成最终的mp4。在压缩过程中,通过调用GetNowFrameCnt来周期性的获取压缩进度。
? ? ? 至此,微信视频录制分析完成。接下来赶紧新建测试工程,并将libvprotocal.so拷过来,然后实现vprotocal.java。小测一把后,果然一段活生生视频出现在眼前。