Flutter plugin for mofun flutter video.

Render.java 5.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. package com.shuangyubang.mofun_flutter_plugin_video.mixplayer;
  2. import android.content.Context;
  3. import android.media.AudioFormat;
  4. import android.media.AudioManager;
  5. import android.media.AudioTrack;
  6. import android.os.Build;
  7. import android.util.Log;
  8. import static java.lang.Thread.sleep;
  9. /**
  10. * Created by rt-zl on 2019/2/15.
  11. */
  12. public class Render extends VideoRender {
  13. static {
  14. System.loadLibrary("mixplayer");
  15. }
  16. private long handler = 0;
  17. private native int setRenderHandler(long handler);
  18. int asample, ach, abit;
  19. public int mixUpdateAudio(byte[] data, int size, double pts) {
  20. playTime = pts;
  21. synchronized (audioBufLock) {
  22. if (audioBufLen - audioHas < size) {
  23. return -1;
  24. }
  25. int len = audioBufLen - audioWPos;
  26. len = len > size ? size : len;
  27. System.arraycopy(data, 0, audioBuf, audioWPos, len);
  28. audioWPos += len;
  29. audioHas += len;
  30. if (audioWPos == audioBufLen) {
  31. audioWPos = 0;
  32. }
  33. if (len < size) {
  34. int les = size - len;
  35. System.arraycopy(data, len, audioBuf, audioWPos, les);
  36. audioWPos += les;
  37. audioHas += les;
  38. }
  39. return 0;
  40. }
  41. }
  42. public int mixOpen(int vWidth, int vHeight, int asample, int ach, int abit) {
  43. if (vWidth > 0) {
  44. Log.d("MIXOPEN", "has video");
  45. nativeInit(getScreenWidth(), getScreenHeight());
  46. this.abit = abit;
  47. this.asample = asample;
  48. this.ach = ach;
  49. initAudioTrack();
  50. return 0;
  51. }
  52. return -1;
  53. }
  54. public void mixClose() {
  55. super.close();
  56. }
  57. public void renderClose() {
  58. play = false;
  59. if (audioTrack != null) {
  60. audioTrack.stop();
  61. totalAudioBuf = 0;
  62. }
  63. }
  64. public Render(Context context) {
  65. super(context);
  66. }
  67. public void init(long handler) {
  68. this.handler = handler;
  69. setMixHander(handler);
  70. this.setRenderHandler(handler);
  71. }
  72. public double getPlaytime() {
  73. return playTime;
  74. }
  75. AudioTrack audioTrack;
  76. final Object audioBufLock = new Object();
  77. byte[] audioBuf;
  78. long totalAudioBuf;
  79. int audioHas;
  80. int audioRPos, audioWPos;
  81. int audioBufLen = 4096 * 3;
  82. long silenceLen = 0;
  83. boolean play = false;
  84. double playTime = 0;
  85. byte[] silencBuf;
  86. private void initAudioTrack() {
  87. silencBuf = new byte[4096];
  88. synchronized (audioBufLock) {
  89. audioBuf = new byte[audioBufLen];
  90. }
  91. audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, asample,
  92. AudioFormat.CHANNEL_IN_STEREO, AudioFormat.ENCODING_PCM_16BIT, audioBufLen, AudioTrack.MODE_STREAM);
  93. play = true;
  94. new Thread(() -> {
  95. int wsize = 1024;
  96. long posPre = 0;
  97. boolean needUpdate = false;
  98. int retryCount = 0;
  99. while (play) {
  100. synchronized (audioBufLock) {
  101. long pos = audioTrack.getPlaybackHeadPosition();
  102. // 16bit 2channels = 4 Byte
  103. pos *= 4;
  104. pos -= silenceLen;
  105. if (posPre != pos) {
  106. posPre = pos;
  107. retryCount = 0;
  108. } else {
  109. if (retryCount > 5)
  110. needUpdate = true;
  111. retryCount++;
  112. }
  113. if (audioHas >= wsize && totalAudioBuf - pos < audioBufLen || pos <= 0 || needUpdate) {
  114. needUpdate = false;
  115. int len = audioBufLen - audioRPos;
  116. len = len > wsize ? wsize : len;
  117. int ret = audioTrack.write(audioBuf, audioRPos, len);
  118. audioRPos += ret;
  119. audioHas -= ret;
  120. totalAudioBuf += ret;
  121. if (audioRPos == audioBufLen) {
  122. audioRPos = 0;
  123. }
  124. } else {
  125. // if (pos == totalAudioBuf && audioHas < wsize){
  126. // int c = audioTrack.write(silencBuf,0,2048);
  127. // silenceLen +=c;
  128. // }
  129. }
  130. if (ispause) {
  131. if (audioTrack.getPlayState() != AudioTrack.PLAYSTATE_PAUSED) {
  132. audioTrack.pause();
  133. if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
  134. audioTrack.setVolume(0);
  135. } else {
  136. audioTrack.setStereoVolume(0, 0);
  137. }
  138. }
  139. } else {
  140. if (audioTrack.getPlayState() != AudioTrack.PLAYSTATE_PLAYING) {
  141. audioTrack.play();
  142. if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
  143. audioTrack.setVolume(volume);
  144. } else {
  145. audioTrack.setStereoVolume(volume, volume);
  146. }
  147. }
  148. }
  149. }
  150. try {
  151. sleep(3);
  152. } catch (Exception ignored) {
  153. }
  154. }
  155. Log.d("mixplayer", "audio close");
  156. }).start();
  157. audioTrack.play();
  158. }
  159. @Override
  160. protected void finalize() throws Throwable {
  161. super.finalize();
  162. play = false;
  163. renderClose();
  164. }
  165. }