概述
詳細
之前做的一個demo,Android錄音獲取pcm數據(音頻原始數據),然后利用 FFmpeg將PCM數據編碼成AAC。
一、准備工作
開發環境
jdk1.8
Eclipse Luna Service Release 1 (4.4.1)
運行環境:
華為榮耀6(Android4.4)、華為p9(Android7.0)
二、程序實現
代碼截圖如下:

該demo依賴v7包。
FFAacEncoderDemo工程src目錄
-
MainActivity.java是主界面,用來控制錄音開始和結束。
-
FFAacEncoder.java時native方法,用來和jni通信。
jni目錄:
-
include目錄下是FFmpeg的一些.h文件
-
libs目錄下是FFmpeg編譯的so
-
AacCoderc 音頻編碼
-
cn_vn_aacEncoder_jni_FFAacEncoderJni jni代碼與java通信。
1 錄音(獲取pcm數據)
開始錄音
private void startRecord(){
Log.i(TAG, "startRecord mIsRecording="+mIsRecording);
if(!mIsRecording){
mIsRecording = true;
synchronized (mLock) {
mAudioRecordGetExit = false;
}
//初始化ffmpeg 編碼器
mFFAacEncoderJni.start();
//創建錄音線程、開始錄音
mAudioRecordGetThread = new Thread(new AudioRecordGet());
mAudioRecordGetThread.start();
}
}
關閉錄音
private void stoptRecord(){
if(mIsRecording){
synchronized (mLock) {
mAudioRecordGetExit = true;
}
mIsRecording = false;
}
}
具體錄音通過使用AudioRecord。
private class AudioRecordGet implements Runnable{
private AudioRecord mAudioRecord;
private static final boolean PCM_DUMP_DEBUG = true;
private static final boolean AAC_DUMP_DEBUG = false;
private int mAudioSource = MediaRecorder.AudioSource.MIC;
//采樣頻率,采樣頻率越高,音質越好。44100 、22050、 8000、4000等
private int mSampleRateHz = 8000;
//MONO為單聲道 ,STEREO為雙聲道
private int mChannelConfig = AudioFormat.CHANNEL_IN_MONO;
//編碼格式和采樣大小,pcm編碼;支持的采樣大小16bit和8bit,采樣大小越大,信息越多,音質越好。
private int mAudioFormat = AudioFormat.ENCODING_PCM_16BIT;
//該size設置為AudioRecord.getMinBufferSize(mSampleRateHz, mChannelConfig, mAudioFormat); 編碼aac時會失敗。
private int mBufferSizeInBytes = 2048;//AudioRecord.getMinBufferSize(mSampleRateHz, mChannelConfig, mAudioFormat);
private AudioPCMData mAudioPCMData;
public AudioRecordGet() {
Log.i(TAG, "AudioRecordGet ");
mAudioPCMData = new AudioPCMData(mBufferSizeInBytes);
mAudioRecord = new AudioRecord(mAudioSource,
mSampleRateHz, mChannelConfig, mAudioFormat, mBufferSizeInBytes);
Log.i(TAG,"mBufferSizeInBytes="+mBufferSizeInBytes);
}
@Override
public void run() {
mAudioRecord.startRecording();
FileOutputStream outPCM = null;
try {
if (PCM_DUMP_DEBUG) {
String File = "/sdcard/test.pcm";
outPCM = new FileOutputStream(File);
}
} catch (Exception e) {
e.printStackTrace();
}
for(;;){
synchronized (mLock) {
if(mAudioRecordGetExit){
break;
}
}
//讀取錄音數據
int readSize = mAudioRecord.read(mAudioPCMData.mData, 0, mBufferSizeInBytes);
if (AudioRecord.ERROR_INVALID_OPERATION != readSize) {
if (PCM_DUMP_DEBUG && null != outPCM) {
try {
outPCM.write(mAudioPCMData.mData, 0, readSize);
} catch (Exception e) {
e.printStackTrace();
}
}
mAudioPCMData.mFrameSize = readSize;
Log.i(TAG, "audio pcm size="+readSize);
//設置pcm數據,進行aac編碼
mFFAacEncoderJni.setPcmData(mAudioPCMData.mData, readSize);
}
}
if(PCM_DUMP_DEBUG && null != outPCM){
try {
outPCM.close();
} catch (IOException e) {
e.printStackTrace();
}
}
//停止錄音、釋放
mAudioRecord.stop();
mAudioRecord.release();
//停止音頻編碼
mFFAacEncoderJni.stop();
Log.i(TAG,"AudioRecordGet thread exit success");
}
}
2 PCM編碼成AAC
1 初始化編碼器
public class FFAacEncoder {
private String TAG = "FFAacEncoder java";
//load .so
static{
System.loadLibrary("avcodec-57");
System.loadLibrary("avdevice-57");
System.loadLibrary("avfilter-6");
System.loadLibrary("avformat-57");
System.loadLibrary("avutil-55");
System.loadLibrary("postproc-54");
System.loadLibrary("swresample-2");
System.loadLibrary("swscale-4");
System.loadLibrary("aacEncoder");
}
private int mNativeContext = 0;
//初始化編碼器
private native final void nativeStart();
//對pcm數據進行編碼
private native final void nativeSetPcmData(byte[] pcm, int len);
//必要的清理
private native final void nativeStop();
public void start(){
nativeStart();
}
public void setPcmData(byte[] pcm, int len){
nativeSetPcmData(pcm, len);
}
public void stop(){
nativeStop();
}
}
調用nativeStart方法。
2 音頻編碼
//設置pcm數據,進行aac編碼 mFFAacEncoderJni.setPcmData(mAudioPCMData.mData, readSize);
調用nativeSetPcmData
C++層代碼,通過編碼獲取的AAC原始數據不同播放(存儲在/sdcard/test.aac文件中,不能播放),
需要添加adts header(不懂的可以了解一下AAC格式),這樣才可以正常播放。/sdcard/adts.aac該文件添加了header,可以正常播放。
三、運行效果
運行效果:

運行結果將生成文件 /sdcard/test.aac

四、其他補充
博客地址:http://blog.csdn.net/vnanyesheshou/article/details/54560684
注:本文著作權歸作者,由demo大師發表,拒絕轉載,轉載需要作者授權
