关于MediaCodec
MediaCodec 是Android系统提供的硬件编码器,它可以利用设备的硬件来完成编码,从而提高编码效率,并可以减轻CPU压力降低电量的使用,但是必须是4.1以上的系统才可以使用。
MediaCodec编码出来的AAC数据是裸的AAC,即AAC的原始数据块,一个AAC原始数据块的长度是可变的,对原始帧加上ADTS头进行封装,就形成了ADTS帧。ADTS的全称是Audio Data Transport Stream,是AAC音频的传输流格式。
使用流程
1.初始化MediaCodec
private MediaFormat encoderFormat;
private MediaCodec encoder;
private FileOutputStream fos;
private MediaCodec.BufferInfo info;
private int perpcmsize;
private byte[] outByteBuffer;
private int aacsamplerate = 4;
private void initMediaCodec(int samperate, File outfile) {
try {
aacsamplerate = getADTSsamplerate(samperate);
encoderFormat = MediaFormat.createAudioFormat(MediaFormat.MIMETYPE_AUDIO_AAC,samperate,2);
encoderFormat.setInteger(MediaFormat.KEY_BIT_RATE,96000);
encoderFormat.setInteger(MediaFormat.KEY_AAC_PROFILE, MediaCodecInfo.CodecProfileLevel.AACObjectLC);
encoderFormat.setInteger(MediaFormat.KEY_MAX_INPUT_SIZE, 100 * 1024);
encoder = MediaCodec.createEncoderByType(MediaFormat.MIMETYPE_AUDIO_AAC);
info = new MediaCodec.BufferInfo();
if (encoder == null) {
return;
}
encoder.configure(encoderFormat,null,null,MediaCodec.CONFIGURE_FLAG_ENCODE);
fos = new FileOutputStream(outfile);
encoder.start();
}catch (IOException e) {
e.printStackTrace();
}
}
2.编码
private void encodecPcmToAAC(int size, byte[] buffer) {
if (buffer != null && encoder !=null) {
int inputBufferIndex = encoder.dequeueInputBuffer(0);
if (inputBufferIndex >= 0) {
ByteBuffer byteBuffer = encoder.getInputBuffers()[inputBufferIndex];
Log.e("byteBuffer","byteBuffer:" +byteBuffer.capacity()+",buffer:" +buffer.length);
byteBuffer.clear();
byteBuffer.put(buffer);
encoder.queueInputBuffer(inputBufferIndex,0,size,0,0);
}
int index = encoder.dequeueOutputBuffer(info,0);
while (index >= 0) {
try {
perpcmsize = info.size + 7;
outByteBuffer = new byte[perpcmsize];
ByteBuffer byteBuffer = encoder.getOutputBuffers()[index];
byteBuffer.position(info.offset);
byteBuffer.limit(info.offset + info.size);
addADTSHeader(outByteBuffer,perpcmsize,aacsamplerate);
byteBuffer.get(outByteBuffer,7,info.size);
byteBuffer.position(info.offset);
fos.write(outByteBuffer,0,perpcmsize);
encoder.releaseOutputBuffer(index,false);
index = encoder.dequeueOutputBuffer(info,0);
outByteBuffer = null;
Log.d("Player","编码中。。。");
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
3.添加ADTS头信息
private void addADTSHeader(byte[] packet, int packetLen,int samplerate){
int profile = 2;//AAC LC
int freqIdx = samplerate; //samplerate
int chanCfg = 2; //CPE
packet[0] = (byte) 0xFF; // 0xFFF(12bit) 这里只取了8位,所以还差4位放到下一个里面
packet[1] = (byte) 0xF9; // 第一个t位放F
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;
}
4.释放Mediacodec
private void releaseMediaCodec() {
try {
fos.close();
encoder.stop();
encoder.release();
encoderFormat = null;
info = null;
initmediacodec = false;
} catch (IOException e) {
e.printStackTrace();
}finally {
if (fos != null) {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}