之前在公司一个项目中一直使用 http://www.cnblogs.com/mcodec/articles/1780598.html 提供的H264 Android解码库
但是经常崩溃,最终定位到mc_dir_part函数中的
1 |
qpix_op[luma_xy](dest_y, src_y, s->linesize); //FIXME try variable height perhaps? |
尝试了一晚上也没修复好这个问题,于是打算自己移植FFmpeg
mcodec 兄所做的工作是将H264解码的代码从ffmpeg中提取出来做了深度优化,而本人对FFmpeg?还不甚了解,无法做到提取,而且新版本相互依赖太重,于是将整个FFmpeg?移植过来使用。
在配置时关闭了所有特性,只开启了所需的H264解码库,arm汇编特性,其余全部关闭。
以下是我的配置代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
#!/bin/bash NDKRROOT=/home/aliang/Application/android-ndk PREBUILT=$NDKRROOT/toolchains/arm-linux-androideabi-4.6/prebuilt/linux-x86 PLATFORM=$NDKRROOT/platforms/android-14/arch-arm export PATH=$PATH:$PREBUILT/bin FFCONFIG_COMMON=' --enable-version3 --disable-gpl --disable-nonfree --disable-everything --enable-decoder=h264 --enable-armv5te --disable-ffmpeg --disable-ffplay --disable-ffprobe --disable-ffserver --disable-avfilter --disable-network --disable-avformat --disable-avdevice --disable-swresample --disable-swscale ' ./configure --prefix=$PWD/_install_arm $FFCONFIG_COMMON --arch=arm --target-os=linux --enable-small --disable-debug --disable-logging --enable-cross-compile --sysroot=$PLATFORM/user --sysinclude=$PLATFORM/usr/include --cross-prefix=arm-linux-androideabi- --extra-ldflags=" -L$PLATFORM/usr/lib -nostdlib -lc -lm -ldl" --extra-cflags="-I$PLATFORM/usr/include -O3" |
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
你好,可否提供编译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 ? 非常感谢
你好,问题已经解决。加一条命令
cat libavcodec/avcodec.h | libavcodec/codec_names.sh config.h libavcodec/codec_names.h
生成codec_names.h就行了。
对你提到的mcodec 的H.264的库比较感兴趣,以后学习过程中有问题还请多多指点~~ ^_^
😀
建议你直接研究FFmpeg ,汇编优化,通用性强 。
今天还测试了H264 HighProfile ,正常解码,而mcodec兄的库就不行。
高深
您好,最近对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都注释掉。也是在网上边学边做,不知博主能否抽出点宝贵的时间~谢谢
android.mk方法来编译整个ffmpeg项目我反而不会使用我上面的脚本编译出.a文件后,android.mk只需要简单引入这个库就行了
编最新的ffmpeg1.0一直不通过啊,有没有写好的android.mk借鉴下
依旧谢谢啊 你说的这个方法不怎么懂,能不能具体说下步骤呢,当然写个新文章介绍下更好了。
楼主有没有尝试使用ffmpeg里面的libstagefright来做硬解呢?我尝试使用关闭H264而用libstagefright来解码H264的时候在avcodec_decode_video2时崩溃。崩溃堆栈基本都是内存释放错误,例如libstagefright.cpp里的av_freep(&frame->buffer);等等。不知楼主是否也有尝试,可以探讨一下吗?
你好,我和你遇到的问题一模一样,也是av_freep崩溃了,请问你有什么进展吗?可以探讨一下吗?
楼主 关于对mcodec老兄的jni接口代码的复用 应该需要改跟多地方才对啊 我最近就是卡在这个的地方 能不能分享一下jni部分的代码 rui-house@163.com 谢谢
mcodec 那儿不是提供了jni部分的全部代码了么实际使用中 只需要将H264Android.java 文件提炼下就可以使用了
楼主后来不是重新移植了ffmpeg吗,如果直接使用这个jni接口的话,好像H264Android里面所使用的很多函数接口都被mcodec重新定义了,关于这部分能不能都给点指导
重新移植后我重写了jni部分,里面大部分是调用ffmpeg的API。并不是通用接口,只为了满足项目需要。因为是回放直播流,只留了open和close两个jni接口,数据通过线程里回调java方法来传递的。
非常感谢楼主!
博主最后推荐的YUV2RGB的库我看了,,是我现在用的,存在一些问题,速度是快了,但是在大一点的屏幕上播放,就会存在白色的躁点,如果用电视输出,会更明显。目前我在考虑用openGL做加速,如果有别的好方案,也请博主介绍一下吧,多谢
大屏上没有测试过
我们的项目实时性需求高 对质量本来不是最主要的指标
网上也有用OpenGL直接渲染YUV的方案,估计会好很多吧
有空研究下
我换了以软解+openGL为辅,硬解码为主,解码速度和效果都不错
这方面有什么经验,跟大伙分享下呗。
硬解是个大坑,严重依赖各家实现,openGL值得使用
博主你好!
看了你的文章,在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);
}
哦?看你这方法应该是Pinknoise的
你看他c实现的源码里倒数第3个参数做了 dst_span >>= 1;
所以这个地方你传iWidth<<1进去 应该就行了
是的,它的性能相对较高。
后来讲倒数第三个参数iWidth修改为“iWidth*2”倒是正常了。
我后面为libswscale移植的arm汇编 yuv2rgb 就是使用的Pinknoise
<<1 和*2是一样的 从性能上来讲 位移比乘法运算快多了
我从网络SOCKET得到一个h264的流文件
然后使用eseye打开这个流文件,没有任何问题(没有任何马赛克),但是我自己使用ffmpeg解码时,发现运动部分全是马赛克 ,而静止部分没有问题。