移动视频编码学习笔记(一)
初次接触视频编码,才发现原来天天在用的直播App和视频功能里有这么多门道。学的过程历经“坎坷“也很有意思,在这里记录一下,我的移动视频编码学习历程。
Overview
- Android Camera与Camera2
- Android X Python Socket通信
- 雷神视频讲解入门
- FFmpeg X CentOS 环境搭建
- FFmpeg重编译过程
- FFmpeg X Android 项目实现
- 对遇到的问题做一些记录
- 对CentOS的其他折腾
1 Android Camera与Camera2
像在接触大多数陌生知识时一样,我在知道FFmpeg和很多入门知识之前感觉无从下手。
如果说必须做点什么,我能想到的就是先试试调用Android的相机,拿到所谓的“视频”。当然视频的来源可以有很多,不过我努力的方向就是移动直播相关。而想要获取Android摄像头的资源并不困难,因为hardware.Camera包本身的使用并不复杂:
- 获取手机摄像头权限
- 获得Camera实体
- 设置参数并绑定相机
- 在屏幕上进行预览/展示
关于Camera的具体设置和利用SurfaceView展示的具体实现方法网上资源较多。
但Camera包已经过时(API21),应更换成更加复杂但也更加强大的Camera2包,可以参考简书-Android Camera2 拍照入门学习。
2 Android X Python Socket通信
在获取视频数据的同时为Camera添加回调函数onPreviewFrame处理帧数据,可以实现按帧取出数据。分别在Android和PC(Python)上实现局域网的Socket通信,可以将数据实时传送到PC上。
然而,这个阶段实现的成果并不理想:没有任何处理的数据即使传送到PC上也没有任何作用,而且数据量也非常庞大。
3 雷神视频讲解入门
在学长的推荐下我开始学习FFmpeg的相关知识,同时也听闻了雷霄骅-雷神的大名。在为雷神的遭遇感到惋惜的同时我开始了真正的视频学习入门之旅。
在雷神为中传广电小学期讲课的视频中,我学到了很多有趣的知识:
- 视频封装与视频编码
- 视频播放的一般流程
- TS文件与FLV文件代表的两种形式
- H.264与NALU(I.P.B帧都是什么)
- YUV编码与RGB编码
- 图像划分与音频采样
- FFmpeg使用入门(Windows)
【详细内容已单独整理:移动视频编码学习笔记(二)】
但视频中主要介绍的是FFmpeg与SDL结合的使用过程,Android具体开发需要自己重新编译并对安卓开发框架作出简单更改。在Windows下进行开发除了需要安装复杂的Cygwin外还很容易出现兼容性问题,所以最终我选择在Linux双系统下尝试进行开发。
4 FFmpeg X CentOS 环境搭建
Linux下Android开发环境搭建主要任务:
- JDK安装及其环境变量的配置
- IDE的安装(暂时选择eclipse)
- NDK的安装及与编译器配置
【此处省略安装输入法的心塞旅程】
>添加需要用到的工具:
yum install -y autoconf automake cmake freetype-devel gcc gcc-c++ git libtool make mercurial nasm pkgconfig zlib-devel
>在/etc/profile中将NDK、JDK路径进行配置并source生效
5 FFmpeg重编译过程
具体重编译因为各种问题耗时很久,主要步骤如下:
- 下载FFmpeg源代码
- 更改默认命名方式(.so.xxx => .xxx.so)
- 编写脚本生成所需类库(include、libs、.so)
在编译过程中遇到了很多像文件不存在、方法丢失、未知错误等问题,特别是在交叉编译的时候,主要是两个方面:
- 配置问题:路径设置、编译器设置、权限设置、包缺失、文件/函数缺失
- 冲突问题:路径冲突、宏定义冲突、包版本冲突
部分问题及解决办法记录在下。最终正确获得了基本的结果——成功使用编译出依赖需要的头文件及.so文件。
6 FFmpeg X Android 项目实现
实现的项目号称Android-FFmpeg界的HelloWorld程序,主要功能就是把Protocol(支持的协议)、Format(支持的格式)、Codec(支持的编码)、Filter(过滤器_无法运行)、Configuration(配置信息)获取并打印出来,实现方法依旧是参考雷神的项目思路通过简单的向C文件中添加必要逻辑实现在空文件读入后打印所选方法的枚举类信息将信息打印到屏幕上。最终的实现效果如图:
![](https://img.haomeiwen.com/i5698490/590fb432a1bc83e3.png)
7 但仍存在问题
- 编译FFmpeg 3.4.1版本时出现C语言宏定义不识别的问题(暂时回退到v2.8.8)
- 使用Filter打印配置信息时会出现未知错误崩溃(准备配置CatLog详细调试)
- 编译脚本没有实现过滤,目前是全支持的臃肿依赖(学习更改脚本配置添加过滤)
优化:搜集资料时发现了一篇博客给出了一种将所有.so文件合并的方法,将合并方式记录在下:
尝试把.so文件合并
$TOOLCHAIN/bin/arm-linux-androideabi-ld -rpath-link=$PLATFORM/usr/lib -L$PLATFORM/usr/lib -L$PREFIX/lib -soname libffmpeg.so -shared -nostdlib -Bsymbolic --whole-archive --no-undefined -o $PREFIX/libffmpeg.so android-lib/lib/libx264.a libavcodec/libavcodec.a libavfilter/libavfilter.a libswresample/libswresample.a libavformat/libavformat.a libavutil/libavutil.a ibswscale/libswscale.a libpostproc/libpostproc.a libavdevice/libavdevice.a -lc -lm -lz -ldl -llog --dynamic-linker=/system/bin/linker $TOOLCHAIN/lib/gcc/arm-linux- androideabi/4.9.x/libgcc.a
同时记录下在Linux(CentOS)下使用eclipse时连接真机进行测试的方法介绍
遇到的其他问题记录
- Makefile:2: ffbuild/config.mak: 没有那个文件或目录
Makefile:40: /tools/Makefile: 没有那个文件或...
- 运行make clean时出现,本质是没有执行过./configure无法clean,并不是真的文件缺失。
- nasm/yasm not found or too old.
- 可以添加--disable-x86asm(* --disable-yasm)关闭asm,也可以对ysam进行安装/升级。
- libavcodec/hevc_mvs.c: In function 'derive_spatial_merge_candidates':
libavcodec/hevc_mvs.c:208:15: error: 'y0000000' undeclared (first use in this function)
((y ## v) >> s->ps.sps->log2_min_pu_size))
^
libavcodec/hevc_mvs.c:204:14: note: in definition of macro 'TAB_MVF'
tab_mvf[(y) * min_pu_width + x]
^
libavcodec/hevc_mvs.c:274:16: ......
- 版本3.4.1问题-暂时只能回退。新版本同时还存在“(”丢失问题,实际为变量(B0/B1)定义与宏定义冲突,更改变量名称可以解决(但我觉得应该有正式的解决方法,不应该随意更改文件逻辑)。
8 对CentOS的其他折腾
做安卓底层用到的Linux越玩越好玩....嗯...就忍不住玩崩了好几次,这里是使用过程的其他折腾,有兴趣的读者欢迎戳开~