8000 A little accident :(, restore the code submitted by @rostopira. · Condelab/flutter-webrtc@11918fe · GitHub
[go: up one dir, main page]

Skip to content

Commit 11918fe

Browse files
committed
A little accident :(, restore the code submitted by @rostopira.
1 parent 6e5ab94 commit 11918fe

15 files changed

+269
-42
lines changed

android/build.gradle

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ buildscript {
88
}
99

1010
dependencies {
11-
classpath 'com.android.tools.build:gradle:3.2.1'
11+
classpath 'com.android.tools.build:gradle:3.3.1'
1212
}
1313
}
1414

@@ -40,6 +40,6 @@ android {
4040
}
4141

4242
dependencies {
43-
api 'org.webrtc:google-webrtc:1.0.26131'
44-
implementation "androidx.annotation:annotation:1.1.0-alpha01"
43+
api 'org.webrtc:google-webrtc:1.0.26885'
44+
implementation "androidx.annotation:annotation:1.0.1"
4545
}

android/src/main/java/com/cloudwebrtc/webrtc/FlutterWebRTCPlugin.java

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import android.util.Log;
88
import android.util.LongSparseArray;
99

10+
import com.cloudwebrtc.webrtc.record.AudioChannel;
1011
import com.cloudwebrtc.webrtc.record.FrameCapturer;
1112
import com.cloudwebrtc.webrtc.utils.ConstraintsArray;
1213
import com.cloudwebrtc.webrtc.utils.ConstraintsMap;
@@ -104,12 +105,13 @@ private FlutterWebRTCPlugin(Registrar registrar, MethodChannel channel) {
104105

105106
getUserMediaImpl = new GetUserMediaImpl(this, registrar.context());
106107

107-
final AudioDeviceModule audioDeviceModule = JavaAudioDeviceModule.builder(registrar.context())
108+
AudioDeviceModule audioDeviceModule = JavaAudioDeviceModule.builder(registrar.context())
108109
.setUseHardwareAcousticEchoCanceler(true)
109110
.setUseHardwareNoiseSuppressor(true)
110-
.setSamplesReadyCallback(getUserMediaImpl.audioSamplesInterceptor)
111+
.setSamplesReadyCallback(getUserMediaImpl.inputSamplesInterceptor)
111112
.createAudioDeviceModule();
112113

114+
getUserMediaImpl.audioDeviceModule = (JavaAudioDeviceModule) audioDeviceModule;
113115

114116
mFactory = PeerConnectionFactory.builder()
115117
.setOptions(new PeerConnectionFactory.Options())
@@ -298,19 +300,15 @@ public void onMethodCall(MethodCall call, Result result) {
298300
if (track instanceof VideoTrack)
299301
videoTrack = (VideoTrack) track;
300302
}
301-
AudioTrack audioTrack = null;
302-
String audioTrackId = call.argument("audioTrackId");
303+
AudioChannel audioChannel = null;
304+
if (call.hasArgument("audioChannel"))
305+
audioChannel = AudioChannel.values()[(Integer) call.argument("audioChannel")];
303306
Integer recorderId = call.argument("recorderId");
304-
if (audioTrackId != null) {
305-
MediaStreamTrack track = localTracks.get(audioTrackId);
306-
if (track instanceof AudioTrack)
307-
audioTrack = (AudioTrack) track;
308-
}
309-
if (videoTrack != null || audioTrack != null) {
310-
getUserMediaImpl.startRecordingToFile(path, recorderId, videoTrack, audioTrack);
307+
if (videoTrack != null || audioChannel != null) {
308+
getUserMediaImpl.startRecordingToFile(path, recorderId, videoTrack, audioChannel);
311309
result.success(null);
312310
} else {
313-
result.error("0", "No track", null);
311+
result.error("0", "No tracks", null);
314312
}
315313
} catch (Exception e) {
316314
result.error("-1", e.getMessage(), e);

android/src/main/java/com/cloudwebrtc/webrtc/GetUserMediaImpl.java

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,10 @@
2121
import android.media.projection.MediaProjectionManager;
2222
import android.util.SparseArray;
2323

24+
import com.cloudwebrtc.webrtc.record.AudioChannel;
2425
import com.cloudwebrtc.webrtc.record.AudioSamplesInterceptor;
2526
import com.cloudwebrtc.webrtc.record.MediaRecorderImpl;
27+
import com.cloudwebrtc.webrtc.record.OutputAudioSamplesInterceptor;
2628
import com.cloudwebrtc.webrtc.utils.Callback;
2729
import com.cloudwebrtc.webrtc.utils.ConstraintsArray;
2830
import com.cloudwebrtc.webrtc.utils.ConstraintsMap;
@@ -37,6 +39,7 @@
3739
import java.util.Map;
3840

3941
import org.webrtc.*;
42+
import org.webrtc.audio.JavaAudioDeviceModule;
4043

4144
import io.flutter.plugin.common.MethodChannel.Result;
4245

@@ -71,7 +74,9 @@ class GetUserMediaImpl{
7174
private MediaProjectionManager mProjectionManager = null;
7275
private static MediaProjection sMediaProjection = null;
7376

74-
final AudioSamplesInterceptor audioSamplesInterceptor = new AudioSamplesInterceptor();
77+
final AudioSamplesInterceptor inputSamplesInterceptor = new AudioSamplesInterceptor();
78+
private OutputAudioSamplesInterceptor outputSamplesInterceptor = null;
79+
JavaAudioDeviceModule audioDeviceModule;
7580
private final SparseArray<MediaRecorderImpl> mediaRecorders = new SparseArray<>();
7681

7782
public void screenRequestPremissions(ResultReceiver resultReceiver){
@@ -746,12 +751,18 @@ void switchCamera(String id) {
746751
/** Creates and starts recording of local stream to file
747752
* @param path to the file for record
748753
* @param videoTrack to record or null if only audio needed
749-
* @param audioTrack actually ignored, because current WebRTC implementation allows only
750-
* local track to be recorded, but if null passed, no audio will be recorded
754+
* @param audioChannel channel for recording or null
751755
* @throws Exception lot of different exceptions, pass back to dart layer to print them at least
752756
* **/
753-
void startRecordingToFile(String path, Integer id, @Nullable VideoTrack videoTrack, @Nullable AudioTrack audioTrack) throws Exception {
754-
AudioSamplesInterceptor interceptor = audioTrack == null ? null : audioSamplesInterceptor;
757+
void startRecordingToFile(String path, Integer id, @Nullable VideoTrack videoTrack, @Nullable AudioChannel audioChannel) throws Exception {
758+
AudioSamplesInterceptor interceptor = null;
759+
if (audioChannel == AudioChannel.INPUT)
760+
interceptor = inputSamplesInterceptor;
761+
else if (audioChannel == AudioChannel.OUTPUT) {
762+
if (outputSamplesInterceptor == null)
763+
outputSamplesInterceptor = new OutputAudioSamplesInterceptor(audioDeviceModule);
764+
interceptor = outputSamplesInterceptor;
765+
}
755766
MediaRecorderImpl mediaRecorder = new MediaRecorderImpl(id, videoTrack, interceptor);
756767
mediaRecorder.startRecording(new File(path));
757768
mediaRecorders.append(id, mediaRecorder);
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
package com.cloudwebrtc.webrtc.record;
2+
3+
public enum AudioChannel {
4+
INPUT,
5+
OUTPUT
6+
}

android/src/main/java/com/cloudwebrtc/webrtc/record/AudioSamplesInterceptor.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package com.cloudwebrtc.webrtc.record;
22

33
import android.annotation.SuppressLint;
4-
import android.util.Log;
54

65
import org.webrtc.audio.JavaAudioDeviceModule.SamplesReadyCallback;
76
import org.webrtc.audio.JavaAudioDeviceModule.AudioSamples;
@@ -11,10 +10,11 @@
1110
/** JavaAudioDeviceModule allows attaching samples callback only on building
1211
* We don't want to instantiate VideoFileRenderer and codecs at this step
1312
* It's simple dummy class, it does nothing until samples are necessary */
13+
@SuppressWarnings("WeakerAccess")
1414
public class AudioSamplesInterceptor implements SamplesReadyCallback {
1515

1616
@SuppressLint("UseSparseArrays")
17-
private HashMap<Integer, SamplesReadyCallback> callbacks = new HashMap<>();
17+
protected final HashMap<Integer, SamplesReadyCallback> callbacks = new HashMap<>();
1818

1919
@Override
2020
public void onWebRtcAudioRecordSamplesReady(AudioSamples audioSamples) {
@@ -23,7 +23,7 @@ public void onWebRtcAudioRecordSamplesReady(AudioSamples audioSamples) {
2323
}
2424
}
2525

26-
public void attachCallback(Integer id, SamplesReadyCallback callback) {
26+
public void attachCallback(Integer id, SamplesReadyCallback callback) throws Exception {
2727
callbacks.put(id, callback);
2828
}
2929

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
package com.cloudwebrtc.webrtc.record;
2+
3+
import android.annotation.TargetApi;
4+
import android.media.AudioFormat;
5+
import android.media.AudioManager;
6+
import android.media.AudioTrack;
7+
import android.os.Build;
8+
9+
import org.webrtc.audio.JavaAudioDeviceModule.AudioSamples;
10+
import org.webrtc.audio.JavaAudioDeviceModule.SamplesReadyCallback;
11+
12+
import java.nio.ByteBuffer;
13+
14+
import androidx.annotation.NonNull;
15+
16+
/**
17+
* Wrapper around audio track
18+
* Intercepts write calls and passes it to callback
19+
* **/
20+
public final class AudioTrackInterceptor extends AudioTrack {
21+
final public AudioTrack originalTrack;
22+
final private SamplesReadyCallback callback;
23+
24+
public AudioTrackInterceptor(@NonNull AudioTrack originalTrack, @NonNull SamplesReadyCallback callback) {
25+
// That just random params, we don't care about object that will be created
26+
super(
27+
AudioManager.STREAM_VOICE_CALL,
28+
44200,
29+
AudioFormat.CHANNEL_OUT_MONO,
30+
AudioFormat.ENCODING_PCM_16BIT,
31+
128,
32+
AudioTrack.MODE_STREAM
33+
);
34+
this.originalTrack = originalTrack;
35+
this.callback = callback;
36+
}
37+
38+
@Override
39+
public int write(@NonNull byte[] audioData, int offsetInBytes, int sizeInBytes) {
40+
callback.onWebRtcAudioRecordSamplesReady(new AudioSamples(
41+
originalTrack.getAudioFormat(),
42+
originalTrack.getChannelCount(),
43+
originalTrack.getSampleRate(),
44+
audioData
45+
));
46+
return originalTrack.write(audioData, offsetInBytes, sizeInBytes);
47+
}
48+
49+
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
50+
@Override
51+
public int write(@NonNull ByteBuffer audioData, int sizeInBytes, int writeMode) {
52+
byte[] trimmed = new byte[sizeInBytes];
53+
int position = audioData.position();
54+
audioData.get(trimmed, 0, sizeInBytes);
55+
audioData.position(position);
56+
callback.onWebRtcAudioRecordSamplesReady(new AudioSamples(
57+
originalTrack.getAudioFormat(),
58+
originalTrack.getChannelCount(),
59+
originalTrack.getSampleRate(),
60+
trimmed
61+
));
62+
return originalTrack.write(audioData, sizeInBytes, writeMode);
63+
}
64+
65+
/**
66+
* Override all required calls to mimic original track
67+
* https://webrtc.googlesource.com/src/+/master/sdk/android/src/java/org/webrtc/audio/WebRtcAudioTrack.java
68+
* **/
69+
70+
@Override
71+
public int getPlayState() {
72+
return originalTrack.getPlayState();
73+
}
74+
75+
@Override
76+
public void play() throws IllegalStateException {
77+
originalTrack.play();
78+
}
79+
80+
@Override
81+
public void stop() throws IllegalStateException {
82+
originalTrack.stop();
83+
}
84+
85+
@TargetApi(Build.VERSION_CODES.N)
86+
@Override
87+
public int getUnderrunCount() {
88+
return originalTrack.getUnderrunCount();
89+
}
90+
91+
@TargetApi(Build.VERSION_CODES.N)
92+
@Override
93+
public int getBufferCapacityInFrames() {
94+
return originalTrack.getBufferCapacityInFrames();
95+
}
96+
97+
@TargetApi(Build.VERSION_CODES.M)
98+
@Override
99+
public int getBufferSizeInFrames() {
100+
return originalTrack.getBufferSizeInFrames();
101+
}
102+
103+
@Override
104+
public void release() {
105+
originalTrack.r 10000 elease();
106+
}
107+
108+
@Override
109+
public int getPlaybackHeadPosition() {
110+
return originalTrack.getPlaybackHeadPosition();
111+
}
112+
}

android/src/main/java/com/cloudwebrtc/webrtc/record/MediaRecorderImpl.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
import org.webrtc.VideoTrack;
99

1010
import java.io.File;
11-
import java.io.IOException;
1211

1312
public class MediaRecorderImpl {
1413

@@ -25,7 +24,7 @@ public MediaRecorderImpl(Integer id, @Nullable VideoTrack videoTrack, @Nullable
2524
this.audioInterceptor = audioInterceptor;
2625
}
2726

28-
public void startRecording(File file) throws IOException {
27+
public void startRecording(File file) throws Exception {
2928
recordFile = file;
3029
if (isRunning)
3130
return;
@@ -45,6 +44,7 @@ public void startRecording(File file) throws IOException {
4544
Log.e(TAG, "Video track is null");
4645
if (audioInterceptor != null) {
4746
//TODO(rostopira): audio only recording
47+
throw new Exception("Audio-only recording not implemented yet");
4848
}
4949
}
5050
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package com.cloudwebrtc.webrtc.record;
2+
3+
import org.webrtc.audio.JavaAudioDeviceModule;
4+
import org.webrtc.audio.WebRtcAudioTrackUtils;
5+
6+
public class OutputAudioSamplesInterceptor extends AudioSamplesInterceptor {
7+
private final JavaAudioDeviceModule audioDeviceModule;
8+
9+
public OutputAudioSamplesInterceptor(JavaAudioDeviceModule audioDeviceModule) {
10+
super();
11+
this.audioDeviceModule = audioDeviceModule;
12+
}
13+
14+
@Override
15+
public void attachCallback(Integer id, JavaAudioDeviceModule.SamplesReadyCallback callback) throws Exception {
16+
if (callbacks.isEmpty())
17+
WebRtcAudioTrackUtils.attachOutputCallback(this, audioDeviceModule);
18+
super.attachCallback(id, callback);
19+
}
20+
21+
@Override
22+
public void detachCallback(Integer id) {
23+
super.detachCallback(id);
24+
if (callbacks.isEmpty())
25+
WebRtcAudioTrackUtils.detachOutputCallback(audioDeviceModule);
26+
}
27+
}

android/src/main/java/com/cloudwebrtc/webrtc/utils/EglUtils.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package com.cloudwebrtc.webrtc.utils;
22

3+
import android.os.Build;
4+
35
import org.webrtc.EglBase;
46

57
public class EglUtils {
@@ -16,7 +18,10 @@ public class EglUtils {
1618
*/
1719
public static synchronized EglBase getRootEglBase() {
1820
if (rootEglBase == null) {
19-
rootEglBase = EglBase.create();
21+
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP)
22+
rootEglBase = EglBase.createEgl10(EglBase.CONFIG_PLAIN);
23+
else
24+
rootEglBase = EglBase.create();
2025
}
2126

2227
return rootEglBase;

0 commit comments

Comments
 (0)
0