使用Android NDK8 移植FFmpeg 0.11.1

之前在公司一个项目中一直使用 http://www.cnblogs.com/mcodec/articles/1780598.html 提供的H264 Android解码库
但是经常崩溃,最终定位到mc_dir_part函数中的

尝试了一晚上也没修复好这个问题,于是打算自己移植FFmpeg
mcodec 兄所做的工作是将H264解码的代码从ffmpeg中提取出来做了深度优化,而本人对FFmpeg?还不甚了解,无法做到提取,而且新版本相互依赖太重,于是将整个FFmpeg?移植过来使用。
在配置时关闭了所有特性,只开启了所需的H264解码库,arm汇编特性,其余全部关闭。
以下是我的配置代码

JNI部分使用了mcodec兄的代码,编译后so库大小控制在680k 在未开启NEON和VPF的情况下
测试机QSD8250处理器在解码320*240 512Kbps Baseline 视频流的CPU占用为40%左右

接下来的工作就是编译armv7-a处理器优化的解码库。新版本的FFmpeg支持调用libstagefright来实现Android上的硬解码H264也是非常吸引人的地方。
感谢FFMPEG 感谢mcodec 兄。
======================== 9月21日的分割线 ========================
今天分别编译了VPF和NEON两个版本
–enable-armvpf
–enable-neon
开启VPF后在我的测试平台上提升并不明显,下降到38%左右
而开启NEON的版本则非常明显,与上面相同的码率分辨率下,保持在27%的CPU占用
因此 针对armv7-a及以上版本的cpu架构开启NEON优化是非常有必要的。
当然 也更加期待引入libstagefright来实现硬解码
======================== 12月1日的分割线 ========================
经过大量测试,性能瓶颈目前存在于色彩空间转换和缩放
使用libswscale进行这两步操作在arm处理器上没有更好的利用到arm指令集
于是将PINK NOISE的 YUV2RGB ARM汇编版 ?(?http://wss.co.uk/pinknoise/yuv2rgb)?移植到libswscale中,性能再次大幅提升。依然是上面的码率分辨率,下降到18%~20%。待这部分整理出后给出我的移植代码 🙂
========================?12月27日==============================
YUV2RGB ARM汇编版补丁

原创文章,转载请注明: 转载自贝壳博客

本文链接地址: 使用Android NDK8 移植FFmpeg 0.11.1

26 评论

  1. 你好,可否提供编译NDK下编译FFmpeg0.11的方法?我这边win7+cygwin+ndk-r8+ffmpeg-0.6是编译得过了。。可是同样的方法编译0.11.2就有错误。提示的是源码的错误:没有找到文件
    /utils.c:1760:36: fatal error: libavcodec/codec_names.h: No such file or directory
    对Makefile比较陌生,可否提供以下mk文件和编译的步骤?
    如有文件,可否发至gzu.lpl@qq.com ? 非常感谢

  2. 你好,问题已经解决。加一条命令
    cat libavcodec/avcodec.h | libavcodec/codec_names.sh config.h libavcodec/codec_names.h
    生成codec_names.h就行了。
    对你提到的mcodec 的H.264的库比较感兴趣,以后学习过程中有问题还请多多指点~~ ^_^

    1. 😀
      建议你直接研究FFmpeg ,汇编优化,通用性强 。
      今天还测试了H264 HighProfile ,正常解码,而mcodec兄的库就不行。

  3. 您好,最近对ffmpeg1.0(官网下载最新)源码进行android移植时遇到一些疑惑,我是win7-64的系统,用的cygwin,在最后so文件的编译时出现如下错误use_yg@LP0201 /cygdrive/f/Android/android-ndk-r8c/ffmpeg1.0$ $ndk/ndk-buildjni/ffmpeg/libavcodec/Makefile:1: *** 分離記号を欠いています. 中止.对ffmpeg源码目录中的libavcodev,libavfilter,libavformat,libavutil,libpostproc,libswscale中的Makefile,我是这样操作的,将Makefile中的开头:include $(SUBDIR)../config.mak都注释掉。也是在网上边学边做,不知博主能否抽出点宝贵的时间~谢谢

    1. android.mk方法来编译整个ffmpeg项目我反而不会使用我上面的脚本编译出.a文件后,android.mk只需要简单引入这个库就行了

    1. 依旧谢谢啊 你说的这个方法不怎么懂,能不能具体说下步骤呢,当然写个新文章介绍下更好了。

  4. 楼主有没有尝试使用ffmpeg里面的libstagefright来做硬解呢?我尝试使用关闭H264而用libstagefright来解码H264的时候在avcodec_decode_video2时崩溃。崩溃堆栈基本都是内存释放错误,例如libstagefright.cpp里的av_freep(&frame->buffer);等等。不知楼主是否也有尝试,可以探讨一下吗?

  5. 楼主 关于对mcodec老兄的jni接口代码的复用 应该需要改跟多地方才对啊 我最近就是卡在这个的地方 能不能分享一下jni部分的代码 rui-house@163.com 谢谢

      1. 楼主后来不是重新移植了ffmpeg吗,如果直接使用这个jni接口的话,好像H264Android里面所使用的很多函数接口都被mcodec重新定义了,关于这部分能不能都给点指导

        1. 重新移植后我重写了jni部分,里面大部分是调用ffmpeg的API。并不是通用接口,只为了满足项目需要。因为是回放直播流,只留了open和close两个jni接口,数据通过线程里回调java方法来传递的。

  6. 博主最后推荐的YUV2RGB的库我看了,,是我现在用的,存在一些问题,速度是快了,但是在大一点的屏幕上播放,就会存在白色的躁点,如果用电视输出,会更明显。目前我在考虑用openGL做加速,如果有别的好方案,也请博主介绍一下吧,多谢

    1. 大屏上没有测试过
      我们的项目实时性需求高 对质量本来不是最主要的指标
      网上也有用OpenGL直接渲染YUV的方案,估计会好很多吧
      有空研究下

  7. 博主你好!
    看了你的文章,在jni对720p的视频进行了格式转换,转换后发现高度变成大概一半左右,不知道什么原因。

    avcodec_decode_video2(c, picture, &frameFinished, &packet);
    if(frameFinished)//成功解码
    {
    yuv420_2_rgb565(Pixel,
    picture->data[0],
    picture->data ,
    picture->data ,
    c->width,
    c->height,
    picture->linesize[0],
    picture->linesize ,
    iWidth,
    yuv2rgb565_table,
    0);
    }

    1. 哦?看你这方法应该是Pinknoise的
      你看他c实现的源码里倒数第3个参数做了 dst_span >>= 1;
      所以这个地方你传iWidth<<1进去 应该就行了

      1. 是的,它的性能相对较高。
        后来讲倒数第三个参数iWidth修改为“iWidth*2”倒是正常了。

  8. 我从网络SOCKET得到一个h264的流文件
    然后使用eseye打开这个流文件,没有任何问题(没有任何马赛克),但是我自己使用ffmpeg解码时,发现运动部分全是马赛克 ,而静止部分没有问题。

回复 Danny Lui 取消回复

您的电子邮箱地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据