Skip to content

Commit 7cfcaf8

Browse files
committed
Android demo test recorder and mixer
1 parent fc235e5 commit 7cfcaf8

File tree

3 files changed

+112
-63
lines changed

3 files changed

+112
-63
lines changed

example/androidApp/src/main/java/com/piasy/kmp/webrtc/android/CallActivity.java

Lines changed: 85 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import android.content.Context;
44
import android.content.Intent;
5+
import android.content.res.AssetManager;
56
import android.os.Bundle;
67
import android.os.Handler;
78
import android.os.HandlerThread;
@@ -14,8 +15,14 @@
1415
import android.widget.Button;
1516
import android.widget.FrameLayout;
1617
import androidx.appcompat.app.AppCompatActivity;
18+
19+
import com.piasy.avconf.AudioMixer;
1720
import com.piasy.avconf.view.FreezeAwareRenderer;
1821

22+
import java.io.File;
23+
import java.io.FileOutputStream;
24+
import java.io.IOException;
25+
import java.io.InputStream;
1926
import java.util.Collections;
2027
import java.util.List;
2128

@@ -47,12 +54,11 @@
4754
import static com.piasy.kmp.webrtc.android.HallActivity.EXTRA_VIDEO_HEIGHT;
4855
import static com.piasy.kmp.webrtc.android.HallActivity.EXTRA_VIDEO_WIDTH;
4956

