ffmpeg neon优化必看!!android下编译ffmpeg with neon的正确方法(已验证)



ffmpeg neon优化必看!!android下编译ffmpeg with neon的正确方法(已验证)

(2013-01-29 15:28:23)
标签:

android

ffmpeg

make

neon

优化

分类: 音视频
    最近搞的视频监控项目,需要在android移动端做视频显示。用的是android ndk的开发方式,利用ffmpeg作为解码库。640*480 分辨率下, 10帧每秒尚可正常播放,但是15fps就比较吃力了,20fps就几乎不能看了。通过打日志的方式发现: 每显示一帧需要133毫秒,解码的时间占据了64毫秒,很显然, 解码已经成为了最大的瓶颈。
    我们在网上搜了一圈之后,发现用arm扩展的neon指令集可以很大的优化ffmpeg的解码功能。但是在编译ffmpeg库的时候要把这部分功能加进去。但是这个编译真的把我们头都要搞大了。网上的帖子试来试去没一个能用的。经过痛苦而艰难的摸索,今天下午终于编出可以用的库了!  ffmpeg <wbr>neon优化必看!!android下编译ffmpeg <wbr>with <wbr>neon的正确方法(已验证)。 亢奋之余,必须把心得总结一下。
    总的来说,编译方法分为四步:
    a)创建android工程,在工程目录下手动创建jni目录,下载ffmpeg(可以用最新的,我用的是ffmpeg0.11),解压到刚才的jni目录下
    b) 编写针对ffmpeg configure的 config.sh 使能neon功能
    c)   利用ffmpeg自己的make 编译 静态库文件libavcodec.a, libavformat.a ,libavutil.a ... (注意,一定不要编译动态库,不然还要移到机器上面很麻烦),将生成的.a文件移到之前的jni目录下
    d)   编写jni目录下的 Android.mk 和ffmpeg_jni.c(名字你自取,就是给java调用的文件) ,然后ndk-build 生成so文件, 编译完成
    以上最重要的就是:   千万别用av.mk配合ndk-build 之类的方法编译ffmpeg静态库比如这篇文章提到的方式:http://blog.csdn.net/perfectpdl/article/details/6932696(当然,我本人对此文作者毫无攻击的意思,相反借鉴了很多,如果不用到neon功能的话,此文方法应该是可以编译的)
    之所以不提倡用ndk方式编译静态库是因为比之ndk-build ,ffmpeg本身自带的make功能要强大的多。而且ndk-build需要把所有的.c .S文件都要获取一遍再生成依赖关系,有点脱裤放啥的感觉。再者,利用ndk-build编译静态库要自己写一堆Android。mk文件,繁琐不说,很多关门末节的东西弄得人要崩溃。
     
    下面逐渐来介绍一下:  
    创建android工程什么的就不多说了。既然用到neon你们之前就应该已经编译出过版本了,目录结构如下:
