Custom Build Bilibili ijkplayer


Build Bilibili ijkplayer

MacOS 环境

Homebrew
git、yasm

NDK

必需 Android NDK 10-14

https://developer.android.google.cn/ndk/downloads/older_releases.html

Build

export ANDROID_NDK=~/workspace/android/ndk-r10e
export PATH=$PATH:$ANDROID_NDK

配置编解码器格式支持

默认为最少支持,如果足够你使用,可以跳过这一步,否则可以改为以下配置:

  • module-default.sh 更多的编解码器/格式
  • module-lite-hevc.sh 较少的编解码器/格式(包括 hevc)
  • module-lite.sh 较少的编解码器/格式(默认情况)
git clone https://github.com/bilibili/ijkplayer.git

// 这步会下载 FFmpeg 源码,并自动执行 init-config.sh 和 ./init-android-libyuv.sh
./init-android.sh
// 如果需要启用 ssl、https 支持,执行这步
./init-android-openssl.sh
// 其他文件有待探索
// ./init-android-j4a.sh
// ./init-android-prof.sh
// ./init-android-libsoxr.sh
// ./init-android-exo.sh


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


cd ..
./compile-ijk.sh all

NDK

注意申明ANDROID_NDK为指定版本的

# export ANDROID_SDK=<your sdk path>
# export ANDROID_NDK=<your ndk path>

0.8.8 Build

module.sh add this

export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-linux-perf"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-bzlib"

参考

https://www.jianshu.com/p/11493731ea2c

优化

// 添加格式、rtsp(tcp)支持
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-decoder=mpeg4"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-decoder=mp2*"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-decoder=ac3"
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 --disable-protocol=rtp"

Gradlew

#强制清除 gradle 依赖缓存
./gradlew build --refresh-dependencies  

问题集合

1、IJKPlayer 不像系统播放器会给你旋转视频角度,所以你需要通过onInfowhat == IMediaPlayer.MEDIA_INFO_VIDEO_ROTATION_CHANGED去获取角度,自己旋转画面;或者开启硬解硬解码,不过硬解码容易造成黑屏无声

mediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "mediacodec", 1);
mediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "mediacodec-auto-rotate", 1);
mediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "mediacodec-handle-resolution-change", 1);

2、 IJKPlayer 出现黑色有声音没图像,看看你的视频编码是不是H264,pixel format是否存在,音频编码是不是AAC?默认IJKPlayer是不支持3pg(支持它干啥(・-・)?),不支持mepg(比如这个库RecordVideoDemo ),不支持AMR。所以如果你真的想要支持,那么参考这个#1961,打开mpeg支持,重新编ffmpeg,然后通过硬解码播放mpeg;或者通过系统的录制VideoRecord;或者选另外的JAVACV录制封装FFmpegRecorder。

ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "mediacodec", 1);
ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "mediacodec_mpeg4", 1);

3、 **快进和慢放接口,已经支持全版本,如果遇到声调问题,可以设置:

ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "soundtouch", 1);

4、暂停的时候,退到后台再回到前台,画面黑了?

1、
这时候个人处理方式是,可以在暂停的时候,通过TextureView.getBitmap(point.x, point.y);获取到暂停的画面,用ImageView显示它,在onSurfaceTextureUpdated的时候隐藏ImageView,来实现画面的衔接。

2、暂停时绘制静态画面多TextureView的Surface上,详细参考GSYVideoPlayer。

5、一些视频返回码

int MEDIA_INFO_VIDEO_RENDERING_START = 3;//视频准备渲染
int MEDIA_INFO_BUFFERING_START = 701;//开始缓冲
int MEDIA_INFO_BUFFERING_END = 702;//缓冲结束
int MEDIA_INFO_VIDEO_ROTATION_CHANGED = 10001;//视频选择信息
int MEDIA_ERROR_SERVER_DIED = 100;//视频中断,一般是视频源异常或者不支持的视频类型。
int MEDIA_ERROR_IJK_PLAYER = -10000,//一般是视频源有问题或者数据格式不支持,比如音频不是AAC之类的
int MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK = 200;//数据错误没有有效的回收

