/** * <pre> * author : ych * email : 1147471053@qq.com * time : 2018/08/18 * desc : 解码器 -》PCM * version: * </pre> */ public class AudioDecoder2PCM { private static AudioDecoder2PCM INSTANCE=null; private MediaExtractor mExtractor; private int mSampleRate=0;//采样率 private int channel=0;//通道数 private LinkedList<byte[]> data = new LinkedList<>(); private MediaCodec mDecoder; private boolean eosReceived; public static AudioDecoder2PCM getINSTANCE(){ if (INSTANCE==null){ synchronized (AudioDecoder2PCM.class){ if (INSTANCE==null){ INSTANCE= new AudioDecoder2PCM(); } } } return INSTANCE; } public void setData(byte[] bytes){ data.add(bytes); } public byte[] getData(){ return data.poll(); } public void startDecoder(String path){ try { eosReceived=false; //创建MediaExtractor对象用来解码 mExtractor = new MediaExtractor(); //添加需要解码的文件路径 mExtractor.setDataSource(path); MediaFormat format = mExtractor.getTrackFormat(0); if (format==null){ Log.e("tag","format is null"); return; } //判断当前文件类型是否是音频 String mime=format.getString(MediaFormat.KEY_MIME); if (mime.startsWith("audio/")){ Log.e("tag",mime); //获取当前音频的采样率 mExtractor.selectTrack(0); mSampleRate=format.getInteger(MediaFormat.KEY_SAMPLE_RATE); //获取当前帧的通道数 channel=format.getInteger(MediaFormat.KEY_CHANNEL_COUNT); //音频文件长度 long duration = format.getLong(MediaFormat.KEY_DURATION); } //创建MedioCodec对象 mDecoder = MediaCodec.createDecoderByType(mime); //配置Mediacodec mDecoder.configure(format,null,null,0); if (mDecoder==null){ Log.e("tag","mDecoder is null"); return; } //启动MedioCodec等待传入数据 mDecoder.start(); //启动线程 new Thread(DecoderAndPlayRunnable).start(); } catch (IOException e) { e.printStackTrace(); } } Runnable DecoderAndPlayRunnable = new Runnable() { @Override public void run() { DecoderAndPlay(); } }; private void DecoderAndPlay() { //MeiaCodec在此ByteBuffer[]中获取输入的数据 ByteBuffer[] inputBuffers = mDecoder.getInputBuffers(); //MediaCodec将解码后的数据放在ButeBuffer[]中,我们将可以直接从这里面得到pcm数据 ByteBuffer[] outputBuffers = mDecoder.getOutputBuffers(); //用于描述解码得到的byte[]数据的相关信息 MediaCodec.BufferInfo info = new MediaCodec.BufferInfo(); while (!eosReceived){ //获取可用的inputBuffer int inIndex=mDecoder.dequeueInputBuffer(-1);//一直等待 if (inIndex>=0){ ByteBuffer buffers=inputBuffers[inIndex]; //从MediaExtractor中读取一帧待解码的数据 int sampleSize=mExtractor.readSampleData(buffers,0); //小于0 代表全部读取完成 if (sampleSize<0){ mDecoder.queueInputBuffer(inIndex,0,0,0, MediaCodec.BUFFER_FLAG_END_OF_STREAM); }else { //插入一帧待解码的数据 mDecoder.queueInputBuffer(inIndex,0,sampleSize, mExtractor.getSampleTime(),0); //MediaExtractor移动到下一取样处 mExtractor.advance(); } //从mediadecoder队列取出一帧解码后的数据 参数BufferInfo上面已介绍 10000同样为等待时间 同上-1代表一直等待,0代表不等待。此处单位为微秒 //此处建议不要填-1 有些时候并没有数据输出,那么他就会一直卡在这 等待 int outIndex = mDecoder.dequeueOutputBuffer(info, 0); switch (outIndex){ case MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED: outputBuffers = mDecoder.getOutputBuffers(); break; case MediaCodec.INFO_OUTPUT_FORMAT_CHANGED: break; case MediaCodec.INFO_TRY_AGAIN_LATER: break; default: ByteBuffer outBuffer = outputBuffers[outIndex]; //BufferInfo内定义了此数据的大小 final byte[] chunk = new byte[info.size]; //将buffer中的数据取出,保存在字节数组中 outBuffer.get(chunk); //清空 outBuffer.clear(); //将解码出来的pcm数据Io流保存 setData(chunk); mDecoder.releaseOutputBuffer(outIndex,false); break; } } } mDecoder.stop(); mDecoder.release(); mDecoder=null; mExtractor.release(); mExtractor=null; } }
音频解码为PCM
最新推荐文章于 2023-12-10 15:37:42 发布