Android使用MediaCodec编码AAC

关于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();
                }
            }
        }
    }
编码完后,我们可以使用常用的播放器播放,如果能正常播放说明编码的AAC数据是正确的。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值