利用媒体codeC PCM到AAC转换 [英] PCM to AAC conversion using mediacodec

查看:160
本文介绍了利用媒体codeC PCM到AAC转换的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用的Andr​​oid(果冻豆)媒体codeC等级,符合EN code PCM格式为AAC。该文件是EN codeD,但没有音乐播放器能够播放该文件。我无法在网络上找到任何工作code或适当的文件。

这是我的code:

 公共无效doConvert()
{

    新的AsyncTask<虚空,虚空,虚空>()
    {

        @覆盖
        保护无效doInBackground(空... PARAMS)
        {
            尝试
            {
                INT codecCount =媒体codecList.get codecCount();

                的for(int i = 0; I< codecCount;我++)
                {
                    媒体codecInfo信息=媒体codecList.get codecInfoAt(我);
                    。Logger.getLogger(MainActivity.class.getSimpleName())日志(Level.INFO,info.getName());
                    对于(字符串类型:info.getSupportedTypes())
                    {
                        Logger.getLogger(MainActivity.class.getSimpleName())日志(Level.INFO,类型)。
                    }

                }

                inputfile文件=新的文件(Environment.getExternalStorageDirectory()getAbsolutePath()+/下载/ Ghajini27_Mono_8Khz.wav。);
                // inputfile文件=新的文件(sampleFD.get);
                Log.e(文件,将String.valueOf(inputFile.length()));
                的FileInputStream FIS =新的FileInputStream(INPUTFILE);
                fis.skip(44); //删除WAV头

                文件OUTPUTFILE =新的文件(Environment.getExternalStorageDirectory()getAbsolutePath()+/下载/ out.m4a。);
                如果(outputFile.exists())outputFile.delete();

                FileOutputStream中FOS =新的FileOutputStream(OUTPUTFILE);

                //的BufferedOutputStream BOS =新的BufferedOutputStream(新的FileOutputStream(OUTPUTFILE));
                媒体codeC codeC =媒体codec.createEn coderByType(音频/ MP4A-LATM);
                MediaFormat OUTPUTFORMAT = MediaFormat.createAudioFormat(音频/ MP4A-LATM,22050,1);
                outputFormat.setInteger(MediaFormat.KEY_AAC_PROFILE,媒体codecInfo codecProfileLevel.AACObjectLC。);
             // outputFormat.setInteger(MediaFormat.KEY_CHANNEL_MASK,AudioFormat.CHANNEL_CONFIGURATION_MONO);
                outputFormat.setInteger(MediaFormat.KEY_BIT_RATE,22050);
                outputFormat.setInteger(MediaFormat.KEY_CHANNEL_COUNT,1);
                //outputFormat.setLong(MediaFormat.KEY_MAX_INPUT_SIZE,inputFile.length());
                双durationInMs =(inputFile.length()/ 16000)* 1000;
                Log.e(持续时间,将String.valueOf((长)durationInMs));
                outputFormat.setLong(MediaFormat.KEY_DURATION,(长)durationInMs);


                codec.configure(OUTPUTFORMAT,NULL,NULL,媒体codec.CONFIGURE_FLAG_EN code);
                codec.start();

                ByteBuffer的[] inputBuffers = codec.getInputBuffers();
                ByteBuffer的[] OUTPUTBUFFER = codec.getOutputBuffers();

                布尔hasMoreData = TRUE;
                媒体codec.BufferInfo outBuffInfo =新BufferInfo();
                字节readBuffer [] =新的字节[48000]
                字节writeBuffer [] =新的字节[48000]

                做
                {
                   INT nextBuffer = codec.dequeueInputBuffer(5000);
                   Log.e(NextBuffer,nextInputBuffer =+ nextBuffer);

                    如果(nextBuffer> = 0)
                    {



                        ByteBuffer的INBUF = inputBuffers [nextBuffer]
                        inBuf.clear();
                        INT读取动作= fis.read(readBuffer,0,inBuf.capacity());

                        Log.e(读取动作,读=+读取动作);

                        如果(读取动作&其中; inBuf.capacity())
                        {
                            hasMoreData = FALSE;
                        }

                        inBuf.put(readBuffer,0,读取动作);

                        codec.queueInputBuffer(nextBuffer,0,读取动作,0,0 hasMoreData:媒体codec.BUFFER_FLAG_END_OF_STREAM);
                    }


                    INT outputBufferIndex = codec.dequeueOutputBuffer(outBuffInfo,3000);
                / * logger.log(Level.INFOnextOutputBuffer =+ outputBufferIndex);
                    logger.log(Level.INFO,outBuffInfo偏移=+ outBuffInfo.offset);
                    logger.log(Level.INFO,outBuffInfo大小=+ outBuffInfo.size);
                    logger.log(Level.INFO,outBuffInfo标志=+ outBuffInfo.flags); * /


                    //而(outputBufferIndex> -1)
                    // {

                        OUTPUTBUFFER [outputBufferIndex] .position(outBuffInfo.offset);
                        OUTPUTBUFFER [outputBufferIndex]获得(writeBuffer,0,outBuffInfo.size);

                        fos.write(writeBuffer,0,outBuffInfo.size);
                      // logger.log(Level.INFO,写作=+ outBuffInfo.size +字节);


                        OUTPUTBUFFER [outputBufferIndex] .clear();

                        codec.releaseOutputBuffer(outputBufferIndex,假);

                        如果(outBuffInfo.flags ==媒体codec.BUFFER_FLAG_END_OF_STREAM)
                        {
                            codec.flush();
                            codec.stop();
                            codec.release();
                            打破;
                        }

                        // outputBufferIndex = codec.dequeueOutputBuffer(outBuffInfo,1000);
                        //logger.log(Level.INFO,"nextOutputBuffer =+ outputBufferIndex);
                    //}

                }而(outBuffInfo.flags =媒体codec.BUFFER_FLAG_END_OF_STREAM!);

                fis.close();
                fos.flush();
                fos.close();



            }
            赶上(例外五)
            {
                //Logger.getLogger(MainActivity.class.getSimpleName()).log(Level.INFO,codeC错误,E);
            }

            //logger.log(Level.INFO,"Done);

            返回null;
        }

    }。执行();
}
 

