2 Комити

Аутор SHA1 Порука Датум
  ykrank ce735d6cb7 尝试整合video到flutter пре 5 година
  ykrank e29af1b6c8 将mixplayer的demo迁移进项目 пре 5 година

+ 8
- 1
android/build.gradle Прегледај датотеку

@@ -25,7 +25,7 @@ apply plugin: 'com.android.library'
25 25
 apply plugin: 'kotlin-android'
26 26
 
27 27
 android {
28
-    compileSdkVersion 28
28
+    compileSdkVersion 27
29 29
 
30 30
     sourceSets {
31 31
         main.java.srcDirs += 'src/main/kotlin'
@@ -33,6 +33,10 @@ android {
33 33
     defaultConfig {
34 34
         minSdkVersion 16
35 35
         testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
36
+        compileOptions {
37
+            sourceCompatibility JavaVersion.VERSION_1_8
38
+            targetCompatibility JavaVersion.VERSION_1_8
39
+        }
36 40
     }
37 41
     lintOptions {
38 42
         disable 'InvalidPackage'
@@ -40,5 +44,8 @@ android {
40 44
 }
41 45
 
42 46
 dependencies {
47
+    implementation fileTree(dir: 'libs', include: ['*.jar'])
48
+    implementation 'com.android.support:appcompat-v7:27.1.1'
49
+    implementation 'com.android.support.constraint:constraint-layout:1.1.3'
43 50
     implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
44 51
 }

+ 193
- 0
android/src/main/java/com/fgodt/mixplayer/Core.java Прегледај датотеку

@@ -0,0 +1,193 @@
1
+package com.fgodt.mixplayer;
2
+
3
+import android.util.Log;
4
+import android.view.Surface;
5
+import android.view.SurfaceHolder;
6
+
7
+
8
+import java.util.Arrays;
9
+
10
+/**
11
+ * Created by rt-zl on 2019/2/15.
12
+ */
13
+
14
+public class Core {
15
+    static {
16
+        System.loadLibrary("mixplayer");
17
+    }
18
+
19
+    private native int  setJNI(long mix);
20
+    private native long createMix();
21
+    private native void closeMix(long mix,Render render);
22
+    private native int setPlayUrl(long mix,String url);
23
+    private native int open(long mix);
24
+    private native int setMixCall(long mix);
25
+    private native int setSurface(long mix, Surface surface);
26
+    private native int selectAudio(long mix, String name);
27
+    private native int addMixSource(long mix, String name,double stime, double duration);
28
+    private native double getMediaDuration(long mix);
29
+    private native int save(long mix, String output);
30
+    private native void pause(long mix);
31
+    private native void resume(long mix);
32
+    private native void seek(long mix, double time);
33
+    private native int getStatus(long mix);
34
+
35
+    private String url;
36
+
37
+    private Render render;
38
+
39
+    private String output;
40
+
41
+    private mixPlayerCallBack callBack;
42
+
43
+
44
+
45
+    private long mixHandler;
46
+
47
+    public void setUrl(String url){
48
+        this.url = url;
49
+    }
50
+
51
+    public void setSavePath(String output){
52
+        this.output = output;
53
+    }
54
+
55
+    public void setSurface(Surface surface){
56
+        // setSurface(mixHandler,surface);
57
+    }
58
+
59
+    public String getUrl(){
60
+        return this.url;
61
+    }
62
+
63
+
64
+    public boolean init(Render render){
65
+        this.render = render;
66
+        this.mixHandler = createMix();
67
+        int ret = setJNI(this.mixHandler);
68
+        if(ret!=0){
69
+            return false;
70
+        }
71
+        this.render.init(this.mixHandler);
72
+        setMixCall(mixHandler);
73
+        return true;
74
+    }
75
+
76
+
77
+    public boolean open(){
78
+        int ret =setPlayUrl(mixHandler,this.url);
79
+        if(ret!=0){
80
+            return false;
81
+        }
82
+        ret = open(mixHandler);
83
+        if(ret!=0){
84
+            return false;
85
+        }
86
+        return true;
87
+    }
88
+
89
+    public boolean save(){
90
+        int ret = setPlayUrl(mixHandler,this.url);
91
+        if(ret != 0){
92
+            return false;
93
+        }
94
+        ret = save(mixHandler,this.output);
95
+        if(ret != 0){
96
+            return false;
97
+        }
98
+        return true;
99
+    }
100
+
101
+    public  long getMixCtx(){
102
+        return mixHandler;
103
+    }
104
+
105
+    public void mixClose(){
106
+        render.mixClose();
107
+        closeMix(mixHandler,render);
108
+        mixHandler = 0;
109
+    }
110
+
111
+    public void nativeClose(){
112
+        Log.d("MIXPLAYER","CLOSE");
113
+        if(this.callBack != null){
114
+            this.callBack.closeMsg("CLOSE");
115
+        }
116
+    }
117
+
118
+    public void nativeCall(){
119
+
120
+    }
121
+
122
+    public void nativeMsg(String msg){
123
+        Log.d("MIXPLAYER",msg);
124
+    }
125
+
126
+
127
+    public int mixDataCall(String name,byte[] data,int len){
128
+        if(name == null || data == null || len <= 0){
129
+            return 0;
130
+        }
131
+        if(this.callBack!=null){
132
+            int ret = this.callBack.mix_call(name,data,len);
133
+            return ret;
134
+        }
135
+        return 0;
136
+    }
137
+
138
+    public double mixGetDuration() {
139
+        if (mixHandler > 0)
140
+            return getMediaDuration(mixHandler);
141
+        else
142
+            return -1;
143
+    }
144
+
145
+    public int addMixSource(String name,double stime, double duration){
146
+        if(mixHandler >0) {
147
+            return addMixSource(mixHandler,name,stime,duration);
148
+        }
149
+        return -1;
150
+    }
151
+
152
+    public void selectAudioSource(String name){
153
+        selectAudio(mixHandler,name);
154
+    }
155
+
156
+    public void pause(){
157
+        if(mixHandler>0){
158
+            pause(mixHandler);
159
+        }
160
+    }
161
+
162
+    public void resume(){
163
+        if(mixHandler>0){
164
+            resume(mixHandler);
165
+        }
166
+    }
167
+
168
+    public void seek(double time){
169
+        if(mixHandler>0){
170
+            seek(mixHandler,time);
171
+        }
172
+    }
173
+
174
+    void setMixCall(mixPlayerCallBack call){
175
+        this.callBack = call;
176
+    }
177
+
178
+    public int getStatus(){
179
+        if(mixHandler>0){
180
+            return getStatus(mixHandler);
181
+        }
182
+        return 1;//stop
183
+    }
184
+
185
+    @Override
186
+    protected void finalize() throws Throwable {
187
+        super.finalize();
188
+        //make sure close
189
+        if(mixHandler!=0)
190
+            mixClose();
191
+    }
192
+
193
+}

+ 178
- 0
android/src/main/java/com/fgodt/mixplayer/Player.java Прегледај датотеку

@@ -0,0 +1,178 @@
1
+package com.fgodt.mixplayer;
2
+
3
+import android.content.Context;
4
+
5
+import java.util.ArrayList;
6
+
7
+
8
+/**
9
+ * Created by rt-zl on 2019/2/15.
10
+ */
11
+
12
+public class Player extends Render {
13
+
14
+
15
+    public final int STATUS_ERROR = 0;
16
+    public final int STATUS_STOP = 1;
17
+    public final int STATUS_START = 2;
18
+    public final int STATUS_PAUSE = 3;
19
+    public final int STATUS_BUFFING = 4;
20
+    public final int STATUS_RUNNING = 5;
21
+
22
+    private Core mixCore;
23
+    private Core enMixCore;
24
+    private String url ;
25
+    private mixPlayerCallBack callBack;
26
+    private boolean needSelectAudioSource = false;
27
+
28
+    public Player(Context context){
29
+        super(context);
30
+    }
31
+
32
+    ArrayList<mixSource> mixSourceName = new ArrayList<mixSource>();
33
+    private void addMixList(){
34
+        if(mixCore == null){
35
+            return;
36
+        }
37
+        for (mixSource source :mixSourceName){
38
+            mixCore.addMixSource(source.name, source.startTime, source.duration);
39
+        }
40
+    }
41
+
42
+    private void selectAudioSource(){
43
+        if(mixCore == null){
44
+            return;
45
+        }
46
+        for (mixSource source :mixSourceName){
47
+            if(source.select){
48
+                mixCore.selectAudioSource(source.name);
49
+            }
50
+        }
51
+    }
52
+
53
+    private void createCore(){
54
+        if(mixCore != null){
55
+            mixCore.mixClose();
56
+            this.renderClose();
57
+        }
58
+        mixCore = new Core();
59
+        mixCore.init(this);
60
+        mixCore.setMixCall(callBack);
61
+        addMixList();
62
+        if(needSelectAudioSource){
63
+            selectAudioSource();
64
+        }
65
+    }
66
+
67
+    private void createEnCore(){
68
+        if(enMixCore != null){
69
+            enMixCore.mixClose();
70
+        }
71
+        enMixCore = new Core();
72
+    }
73
+
74
+    public void open(String url){
75
+        createCore();
76
+        this.url = url;
77
+        mixCore.setUrl(url);
78
+        new Thread(new Runnable() {
79
+            @Override
80
+            public void run() {
81
+                mixCore.open();
82
+            }
83
+        }).start();
84
+    }
85
+
86
+
87
+    public void resume(){
88
+        if(mixCore!=null){
89
+            mixCore.resume();
90
+        }
91
+        ispause = false;
92
+    }
93
+    public void stop(){
94
+        if(mixCore!=null){
95
+            mixCore.mixClose();
96
+            this.renderClose();
97
+        }
98
+    }
99
+    public void pause(){
100
+        if(mixCore!=null){
101
+            mixCore.pause();
102
+        }
103
+        ispause = true;
104
+    }
105
+    public void seek(double time){
106
+        if(mixCore != null){
107
+            mixCore.seek(time);
108
+        }
109
+    }
110
+    public void setMixCall(mixPlayerCallBack call){
111
+        this.callBack = call;
112
+    }
113
+    public double getDuration(){
114
+        if(mixCore!=null){
115
+            return mixCore.mixGetDuration();
116
+        }
117
+        return -1;
118
+    }
119
+    public double getPlayTime(){
120
+        double time = super.getPlaytime();
121
+        return time;
122
+    }
123
+
124
+    public double getSaveTime(){
125
+        return -1;
126
+    }
127
+
128
+    public void addMixSource(String name ,double stime, double duration){
129
+        mixSource source = new mixSource();
130
+        source.name = name;
131
+        source.startTime = stime;
132
+        source.duration = duration;
133
+        source.select  = false;
134
+        mixSourceName.add(source);
135
+    }
136
+
137
+    public void saveFile(String input, String output){
138
+        createCore();
139
+        this.url = input;
140
+        mixCore.setUrl(url);
141
+        mixCore.setSavePath(output);
142
+        mixCore.save();
143
+    }
144
+
145
+    public void selectAudioSource(String name){
146
+        needSelectAudioSource = true;
147
+        for(mixSource source : mixSourceName){
148
+            if(source.name.equals(name)){
149
+                source.select = true;
150
+            }
151
+        }
152
+    }
153
+
154
+    public int getStatus(){
155
+        if(mixCore != null){
156
+            return  mixCore.getStatus();
157
+        }
158
+        return STATUS_STOP;
159
+    }
160
+
161
+    public void setVolume(float volume){
162
+        this.volume = volume;
163
+    }
164
+
165
+    @Override
166
+    protected void finalize() throws Throwable {
167
+        super.finalize();
168
+        if(mixCore!= null)
169
+            mixCore.mixClose();
170
+    }
171
+
172
+    class mixSource{
173
+        public String name;
174
+        public double startTime;
175
+        public double duration;
176
+        public boolean select;
177
+    }
178
+}

+ 187
- 0
android/src/main/java/com/fgodt/mixplayer/Render.java Прегледај датотеку

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

+ 93
- 0
android/src/main/java/com/fgodt/mixplayer/VideoRender.java Прегледај датотеку

@@ -0,0 +1,93 @@
1
+package com.fgodt.mixplayer;
2
+
3
+
4
+
5
+import android.content.Context;
6
+import android.opengl.GLES20;
7
+import android.opengl.GLSurfaceView;
8
+
9
+import javax.microedition.khronos.egl.EGLConfig;
10
+import javax.microedition.khronos.opengles.GL10;
11
+
12
+public class VideoRender extends GLSurfaceView implements GLSurfaceView.Renderer {
13
+
14
+    //lib mixplayer hander
15
+    private long  hander = 0;
16
+    private int mScreenWidth, mScreenHeight;
17
+    private native void step(long handler);
18
+    private native void init(long handler,int w, int h);
19
+    private native void nativeChangeSize(long handler, int w, int h);
20
+
21
+    final Object textLocker = new Object();
22
+
23
+    boolean ispause = false;
24
+    float volume = 1.0f;
25
+
26
+
27
+    private boolean createDone=false;
28
+
29
+    public VideoRender(Context context){
30
+        super(context);
31
+        this.setEGLContextClientVersion(2);
32
+        this.setRenderer(this);
33
+    }
34
+    public int getScreenWidth(){
35
+        return mScreenWidth;
36
+    }
37
+    public int getScreenHeight(){
38
+        return mScreenHeight;
39
+    }
40
+
41
+
42
+    boolean inited = false;
43
+    boolean hasrender = false;
44
+    void nativeInit(int w, int h){
45
+        hasrender = true;
46
+    }
47
+    void nativeStep(){
48
+        if(hasrender && !inited){
49
+            init(hander,getScreenWidth(),getScreenHeight());
50
+            inited = true;
51
+        }
52
+        if(hander>0 && inited){
53
+            step(hander);
54
+        }
55
+    }
56
+
57
+    void close(){
58
+        hander = 0;
59
+        inited = false;
60
+        hasrender = false;
61
+    }
62
+
63
+
64
+    public void setMixHander(long hander){
65
+        this.hander = hander;
66
+    }
67
+
68
+    @Override
69
+    public void onSurfaceCreated(GL10 gl, EGLConfig config) {
70
+        return;
71
+    }
72
+
73
+    @Override
74
+    public void onSurfaceChanged(GL10 gl, int width, int height) {
75
+        mScreenWidth =width;
76
+        mScreenHeight = height;
77
+        if(this.hander>0){
78
+            nativeChangeSize(this.hander,width,height);
79
+        }
80
+        return;
81
+    }
82
+
83
+
84
+    @Override
85
+    public void onDrawFrame(GL10 gl) {
86
+        if(hander == 0){
87
+            GLES20.glClearColor(0,0,0,1);
88
+            GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
89
+        }
90
+        nativeStep();
91
+        return;
92
+    }
93
+}

+ 6
- 0
android/src/main/java/com/fgodt/mixplayer/mixPlayerCallBack.java Прегледај датотеку

@@ -0,0 +1,6 @@
1
+package com.fgodt.mixplayer;
2
+
3
+public interface mixPlayerCallBack{
4
+    public int mix_call(String name, byte[] data, int len);
5
+    public void closeMsg(String msg);
6
+}

+ 252
- 0
android/src/main/java/com/fogdt/mixsample/MainActivity.java Прегледај датотеку

@@ -0,0 +1,252 @@
1
+package com.fogdt.mixsample;
2
+
3
+import android.Manifest;
4
+import android.app.ActivityManager;
5
+import android.app.AlertDialog;
6
+import android.content.DialogInterface;
7
+import android.content.pm.PackageManager;
8
+import android.content.res.Configuration;
9
+import android.media.AudioFormat;
10
+import android.media.AudioRecord;
11
+import android.media.MediaCodecInfo;
12
+import android.media.MediaRecorder;
13
+import android.os.Environment;
14
+import android.os.PersistableBundle;
15
+import android.support.annotation.Nullable;
16
+import android.support.v4.app.ActivityCompat;
17
+import android.support.v4.content.ContextCompat;
18
+import android.support.v7.app.AppCompatActivity;
19
+import android.os.Bundle;
20
+import android.text.TextPaint;
21
+import android.util.DisplayMetrics;
22
+import android.util.Log;
23
+import android.view.Gravity;
24
+import android.view.SurfaceHolder;
25
+import android.view.SurfaceView;
26
+import android.view.View;
27
+import android.view.ViewGroup;
28
+import android.view.WindowManager;
29
+import android.widget.EditText;
30
+import android.widget.FrameLayout;
31
+import android.widget.TextView;
32
+import android.widget.Toast;
33
+
34
+import com.fgodt.mixplayer.Core;
35
+import com.fgodt.mixplayer.Player;
36
+import com.fgodt.mixplayer.mixPlayerCallBack;
37
+
38
+import java.io.File;
39
+
40
+
41
+public class MainActivity extends AppCompatActivity implements mixPlayerCallBack {
42
+
43
+
44
+    private long handler =0;
45
+
46
+    AudioRecord audioRecord = null;
47
+    @Override
48
+    protected void onCreate(Bundle savedInstanceState) {
49
+        super.onCreate(savedInstanceState);
50
+
51
+
52
+
53
+        setContentView(R.layout.activity_main);
54
+
55
+
56
+
57
+        // Example of a call to a native method
58
+        TextView tv = (TextView) findViewById(R.id.sample_text);
59
+
60
+        tv.setText("el");
61
+        getPermission();
62
+
63
+
64
+        if(savedInstanceState == null)
65
+            test();
66
+    }
67
+
68
+    @Override
69
+    public void onWindowAttributesChanged(WindowManager.LayoutParams params) {
70
+        super.onWindowAttributesChanged(params);
71
+    }
72
+
73
+    private Player mixplayer ;
74
+    private void test(){
75
+
76
+        FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.FILL_PARENT,
77
+                FrameLayout.LayoutParams.WRAP_CONTENT);
78
+        params.gravity = Gravity.TOP;
79
+        params.height = 1080*9/16;
80
+        mixplayer = new Player(this);
81
+        mixplayer.setMixCall(this);
82
+        mixplayer.addMixSource("mix1",0,-1);
83
+        mixplayer.addMixSource("silence",0,-1);
84
+       // mixplayer.selectAudioSource("silence");
85
+       // mixplayer.selectAudioSource("mix1");
86
+        addContentView(mixplayer,params);
87
+        editText = findViewById(R.id.editText);
88
+    }
89
+
90
+    private String getPath(){
91
+        String  file = Environment.getExternalStoragePublicDirectory(
92
+                Environment.DIRECTORY_MOVIES)+"" ;
93
+        return file;
94
+    }
95
+
96
+    private EditText editText;
97
+    public void playClick(View sender){
98
+        if(!hasRWPermission) {
99
+            getPermission();
100
+            return;
101
+        }
102
+        mixplayer.open(editText.getText().toString());
103
+    }
104
+
105
+    public void savedClick(View view){
106
+        //mixplayer.selectAudioSource(editText.getText().toString());
107
+        mixplayer.saveFile(editText.getText().toString(),getPath()+"/mixtest.mp4");
108
+        //mixplayer.saveFile(editText.getText().toString(),"rtmp://192.168.3.10/live/abc1234");
109
+    }
110
+
111
+    //10s pcm data
112
+    int totalLen = 4*44100*10;
113
+    byte[] pcmData = new byte[4*44100*10];
114
+    int pcmWritePos = 0;
115
+    public void closeClick(View sender){
116
+       mixplayer.stop();
117
+    }
118
+
119
+    public void recorderClick(View view){
120
+        if(!hasRcordPermission) {
121
+            getPermission();
122
+            return;
123
+        }
124
+
125
+
126
+        audioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC,44100, AudioFormat.CHANNEL_IN_STEREO,AudioFormat.ENCODING_PCM_16BIT,4096*3);
127
+        if(audioRecord.getState() != AudioRecord.STATE_INITIALIZED){
128
+            Toast.makeText(this,"初始化录音失败",Toast.LENGTH_SHORT).show();
129
+            return;
130
+        }
131
+
132
+        if(audioRecord != null){
133
+            audioRecord.startRecording();
134
+            pcmWritePos = 0;
135
+            pcmReadPos = 0;
136
+            new Thread(new Runnable() {
137
+                @Override
138
+                public void run() {
139
+                    while (pcmWritePos<totalLen){
140
+                        int wlen = totalLen-pcmWritePos > 4096? 4096:totalLen-pcmWritePos;
141
+                        int ret = audioRecord.read(pcmData,pcmWritePos,wlen);
142
+                        pcmWritePos+=ret;
143
+                    }
144
+                    audioRecord.stop();
145
+                }
146
+            }).start();
147
+        }
148
+    }
149
+
150
+    public void playerAndResume(View view){
151
+        if(mixplayer.getStatus() == mixplayer.STATUS_PAUSE){
152
+            mixplayer.resume();
153
+        }else if(mixplayer.getStatus() == mixplayer.STATUS_RUNNING){
154
+            mixplayer.pause();
155
+        }
156
+    }
157
+
158
+    @Override
159
+    protected void onSaveInstanceState(Bundle outState) {
160
+        super.onSaveInstanceState(outState);
161
+    }
162
+
163
+
164
+    @Override
165
+    protected void onRestoreInstanceState(Bundle savedInstanceState) {
166
+        super.onRestoreInstanceState(savedInstanceState);
167
+    }
168
+
169
+
170
+    int pcmReadPos = 0;
171
+    @Override
172
+    public int mix_call(String name, byte[] data, int len) {
173
+        if(name.equals("silence")){
174
+            return 0;
175
+        }
176
+        if(totalLen - pcmReadPos < len){
177
+            return 0;
178
+        }else {
179
+            System.arraycopy(pcmData,pcmReadPos,data,0,len);
180
+            pcmReadPos += len;
181
+            return len;
182
+        }
183
+    }
184
+
185
+    @Override
186
+    public void closeMsg(String msg) {
187
+        Toast.makeText(this,"MIX CLOSE",Toast.LENGTH_SHORT).show();
188
+    }
189
+
190
+
191
+    private boolean hasRWPermission = false;
192
+    private boolean hasRcordPermission = false;
193
+
194
+    private  void getPermission(){
195
+        int has = ContextCompat.checkSelfPermission(getApplication(), Manifest.permission.WRITE_EXTERNAL_STORAGE);
196
+        if (has == PackageManager.PERMISSION_GRANTED){
197
+            hasRWPermission = true;
198
+        }else {
199
+            ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE  },1);
200
+        }
201
+
202
+        has = ContextCompat.checkSelfPermission(getApplication(), Manifest.permission.RECORD_AUDIO);
203
+        if (has == PackageManager.PERMISSION_GRANTED){
204
+            hasRcordPermission = true;
205
+        }else {
206
+            ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.RECORD_AUDIO},2);
207
+        }
208
+    }
209
+
210
+    @Override
211
+    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults){
212
+        if(requestCode == 1){
213
+            if(grantResults.length>0&&grantResults[0] == PackageManager.PERMISSION_GRANTED){
214
+                hasRWPermission = true;
215
+            }else {
216
+                if(ActivityCompat.shouldShowRequestPermissionRationale(this,Manifest.permission.WRITE_EXTERNAL_STORAGE)){
217
+                    new AlertDialog.Builder(this)
218
+                            .setMessage("need read write permisson")
219
+                            .setPositiveButton("ok",(d,w)->{
220
+                                if (w == DialogInterface.BUTTON_POSITIVE){
221
+                                    ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},1);
222
+                                }
223
+                            })
224
+                            .setNegativeButton("cancle",null)
225
+                            .setTitle("需要提供相应权限")
226
+                            .create()
227
+                            .show();
228
+                }
229
+            }
230
+        }
231
+        if (requestCode == 2){
232
+            if(grantResults.length>0&&grantResults[0] == PackageManager.PERMISSION_GRANTED){
233
+                hasRcordPermission = true;
234
+            }else {
235
+                if(ActivityCompat.shouldShowRequestPermissionRationale(this,Manifest.permission.RECORD_AUDIO)){
236
+                    new AlertDialog.Builder(this)
237
+                            .setMessage("need record audio permisson")
238
+                            .setPositiveButton("ok",(dialog,which)->{
239
+                                if (which == DialogInterface.BUTTON_POSITIVE){
240
+                                    ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.RECORD_AUDIO},1);
241
+                                }
242
+                            })
243
+                            .setNegativeButton("cancle",null)
244
+                            .setTitle("需要录音权限")
245
+                            .create()
246
+                            .show();
247
+                }
248
+            }
249
+        }
250
+    }
251
+
252
+}

