直播云

  • Android 播放端 SDK

    最近更新时间:2018-05-30 18:52:13

    1 概述

    PLDroidPlayer 是一个适用于 Android 平台的音视频播放器 SDK,可高度定制化和二次开发,为 Android 开发者提供了简单、快捷的接口,帮助开发者在 Android 平台上快速开发播放器应用。

    SDK 的 Github 地址:https://github.com/pili-engineering/PLDroidPlayer

    1 功能特性及版本号

    功能 描述 版本
    PLMediaPlayer 类似 Android MediaPlayer,提供了播放器的核心功能 1.2.0+
    PLVideoView 类似 Android VideoView,基于 SurfaceView 的播放控件 1.2.0+
    PLVideoTextureView 类似 Android VideoView,基于 TextureView 的播放控件 1.2.0+
    全架构支持 包括 arm64-v8a, armeabi-v7a, armeabi 与 x86 1.2.0+
    画面镜像与旋转 由 PLVideoTextureView 提供,支持播放画面镜像与旋转 1.2.2+
    后台播放 退到后台只播放音频 1.2.3+
    IP 地址播放 URL 格式:protocol://ip/path?domain=xxxx.com 1.3.0+
    设置播放封面 在播放开始前显示封面 view 1.4.0+
    软硬解自动切换 优先硬解,硬解失败自动切换到软解 1.4.1+
    自动直播延迟优化 播放直播流时可以通过自动变速播放来优化延迟 2.0.0+
    H.265 软解 软解播放 H.265 视频流 2.0.0+
    变速播放 支持设置播放速度 2.0.0+
    MP4 离线缓存 支持播放过程中缓存 MP4 文件到本地 2.0.0+
    解码数据回调 回调解码后的音视频数据,可以外部渲染 2.0.0+
    七牛私有加密播放 支持播放七牛私有加密视频 2.0.0+
    分屏播放 由 PLVideoTextureView 提供,支持两个 view 并排分屏播放 2.0.3+
    自定义 DNS 服务器 支持自定义 DNS 服务器与设置预解析域名 2.0.5+
    视频截图 支持视频截图 2.1.0+
    区域播放 支持播放视频画面的部分区域 2.1.0+
    音量增强 支持将播放音量增强到大于原始音量 2.1.0+
    快开模式 极大加快相同协议与格式的视频流的打开速度 2.1.0+

    2 阅读对象

    本文档为技术文档,需要阅读者:

    • 具有基本的 Android 开发能力
    • 准备接入七牛云直播

    3 开发准备

    3.1 设备以及系统要求

    • 系统要求:Android 2.3 (API 9) 及其以

    3.2 混淆

    为了保证正常使用 SDK ,请在 proguard-rules.pro 文件中添加以下代码:

    -keep class com.pili.pldroid.player.** { *; }
    -keep class com.qiniu.qplayer.mediaEngine.MediaPlayer{*;}
    

    4 快速开始

    4.1 开发环境

    4.2 SDK 集成

    首先,下载最新版本的 PLDroidPlayer SDK

    4.2.1 导入 SDK

    SDK 主要包含 demo 代码、 PLDroidPlayer jar 包,以及 sdk 依赖的动态库文件。

    将 SDK 文件导入您的工程:

    PLDroidPlayer SDK 支持 armv5、armv7、arm64 和 x86 多种 CPU 架构,目前市场上主流机型的 CPU 都采用的是 armv7 架构。您可以根据兼容性的需要,将 release 目录下的动态库,拷贝到您的工程对应的目录下,例如:armeabi-v7a 目录下的 so 则拷贝到工程的 jniLibs/armeabi-v7a 目录下。

    由于 Android 7.0 使用 BoringSSL 替换了 OpenSSL,一些依赖系统内建 OpenSSL 的程序在一些 7.0+ 的 ROM 里可能会崩溃。如果您的应用 targetSdkVersion >= 24,那么强烈推荐将 libopenssl.so 加入至 jniLibs 目录。

    同时,还需要将 pldroid-player-x.x.x.jar 包也拷贝到工程的 libs 目录下,具体可以参考 SDK 包含的 demo 工程,集成后的工程示例如下:

    4.2.2 修改 build.gradle

    双击打开您的工程目录下的 build.gradle,确保已经添加了如下依赖,如下所示:

    dependencies {
        compile files('libs/pldroid-player-x.x.x.jar')
    }
    

    4.2.3 添加相关权限

    在 app/src/main 目录中的 AndroidManifest.xml 中增加如下 uses-permission 声明

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.WAKE_LOCK" />
    

    4.3 使用 PLVideoView 或者 PLVideoTextureView 实现媒体播放功能

    PLDroidPlayer SDK 提供的 PLVideoView 类和 PLVideoTextureView 类可以快速实现带界面的播放器功能,它们的接口与 Android 官方的 VideoView 类基本保持一致,其内部封装了 PLMediaPlayer 类所提供的播放功能。

    他们的使用方法基本相同,唯一的区别在于 PLVideoView 类使用了 SurfaceView 来完成视频画面的渲染,而 PLVideoTextureView 采用了 TextureView 完成视频画面的渲染 ,因此,在这里合并在一起来介绍。

    4.3.1 布局

    如果采用 PLVideoView 的话,布局如下:

    <com.pili.pldroid.player.widget.PLVideoView
            android:id="@+id/PLVideoView"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_gravity="center" />
    
    

    如果采用 PLVideoTextureView 的话,布局如下:

    <com.pili.pldroid.player.widget.PLVideoTextureView
            android:id="@+id/PLVideoTextureView"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_gravity="center" />
    
    

    4.3.2 初始化

    如果采用 PLVideoView 的话,初始化的方法如下:

    PLVideoView mVideoView = (PLVideoView) findViewById(R.id.PLVideView);
    

    如果采用 PLVideoTextureView 的话,初始化的方法如下:

    PLVideoTextureView mVideoView = (PLVideoTextureView) findViewById(R.id.PLVideoTextureView);
    

    4.3.3 关联播放控制器

    Demo 里面提供了一个播放控制器示例,MediaController,您可以随意修改满足定制化需求,将该控制器控件关联到 PLVideoView 或者 PLVideoTextureView 的方法如下:

    MediaController mMediaController = new MediaController(this);
    mVideoView.setMediaController(mMediaController);
    

    4.3.4 设置加载动画

    PLVideoViewPLVideoTextureView 提供了设置加载动画的接口,在播放器进入缓冲状态时,自动显示加载界面,缓冲结束后,自动隐藏加载界面,设置方法如下:

    View loadingView = findViewById(R.id.LoadingView);
    mVideoView.setBufferingIndicator(loadingView);
    

    loadingView 可以是任意的 Android View 视图对象。

    4.3.5 设置播放状态监听器

    PLVideoViewPLVideoTextureView 都提供了丰富的播放状态消息回调,您可以通过 setXXXListener 接口实现各种消息状态的获取,示例如下:

    public class PLVideoViewActivity extends Activity implements
            PLPreparedListener,
            PLOnInfoListener,
            PLOnCompletionListener,
            PLOnVideoSizeChangedListener,
            PLOnErrorListener {
    ...
        mVideoView.setOnPreparedListener(this);
        mVideoView.setOnInfoListener(this);
        mVideoView.setOnCompletionListener(this);
        mVideoView.setOnVideoSizeChangedListener(this);
        mVideoView.setOnErrorListener(this);
    ...
    

    关于各个消息状态的详细含义,将在 功能使用 章节详细说明。

    4.3.6 设置画面预览模式

    PLVideoViewPLVideTextureView 提供了各种画面预览模式,包括:原始尺寸、适应屏幕、全屏铺满、16:9、4:3 等,设置方法如下:

    mVideoView.setDisplayAspectRatio(PLVideoView.ASPECT_RATIO_ORIGIN);
    mVideoView.setDisplayAspectRatio(PLVideoView.ASPECT_RATIO_FIT_PARENT);
    mVideoView.setDisplayAspectRatio(PLVideoView.ASPECT_RATIO_PAVED_PARENT);
    mVideoView.setDisplayAspectRatio(PLVideoView.ASPECT_RATIO_16_9);
    mVideoView.setDisplayAspectRatio(PLVideoView.ASPECT_RATIO_4_3);
    

    4.3.7 设置画面旋转

    PLVideTextureView 还支持画面旋转,支持播放画面以 0度,90度,180度,270度旋转,设置方法如下:

    mVideoView.setDisplayOrientation(90); // 旋转90度
    

    4.3.8 设置播放画面镜像变换

    PLVideTextureView 还支持画面的镜像变换,设置方法如下:

    mVideoView.setMirror(true); 
    

    4.3.9 设置播放地址

    这是最重要的环节,在调用播放器的控制接口之前,必须先设置好播放地址。

    传入播放地址,可以是 /path/to/local.mp4 本地文件绝对路径,或 HLS URL,或 RTMP URL

    mVideoView.setVideoPath(videoPath);
    
    /**
     * Sets video path.
     *
     * @param path the path of the video.
     */
    public void setVideoPath(String path)
    
    /**
     * Sets video path
     * @param path path of the video
     * @param headers http headers
     */
    public void setVideoPath(String path, Map<String, String> headers)
    

    4.3.10 播放控制

    如果已经关联了 MediaController,可以直接通过该控件实现播放过程的控制,包括:暂停、继续、停止等,当然,您也可以通过 PLVideoView 提供的接口自行进行播放过程的控制,相关函数如下:

    mVideoView.start();
    mVideoView.pause();
    mVideoView.stopPlayback();
    

    4.3.11 并排模式

    一个常见的场景是多个播放器实例并排播放,PLVideoTextureView 对此场景进行了专门优化,可以通过设置 PLVideoTexureView.setSplitMode() 进行处理。目前提供 PLVideoTextureView.SPLIT_MODE_VERTICALPLVideoTextureView.SPLIT_MODE_HORIZONTAL 两种。若需要取消并排模式,则需调用 PLVideoTextureView.disableSplitMode()

    /**
     * Set split mode
     * @param mode the mode
     * @param preferredSplitWidth preferred width, in px
     * @param preferredSplitHeight preferred height, in px               
     */
    public void setSplitMode(int mode, int preferredSplitWidth, int preferredSplitHeight)
    
    /**
     * Disable split mode
     */
    public void disableSplitMode() 
    

    4.3.12 获取 RTMP Message Timestamp

    可以通过 getRtmpAudioTimestampgetRtmpVideoTimestamp 方法获取时间戳

    
    /**
     * Get video timestamp in RTMP message
     * @return timestamp
     */
    public long getRtmpVideoTimestamp();
    
    /**
     * Get audio timestamp in RTMP message
     * @return timestamp
     */
    public long getRtmpAudioTimestamp();
    
    

    4.3.13 视频截图

    可以通过 captureImage 方法进行视频截图,截图数据将会在 PLOnImageCapturedListener 中回调

    /**
     * Capture video image
     * @param delayTimeMs 截取调用此方法后相应毫秒后的视频画面,仅对点播流生效
     */
    public void captureImage(long delayTimeMs);
    

    4.3.14 设置播放区域

    可以通过 setVideoArea 方法,播放视频的一部分区域。若所有参数均为 0,则不裁剪画面。

    /**
     * Set video area
     * @param topLeftX top left x
     * @param topLeftY top left y
     * @param bottomRightX bottom right x
     * @param bottomRightY bottom right y
     */
     public void setVideoArea(int topLeftX, int topLeftY, int bottomRightX, int bottomRightY);
    

    4.3.15 设置 ZOrder 属性

    可以像系统的 SurfaceView 一样设置 PLVideoView 的 ZOrder 属性,方法如下:

    public void setZOrderOnTop(boolean onTop);
    
    public void setZOrderMediaOverlay(boolean overlay);
    

    4.3.16 暂停/恢复播放器的预缓冲

    在播放点播流时,可以根据具体需求动态暂停/恢复播放器的预缓冲,方法如下:

    /**
     * Set buffering enabled
     * @param enabled enable or not
     */
    public void setBufferingEnabled(boolean enabled);
    

    4.3.17 获取已经缓冲的长度

    在播放 http 点播流时,可以获取播放器已经缓冲的 byte 数,方法如下:

    /**
     * Get buffered length
     * @return length
     */
    public BigInteger getHttpBufferSize();
    

    4.4 使用 PLMediaPlayer 实现媒体播放功能

    PLDroidPlayer SDK 提供的 PLMediaPlayer 实现了一个媒体播放器的各种基础功能和接口,与 Android 官方的 MediaPlayer 的设计基本保持一致。

    4.4.1 布局

    PLMediaPlayer 不是一个 View 控件,因此,如果希望用它播放视频而不是纯音频的话,则需要在布局文件中自己定义一个 SurfaceView 或者 TextureView 控件,然后将 Surface 或者 SurfaceHolder 传递给 PLMediaPlayer,示例布局如下:

    <SurfaceView
        android:id="@+id/SurfaceView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_gravity="center" />
    

    4.4.2 创建对象

    PLMediaPlayer mMediaPlayer = new PLMediaPlayer(mContext);
    PLMediaPlayer mMediaPlayer = new PLMediaPlayer(mContext, mAVOptions);
    

    4.4.3 设置播放地址

    mMediaPlayer.setDataSource(mVideoPath);
    

    4.4.4 设置播放状态监听器

    PLMediaPlayer 提供了丰富的播放状态消息回调,您可以通过 setXXXListener 接口实现各种消息状态的获取,示例如下:

    public class PLMediaPlayerActivity extends Activity implements
            PLOnPreparedListener,
            PLOnInfoListener,
            PLOnCompletionListener,
            PLOnVideoSizeChangedListener,
            PLOnErrorListener {
    ...
        mMediaPlayer.setOnPreparedListener(this);
        mMediaPlayer.setOnInfoListener(this);
        mMediaPlayer.setOnCompletionListener(this);
        mMediaPlayer.setOnVideoSizeChangedListener(this);
        mMediaPlayer.setOnErrorListener(this);
    ...
    

    关于各个消息状态的详细含义,将在 功能使用 章节详细说明。

    4.4.5 配置和准备

    SurfaceView 成功创建后,需要将 SurfaceHolder 传入PLMediaPlayer,示例如下:

    mMediaPlayer.setDisplay(mSurfaceHolder);
    

    注意,如果是纯音频播放的话,则没有这一步。

    当一切都准备就绪以后,就可以调用 prepareAsync() 开始准备播放了,该过程是异步的,因此需要首先注册一个 PLOnPreparedListener 获取准备结束的回调(如果前面已经注册过,则不用重复注册)。

    mMediaPlayer.setOnPreparedListener(new PLOnPreparedListener() {
        @Override
        public void onPrepared(PLMediaPlayer plMediaPlayer) {
            mMediaPlayer.start();
        }
    });
    mMediaPlayer.prepareAsync();
    

    4.4.6 播放控制

    PLMediaPlayer 提供的播放控制接口如下:

    mMediaPlayer.start();
    mMediaPlayer.pause();
    mMediaPlayer.stop();
    mMediaPlayer.reset();
    

    当播放完成,系统退出时,不要忘记调用 release 函数释放资源:

    mMediaPlayer.release();
    

    4.4.7 获取 RTMP Message Timestamp

    可以通过 getRtmpAudioTimestampgetRtmpVideoTimestamp 方法获取时间戳

    
    /**
     * Get video timestamp in RTMP message
     * @return timestamp
     */
    public long getRtmpVideoTimestamp();
    
    /**
     * Get audio timestamp in RTMP message
     * @return timestamp
     */
    public long getRtmpAudioTimestamp();
    
    

    4.4.8 视频截图

    可以通过 captureImage 方法进行视频截图,截图数据将会在 PLOnImageCapturedListener 中回调

    /**
     * Capture video image
     * @param delayTimeMs 截取调用此方法后相应毫秒后的视频画面
     */
    public void captureImage(long delayTimeMs);
    

    4.4.9 设置播放区域

    可以通过 setVideoArea 方法,播放视频的一部分区域。若所有参数均为 0,则不裁剪画面。

    /**
     * Set video area
     * @param topLeftX top left x
     * @param topLeftY top left y
     * @param bottomRightX bottom right x
     * @param bottomRightY bottom right y
     */
     public void setVideoArea(int topLeftX, int topLeftY, int bottomRightX, int bottomRightY);
    

    4.4.10 暂停/恢复播放器的预缓冲

    在播放点播流时,可以根据具体需求动态暂停/恢复播放器的预缓冲,方法如下:

    /**
     * Set buffering enabled
     * @param enabled enable or not
     */
    public void setBufferingEnabled(boolean enabled);
    

    4.4.11 获取已经缓冲的长度

    在播放 http 点播流时,可以获取播放器已经缓冲的 byte 数,方法如下:

    /**
     * Get buffered length
     * @return length
     */
    public BigInteger getHttpBufferSize();
    

    5 功能使用

    5.1 播放参数配置

    PLDroidPlayer SDK 提供的 AVOptions 类,可以用来配置播放参数,例如:

    AVOptions options = new AVOptions();
    
    public final static int MEDIA_CODEC_SW_DECODE = 0;
    public final static int MEDIA_CODEC_HW_DECODE = 1;
    public final static int MEDIA_CODEC_AUTO = 2;
    
    // DNS 服务器设置
    // 若不设置此项,则默认使用 DNSPod 的 httpdns 服务
    // 若设置为 127.0.0.1,则会使用系统的 DNS 服务器
    // 若设置为其他 DNS 服务器地址,则会使用设置的服务器
    options.setString(AVOptions.KEY_DNS_SERVER, server);
    
    // DNS 缓存设置
    // 若不设置此项,则每次播放未缓存的域名时都会进行 DNS 解析,并将结果缓存
    // 参数为 String[],包含了要缓存 DNS 结果的域名列表
    // SDK 在初始化时会解析列表中的域名,并将结果缓存
    options.setStringArray(AVOptions.KEY_DOMAIN_LIST, domainList);
    
    // 解码方式:
    // codec=AVOptions.MEDIA_CODEC_HW_DECODE,硬解
    // codec=AVOptions.MEDIA_CODEC_SW_DECODE, 软解
    // codec=AVOptions.MEDIA_CODEC_AUTO, 硬解优先,失败后自动切换到软解
    // 默认值是:MEDIA_CODEC_SW_DECODE
    options.setInteger(AVOptions.KEY_MEDIACODEC, codec);
    
    // 若设置为 1,则底层会进行一些针对直播流的优化
    options.setInteger(AVOptions.KEY_LIVE_STREAMING, 1);
    
    // 快开模式,启用后会加快该播放器实例再次打开相同协议的视频流的速度
    options.setInteger(AVOptions.KEY_FAST_OPEN, 1);
    
    // 打开重试次数,设置后若打开流地址失败,则会进行重试
    options.setInteger(AVOptions.KEY_OPEN_RETRY_TIMES, 5);
    
    // 预设置 SDK 的 log 等级, 0-4 分别为 v/d/i/w/e
    options.setInteger(AVOptions.KEY_LOG_LEVEL, 2);
    
    // 打开视频时单次 http 请求的超时时间,一次打开过程最多尝试五次
    // 单位为 ms
    options.setInteger(AVOptions.KEY_PREPARE_TIMEOUT, 10 * 1000);
    
    // 默认的缓存大小,单位是 ms
    // 默认值是:500
    options.setInteger(AVOptions.KEY_CACHE_BUFFER_DURATION, 500);
    
    // 最大的缓存大小,单位是 ms
    // 默认值是:2000,若设置值小于 KEY_CACHE_BUFFER_DURATION 则不会生效
    options.setInteger(AVOptions.KEY_MAX_CACHE_BUFFER_DURATION, 4000);
    
    // 是否开启直播优化,1 为开启,0 为关闭。若开启,视频暂停后再次开始播放时会触发追帧机制
    // 默认为 0
    options.setInteger(AVOptions.KEY_LIVE_STREAMING);
    
    // 设置拖动模式,1 位精准模式,即会拖动到时间戳的那一秒;0 为普通模式,会拖动到时间戳最近的关键帧。默认为 0
    options.setInteger(AVOptions.KEY_SEEK_MODE);
    
    // 设置 DRM 密钥
    byte[] key = {xxx, xxx, xxx, xxx, xxx ……};
    options.setByteArray(AVOptions.KEY_DRM_KEY, key);
    
    // 设置偏好的视频格式,设置后会加快对应格式视频流的打开速度,但播放其他格式会出错
    // m3u8 = 1, mp4 = 2, flv = 3
    options.setInteger(AVOptions.KEY_PREFER_FORMAT, 1);
    
    // 开启解码后的视频数据回调
    // 默认值为 0,设置为 1 则开启
    options.setInteger(AVOptions.KEY_VIDEO_DATA_CALLBACK, 1);
    
    // 开启解码后的音频数据回调
    // 默认值为 0,设置为 1 则开启
    options.setInteger(AVOptions.KEY_VIDEO_DATA_CALLBACK, 1);
    
    // 设置开始播放位置
    // 默认不开启,单位为 ms
    options.setInteger(AVOptions.KEY_START_POSITION, 10 * 1000);
    
    // 请在开始播放之前配置
    mVideoView.setAVOptions(options);
    

    5.2 播放状态回调

    PLDroidPlayer SDK 提供的所有状态监听接口,状态、错误的常量,均定义在 PLMediaPlayer 类中。

    5.2.1 PLOnPreparedListener

    /**
     * Called when the media file is ready for playback.
     *
     * @param preparedTime prepared time: ms
     */
    public interface PLOnPreparedListener