解决方案

您需要选择一个容器它。我preFER ADTS。

复制的有效载荷数据到阿雷那是你的容器足够大,只需添加上你的位。所以冲刷互联网为我的解决方案后,我工作过的一些片段到位

办法fillInADTSHeader

 配置=(configParams [0]>> 3)及0x1F的;

    frequency_index =(this.configParams [0]放大器;为0x7)<< 1 | (this.configParams [1]≥大于7)及为0x1;

    channel_config =(this.configParams [1]≥→3)及0xF的;

    INT finallength = EN coded_length + 7;
    EN codedByteArray [0] =(字节)0xFF的;
    EN codedByteArray [1] =(字节)的0xf1;
    EN codedByteArray [2] =(字节)(((资料 -  1) - ;&10 6)+(frequency_index&其中; 2)+(channel_config>&→2));
    EN codedByteArray [3] =(字节)(((channel_config&安培; 0x3中)所述;&10 6)+(finallength>> 11));
    EN codedByteArray [4] =(字节)((finallength&安培; 0x7ff)>→3);
    EN codedByteArray [5] =(字节)(((finallength和7)其中;小于5)+ 0x1F的);
    EN codedByteArray [6] =(字节)0xFC有;
 

使用类似

 字节chunkADTS [] =新的字节[info.size + 7]。
            fillInADTSHeader(chunkADTS,info.size);
            outputBuffers [BR]获得(chunkADTS,7,info.size);
            buffer.pushData(chunkADTS);
 

在Shoutcast的应该扮演,等等...

I am using a media codec class in Android (Jelly Bean) to encode PCM format to AAC. The file was encoded but no music player is able to play that file. I was not able to find any working code or proper documentation on the net.

This is my code:

