-
Notifications
You must be signed in to change notification settings - Fork 12
/
AudioCodec.java
135 lines (113 loc) · 4.06 KB
/
AudioCodec.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
package com.lyman.audio.base.codec;
import android.media.AudioRecord;
import android.os.SystemClock;
import android.util.Log;
import com.lyman.audio.base.capturer.AudioRecordCapturer;
import com.lyman.audio.base.capturer.OnAudioFrameCapturedListener;
import com.lyman.audio.base.player.AudioTrackPlayer;
/**
* Author: lyman
* Email: lymenye@gmail.com
* Date: 2017/11/27
* Description:
*/
public class AudioCodec implements IAudioCodec, AudioEncoder.OnAudioEncodedListener, AudioDecoder.OnAudioDecodedListener {
private static final String TAG = "AudioCodec";
private AudioEncoder mAudioEncoder;
private AudioDecoder mAudioDecoder;
private AudioRecordCapturer mAudioCapturer;
private AudioTrackPlayer mAudioPlayer;
private volatile boolean mIsCodecExit = true;
private OnAudioFrameCapturedListener mAudioFrameCapturedListener = new OnAudioFrameCapturedListener() {
@Override
public void onAudioFrameCaptured(byte[] audioData) {
Log.d(TAG, "onAudioFrameCaptured: " + audioData);
long presentationTimeUs = (System.nanoTime()) / 1000L;
mAudioEncoder.encode(audioData, presentationTimeUs);
}
};
public boolean isCodecStart() {
return mIsCodecExit;
}
@Override
public boolean startCodec() {
if (!mIsCodecExit) {
Log.d(TAG, "startCodec: already exit");
return false;
}
mAudioCapturer = new AudioRecordCapturer();
mAudioPlayer = new AudioTrackPlayer();
mAudioEncoder = new AudioEncoder();
mAudioDecoder = new AudioDecoder();
if (!mAudioEncoder.open() || !mAudioDecoder.open()) {
return false;
}
mAudioEncoder.setAudioEncodedListener(this);
mAudioDecoder.setAudioDecodedListener(this);
mIsCodecExit = false;
new Thread(mEncodeRunnable).start();
new Thread(mDecodeRunnable).start();
new Thread(mAudioCaptureRunnable).start();
if (!mAudioCapturer.startCapturer()) {
return false;
}
mAudioPlayer.startPlayer();
Log.d(TAG, "startCodec: success");
return true;
}
@Override
public boolean stopCodec() {
mIsCodecExit = true;
mAudioCapturer.stopCapturer();
mAudioCapturer = null;
return true;
}
@Override
public void onFrameEncoded(byte[] encoded, long presentationTimeUs) {
Log.d(TAG, "onFrameEncoded: ");
mAudioDecoder.decode(encoded, presentationTimeUs);
}
@Override
public void onFrameDecoded(byte[] decoded, long presentationTimeUs) {
Log.d(TAG, "onFrameDecoded: ");
mAudioPlayer.play(decoded, 0, decoded.length);
}
private Runnable mEncodeRunnable = new Runnable() {
@Override
public void run() {
while (!mIsCodecExit) {
mAudioEncoder.retrieve();
}
mAudioEncoder.close();
}
};
private Runnable mDecodeRunnable = new Runnable() {
@Override
public void run() {
while (!mIsCodecExit) {
mAudioDecoder.retrieve();
}
mAudioDecoder.close();
}
};
private Runnable mAudioCaptureRunnable = new Runnable() {
@Override
public void run() {
while (!mIsCodecExit) {
byte[] buffer = new byte[mAudioCapturer.mMinBufferSize];
int ret = mAudioCapturer.capture(buffer, 0, mAudioCapturer.mMinBufferSize);
if (ret == AudioRecord.ERROR_INVALID_OPERATION) {
Log.e(TAG, "Error ERROR_INVALID_OPERATION");
} else if (ret == AudioRecord.ERROR_BAD_VALUE) {
Log.e(TAG, "Error ERROR_BAD_VALUE");
} else {
if (mAudioFrameCapturedListener != null) {
mAudioFrameCapturedListener.onAudioFrameCaptured(buffer);
}
Log.d(TAG, "OK, Captured " + ret + " bytes !");
}
SystemClock.sleep(10);
}
}
};
}