JZMediaIjk.java 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. package com.edufound.reader.videoutil;
  2. import android.graphics.SurfaceTexture;
  3. import android.media.AudioManager;
  4. import android.os.Handler;
  5. import android.os.HandlerThread;
  6. import android.text.TextUtils;
  7. import android.view.Surface;
  8. import java.io.IOException;
  9. import cn.jzvd.JZMediaInterface;
  10. import cn.jzvd.Jzvd;
  11. import tv.danmaku.ijk.media.player.IMediaPlayer;
  12. import tv.danmaku.ijk.media.player.IjkMediaPlayer;
  13. import tv.danmaku.ijk.media.player.IjkTimedText;
  14. /**
  15. * Created by Nathen on 2017/11/18.
  16. * ijk兼容SO库:https://github.com/NamHofstadter/IjkPlayerSos
  17. * ijk默认不支持https协议,需要的请自行下载so库
  18. */
  19. public class JZMediaIjk extends JZMediaInterface implements IMediaPlayer.OnPreparedListener, IMediaPlayer.OnVideoSizeChangedListener, IMediaPlayer.OnCompletionListener, IMediaPlayer.OnErrorListener, IMediaPlayer.OnInfoListener, IMediaPlayer.OnBufferingUpdateListener, IMediaPlayer.OnSeekCompleteListener, IMediaPlayer.OnTimedTextListener {
  20. IjkMediaPlayer ijkMediaPlayer;
  21. public JZMediaIjk(Jzvd jzvd) {
  22. // init player
  23. super(jzvd);
  24. }
  25. @Override
  26. public void start() {
  27. if (ijkMediaPlayer != null) ijkMediaPlayer.start();
  28. }
  29. @Override
  30. public void prepare() {
  31. IjkMediaPlayer.loadLibrariesOnce(null);
  32. IjkMediaPlayer.native_profileBegin("libijkplayer.so");
  33. release();
  34. mMediaHandlerThread = new HandlerThread("JZVD");
  35. mMediaHandlerThread.start();
  36. mMediaHandler = new Handler(mMediaHandlerThread.getLooper());//主线程还是非主线程,就在这里
  37. handler = new Handler();
  38. mMediaHandler.post(() -> {
  39. try {
  40. ijkMediaPlayer = new IjkMediaPlayer();
  41. ijkMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
  42. ////1为硬解 0为软解
  43. ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "mediacodec", 0);
  44. ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "mediacodec-auto-rotate", 1);
  45. ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "mediacodec-handle-resolution-change", 1);
  46. //使用opensles把文件从java层拷贝到native层
  47. ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "opensles", 0);
  48. //视频格式
  49. ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "overlay-format", IjkMediaPlayer.SDL_FCC_RV32);
  50. //跳帧处理(-1~120)。CPU处理慢时,进行跳帧处理,保证音视频同步
  51. ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "framedrop", 1);
  52. //0为一进入就播放,1为进入时不播放
  53. ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "start-on-prepared", 0);
  54. ////域名检测
  55. ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "http-detect-range-support", 0);
  56. //设置是否开启环路过滤: 0开启,画面质量高,解码开销大,48关闭,画面质量差点,解码开销小
  57. ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_CODEC, "skip_loop_filter", 48);
  58. //最大缓冲大小,单位kb
  59. ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "max-buffer-size", 1024 * 1024);
  60. //某些视频在SeekTo的时候,会跳回到拖动前的位置,这是因为视频的关键帧的问题,通俗一点就是FFMPEG不兼容,视频压缩过于厉害,seek只支持关键帧,出现这个情况就是原始的视频文件中i 帧比较少
  61. ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "enable-accurate-seek", 1);
  62. //是否重连
  63. ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "reconnect", 1);
  64. //http重定向https
  65. ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "dns_cache_clear", 1);
  66. //设置seekTo能够快速seek到指定位置并播放
  67. ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "fflags", "fastseek");
  68. //播放前的探测Size,默认是1M, 改小一点会出画面更快(开了这个官方视频没声音)
  69. // ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "probesize", 1024 * 10);
  70. //1变速变调状态 0变速不变调状态
  71. ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "soundtouch", 1);
  72. ijkMediaPlayer.setOnPreparedListener(JZMediaIjk.this);
  73. ijkMediaPlayer.setOnVideoSizeChangedListener(JZMediaIjk.this);
  74. ijkMediaPlayer.setOnCompletionListener(JZMediaIjk.this);
  75. ijkMediaPlayer.setOnErrorListener(JZMediaIjk.this);
  76. ijkMediaPlayer.setOnInfoListener(JZMediaIjk.this);
  77. ijkMediaPlayer.setOnBufferingUpdateListener(JZMediaIjk.this);
  78. ijkMediaPlayer.setOnSeekCompleteListener(JZMediaIjk.this);
  79. ijkMediaPlayer.setOnTimedTextListener(JZMediaIjk.this);
  80. ijkMediaPlayer.setDataSource(jzvd.jzDataSource.getCurrentUrl().toString());
  81. ijkMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
  82. ijkMediaPlayer.setScreenOnWhilePlaying(true);
  83. ijkMediaPlayer.prepareAsync();
  84. if (jzvd.textureView.getSurfaceTexture() != null) {
  85. ijkMediaPlayer.setSurface(new Surface(jzvd.textureView.getSurfaceTexture()));
  86. }
  87. } catch (IOException e) {
  88. e.printStackTrace();
  89. }
  90. });
  91. }
  92. @Override
  93. public void pause() {
  94. ijkMediaPlayer.pause();
  95. }
  96. @Override
  97. public boolean isPlaying() {
  98. return ijkMediaPlayer.isPlaying();
  99. }
  100. @Override
  101. public void seekTo(long time) {
  102. ijkMediaPlayer.seekTo(time);
  103. }
  104. @Override
  105. public void release() {
  106. if (mMediaHandler != null && mMediaHandlerThread != null && ijkMediaPlayer != null) {//不知道有没有妖孽
  107. HandlerThread tmpHandlerThread = mMediaHandlerThread;
  108. IjkMediaPlayer tmpMediaPlayer = ijkMediaPlayer;
  109. JZMediaInterface.SAVED_SURFACE = null;
  110. mMediaHandler.post(() -> {
  111. tmpMediaPlayer.setSurface(null);
  112. tmpMediaPlayer.release();
  113. tmpHandlerThread.quit();
  114. });
  115. ijkMediaPlayer = null;
  116. }
  117. }
  118. @Override
  119. public long getCurrentPosition() {
  120. if (ijkMediaPlayer == null) {
  121. return 0;
  122. }
  123. return ijkMediaPlayer.getCurrentPosition();
  124. }
  125. @Override
  126. public long getDuration() {
  127. if (ijkMediaPlayer == null) return 0;
  128. return ijkMediaPlayer.getDuration();
  129. }
  130. @Override
  131. public void setVolume(float leftVolume, float rightVolume) {
  132. ijkMediaPlayer.setVolume(leftVolume, rightVolume);
  133. }
  134. @Override
  135. public void setSpeed(float speed) {
  136. ijkMediaPlayer.setSpeed(speed);
  137. }
  138. @Override
  139. public void onPrepared(IMediaPlayer iMediaPlayer) {
  140. handler.post(() -> jzvd.onPrepared());
  141. }
  142. @Override
  143. public void onVideoSizeChanged(IMediaPlayer iMediaPlayer, int i, int i1, int i2, int i3) {
  144. handler.post(() -> jzvd.onVideoSizeChanged(iMediaPlayer.getVideoWidth(), iMediaPlayer.getVideoHeight()));
  145. }
  146. @Override
  147. public boolean onError(IMediaPlayer iMediaPlayer, final int what, final int extra) {
  148. handler.post(() -> jzvd.onError(what, extra));
  149. return true;
  150. }
  151. @Override
  152. public boolean onInfo(IMediaPlayer iMediaPlayer, final int what, final int extra) {
  153. handler.post(() -> jzvd.onInfo(what, extra));
  154. return false;
  155. }
  156. @Override
  157. public void onBufferingUpdate(IMediaPlayer iMediaPlayer, final int percent) {
  158. handler.post(() -> jzvd.setBufferProgress(percent));
  159. }
  160. @Override
  161. public void onSeekComplete(IMediaPlayer iMediaPlayer) {
  162. handler.post(() -> jzvd.onSeekComplete());
  163. }
  164. @Override
  165. public void onTimedText(IMediaPlayer iMediaPlayer, IjkTimedText ijkTimedText) {
  166. }
  167. @Override
  168. public void setSurface(Surface surface) {
  169. ijkMediaPlayer.setSurface(surface);
  170. }
  171. @Override
  172. public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
  173. if (SAVED_SURFACE == null) {
  174. SAVED_SURFACE = surface;
  175. prepare();
  176. } else {
  177. jzvd.textureView.setSurfaceTexture(SAVED_SURFACE);
  178. }
  179. }
  180. @Override
  181. public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
  182. }
  183. @Override
  184. public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
  185. return false;
  186. }
  187. @Override
  188. public void onSurfaceTextureUpdated(SurfaceTexture surface) {
  189. }
  190. @Override
  191. public void onCompletion(IMediaPlayer iMediaPlayer) {
  192. handler.post(() -> jzvd.onCompletion());
  193. }
  194. }