50-
public class CallActivity extends AppCompatActivity implements PeerConnectionClientCallback {
57+
public class CallActivity extends AppCompatActivity implements PeerConnectionClientCallback, AudioMixer.MixerCallback {
5158

5259
private static final String TAG = "CallActivity";
5360

5461
private static final boolean SAVE_YUV_FRAME = false;
55-
private static final boolean LOCAL_RECORD = false;
5662
private static final boolean PAUSE_STREAMING = true;
5763

5864
private boolean isPublisher;
@@ -66,8 +72,8 @@ public class CallActivity extends AppCompatActivity implements PeerConnectionCli
6672
private Button recordButton;
6773
private boolean recording;
6874

69-
private Button recordLButton;
70-
private boolean localRecording = false;
75+
private Button mixerButton;
76+
private boolean mixing;
7177

7278
private Button pauseButton;
7379
private boolean streamingPaused = false;
@@ -82,6 +88,7 @@ public class CallActivity extends AppCompatActivity implements PeerConnectionCli
8288
private EglBase eglBase;
8389
private PeerConnectionClientFactory pcClientFactory;
8490
private PeerConnectionClient pcClient;
91+
private AudioMixer mixer;
8592

8693
private static int getSystemUiVisibility() {
8794
return View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
@@ -129,26 +136,28 @@ protected void onCreate(Bundle savedInstanceState) {
129136
recordButton.setOnClickListener(v -> {
130137
recording = !recording;
131138
recordButton.setText(recording ? "stop record" : "start record");
132-
// if (recording) {
133-
// avConf.startRecording(new StartRecordingCallback() {
134-
// @Override
135-
// public void onStartSuccess(final String filename) {
136-
// Toast.makeText(CallActivity.this,
137-
// "start record success: " + filename + ".mkv",
138-
// Toast.LENGTH_SHORT).show();
139-
// }
140-
//
141-
// @Override
142-
// public void onStartFail() {
143-
// Toast.makeText(CallActivity.this, "start record fail",
144-
// Toast.LENGTH_SHORT).show();
145-
// recording = false;
146-
// recordButton.setText("start record");
147-
// }
148-
// });
149-
// } else {
150-
// avConf.stopRecording();
151-
// }
139+
if (recording) {
140+
File path = new File(getExternalFilesDir(null), "send.mkv");
141+
pcClient.startRecorder(PeerConnectionClient.DIR_SEND_ONLY, path.getAbsolutePath());
142+
} else {
143+
pcClient.stopRecorder(PeerConnectionClient.DIR_SEND_ONLY);
144+
}
145+
});
146+
147+
mixerButton = findViewById(R.id.btnMixer);
148+
mixerButton.setText(mixing ? "stop mixer" : "start mixer");
149+
mixerButton.setOnClickListener(v -> {
150+
mixing = !mixing;
151+
mixerButton.setText(mixing ? "stop mixer" : "start mixer");
152+
if (mixing) {
153+
File path = new File(getExternalFilesDir(null), "mozart.mp3");
154+
mixer = new AudioMixer(path.getAbsolutePath(), 48000, 1, 10000, false, 5, this);
155+
mixer.startMixer();
156+
mixer.toggleMusicStreaming(true);
157+
} else {
158+
mixer.stopMixer();
159+
mixer = null;
160+
}
152161
});
153162

154163
Button switchCamera = findViewById(R.id.btnCamera);
@@ -175,22 +184,6 @@ public void run() {
175184
// avConf.setVideoEnabled(!audioOnly);
176185
});
177186

178-
recordLButton = findViewById(R.id.btnRecordL);
179-
if (LOCAL_RECORD) {
180-
recordLButton.setOnClickListener(v -> {
181-
localRecording = !localRecording;
182-
recordLButton.setText(localRecording ? "stop record L" : "start record L");
183-
// if (localRecording) {
184-
// avConf.startLocalRecording(selfUid, PeerConnectionClient.DIR_SEND_ONLY,
185-
// "/sdcard/avconf/record_" + System.currentTimeMillis() + ".mkv");
186-
// } else {
187-
// avConf.stopLocalRecording(selfUid, PeerConnectionClient.DIR_SEND_ONLY);
188-
// }
189-
});
190-
} else {
191-
recordButton.setVisibility(View.GONE);
192-
}
193-
194187
pauseButton = findViewById(R.id.btnPauseStreaming);
195188
if (PAUSE_STREAMING) {
196189
pauseButton.setOnClickListener(v -> {
@@ -216,9 +209,33 @@ public void run() {
216209
localRenderer = createRenderer(true);
217210
remoteRenderer = createRenderer(false);
218211

212+
prepareMusic();
213+
219214
startLoopback();
220215
}
221216

217+
private void prepareMusic() {
218+
try {
219+
File path = new File(getExternalFilesDir(null), "mozart.mp3");
220+
if (path.exists()) {
221+
return;
222+
}
223+
InputStream inputStream = getAssets().open("mozart.mp3");
224+
FileOutputStream outputStream = new FileOutputStream(path);
225+
226+
byte[] buffer = new byte[1024];
227+
int length;
228+
while ((length = inputStream.read(buffer)) > 0) {
229+
outputStream.write(buffer, 0, length);
230+
}
231+
inputStream.close();
232+
outputStream.close();
233+
Logging.INSTANCE.info(TAG, "copy music success");
234+
} catch (IOException e) {
235+
e.printStackTrace();
236+
}
237+
}
238+
222239
private FreezeAwareRenderer createRenderer(boolean local) {
223240
WindowManager windowManager = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
224241
DisplayMetrics displayMetrics = new DisplayMetrics();
@@ -237,6 +254,7 @@ private FreezeAwareRenderer createRenderer(boolean local) {
237254
local ? "loopback_local" : "loopback_remote", FreezeAwareRenderer.SCALE_TYPE_CENTER_CROP);
238255
renderer.init(eglBase.getEglBaseContext(), null);
239256
renderer.setScalingType(RendererCommon.ScalingType.SCALE_ASPECT_FIT);
257+
renderer.setMirror(local);
240258

241259
wrapper.addView(renderer, ViewGroup.LayoutParams.MATCH_PARENT,
242260
ViewGroup.LayoutParams.MATCH_PARENT);
@@ -318,6 +336,10 @@ public void run() {
318336

319337
// Disconnect from remote resources, dispose of local resources, and exit.
320338
private void disconnect() {
339+
if (mixer != null) {
340+
mixer.stopMixer();
341+
mixer = null;
342+
}
321343
if (pcClientFactory != null) {
322344
pcClientFactory.stopVideoCapture();
323345
pcClient.close();
@@ -339,21 +361,41 @@ private void disconnect() {
339361

340362
@Override
341363
public void onIceCandidatesRemoved(@NotNull String peerUid, @NotNull List<@NotNull IceCandidate> candidates) {
342-
343364
}
344365

345366
@Override
346367
public void onPeerConnectionStatsReady(@NotNull String peerUid, @NotNull RtcStatsReport report) {
347-
348368
}
349369

350370
@Override
351371
public void onIceDisconnected(@NotNull String peerUid) {
352-
353372
}
354373

355374
@Override
356375
public void onError(@NotNull String peerUid, int code) {
376+
}
377+
378+
@Override
379+
public void onMixerSsrcFinished(int ssrc) {
380+
Logging.INSTANCE.info(TAG, "onMixerSsrcFinished " + ssrc);
381+
onMixerStopped();
382+
}
357383

384+
@Override
385+
public void onMixerSsrcError(int ssrc, int error) {
386+
Logging.INSTANCE.error(TAG, "onMixerSsrcError " + ssrc + ", " + error);
387+
onMixerStopped();
388+
}
389+
390+
private void onMixerStopped() {
391+
runOnUiThread(new Runnable() {
392+
@Override
393+
public void run() {
394+
mixing = false;
395+
mixerButton.setText("start mixer");
396+
mixer.stopMixer();
397+
mixer = null;
398+
}
399+
});
358400
}
359401
}

example/androidApp/src/main/res/layout/activity_call.xml

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -21,19 +21,19 @@
2121
>
2222

2323
<Button
24-
android:id="@+id/btnVideo"
25-
android:layout_width="wrap_content"
26-
android:layout_height="wrap_content"
27-
android:layout_gravity="center"
28-
android:text="Video"
29-
/>
24+
android:id="@+id/btnCamera"
25+
android:layout_width="wrap_content"
26+
android:layout_height="wrap_content"
27+
android:layout_gravity="center"
28+
android:text="FRONT"
29+
/>
3030

3131
<Button
32-
android:id="@+id/btnRecordL"
32+
android:id="@+id/btnVideo"
3333
android:layout_width="wrap_content"
3434
android:layout_height="wrap_content"
3535
android:layout_gravity="center"
36-
android:text="start record L"
36+
android:text="Video"
3737
/>
3838

3939
<Button
@@ -65,12 +65,12 @@
6565
/>
6666

6767
<Button
68-
android:id="@+id/btnCamera"
69-
android:layout_width="wrap_content"
70-
android:layout_height="wrap_content"
71-
android:layout_gravity="center"
72-
android:text="FRONT"
73-
/>
68+
android:id="@+id/btnMixer"
69+
android:layout_width="wrap_content"
70+
android:layout_height="wrap_content"
71+
android:layout_gravity="center"
72+
android:text="start mixer"
73+
/>
7474

7575
<Button
7676
android:id="@+id/btnStop"

example/iosApp/iosApp/CallViewController.m

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,9 @@ - (void)dealloc {
212212
- (void)hangup:(BOOL)dismissView {
213213
_left = true;
214214

215+
[_mixer stopMixer];
216+
_mixer = nil;
217+
215218
[_statsTimer invalidate];
216219
_statsTimer = nil;
217220
[_pcClientFactory stopVideoCapture];
@@ -425,19 +428,23 @@ - (void)onIceDisconnectedPeerUid:(nonnull NSString *)peerUid {
425428

426429
- (void)onSsrcError:(int32_t)ssrc code:(int32_t)code {
427430
NSLog(@"XXPXX onSsrcError %d %d", ssrc, code);
428-
__weak typeof(self) wself = self;
429-
dispatch_async(dispatch_get_main_queue(), ^{
430-
typeof(self) sself = wself;
431-
[sself onMixer:nil];
432-
});
431+
[self onMixerStopped];
433432
}
434433

435434
- (void)onSsrcFinished:(int32_t)ssrc {
436435
NSLog(@"XXPXX onSsrcFinished %d", ssrc);
436+
[self onMixerStopped];
437+
}
438+
439+
- (void)onMixerStopped {
437440
__weak typeof(self) wself = self;
438441
dispatch_async(dispatch_get_main_queue(), ^{
439442
typeof(self) sself = wself;
440-
[sself onMixer:nil];
443+
sself->_mixingMusic = NO;
444+
[sself->_mixerButton setTitle:@"start mixer"
445+
forState:UIControlStateNormal];
446+
[sself->_mixer stopMixer];
447+
sself->_mixer = nil;
441448
});
442449
}
443450

0 commit comments

Comments
 (0)