package lavender.com.myaudiodecoder;
import android.content.Context;
import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioTrack;
import android.media.MediaCodec;
import android.media.MediaCodecInfo;
import android.media.MediaFormat;
import android.util.Log;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
/**
* @author lavender
* @createtime 2018/5/24
* @desc
*/
public class AudioDecoder {
private MediaCodec audioDecoder;//音频解码器
private static final String TAG = "AACDecoderUtil";
//声道数
private static final int KEY_CHANNEL_COUNT = 1;
//采样率
private static final int KEY_SAMPLE_RATE = 16000;
private final Object obj = new Object();
private Thread audioThread;
private long prevPresentationTimes;
private InputStream inputStream;
private Context context;
private MediaCodec.BufferInfo encodeBufferInfo;
private ByteBuffer[] encodeInputBuffers;
private ByteBuffer[] encodeOutputBuffers;
public boolean isStop = false;
public AudioDecoder(Context context) {
this.context = context;
prepare();
}
/**
* 获取当前的时间戳
*
* @return
*/
private long getPTSUs() {
long result = System.nanoTime() / 1000;
if (result < prevPresentationTimes) {
result = (prevPresentationTimes - result) + result;
}
return result;
}
/**
* 开启解码播放
*/
public void startPlay() {
isStop = false;
prevPresentationTimes = 0;
audioThread = new Thread(new AudioThread(),
"Audio Thread");
audioThread.start();
try {
audioThread.join();
} catch (InterruptedException e) {
e.printStackTrace();
return;
}
}
/**
* 停止并且重启解码器以便下次使用
*/
public void stop() {
isStop = true;
if (audioThread != null) {
audioThread.interrupt();
}
try {
audioDecoder.stop();
audioDecoder.release();
prepare();
} catch (RuntimeException e) {
e.printStackTrace();
}
}
public class AudioThread implements Runnable {
int SAMPLE_RATE = 16000; //采样率8K或16k
private AudioTrack audioTrack;
private int buffSize = 0;
private int bufferSizeInBytes = 0;
int size = 0;
public AudioThread() {
bufferSizeInBytes = AudioTrack.getMinBufferSize(SAMPLE_RATE, AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT);
audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC,//播放途径 外放
SAMPLE_RATE,
AudioFormat.CHANNEL_OUT_MONO,
AudioFormat.ENCODING_PCM_16BIT,
bufferSizeInBytes * 4,
AudioTrack.MODE_STREAM);
//启动AudioTrack
audioTrack.play();
// inputStream = context.getResources().openRawResource(R.raw.myaudio);
try {
size = inputStream.available();
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void run() {
try {
while (buffSize <size) {
//数据一定要一帧一帧取出来放到解码器中,否则会报解码器的状态不正确
byte[] audioBuffer = new byte[519];
int ret=inputStream.read(audioBuffer,0,519);
Log.i("ret---------->", ret + "");
if(ret>0){
Log.e("audioBuffer---->", audioBuffer.length + "");
decode(audioBuffer, 0, ret, audioTrack);
buffSize += 519;
}
}
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
stop();
}
}
/**
* 初始化音频解码器
*
* @return 初始化失败返回false,成功返回true
*/
public boolean prepare() {
// 初始化AudioTrack
try {
//需要解码数据的类型
String mine = "audio/mp4a-latm";
//初始化解码器
audioDecoder = MediaCodec.createDecoderByType(mine);
//MediaFormat用于描述音视频数据的相关参数
MediaFormat mediaFormat = MediaFormat.createAudioFormat(MediaFormat.MIMETYPE_AUDIO_AAC, 16000, 1);
//数据类型
mediaFormat.setString(MediaFormat.KEY_MIME, mine);
//采样率
mediaFormat.setInteger(MediaFormat.KEY_SAMPLE_RATE, KEY_SAMPLE_RATE);//16k
//声道个数
mediaFormat.setInteger(MediaFormat.KEY_CHANNEL_COUNT, KEY_CHANNEL_COUNT);//单声道
mediaFormat.setInteger(MediaFormat.KEY_CHANNEL_MASK, AudioFormat.CHANNEL_IN_MONO);
mediaFormat.setInteger(MediaFormat.KEY_MAX_INPUT_SIZE, 1024);//作用于inputBuffer的大小
//比特率
mediaFormat.setInteger(MediaFormat.KEY_BIT_RATE, 64000);
//用来标记AAC是否有adts头,1->有
mediaFormat.setInteger(MediaFormat.KEY_IS_ADTS, 1);
mediaFormat.setInteger(MediaFormat.KEY_AAC_PROFILE, MediaCodecInfo.CodecProfileLevel.AACObjectLC);
//ByteBuffer key(参数代表 单声道,16000采样率,AAC LC数据)
// *******************根据自己的音频数据修改data参数*************************************************
byte[] data = new byte[]{(byte) 0x14, (byte) 0x08};
ByteBuffer csd_0 = ByteBuffer.wrap(data);
mediaFormat.setByteBuffer("csd-0", csd_0);
//解码器配置
audioDecoder.configure(mediaFormat, null, null, 0);
} catch (IOException e) {
e.printStackTrace();
return false;
}
if (audioDecoder == null) {
return false;
}
audioDecoder.start();
encodeInputBuffers = audioDecoder.getInputBuffers();
encodeOutputBuffers = audioDecoder.getOutputBuffers();
encodeBufferInfo = new MediaCodec.BufferInfo();
return true;
}
/**
* aac音频解码+播放
*/
public void decode(byte[] buf, int offset, int length, AudioTrack audioTrack) {
//等待时间,0->不等待,-1->一直等待
long kTimeOutUs = 1000;
try {
//返回一个包含有效数据的input buffer的index,-1->不存在
int inputBufIndex = audioDecoder.dequeueInputBuffer(kTimeOutUs);
Log.i("inputBufIndex**", "\n"+inputBufIndex + "\n");
if (inputBufIndex >= 0) {
//获取当前的ByteBuffer
ByteBuffer dstBuf = encodeInputBuffers[inputBufIndex];
//清空ByteBuffer
dstBuf.clear();
//填充数据
dstBuf.put(buf, 0, length);
//将指定index的input buffer提交给解码器
audioDecoder.queueInputBuffer(inputBufIndex, 0, length, getPTSUs(), 0);
}
//返回一个output buffer的index,-1->不存在
int outputBufferIndex = audioDecoder.dequeueOutputBuffer(encodeBufferInfo, kTimeOutUs);
Log.i("outputBufferIndex**", "\n"+outputBufferIndex + "\n");
ByteBuffer outputBuffer;
while (outputBufferIndex > 0) {
//获取解码后的ByteBuffer
out
评论5
最新资源