Ijkplayer编译成Android的so库的详细步骤

Ijkplyer简介

          本人在做网络摄像头的时候遇到的一个需求就是要做一个手机app能够实时看rtsp流传过来的视频,首先当然是用MediaPlayer去播放视频,结果是延时的要命,自己写一个播放器框架也是不实际的,只好上网找框架,发现了这个来源于B站的开源播放框架Ijkplyer。发现网上有许多前辈做过,于是今天总结一下这几天遇到的问题。

           从源码可以看出 ijkplayer是一个基于FFmpeg封装的Android/iOS视频播放器。而FFmpeg不用说,能够解码,编码, 转码,复用,解复用,流,过滤器和播放大部分的视频格式。它提供了录制、转换以及流化音视频的完整解决方案。

 

Ijkplyer编译SO库

           Android集成Ijkplyer的方法有两种:一种是直接在gradle里面直接设置引用。       

dependencies {
    # required, enough for most devices.
    compile 'tv.danmaku.ijk.media:ijkplayer-java:0.6.1'
    compile 'tv.danmaku.ijk.media:ijkplayer-armv7a:0.6.1'

    # Other ABIs: optional
    compile 'tv.danmaku.ijk.media:ijkplayer-armv5:0.6.1'
    compile 'tv.danmaku.ijk.media:ijkplayer-arm64:0.6.1'
    compile 'tv.danmaku.ijk.media:ijkplayer-x86:0.6.1'
    compile 'tv.danmaku.ijk.media:ijkplayer-x86_64:0.6.1'

    # ExoPlayer as IMediaPlayer: optional, experimental
    compile 'tv.danmaku.ijk.media:ijkplayer-exo:0.6.1'
}

      其中版本号可以去看github上的具体分支号 https://github.com/Bilibili/ijkplayer 

      我没有测试使用过这种方法,所以就不误导大家了(PS:使用依赖包有些视频格式和音频格式它不支持,所以要自己编译)

第一步 编译环境

       编译的要求是需要在Linux下编译,所以我搭建了一个虚拟机的Ubuntu环境,以下是要下载的一些东西

sudo apt-get install git
sudo apt-get install yasm

       git 好从github下载分支。 Yasm的官网翻译解释是 :一个完全重写的NASM汇编。目前,它支持x86和AMD64指令集,接受NASM和气体汇编语法,产出二进制, ELF32 , ELF64 , COFF , Mach - O的( 32和64 ) , RDOFF2 ,的Win32和Win64对象的格式,并生成STABS 调试信息的来源,DWARF 2 ,CodeView 8格式。

   第二步  安装Android环境

    接下来就是安装Android的SDK和NDK,我遇到的一个坑就是版本问题,所以如果编译报错提示需要ndk10的可能就是你的NDK版本过高。NDK和SDK的安装都比较简单,要么用sudo apt-get intsall 去下载安装,要么就去官网下载zip,解压配置路径。我都是下载zip安装环境的。

     首先是SDK,我从官网下载linux版本的sdk,android-sdk_r24.4.1-linux.tgz,下载解压到一个目录下,配置环境

export ANDROID_SDK_HOME=/home/xiuwenwang/android-sdk-linux
export PATH=$PATH:${ANDROID_SDK_HOME}/tools
export PATH=$PATH:${ANDROID_SDK_HOME}/platforms

     路径注意改成自己的,而且tools和platforms有的时候文件夹名字不一样,注意看一下自己的文件夹名字

     再是NDK,ndk版本太高会报错,我是从git上下载的  

wget -c http://dl.google.com/android/ndk/android-ndk-r10e-linux-x86_64.bin
chmod 777 android-ndk-r10e-linux-x86_64.bin
./android-ndk-r10e-linux-x86_64.bin

      (11.29 补充一点:后来发现不用费劲心思的去下相应的版本,去他检测版本的sh脚本修改就可以了,发现报错时

       You need the NDKr10e or later ,找到do-detect-env.sh 脚本,修改里面的第78行  11*|12*|13*|14*),就是添加你所用的NDK版本好,如果NDK升级变动不是很大,都没问题)

       如果不给权限运行生成的文件夹是不能访问的,设置路径

