Skip to content

Commit cc59bf4

Browse files
committed
修改AEC调用方式
Change-Id: I55b630fc1ff8b8d3c2242077f9d89823de32bb89
1 parent 987c134 commit cc59bf4

File tree

6 files changed

+175
-73
lines changed

6 files changed

+175
-73
lines changed

sdk/video-link-android/build.gradle

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,10 +53,7 @@ dependencies {
5353
// changing = true
5454
// }
5555
// api 'com.tencent.iot.thirdparty.android:xp2p-sdk:2.4.23'
56-
api 'com.tencent.iot.thirdparty.android:xp2p-sdk:2.4.41-SNAPSHOT'
57-
api 'com.tencent.iot.thirdparty.android:ijkplayer-java:2.0.11'
58-
api 'com.tencent.iot.thirdparty.android:ijkplayer-armv7a:2.0.11'
59-
api 'com.tencent.iot.thirdparty.android:ijkplayer-arm64:2.0.11'
56+
api 'com.tencent.iot.thirdparty.android:xp2p-sdk:2.4.43-SNAPSHOT'
6057
api 'com.tencent.iot.thirdparty.android:media-server:1.0.5'
6158
api 'io.github.sundoggynew:iot-soundtouch:1.0.0'
6259
api 'io.github.sundoggynew:iot-voice-changer:1.0.0'

sdk/video-link-android/src/main/java/com/tencent/iot/video/link/util/audio/AudioRecordUtil.java

Lines changed: 145 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
import android.media.audiofx.AcousticEchoCanceler;
88
import android.media.audiofx.AutomaticGainControl;
99
import android.os.Handler;
10+
import android.os.HandlerThread;
11+
import android.os.Looper;
1012
import android.os.Message;
1113
import android.text.TextUtils;
1214
import android.util.Log;
@@ -17,6 +19,7 @@
1719
import com.tencent.iot.thirdparty.flv.FLVPacker;
1820
import com.tencent.xnet.XP2P;
1921

22+
import org.jetbrains.annotations.NotNull;
2023
import org.json.JSONException;
2124
import org.json.JSONObject;
2225

@@ -26,25 +29,29 @@
2629
import java.io.IOException;
2730
import java.util.ArrayList;
2831
import java.util.List;
32+
import java.util.concurrent.CountDownLatch;
2933
import java.util.concurrent.ExecutorService;
3034
import java.util.concurrent.Executors;
3135
import java.util.concurrent.LinkedBlockingDeque;
32-
import java.util.concurrent.atomic.AtomicInteger;
3336

3437
import com.iot.gvoice.interfaces.GvoiceJNIBridge;
3538

36-
import tv.danmaku.ijk.media.player.IjkMediaPlayer;
3739

38-
39-
public class AudioRecordUtil implements EncoderListener, FLVListener {
40+
public class AudioRecordUtil implements EncoderListener, FLVListener, Handler.Callback {
4041
private static final int DEFAULT_CHANNEL_CONFIG = AudioFormat.CHANNEL_IN_STEREO; //设置音频的录制的声道CHANNEL_IN_STEREO为双声道,CHANNEL_CONFIGURATION_MONO为单声道
4142
private static final int DEFAULT_AUDIO_FORMAT = AudioFormat.ENCODING_PCM_16BIT; //音频数据格式:PCM 16位每个样本。保证设备支持。PCM 8位每个样本。不一定能得到设备支持。
42-
private static final String TAG = AudioRecordUtil.class.getName();;
43+
private static final String TAG = AudioRecordUtil.class.getName();
44+
private static final int MSG_START = 1;
45+
private static final int MSG_STOP = 2;
46+
private static final int MSG_ENCODE = 3;
47+
private static final int MSG_RELEASE = 4;
48+
private final HandlerThread readThread;
49+
private final ReadHandler mReadHandler;
4350
private volatile boolean recorderState = true; //录制状态
4451
private byte[] buffer;
4552
private AudioRecord audioRecord;
46-
private AcousticEchoCanceler canceler;
47-
private AutomaticGainControl control;
53+
private volatile AcousticEchoCanceler canceler;
54+
private volatile AutomaticGainControl control;
4855
private volatile PCMEncoder pcmEncoder;
4956
private volatile FLVPacker flvPacker;
5057
private Context context;
@@ -73,8 +80,27 @@ public class AudioRecordUtil implements EncoderListener, FLVListener {
7380

7481
private static final int SAVE_PCM_DATA = 1;
7582

76-
private IjkMediaPlayer player;
7783
private LinkedBlockingDeque<Byte> playPcmData = new LinkedBlockingDeque<>(); // 内存队列,用于缓存获取到的播放器音频pcm
84+
private AudioRecordUtilListener audioRecordUtilListener = null;
85+
86+
@Override
87+
public boolean handleMessage(@NotNull Message msg) {
88+
switch (msg.what) {
89+
case MSG_START:
90+
startInternal();
91+
break;
92+
case MSG_STOP:
93+
stopInternal();
94+
break;
95+
case MSG_ENCODE:
96+
// renderInternal((TRTCCloudDef.TRTCVideoFrame) msg.obj);
97+
break;
98+
case MSG_RELEASE:
99+
releaseInternal();
100+
break;
101+
}
102+
return false;
103+
}
78104

79105
private class MyHandler extends Handler {
80106

@@ -114,24 +140,36 @@ public AudioRecordUtil(Context ctx, String id, int sampleRate) {
114140
context = ctx;
115141
deviceId = id;
116142
init(sampleRate, DEFAULT_CHANNEL_CONFIG, DEFAULT_AUDIO_FORMAT);
143+
readThread = new HandlerThread(TAG);
144+
readThread.start();
145+
mReadHandler = new ReadHandler(readThread.getLooper(), this);
117146
}
118147
public AudioRecordUtil(Context ctx, String id, int sampleRate, int channel, int bitDepth) {
119148
context = ctx;
120149
deviceId = id;
121150
init(sampleRate, channel, bitDepth);
151+
readThread = new HandlerThread(TAG);
152+
readThread.start();
153+
mReadHandler = new ReadHandler(readThread.getLooper(), this);
122154
}
123155
public AudioRecordUtil(Context ctx, String id, int sampleRate, int channel, int bitDepth, int pitch) {
124156
context = ctx;
125157
deviceId = id;
126158
this.pitch = pitch;
127159
init(sampleRate, channel, bitDepth);
160+
readThread = new HandlerThread(TAG);
161+
readThread.start();
162+
mReadHandler = new ReadHandler(readThread.getLooper(), this);
128163
}
129164
public AudioRecordUtil(Context ctx, String id, int sampleRate, int channel, int bitDepth, boolean enableAEC, boolean enableAGC) {
130165
context = ctx;
131166
deviceId = id;
132167
this.enableAEC = enableAEC;
133168
this.enableAGC = enableAGC;
134169
init(sampleRate, channel, bitDepth);
170+
readThread = new HandlerThread(TAG);
171+
readThread.start();
172+
mReadHandler = new ReadHandler(readThread.getLooper(), this);
135173
}
136174
public AudioRecordUtil(Context ctx, String id, int sampleRate, int channel, int bitDepth, int pitch, boolean enableAEC, boolean enableAGC) {
137175
context = ctx;
@@ -140,6 +178,21 @@ public AudioRecordUtil(Context ctx, String id, int sampleRate, int channel, int
140178
this.enableAEC = enableAEC;
141179
this.enableAGC = enableAGC;
142180
init(sampleRate, channel, bitDepth);
181+
readThread = new HandlerThread(TAG);
182+
readThread.start();
183+
mReadHandler = new ReadHandler(readThread.getLooper(), this);
184+
}
185+
public AudioRecordUtil(Context ctx, String id, int sampleRate, int channel, int bitDepth, int pitch, AudioRecordUtilListener audioRecordUtilListener) {
186+
context = ctx;
187+
deviceId = id;
188+
this.pitch = pitch;
189+
this.enableAEC = false;
190+
this.enableAGC = false;
191+
this.audioRecordUtilListener = audioRecordUtilListener;
192+
init(sampleRate, channel, bitDepth);
193+
readThread = new HandlerThread(TAG);
194+
readThread.start();
195+
mReadHandler = new ReadHandler(readThread.getLooper(), this);
143196
}
144197

145198
private void init(int sampleRate, int channel, int bitDepth) {
@@ -229,14 +282,15 @@ public void setMode(VoiceChangerMode mode) {
229282
}
230283
}
231284

232-
public void setPlayer(IjkMediaPlayer player) {
233-
this.player = player;
234-
}
235-
236285
/**
237286
* 开始录制
238287
*/
239288
public void start() {
289+
Log.i(TAG, "start");
290+
mReadHandler.obtainMessage(MSG_START).sendToTarget();
291+
}
292+
293+
private void startInternal() {
240294
if (isRecord) {
241295
fos1 = createFiles("near");
242296
fos2 = createFiles("far");
@@ -256,9 +310,12 @@ public void start() {
256310
VoiceChangerJNIBridge.setMode(this.mode.getValue());
257311
}
258312
recorderState = true;
313+
Log.e(TAG, "turn recorderState : " + recorderState);
259314
audioRecord.startRecording();
260315
new RecordThread().start();
261-
new WriteThread().start();
316+
if (audioRecordUtilListener != null) {
317+
new WriteThread().start();
318+
}
262319
}
263320

264321
private void reset() {
@@ -283,43 +340,57 @@ private void reset() {
283340
* 停止录制
284341
*/
285342
public void stop() {
286-
recorderState = false;
287-
if (audioRecord != null) {
288-
audioRecord.stop();
289-
}
290-
291-
executor.shutdown();
292-
audioRecord = null;
293-
pcmEncoder = null;
294-
if (flvPacker != null) {
295-
flvPacker.release();
296-
flvPacker = null;
297-
}
298-
if (canceler != null) {
299-
canceler.setEnabled(false);
300-
canceler.release();
301-
canceler = null;
302-
}
303-
if (control != null) {
304-
control.setEnabled(false);
305-
control.release();
306-
control = null;
307-
}
343+
Log.i(TAG, "stop");
344+
mReadHandler.obtainMessage(MSG_STOP).sendToTarget();
345+
}
308346

309-
if (!VoiceChangerJNIBridge.isAvailable()) {
310-
if (st != null) {
311-
st.finish();
312-
st.clearBuffer(0);
313-
st = null;
347+
private void stopInternal() {
348+
recorderState = false;
349+
Log.e(TAG, "turn recorderState : " + recorderState);
350+
mReadHandler.postDelayed(new Runnable() {
351+
@Override
352+
public void run() {
353+
Log.e(TAG, "mReadHandler.postDelayed 200 turn recorderState : " + recorderState);
354+
if (audioRecord != null) {
355+
audioRecord.stop();
356+
}
357+
executor.shutdown();
358+
audioRecord = null;
359+
pcmEncoder = null;
360+
if (flvPacker != null) {
361+
flvPacker.release();
362+
flvPacker = null;
363+
}
364+
if (canceler != null) {
365+
canceler.setEnabled(false);
366+
canceler.release();
367+
canceler = null;
368+
}
369+
if (control != null) {
370+
control.setEnabled(false);
371+
control.release();
372+
control = null;
373+
}
374+
if (!VoiceChangerJNIBridge.isAvailable()) {
375+
if (st != null) {
376+
st.finish();
377+
st.clearBuffer(0);
378+
st = null;
379+
}
380+
} else {
381+
VoiceChangerJNIBridge.destory();
382+
}
383+
// GvoiceJNIBridge.destory();
314384
}
315-
} else {
316-
VoiceChangerJNIBridge.destory();
317-
}
318-
319-
GvoiceJNIBridge.destory();
385+
}, 200);
320386
}
321387

322388
public void release() {
389+
Log.i(TAG, "release");
390+
mReadHandler.obtainMessage(MSG_STOP).sendToTarget();
391+
}
392+
393+
private void releaseInternal() {
323394
audioRecord.release();
324395
}
325396

@@ -336,7 +407,7 @@ public void encodeG711(byte[] data) { }
336407
@Override
337408
public void onFLV(byte[] data) {
338409
if (recorderState) {
339-
Log.d(TAG, "===== XP2P.dataSend dataLen:" + data.length);
410+
// Log.d(TAG, "===== XP2P.dataSend dataLen:" + data.length);
340411
XP2P.dataSend(deviceId, data, data.length);
341412

342413
if (executor.isShutdown()) return;
@@ -373,7 +444,7 @@ private class RecordThread extends Thread {
373444
public void run() {
374445
while (recorderState) {
375446
int read = audioRecord.read(buffer, 0, buffer.length);
376-
Log.e(TAG, "audioRecord.read: "+read + ", buffer.length: " + buffer.length);
447+
Log.e(TAG, "audioRecord.read: "+read + ", buffer.length: " + buffer.length + ", recorderState: " + recorderState);
377448
if (!VoiceChangerJNIBridge.isAvailable()) {
378449
if (pitch != 0 && st != null) {
379450
st.putBytes(buffer);
@@ -387,7 +458,7 @@ public void run() {
387458
if (AudioRecord.ERROR_INVALID_OPERATION != read) {
388459
//获取到的pcm数据就是buffer了
389460
if (buffer != null && pcmEncoder != null) {
390-
if (player != null && player.isPlaying()) {
461+
if (audioRecordUtilListener != null) {
391462
byte [] playerPcmBytes = onReadPlayerPlayPcm(buffer.length);
392463
byte[] aecPcmBytes = GvoiceJNIBridge.cancellation(buffer, playerPcmBytes);
393464
if (isRecord) {
@@ -460,14 +531,12 @@ private class WriteThread extends Thread {
460531
@Override
461532
public void run() {
462533
while (recorderState) {
463-
if (player != null && player.isPlaying()) {
464-
byte[] data = new byte[204800];
465-
int len = player._getPcmData(data);
466-
if (len > 0) {
467-
byte[] playerBytes = new byte[len];
468-
System.arraycopy(data, 0, playerBytes, 0, len);
534+
if (audioRecordUtilListener != null) {
535+
byte[] data = audioRecordUtilListener.onReadPlayerPcmByte();
536+
if (data != null && data.length > 0) {
537+
Log.e(TAG, "data.length: " + data.length + " , recorderState : " + recorderState);
469538
List<Byte> tmpList = new ArrayList<>();
470-
for (byte b : playerBytes) {
539+
for (byte b : data) {
471540
tmpList.add(b);
472541
}
473542
playPcmData.addAll(tmpList);
@@ -476,4 +545,25 @@ public void run() {
476545
}
477546
}
478547
}
548+
549+
public static class ReadHandler extends Handler {
550+
551+
public ReadHandler(Looper looper, Callback callback) {
552+
super(looper, callback);
553+
}
554+
555+
public void runAndWaitDone(final Runnable runnable) {
556+
final CountDownLatch countDownLatch = new CountDownLatch(1);
557+
post(() -> {
558+
runnable.run();
559+
countDownLatch.countDown();
560+
});
561+
562+
try {
563+
countDownLatch.await();
564+
} catch (InterruptedException e) {
565+
e.printStackTrace();
566+
}
567+
}
568+
}
479569
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package com.tencent.iot.video.link.util.audio;
2+
3+
public interface AudioRecordUtilListener {
4+
byte[] onReadPlayerPcmByte();
5+
}

sdk/video-link-android/src/main/java/com/tencent/iot/video/link/util/audio/OnReadAECProcessedPcmListener.java

Lines changed: 0 additions & 5 deletions
This file was deleted.

sdkdemo/build.gradle

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -139,9 +139,9 @@ dependencies {
139139

140140
// implementation 'com.tencent.iot.thirdparty.android:ijkplayer-java:1.0.7'
141141
// implementation 'com.tencent.iot.thirdparty.android:ijkplayer-armv7a:1.0.7'
142-
api 'com.tencent.iot.thirdparty.android:ijkplayer-java:2.0.11'
143-
api 'com.tencent.iot.thirdparty.android:ijkplayer-armv7a:2.0.11'
144-
api 'com.tencent.iot.thirdparty.android:ijkplayer-arm64:2.0.11'
142+
api 'com.tencent.iot.thirdparty.android:ijkplayer-java:2.0.12-SNAPSHOT'
143+
api 'com.tencent.iot.thirdparty.android:ijkplayer-armv7a:2.0.12-SNAPSHOT'
144+
api 'com.tencent.iot.thirdparty.android:ijkplayer-arm64:2.0.12-SNAPSHOT'
145145

146146
implementation 'cn.aigestudio.wheelpicker:WheelPicker:1.1.3'
147147
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.7-mpp-dev-11'

0 commit comments

Comments
 (0)