Skip to content

Commit

Permalink
feat:aac conver
Browse files Browse the repository at this point in the history
  • Loading branch information
jeffrey committed Feb 3, 2022
1 parent 0c14333 commit e00c90d
Showing 1 changed file with 50 additions and 134 deletions.
184 changes: 50 additions & 134 deletions app/src/main/java/org/cloud/sonic/android/AudioService.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import android.media.MediaCodec;
import android.media.MediaCodecInfo;
import android.media.MediaFormat;
import android.media.MediaRecorder;
import android.media.projection.MediaProjection;
import android.media.projection.MediaProjectionManager;
import android.net.LocalServerSocket;
Expand All @@ -27,6 +28,7 @@
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.ParcelFileDescriptor;
import android.support.annotation.RequiresApi;
import android.util.Log;

Expand All @@ -36,9 +38,11 @@
import org.cloud.sonic.android.recorder.utils.FileUtils;
import org.cloud.sonic.android.recorder.utils.Logger;

import java.io.DataInputStream;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Locale;

/**
Expand Down Expand Up @@ -68,9 +72,11 @@ public class AudioService extends Service {
private MediaProjection mediaProjection;
private Thread recorderThread;
// private long presentationTimeUs;

private Mp3EncodeThread mp3EncodeThread;

// 处理 AAC 录制音频
private MediaRecorder mediaRecorder;
// 处理录制时候的数据流
private ParcelFileDescriptor parcelWrite;
private DataInputStream inputStream;

@SuppressLint("NewApi")
public static void start(Context context, Intent data) {
Expand Down Expand Up @@ -189,132 +195,57 @@ private static AudioRecord createAudioRecord(MediaProjection mediaProjection) {
return builder.build();
}

// private MediaCodec mediaCodec;
//
// private void initTransferACC() {
// MediaFormat encodeFormat = MediaFormat.createAudioFormat(MediaFormat.MIMETYPE_AUDIO_AAC, 16000, 1);//参数对应-> mime type、采样率、声道数
// encodeFormat.setInteger(MediaFormat.KEY_BIT_RATE, 128 * 100);//比特率
// encodeFormat.setInteger(MediaFormat.KEY_AAC_PROFILE, MediaCodecInfo.CodecProfileLevel.AACObjectLC);
// encodeFormat.setInteger(MediaFormat.KEY_MAX_INPUT_SIZE, 16 * 1024);
// try {
// mediaCodec = MediaCodec.createEncoderByType(MediaFormat.MIMETYPE_AUDIO_AAC);
// } catch (IOException e) {
// e.printStackTrace();
// }
// mediaCodec.configure(encodeFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
// mediaCodec.start();
// }

// private MediaCodec.BufferInfo encodeBufferInfo;
// private ByteBuffer[] encodeOutputBuffers ;
// private ByteBuffer[] encodeInputBuffers ;

// @SuppressLint("NewApi")
// private void encodePCMToAAC(byte[] bytes, OutputStream outputStream) throws IOException {
// encodeBufferInfo = new MediaCodec.BufferInfo();
// ByteBuffer inputBuffer;
// ByteBuffer outputBuffer;
// byte[] chunkAudio;
// encodeInputBuffers = mediaCodec.getInputBuffers();
// encodeOutputBuffers = mediaCodec.getOutputBuffers();
// int outBitSize;
// int outputIndex;
// int outPacketSize;
//
// int inputBufIndex = mediaCodec.dequeueInputBuffer(1000);
// if (inputBufIndex >= 0) {
// inputBuffer = encodeInputBuffers[inputBufIndex];
// inputBuffer.clear();
// inputBuffer.put(bytes);
// mediaCodec.queueInputBuffer(inputBufIndex, 0, bytes.length, 0, 0);
// }
//
// //通过dequeueOutputBuffer(BufferInfo info, long timeoutUs)来请求一个输出缓存,传入一个上面的BufferInfo对象
// outputIndex = mediaCodec.dequeueOutputBuffer(encodeBufferInfo, 10000);
// //然后通过返回的index得到输出缓存,并通过BufferInfo获取ByteBuffer的信息
// while (outputIndex >= 0) {
// outBitSize = encodeBufferInfo.size;
//
// //添加ADTS头,ADTS头包含了AAC文件的采样率、通道数、帧数据长度等信息。
// outPacketSize = outBitSize + 7;//7为ADTS头部的大小
// outputBuffer = encodeOutputBuffers[outputIndex];//拿到输出Buffer
// outputBuffer.position(encodeBufferInfo.offset);
// outputBuffer.limit(encodeBufferInfo.offset + outBitSize);
// chunkAudio = new byte[outPacketSize];
// addADTStoPacket(chunkAudio, outPacketSize);//添加ADTS 代码后面会贴上
// outputBuffer.get(chunkAudio, 7, outBitSize);//将编码得到的AAC数据 取出到byte[]中偏移量offset=7
// outputBuffer.position(encodeBufferInfo.offset);
// //showLog("outPacketSize:" + outPacketSize + " encodeOutBufferRemain:" + outputBuffer.remaining());
// try {
// outputStream.write(chunkAudio, 0, chunkAudio.length);//BufferOutputStream 将文件保存到内存卡中 *.aac
// } catch (IOException e) {
// e.printStackTrace();
// }
// //releaseOutputBuffer方法必须调用
// mediaCodec.releaseOutputBuffer(outputIndex, false);
// outputIndex = mediaCodec.dequeueOutputBuffer(encodeBufferInfo, 10000);
//
// }
// }

// /**
// * 添加ADTS头
// * @param packet
// * @param packetLen
// */
// private void addADTStoPacket(byte[] packet, int packetLen) {
// int profile = 2; // AAC LC
// int freqIdx = 8; // 44.1KHz
// int chanCfg = 1; // CPE
// // fill in ADTS data
// packet[0] = (byte) 0xFF;
// packet[1] = (byte) 0xF9;
// packet[2] = (byte) (((profile - 1) << 6) + (freqIdx << 2) + (chanCfg >> 2));
// packet[3] = (byte) (((chanCfg & 3) << 6) + (packetLen >> 11));
// packet[4] = (byte) ((packetLen & 0x7FF) >> 3);
// packet[5] = (byte) (((packetLen & 7) << 5) + 0x1F);
// packet[6] = (byte) 0xFC;
// }