ffmpeg <wbr>neon优化必看!!android下编译ffmpeg <wbr>with <wbr>neon的正确方法(已验证)


    1)首先贴一下我们用的config文件:(红色的是需要注意的地方,使用的时候注意删除#后面的话)
#!/bin/sh
export TMPDIR="/tmp/"
export NDKROOT="/opt/android-ndk-r8c"   #这个是你ndk安装的目录,自己改
PREBUILT=$NDKROOT/toolchains/arm-linux-androideabi-4.6/prebuilt/linux-x86
./configure --target-os=linux \
--arch=arm \  
--cpu=armv7-a \    #指定处理器
--enable-cross-compile \   #使能交叉编译
--cc=$PREBUILT/bin/arm-linux-androideabi-gcc \
--cross-prefix=$PREBUILT/bin/arm-linux-androideabi- \
--nm=$PREBUILT/bin/arm-linux-androideabi-nm \
--extra-cflags="-fPIC -DANDROID -mfpu=neon -mfloat-abi=softfp -I$NDKROOT/platforms/android-9/arch-arm/usr/include" \
--enable-asm \
--disable-yasm \
--enable-static \
--disable-shared \
--enable-small \
--enable-gpl \
--enable-version3 \
--enable-nonfree \
--enable-neon \
--disable-ffmpeg \
--disable-ffplay \
--disable-ffserver \
--disable-ffprobe \
--prefix=/home/ffmpeg-android-bin \
--extra-ldflags="-Wl,-T,$PREBUILT/arm-linux-androideabi/lib/ldscripts/armelf_linux_eabi.x -Wl,-rpath-link=$NDKROOT/platforms/android-9/arch-arm/usr/lib -L$NDKROOT/platforms/android-9/arch-arm/usr/lib -nostdlib $PREBUILT/lib/gcc/arm-linux-androideabi/4.6/crtbegin.o $PREBUILT/lib/gcc/arm-linux-androideabi/4.6/crtend.o -lc -lm -ldl"

2)编译静态库: 这个就很简单了, 到ffmpeg目录下面make即可。将生成出来的几个.a文件移到jni目录下
3)编写jni目录下mk文件:
include $(CLEAR_VARS)
LOCAL_MODULE     := avfilter
LOCAL_SRC_FILES := libavfilter.a   #这几个prebuild是为了把库预编译一下,ndk会将它移动到libs目录下面去
include $(PREBUILT_STATIC_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE     := avutil
LOCAL_SRC_FILES := libavutil.a
include $(PREBUILT_STATIC_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE     := avcodec
LOCAL_SRC_FILES := libavcodec.a
include $(PREBUILT_STATIC_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE     := avdevice
LOCAL_SRC_FILES := libavdevice.a
include $(PREBUILT_STATIC_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE     := swscale
LOCAL_SRC_FILES := libswscale.a
include $(PREBUILT_STATIC_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE     := swresample
LOCAL_SRC_FILES := libswresample.a
include $(PREBUILT_STATIC_LIBRARY)

include $(CLEAR_VARS)
LOCAL_CFLAGS := -D__STDC_CONSTANT_MACROS -Wno-sign-compare -Wno-switch -Wno-pointer-sign -DHAVE_NEON=1 \
      -mfpu=neon -mfloat-abi=softfp -fPIC -DANDROID  #这里的Cflag是照抄之前的config.sh里面的,实际可能用不到这么多

LOCAL_C_INCLUDES += \
    $(LOCAL_PATH)/ffmpeg \

LOCAL_SRC_FILES := \
    hello-jni.c  #这个写你自己的jni文件名

LOCAL_LDLIBS := -L$(NDK_PLATFORMS_ROOT)/$(TARGET_PLATFORM)/arch-arm/usr/lib \
-L$(LOCAL_PATH)  -lavformat -lavcodec -lavdevice -lavfilter -lavutil \
-lswscale -lswresample -llog -ljnigraphics -lz -ldl -lgcc
#这两个-L很重要, 保证程序能找到库
LOCAL_MODULE := libffmpeg_jni
include $(BUILD_SHARED_LIBRARY)

4) 之后在工程根目录下ndk-build 就能生成带neon的so库拉! 大功告成!

经过实际测试,解码时间缩短为15ms。 提升了4倍!!!!! 还犹豫什么,赶快敲动键盘优化吧!!

最后提醒: 本博文中的选项仅供参考, 具体还要根据实际情况修改。编译ffmpeg本身就是一件很麻烦的事情,大家要有耐心啊

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
编译 FFmpeg for Android 主要有两种方式: 1. 使用 FFmpeg 官方提供的交叉编译脚本 FFmpeg 官方提供了一些脚本,可以用来自动化交叉编译 FFmpeg。这些脚本需要在 Linux 上运行,并且需要安装一些编译工具和库。 首先,你需要安装必要的编译工具和库: ```bash sudo apt-get update sudo apt-get install build-essential git-core checkinstall yasm texi2html \ libvorbis-dev libx11-dev libxfixes-dev zlib1g-dev pkg-config \ libfaac-dev libmp3lame-dev libopencore-amrnb-dev libopencore-amrwb-dev \ libtheora-dev libvdpau-dev libvpx-dev libx264-dev libxvidcore-dev \ libssl-dev libass-dev libgnutls28-dev libsdl2-dev ``` 然后,你需要下载 FFmpeg 源代码: ```bash git clone https://git.ffmpeg.org/ffmpeg.git ffmpeg cd ffmpeg ``` 接下来,你可以使用 FFmpeg 官方提供的脚本来编译 FFmpeg: ```bash ./configure \ --prefix=$PREFIX \ --enable-shared \ --disable-static \ --disable-doc \ --disable-ffmpeg \ --disable-ffplay \ --disable-ffprobe \ --disable-ffserver \ --disable-network \ --disable-everything \ --enable-protocol=file \ --enable-demuxer=mov \ --enable-demuxer=h264 \ --enable-parser=h264 \ --enable-decoder=rawvideo \ --enable-decoder=h264 \ --enable-bsf=h264_mp4toannexb \ --enable-encoder=libx264 \ --enable-muxer=mp4 \ --enable-openssl \ --enable-protocol=https \ --enable-protocol=tls \ --enable-zlib \ --disable-asm \ --disable-armv5te \ --disable-armv6 \ --disable-armv6t2 \ --disable-neon \ --disable-thumb \ --disable-mipsdsp \ --disable-mipsdspr2 \ --disable-mipsfpu \ --disable-mips32r2 \ --disable-mips32r5 \ --disable-mips64r6 \ --disable-mipsdsprev \ --disable-mips32 \ --disable-mips64 \ --disable-x86_64 \ --disable-x86asm \ --disable-mmx \ --disable-mmxext \ --disable-sse \ --disable-sse2 \ --disable-sse3 \ --disable-ssse3 \ --disable-sse4 \ --disable-sse42 \ --disable-avx \ --disable-avx2 \ --disable-fma3 \ --disable-fma4 \ --disable-xop \ --disable-f16c \ --disable-armv8 \ --disable-aarch64 \ --disable-amd3dnow \ --disable-amd3dnowext \ --disable-cuda \ --disable-cudacodec \ --disable-nvenc \ --disable-vaapi \ --disable-vdpau \ --disable-videotoolbox \ --disable-libdrm \ --disable-libmfx \ --disable-libnpp \ --disable-libopencl \ --disable-libv4l2 \ --disable-libxcb \ --disable-libxcb-shm \ --disable-libxcb-xfixes \ --disable-avisynth \ --disable-bzlib \ --disable-iconv \ --disable-libcdio \ --disable-libdc1394 \ --disable-libfontconfig \ --disable-libfreetype \ --disable-libfribidi \ --disable-libgme \ --disable-libgsm \ --disable-libiec61883 \ --disable-libilbc \ --disable-libjack \ --disable-libkvazaar \ --disable-libmodplug \ --disable-libopencore-amrnb \ --disable-libopencore-amrwb \ --disable-libopencv \ --disable-libopenh264 \ --disable-libopenjpeg \ --disable-libopus \ --disable-libpulse \ --disable-librsvg \ --disable-librtmp \ --disable-librubberband \ --disable-libsmbclient \ --disable-libsnappy \ --disable-libsoxr \ --disable-libspeex \ --disable-libssh \ --disable-libtesseract \ --disable-libtheora \ --disable-libtwolame \ --disable-libvorbis \ --disable-libvpx \ --disable-libwavpack \ --disable-libwebp \ --disable-libx265 \ --disable-libxml2 \ --disable-libxslt \ --disable-libzmq \ --disable-libzvbi \ --disable-lzma \ --disable-sdl2 \ --disable-sndio \ --disable-tesseract \ --disable-xlib \ --disable-zimg make -j$(nproc) make install ``` 其中,`$PREFIX` 是你想要安装 FFmpeg 的路径。 2. 使用第三方的 FFmpeg 编译脚本 除了 FFmpeg 官方提供的脚本,还有一些第三方的脚本可以用来编译 FFmpeg for Android。这些脚本一般都使用了更加简单的配置方式,并且支持更多的编译选项。 一个比较流行的第三方脚本是 `ffmpeg-android-maker`,它可以在 macOS 或 Linux 上编译 FFmpeg for Android。 首先,你需要安装必要的编译工具和库: ```bash sudo apt-get install build-essential git-core checkinstall yasm texi2html \ libvorbis-dev libx11-dev libxfixes-dev zlib1g-dev pkg-config \ libfaac-dev libmp3lame-dev libopencore-amrnb-dev libopencore-amrwb-dev \ libtheora-dev libvdpau-dev libvpx-dev libx264-dev libxvidcore-dev \ libssl-dev libass-dev libgnutls28-dev libsdl2-dev ``` 然后,你可以使用以下命令来下载 `ffmpeg-android-maker`: ```bash git clone https://github.com/ajeet17181/ffmpeg-android-maker.git cd ffmpeg-android-maker ``` 接下来,你可以使用以下命令来编译 FFmpeg: ```bash ./build.sh -a armeabi-v7a -o /path/to/output/dir ``` 其中,`-a` 后面的参数表示你要编译Android ABI,`-o` 后面的参数表示你想要存放编译结果的目录。 注意:在使用第三方脚本编译 FFmpeg 时,一定要查看脚本中的编译选项,确保符合你的需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值