6、某些视频在SeekTo的时候,会跳回到拖动前的位置,这是因为视频的关键帧的问题,通俗一点就是FFMPEG不兼容,视频压缩过于厉害,seek只支持关键帧,出现这个情况就是原始的视频文件中i 帧比较少,可开启以下来解决:

setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "enable-accurate-seek", 1);

7、下载速度可以通过IjkMediaPlayer的getTcpSpeed获取。

8、高分辨率开启硬解码,不支持的话会自动切换到软解,就算开启mediacodec,如果设备不支持,显示的解码器也是avcodec软解。

9、ijkMediaPlayer.setOption可配置的对应头文件参考:ff_ffplay_options。

10、缓冲进度条不到100,官方表示我就不保证都100,所以一般我都是:

//95这个数值可能不准确,有些时候可能还需要低一些
if (secProgress > 95) secProgress = 100;

11、上面1、2、6的问题,在IJK封装的EXOPlayer和MediaPlayer都不会有问题,兼容上确实强过IJKPlayer,但是它们在细节上,却没有IJK处理的好,如EXOPlayer:退到后再回到前台、切换渲染控件的黑屏一段时间问题,除了用seekto之外目前没发现其他办法,这样的体验让我最后还是选择IJKPlayer。

12、设置cookie 可以通过ijkPlayer的public void setDataSource(String path, Map<String, String> headers) 的header实现设置,参考ijkPlayer的issues-1150,headers也是在内部被转化为何issuses一样的setOption方法

13、多个分片播放的功能,请查阅:

issues64-一个视频,多个视频片段问题
issues490分段视频
ijkplayer-ffmpeg之concat

14、硬解码黑屏相关issuse以及建议
android用硬解码播放器切后台恢复问题

14、硬解码黑屏相关issuse以及建议

bilibili-issuse-1324

15、出现声音画面不同步

1、关了硬解码。

2、参考如下:

http://www.jianshu.com/p/a5cf04181f3d
设置视频的倍速:
[options setPlayerOptionIntValue:10 forKey:@”framedrop”];
mediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, “framedrop”, 60);

16、rtsp播放失败问题

https://github.com/CarGuo/GSYVideoPlayer/issues/232

https://github.com/CarGuo/GSYVideoPlayer/issues/207

17、m3u8拖动seek之后,加载很长时间

https://github.com/Bilibili/ijkplayer/issues/2874

https://github.com/CarGuo/GSYVideoPlayer/issues/252

18、m3u8本地播放问题

ijkplayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "protocol_whitelist", "crypto,file,http,https,tcp,tls,udp"); 

19、断网自动重新连接
url前接上ijkhttphook:,如

String url = “ijkhttphook:http://baobab.wdjcdn.com/14564977406580.mp4";
然后设置

IjkMediaPlayer.OnNativeInvokeListener() {
@Override public boolean onNativeInvoke(int i, Bundle bundle) { return true; } })

20、url切换400(http与https域名共用)

ijkplayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "dns_cache_clear", 1);

21、Rtsp优化

//硬解码:1、打开,0、关闭
//mMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "mediacodec", 1);
//软解码:1、打开,0、关闭
//mMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "videotoolbox", 0);

//rtsp设置 https://ffmpeg.org/ffmpeg-protocols.html#rtsp
mMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "rtsp_transport", "tcp");
mMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "rtsp_flags", "prefer_tcp");

mMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "allowed_media_types", "video"); //根据媒体类型来配置
mMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "timeout", 20000);
mMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "buffer_size", 1316);
mMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "infbuf", 1);  // 无限读
mMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "analyzemaxduration", 100L);
mMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "probesize", 10240L);
mMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "flush_packets", 1L);
//  关闭播放器缓冲,这个必须关闭,否则会出现播放一段时间后,一直卡主,控制台打印 FFP_MSG_BUFFERING_START 
mMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "packet-buffering", 0L);
mMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "framedrop", 1L);

文章作者: ECM
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 ECM !
评论
  目录