public void doConvert()
{

    new AsyncTask<Void, Void, Void>()
    {

        @Override
        protected Void doInBackground(Void... params) 
        {
            try
            {
                int codecCount = MediaCodecList.getCodecCount();

                for ( int i=0; i < codecCount; i++)
                {
                    MediaCodecInfo info = MediaCodecList.getCodecInfoAt(i);
                    Logger.getLogger(MainActivity.class.getSimpleName()).log(Level.INFO, info.getName());
                    for ( String type : info.getSupportedTypes() )
                    {
                        Logger.getLogger(MainActivity.class.getSimpleName()).log(Level.INFO, type);
                    }

                }

                File inputFile = new File( Environment.getExternalStorageDirectory().getAbsolutePath()+"/Download/Ghajini27_Mono_8Khz.wav");
                //File inputFile = new File( sampleFD.get);
                Log.e("File", String.valueOf(inputFile.length()));
                FileInputStream fis = new FileInputStream(inputFile);
                fis.skip(44);//remove wav header

                File outputFile = new File( Environment.getExternalStorageDirectory().getAbsolutePath()+"/Download/out.m4a");
                if ( outputFile.exists()) outputFile.delete();

                FileOutputStream fos = new FileOutputStream(outputFile);

                //BufferedOutputStream bos=new BufferedOutputStream(new FileOutputStream(outputFile));
                MediaCodec codec = MediaCodec.createEncoderByType("audio/mp4a-latm");
                MediaFormat outputFormat = MediaFormat.createAudioFormat("audio/mp4a-latm", 22050, 1);
                outputFormat.setInteger(MediaFormat.KEY_AAC_PROFILE, MediaCodecInfo.CodecProfileLevel.AACObjectLC);
             //  outputFormat.setInteger(MediaFormat.KEY_CHANNEL_MASK, AudioFormat.CHANNEL_CONFIGURATION_MONO);
                outputFormat.setInteger(MediaFormat.KEY_BIT_RATE, 22050  );
                outputFormat.setInteger(MediaFormat.KEY_CHANNEL_COUNT, 1);
                //outputFormat.setLong(MediaFormat.KEY_MAX_INPUT_SIZE, inputFile.length());
                double durationInMs = (inputFile.length()/16000)*1000;
                Log.e("duration",String.valueOf((long)durationInMs));
                outputFormat.setLong(MediaFormat.KEY_DURATION, (long)durationInMs );


                codec.configure(outputFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE );
                codec.start();

                ByteBuffer[] inputBuffers = codec.getInputBuffers();
                ByteBuffer[] outputBuffer = codec.getOutputBuffers();

                boolean hasMoreData = true;   
                MediaCodec.BufferInfo outBuffInfo = new BufferInfo();
                byte readBuffer[] = new byte[48000];
                byte writeBuffer[] = new byte[48000];

                do
                {
                   int nextBuffer = codec.dequeueInputBuffer(5000);
                   Log.e("NextBuffer","nextInputBuffer = "+nextBuffer);

                    if ( nextBuffer >= 0 )
                    {



                        ByteBuffer inBuf = inputBuffers[nextBuffer];
                        inBuf.clear();
                        int bytesRead = fis.read( readBuffer,0, inBuf.capacity() );

                        Log.e("bytesread","Read = "+bytesRead);

                        if ( bytesRead < inBuf.capacity() )
                        {
                            hasMoreData = false;
                        }

                        inBuf.put(readBuffer, 0, bytesRead);

                        codec.queueInputBuffer(nextBuffer, 0, bytesRead, 0, hasMoreData?0:MediaCodec.BUFFER_FLAG_END_OF_STREAM);
                    }


                    int outputBufferIndex = codec.dequeueOutputBuffer( outBuffInfo, 3000);
                /*    logger.log(Level.INFO,"nextOutputBuffer = "+outputBufferIndex);
                    logger.log(Level.INFO,"outBuffInfo offset = "+outBuffInfo.offset);
                    logger.log(Level.INFO,"outBuffInfo size = "+outBuffInfo.size);
                    logger.log(Level.INFO,"outBuffInfo flags = "+outBuffInfo.flags);*/


                    //while ( outputBufferIndex > -1 )
                    //{ 

                        outputBuffer[outputBufferIndex].position(outBuffInfo.offset);
                        outputBuffer[outputBufferIndex].get(writeBuffer,0,outBuffInfo.size);

                        fos.write(writeBuffer,0, outBuffInfo.size);
                      //  logger.log(Level.INFO,"Writing = "+outBuffInfo.size+" bytes");


                        outputBuffer[outputBufferIndex].clear();

                        codec.releaseOutputBuffer(outputBufferIndex, false);

                        if ( outBuffInfo.flags == MediaCodec.BUFFER_FLAG_END_OF_STREAM )
                        {
                            codec.flush();
                            codec.stop();
                            codec.release();
                            break;
                        }

                        //outputBufferIndex = codec.dequeueOutputBuffer( outBuffInfo, 1000 );
                        //logger.log(Level.INFO,"nextOutputBuffer = "+outputBufferIndex);
                    //}

                } while (outBuffInfo.flags != MediaCodec.BUFFER_FLAG_END_OF_STREAM);

                fis.close();
                fos.flush();
                fos.close();



            }
            catch ( Exception e)
            {
                //Logger.getLogger(MainActivity.class.getSimpleName()).log(Level.INFO, "Codec Error",e);
            }

            //logger.log(Level.INFO,"Done");

            return null;
        }

    }.execute();
}

解决方案

You'll need to choose a container for it. I prefer adts.

Copy the the payload data into an aray that is large enough for your container, just add on your bits. So after scouring the internet for my solution I worked some snippet into place

method 'fillInADTSHeader'

    profile =( configParams[0]>>3 )&0x1f;

    frequency_index = (this.configParams[0]&0x7) <<1 | (this.configParams[1]>>7) &0x1;

    channel_config = (this.configParams[1]>>3) &0xf;

    int finallength = encoded_length + 7;       
    ENCodedByteArray[0] = (byte) 0xff;
    ENCodedByteArray[1] = (byte) 0xf1;
    ENCodedByteArray[2] = (byte) ( ((profile - 1) << 6) + (frequency_index << 2) +(channel_config >> 2));
    ENCodedByteArray[3] = (byte) (((channel_config & 0x3) << 6) + (finallength >> 11));
    ENCodedByteArray[4] = (byte)( (finallength & 0x7ff) >> 3);
    ENCodedByteArray[5] = (byte) (((finallength & 7) << 5) + 0x1f) ;
    ENCodedByteArray[6] = (byte) 0xfc;

Using something like

            byte chunkADTS[]=new byte[info.size + 7];
            fillInADTSHeader(chunkADTS,info.size);
            outputBuffers[bR].get(chunkADTS,7,info.size);
            buffer.pushData(chunkADTS);

Should play in shoutcast, etc...

这篇关于利用媒体codeC PCM到AAC转换的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