BIN
android/src/main/jniLibs/armeabi-v7a/libmixplayer.so Прегледај датотеку


BIN
android/src/main/jniLibs/x86/libmixplayer.so Прегледај датотеку


+ 49
- 0
android/src/main/kotlin/com/shuangyubang/mofun_flutter_plugin_video/MofunRealVideoView.kt Прегледај датотеку

@@ -0,0 +1,49 @@
1
+package com.shuangyubang.mofun_flutter_plugin_video
2
+
3
+import android.content.Context
4
+import android.view.Gravity
5
+import android.view.View
6
+import android.widget.EditText
7
+import android.widget.FrameLayout
8
+import android.widget.LinearLayout
9
+import com.fgodt.mixplayer.Player
10
+import com.fgodt.mixplayer.mixPlayerCallBack
11
+
12
+class MofunRealVideoView(val context: Context) : mixPlayerCallBack {
13
+
14
+    private var trueView:FrameLayout? = null
15
+
16
+    fun getView(): View? {
17
+        synchronized(MofunRealVideoView::class) {
18
+            if (trueView == null){
19
+                initView()
20
+            }
21
+        }
22
+        return trueView
23
+    }
24
+
25
+    private fun initView(){
26
+        trueView = FrameLayout(context)
27
+        val params = FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT,
28
+                FrameLayout.LayoutParams.WRAP_CONTENT)
29
+        params.gravity = Gravity.TOP
30
+        params.height = 1080 * 9 / 16
31
+        val mixplayer = Player(context)
32
+        mixplayer.setMixCall(this)
33
+        mixplayer.addMixSource("mix1", 0.0, -1.0)
34
+        mixplayer.addMixSource("silence", 0.0, -1.0)
35
+        // mixplayer.selectAudioSource("silence");
36
+        // mixplayer.selectAudioSource("mix1");
37
+
38
+        trueView?.addView(mixplayer, params)
39
+
40
+    }
41
+
42
+    override fun mix_call(name: String?, data: ByteArray?, len: Int): Int {
43
+        TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
44
+    }
45
+
46
+    override fun closeMsg(msg: String?) {
47
+        TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
48
+    }
49
+}

+ 2
- 2
example/android/app/build.gradle Прегледај датотеку

@@ -26,7 +26,7 @@ apply plugin: 'kotlin-android'
26 26
 apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
27 27
 
28 28
 android {
29
-    compileSdkVersion 28
29
+    compileSdkVersion 27
30 30
 
31 31
     sourceSets {
32 32
         main.java.srcDirs += 'src/main/kotlin'
@@ -40,7 +40,7 @@ android {
40 40
         // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
41 41
         applicationId "com.shuangyubang.mofun_flutter_plugin_video_example"
42 42
         minSdkVersion 16
43
-        targetSdkVersion 28
43
+        targetSdkVersion 27
44 44
         versionCode flutterVersionCode.toInteger()
45 45
         versionName flutterVersionName
46 46
         testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"