引言:
带JNI的Android项目中,经常需要把C/C++代码编译成库才能使用。
windows系统中,一般来说是用一些模拟类unix的方式,比如先配置cygwin或是minGL等,然后通过这些环境来编译。另一种方式是,配置ubuntu虚拟机,用虚拟机来编译代码。
虚拟机有一些显而易见的好处,一是它和宿主系统是隔离的,不会影响宿主系统的正常使用,二是它使用方便,配置一次之后,既可以多人使用,又方便备份。不足的是,占地太大,性能一般。
这里是一些我用ubuntu虚拟机编译ijkplayer时的笔记,做个小小的分享。
I.环境变量
配置环境变量是玩转ubuntu的第一步。
1.位置
~/.bash_profile
~/.profile
/etc/environment
2.编辑
gedit [环境变量目录] 即可进行编辑,一般来说是在结尾加上新添的环境变量,下面用配置Java环境变量举个栗子:
export JAVA_HOME = [你的jdk目录]
export CLASSPATH = .:$JAVA_HOME/lib:$JAVA_HOME/jre/lib:$CLASSPATH
export PATH = $JAVA_HOME/bin:$JAVA_HOME/jre/bin:$PATH
(ubuntu的环境变量是用shell脚本配置的,$符号代表的是变量)
3.注意
首先,不同用户的环境变量是不通用的,比如,root模式下配置的环境变量,在一般登录的用户下就不起作用。建议是,统一在root用户下进行配置和编译等操作。进入root用户的命令是:sudo su,然后输入root密码。
其次,配置环境变量不会立即生效,要用 source [环境变量目录] 的方式令其立即生效。
II.samba
通俗的来讲,samba服务是windows和ubuntu通信的桥梁,也是这里ubuntu虚拟机和windows宿主系统之间通信的桥梁。除了samba,也可以用U盘或虚拟机自带的文件夹共享来传输文件。但是似乎samba较为实用和简单。
sudo su #进入管理员权限
apt-get update
apt-get install samba #用网络安装samba服务
cp /etc/samba/smb.conf /etc/samba/smb.conf.bak #备份配置文件
gedit /etc/samba/smb.conf #编辑配置文件
在配置文件中添加以下语句:
[share]
path=[samba共享目录]
available=yes
browseable=yes
public=yes
writable=yes
然后创建用户并重启服务
smbpasswd -a [ubuntu用户名] #创建用户
service smb restart #重启samba服务
注意:
1.samba共享经常可能出现权限问题,我是这么解决的
chown -hR [ubuntu用户名] [samba共享目录]
chmod -R 777 [samba共享目录]
2.编译目录可以放在samba共享目录中,这样方便通过宿主系统来查看。查看方式是这样,首先,通过ifconfig 命令获取ubuntu的ip地址,然后可以通过宿主系统,敲\\ubuntu的ip 来找到samba共享目录。虚拟机采用的应该是NAT模式。
III.文件操作
1.创建文件/文件夹
mkdir [目录名] #创建目录
touch [文件名] #创建文件
2.删除文件/文件夹
rmdir [空目录名] #删除空目录
rm [文件名] [文件名] #删除文件
rm –rf [非空目录名] #删除非空目录
3.转移文件/文件夹(也可以重命名)
mv file1 file2 #将文件file1,重命名为file2。
mv file1 dir1 #将文件file1,移到目录dir1下,文件名仍为file1。
mv dir1 dir2 #若目录dir2存在,则将目录dir1移到目录dir2下,名称依然为dir1。若目录dir2不存在,则将dir1更改为目录dir2。
IV.解压缩
对于后缀为bin的文件: ./targetfile.bin
对于后缀为tar的文件: tar -xvf targetfile.tar
对于后缀为gz的文件:tar -zxvf targetfile.tar.gz
V.编译ijkplayer
ijkplayer(https://github.com/Bilibili/ijkplayer)是bilibili在github上发布的一个硬软解都支持的播放器。同时适配了Android和iOS。
Android版本中,它的硬解用的是ExoPlayer,软解是用FFmpeg+SDL。可以做点播播放器,也可以做直播播放器。
一般来说,硬解足够大部分的使用场景,但是有些编码格式,由于设备的系统未更新等原因,硬解无法提供应该有的支持,所以只能用软解来解码。
编译ijkplayer需要一些准备事项。
1.android sdk
2.android ndk(版本r10e以上)
3.jdk
4.官网提示的相关配置(install git, make, yasm)
5.空间要大(我调的是20G)
从官网下载相关文件,解压并转移到合适的位置(我都放在了samba共享目录),配置好环境变量。就可以按照提示准备编译了。提示信息在官网都有。第一步是./init-android.sh ,里面涉及到了要下载FFmpeg的相关代码。如果翻墙的话,下载速度会快一些。FFmpeg代码下载完成但是没有编译的时候,代码应该就有好几G了,等执行完./compile-ffmpeg.sh all 后会更大,建议编译前先备份一下。
FFmpeg编译完,就可以执行./compile-ijk.sh all 了。然后会编译出来三个so文件,位置在
ijkplayer-android\android\ijkplayer\ijkplayer-armv7a\src\main\libs\armeabi-v7a目录下。
此时,ijkplayer-android\android\ijkplayer项目,导入Android Studio,是可以跑通的。其主要运行的是ijkplayer-android\android\ijkplayer\ijkplayer-example项目。
ijkplayer项目里面,有很多项目。结构其实并不复杂,在此做个简单说明。
在ijkplayer-example项目中,负责播放视频的是IjkVideoView这个类,它是个自定义控件。这个类用到了ijkplayer-java项目中的IMediaPlayer接口,和同样这个项目中的IjkMediaPlayer类(实现了IMediaPlayer接口作为软解播放器),和另一个项目中ijkplayer-exo中的IjkExoMediaPlayer类(实现了IMediaPlayer接口作为硬解播放器)。软解播放器IjkMediaPlayer是用JNI实现的主要功能,其JNI库在ijkplayer-armv7a项目中的\src\main\libs\armeabi-v7a目录下。
如果用Android Studio不熟悉,这个项目改一下结构也可以放在Eclipse中,把ijkplayer-java、ijkplayer-exo作为ijkplayer-example项目的lib,然后把仨so文件放到libs/armeabi-v7a下就可以了(可能还需要导入一个ExoPlayer的项目作为lib)。
ijkplayer底层的代码对我来说有点困难。自己对Linux-c只懂一些基本的东西。但是这个项目的核心,我猜应该是这几个文件:
1.ijkplayer_jni.c 在ijkplayer-master\ijkmedia\ijkplayer\android目录下,应该是直接映射上层的JNI调用。
2.ff_ffplay.c 在ijkplayer-master\ijkmedia\ijkplayer目录下,里面的read_thread函数负责读取数据,video_refresh_thread负责渲染视频。
ubuntu下配置Android Studio注意事项
Android Studio似乎只有32位的。64位的ubuntu下需要先安装兼容库才能正常运行。
apt-get install lib32z1 lib32ncurses5 lib32bz2-1.0