export NDK=/home/xiuwenwang/android-ndk-r10e
ANDROID_NDK=/home/xiuwenwang/android-ndk-r10e
export ANDROID_NDK
export   PATH=${PATH}:$NDK

     当然注意要改成你自己的路径

第三步 下载Ijkplayer源码编译

      输入以下命令下载,也可以手动去官网下载

git clone https://github.com/Bilibili/ijkplayer.git ijkplayer-android
cd ijkplayer-android

     初始化android

./init-android.sh

    这里会去下载重要的FFMPEG源码,要花点时间

     编译脚本配置 

     默认的FFmpeg编译选项在文件夹config/module.sh里面,这个是默认编译整个ffmpeg库,我做的项目不需要支持所有的音视频格式,所以改用module-lite.sh文件里的配置,当然要像支持某些功能就要自己添加了。查看config/module-lite.sh文件,里面的enable和disable还是能看懂的吧,接下来就是要添加自己需要的部分,我的要支持rtsp ,h264,g711u,就往上面添加没有的部分

export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-decoder=pcm_alaw"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-decoder=pcm_mulaw"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-decoder=mjpeg"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-demuxer=rtsp"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-demuxer=mjpeg"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-protocol=rtp"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-protocol=tcp"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-protocol=udp"

      要是不知道添加的格式的名字怎么看,可以去ffmpeg里面的ffmpeg_condecs.txt查找相对应的名称。修改完之后执行

rm module.sh
ln -s module-lite.sh module.sh
source module.sh

       这里说一下我在后期测试的时候发现会视频卡顿比较严重,一旦网络情况不好,需要修改一下ffmpeg的源码,找到ff_ffplay.c修改里面的源码,改成如下

//修改后的函数
static int packet_queue_get_or_buffering(FFPlayer *ffp, PacketQueue *q, AVPacket *pkt, int *serial, int finished)
{
    while (1) {
    int new_packet = packet_queue_get(q, pkt, 1, serial);
    if (new_packet < 0)
    {
        new_packet = packet_queue_get(q, pkt, 0, serial);
        if(new_packet < 0)
        return -1;
    }
    else if (new_packet == 0) {
        if (!finished)
            ffp_toggle_buffering(ffp, 1);
        new_packet = packet_queue_get(q, pkt, 1, serial);
        if (new_packet < 0)
            return -1;
    }
    if (finished == *serial) {
        av_free_packet(pkt);
        continue;
    }
    else
        break;
    }
    return 1;
}

      这个修改原因是原函数的队列要一直等待buffer满才会推数据,而网络一旦波动导致丢包就会卡顿。

      初始化android支持Https  如果要支持HTTPS就要下载openssl相关的代码,cd到目录ijkplayer-android下,执行

./init-android-openssl.sh

      这里就会下载openssl的有关代码,需要耐心等待。之后进入目录ijkplayer-android/android/contrib,执行

./compile-openssl.sh clean
./compile-ffmpeg.sh clean
./compile-openssl.sh all
./compile-ffmpeg.sh all

     最后编译ijkplayer ,不加all 只会默认生成armeabi-v7a平台的

cd ..
./compile-ijk.sh all

     这样在当前路径下就会生成一个Ijkplayer的文件夹,里面是不同平台的so库和官方给的demo。

build.gradle       gradlew.bat       ijkplayer-example  ijkplayer-x86_64
gradle             ijkplayer-arm64   ijkplayer-exo      settings.gradle
gradle.properties  ijkplayer-armv5   ijkplayer-java     tools
gradlew            ijkplayer-armv7a  ijkplayer-x86

       其中ijkplayer-java封装了对应的JNI接口,而example这是在上面又自己封装了一个播放类。如果自己想封装的可以看一下example里面的例子。

      到这里so库就编译完成了,那么关于如何调用ijkplayer请看我的下一篇文章。PS,这是我自己编译时经历的各种改动,有限步骤你可能并不需要,参考GitHub上的是最简单的操作,我这里就是给一个如何修改的参考方案。

你可能感兴趣的:(Android,Ijkplayer)