5.3 IJKplayer框架介绍

IJKplayer是Bilibili网站工程师基于FFmpeg及MediaCodec开发的开源播放器框架,内部实现了软解及硬解的功能,其基本流程如下图所示: 针对各种铺天盖地的播放器项目,我们选取了比较出众的IJKplayer进行源码剖析。它是一个基于FFPlay的轻量级Android/iOS视频播放器,实现了跨平台的功能,API易于集成、编译配置可裁剪、方便控制安装包大小。

结构说明

我们可以在GitHub下载或查看ijkplayer项目,地址是https://github.com/Bilibili/ijkplayer ,可看到其主要目录结构如下:

目录名称 说明
tool 初始化项目工程脚本
config 编译ffmpeg使用的配置文件
extra 存放编译ijkplayer所需的依赖源文件, 如ffmpeg、openssl等
ijkmedia 核心代码
ijkplayer 播放器数据下载及解码相关
ijksdl 音视频数据渲染相关
ios iOS平台上的上层接口封装以及平台相关方法
android Android平台上的上层接口封装以及平台相关方法

下面是在android目录中我们看到的目录和说明

目录名称 说明
ijkplayer-arm64 arm64下编译出来的.so文件
ijkplayer-armv5 armv5编译出来的.so文件
ijkplayer-armv7a armv7a编译出来的.so文件
ijkplayer-x86 x86编译出来的.so文件
ijkplayer-x86_64 x86_64编译出来的.so文件
ijkplayer-exo google开源的一个新的播放器ExoPlayer,在Demo中和ijkplayer对比用的。通过安装ijkplayer可以发现setting里面可以选择不同player来渲染多媒体显示,该模块下面就是一个MediaPlayer
ijkplayer-java ijkplayer的一些操作封装及定义。这里面是通用的API接口,里面最主要的是IMediaPlayer,它是用来渲染显示多媒体的
ijkplayer-example ijkplayer官方提供的示例

特性列表

特性名称 说明
Android平台 支持API 9〜23
CPU ARMv7a,ARM64v8a,x86(ARMv5未在真实设备上测试)
API API提供丰富的方法,易于集成
视频输出 NativeWindow,OpenGL ES 2.0
音频输出 AudioTrack,OpenSL ES
编解码器 MediaCodec(API 16+,Android 4.1+),支持硬件加速解码,更加省电
其他 可替代android.media.MediaPlayer,ExoPlayer

在功能的具体实现上,iOS和Android平台的差异主要表现在视频硬件解码以及音视频渲染方面,两者实现的载体区别如下表所示:

Platform Hardware Codec Video Render Audio Output
iOS VideoToolBox OpenGL ES AudioQueue
Android MediaCodec OpenGL ES、MediaCodec OpenSL ES、AudioTrack

前期准备

开发前我们先给大家介绍一下,如何编译ijkplayer和ffmpeg。注意大家尽量不要用Windows下编译,各种想象不到编译不通过的Bug,这里我们以在Ubuntu下编译源码为例。首先必须安装需要安装homebrew, git, yasm三个软件,再次注意AndroidNDK必须安装,最好是r10-14版本内,不然编译可能会出错。

# install homebrew, git, yasm
ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
brew install git
brew install yasm

# add these lines to your ~/.bash_profile or ~/.profile
# export ANDROID_SDK=<your sdk path>
# export ANDROID_NDK=<your ndk path>

# on Cygwin (unmaintained)
# install git, make, yasm

全部安装完成,在命令行继续一步步执行如下代码

git clone https://github.com/Bilibili/ijkplayer.git ijkplayer-android
cd ijkplayer-android
git checkout -B latest k0.8.4

./init-android.sh

cd android/contrib
./compile-ffmpeg.sh clean
./compile-ffmpeg.sh all

cd ..
./compile-ijk.sh all

如果执行过程中没有任何问题,执行成功后我们可以到android文件夹下ijkplayer下,在对应的cpu项目中找到相应的.so文件了。

简单用法

从官方的example项目来看,用到了很多东西,可是大多数我们都不需要,所以需要去掉一些没用的代码精简一下。exo是Google提供的新的播放器,我们这里不需要直接去掉,需要的只有tv.danmaku.ijk.media.example.widget.media包下的部分类。链接库ijkplayer-arm64,ijkplayer-armv5,ijkplayer-armv7a,ijkplayer-x86,ijkplayer-x86_64是不同体系架构的动态链接库,在工程结构里面作为一个模块,如果项目没用要求做兼容多平台,可以删除其他目录结构,单独保留自己需要的平台目录即可。如果对ijkplayer没用改动的话,也可以在Gradle里直接集成。

# required
allprojects {
    repositories {
        jcenter()
    }
}

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

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

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

播放的实现方式

在我们项目的布局xml文件中,我们只需加上这个组件即可

<tv.danmaku.ijk.media.widget.media.IjkVideoView
        android:id="@+id/ijkPlayer"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

然后在activity代码中注册这个组件,并设置其需要的方法

     IjkVideoView videoView = (IjkVideoView) findViewById(R.id.video_view);
     videoView.setAspectRatio(IRenderView.AR_ASPECT_FIT_PARENT);
     String url = "rtmp://192.168.1.92:8080/liveOnline/6666";
     videoView.setVideoURI(Uri.parse(url));
     videoView.start();

常用的方法用

/**
 * 参数aspectRatio(缩放参数)参见IRenderView的常量:
IRenderView.AR_ASPECT_FIT_PARENT,
IRenderView.AR_ASPECT_FILL_PARENT,
IRenderView.AR_ASPECT_WRAP_CONTENT,
IRenderView.AR_MATCH_PARENT,
IRenderView.AR_16_9_FIT_PARENT,
IRenderView.AR_4_3_FIT_PARENT
 */
public void setAspectRatio(int aspectRatio);
//改变视频缩放状态。
public int toggleAspectRatio();
//设置视频路径。
public void setVideoPath(String path);
//设置视频URI。(可以是网络视频地址)
public void setVideoURI(Uri uri);
//停止视频播放,并释放资源。
public void stopPlayback();
/**
 * 设置媒体控制器。
 * 参数controller:媒体控制器,注意是com.hx.ijkplayer_demo.widget.media.IMediaController。
 */
public void setMediaController(IMediaController controller);
//改变媒体控制器显隐
private void toggleMediaControlsVisiblity();
//注册一个回调函数,在视频预处理完成后调用。在视频预处理完成后被调用。此时视频的宽度、高度、宽高比信息已经获取到,此时可调用seekTo让视频从指定位置开始播放。
public void setOnPreparedListener(OnPreparedListener l);
//播放完成回调
public void setOnCompletionListener(IMediaPlayer.OnCompletionListener l);
//播放错误回调
public void setOnErrorListener(IMediaPlayer.OnErrorListener l);
//事件发生回调
public void setOnInfoListener(IMediaPlayer.OnInfoListener l);
//获取总长度
public int getDuration();
//获取当前播放位置。
public long getCurrentPosition();
//设置播放位置。单位毫秒
public void seekTo(long msec);
//是否正在播放。
public boolean isPlaying();
//获取缓冲百分比。
public int getBufferPercentage();

results matching ""

    No results matching ""