//try wav

private void initMp3EncoderThread() {
try {
mp3EncodeThread = new Mp3EncodeThread(new File(getTempFilePath()), 1024 * 1024);
mp3EncodeThread.start();
} catch (Exception e) {
Logger.e(e, TAG, e.getMessage());
}
private MediaRecorder createMediaRecorder(AudioRecord recorder){
MediaRecorder mediaRecorder = new MediaRecorder();
//配置采集方式,这里用的是麦克风的采集方式
mediaRecorder.setAudioSource(recorder.getAudioSource());
//配置输出方式,这里用的是AAC
mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.AAC_ADTS);
//配置采样频率,频率越高月接近原始声音,Android所有设备都支持的采样频率为44100
mediaRecorder.setAudioSamplingRate(44100);
//配置文件的编码格式,AAC是比较通用的编码格式
mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
//配置码率,这里一般通用的是96000
mediaRecorder.setAudioEncodingBitRate(96000);
//设置获取音频流的方式
mediaRecorder.setOutputFile(parcelWrite.getFileDescriptor());
return mediaRecorder;
}


//record audio
private void startRecording() {
//处理线性输出
intPipLine();
final AudioRecord recorder = createAudioRecord(mediaProjection);
mediaRecorder = createMediaRecorder(recorder);

//try not thread
recorderThread = new Thread(() -> {
initMp3EncoderThread();

try (LocalSocket socket = connect()) {
handler.sendEmptyMessage(MSG_CONNECTION_ESTABLISHED);

recorder.startRecording();
int BUFFER_MS = 15; // do not buffer more than BUFFER_MS milliseconds
short[] buf = new short[SAMPLE_RATE * CHANNELS * BUFFER_MS / 1000];
mediaRecorder.prepare();
mediaRecorder.start();
// recorder.startRecording();
// int BUFFER_MS = 15; // do not buffer more than BUFFER_MS milliseconds
byte[] buffer = new byte[900];
// short[] buf = new short[SAMPLE_RATE * CHANNELS * BUFFER_MS / 1000];
while (true) {
int r = recorder.read(buf, 0, buf.length);
// int r = recorder.read(buf, 0, buf.length);
int read = inputStream.read(buffer);
// encodePCMToAAC(buf,socket.getOutputStream());
if (mp3EncodeThread != null) {
mp3EncodeThread.addChangeBuffer(new Mp3EncodeThread.ChangeBuffer(buf, r));
if (read != -1) {
byte[] data = Arrays.copyOfRange(buffer, 0, read);
socket.getOutputStream().write(data, 0, read);
}

socket.getOutputStream().write(ByteUtils.toBytes(buf), 0, r);
}
} catch (IOException e) {
// ignore
} finally {
recorder.stop();
// recorder.stop();
mediaRecorder.stop();
stopSelf();
stopMp3Encoded();
}
});
recorderThread.start();
Expand Down Expand Up @@ -360,29 +291,14 @@ public void handleMessage(Message message) {
}
}

/**
* 根据当前的时间生成相应的文件名
* 实例 record_20160101_13_15_12
*/
private String getTempFilePath() {
String fileDir = String.format(Locale.getDefault(), "%s/Record/", Environment.getExternalStorageDirectory().getAbsolutePath());
if (!FileUtils.createOrExistsDir(fileDir)) {
Logger.e(TAG, "文件夹创建失败:%s", fileDir);
}
String fileName = String.format(Locale.getDefault(), "record_tmp_%s", FileUtils.getNowString(new SimpleDateFormat("yyyyMMdd_HH_mm_ss", Locale.SIMPLIFIED_CHINESE)));
return String.format(Locale.getDefault(), "%s%s.pcm", fileDir, fileName);
}

private void stopMp3Encoded() {
if (mp3EncodeThread != null) {
mp3EncodeThread.stopSafe(new Mp3EncodeThread.EncordFinishListener() {
@Override
public void onFinish() {
mp3EncodeThread = null;
}
});
} else {
Logger.e(TAG, "mp3EncodeThread is null, 代码业务流程有误,请检查!! ");
private void intPipLine() {
try {
ParcelFileDescriptor[] parcelFileDescriptors = ParcelFileDescriptor.createPipe();
ParcelFileDescriptor parcelRead = new ParcelFileDescriptor(parcelFileDescriptors[0]);
parcelWrite = new ParcelFileDescriptor(parcelFileDescriptors[1]);
inputStream = new DataInputStream(new ParcelFileDescriptor.AutoCloseInputStream(parcelRead));
} catch (IOException e) {
e.printStackTrace();
}
}
}

0 comments on commit e00c90d

Please sign in to comment.