首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >PCM - > AAC(编码器) - > PCM(解码器)如何实时进行正确的优化?

PCM - > AAC(编码器) - > PCM(解码器)如何实时进行正确的优化?
EN

Stack Overflow用户
提问于 2018-03-13 06:57:03
回答 6查看 0关注 0票数 0

我在努力实现

AudioRecord (MIC) ->

PCM -> AAC Encoder
AAC -> PCM Decode

-> AudioTrack??  (SPEAKER)

MediaCodec在安卓4.1+上(API 16)。

首先,我成功地实现了PCM -> AAC Encoder通过MediaCodec如下所示

private boolean setEncoder(int rate)
{
    encoder = MediaCodec.createEncoderByType("audio/mp4a-latm");
    MediaFormat format = new MediaFormat();
    format.setString(MediaFormat.KEY_MIME, "audio/mp4a-latm");
    format.setInteger(MediaFormat.KEY_CHANNEL_COUNT, 1);
    format.setInteger(MediaFormat.KEY_SAMPLE_RATE, 44100);
    format.setInteger(MediaFormat.KEY_BIT_RATE, 64 * 1024);//AAC-HE 64kbps
    format.setInteger(MediaFormat.KEY_AAC_PROFILE, MediaCodecInfo.CodecProfileLevel.AACObjectHE);
    encoder.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
    return true;
}

输入:PCM比特率=44100(Hz)x16(位)x1(单片)=705600位/秒

输出:aac-HE比特率=64x1024(位)=65536位/秒

解码器配置文件设置如下:

private boolean setDecoder(int rate)
{
    decoder = MediaCodec.createDecoderByType("audio/mp4a-latm");
    MediaFormat format = new MediaFormat();
    format.setString(MediaFormat.KEY_MIME, "audio/mp4a-latm");
    format.setInteger(MediaFormat.KEY_CHANNEL_COUNT, 1);
    format.setInteger(MediaFormat.KEY_SAMPLE_RATE, 44100);
    format.setInteger(MediaFormat.KEY_BIT_RATE, 64 * 1024);//AAC-HE 64kbps
    format.setInteger(MediaFormat.KEY_AAC_PROFILE, MediaCodecInfo.CodecProfileLevel.AACObjectHE);
    decoder.configure(format, null, null, 0);

    return true;
}

因为UDPserver数据包缓冲区大小是1024

  • UDPserver:接收1024字节由于这是压缩的aac数据,我希望解码的大小将是大约1024x11,但是实际结果是
  • 音频解码器:8192字节解码

解码器代码如下:

    IOudpPlayer = new Thread(new Runnable()
    {
        public void run()
        {
            SocketAddress sockAddress;
            String address;

            int len = 1024;
            byte[] buffer2 = new byte[len];
            DatagramPacket packet;

            byte[] data;

            ByteBuffer[] inputBuffers;
            ByteBuffer[] outputBuffers;

            ByteBuffer inputBuffer;
            ByteBuffer outputBuffer;

            MediaCodec.BufferInfo bufferInfo;
            int inputBufferIndex;
            int outputBufferIndex;
            byte[] outData;
            try
            {
                decoder.start();
                isPlaying = true;
                while (isPlaying)
                {
                    try
                    {
                        packet = new DatagramPacket(buffer2, len);
                        ds.receive(packet);

                        sockAddress = packet.getSocketAddress();
                        address = sockAddress.toString();

                        Log.d("UDP Receiver"," received !!! from " + address);

                        data = new byte[packet.getLength()];
                        System.arraycopy(packet.getData(), packet.getOffset(), data, 0, packet.getLength());

                        Log.d("UDP Receiver",  data.length + " bytes received");

                        //===========
                        inputBuffers = decoder.getInputBuffers();
                        outputBuffers = decoder.getOutputBuffers();
                        inputBufferIndex = decoder.dequeueInputBuffer(-1);
                        if (inputBufferIndex >= 0)
                        {
                            inputBuffer = inputBuffers[inputBufferIndex];
                            inputBuffer.clear();

                            inputBuffer.put(data);

                            decoder.queueInputBuffer(inputBufferIndex, 0, data.length, 0, 0);
                        }

                        bufferInfo = new MediaCodec.BufferInfo();
                        outputBufferIndex = decoder.dequeueOutputBuffer(bufferInfo, 0);

                        while (outputBufferIndex >= 0)
                        {
                            outputBuffer = outputBuffers[outputBufferIndex];

                            outputBuffer.position(bufferInfo.offset);
                            outputBuffer.limit(bufferInfo.offset + bufferInfo.size);

                            outData = new byte[bufferInfo.size];
                            outputBuffer.get(outData);

                            Log.d("AudioDecoder", outData.length + " bytes decoded");

                            decoder.releaseOutputBuffer(outputBufferIndex, false);
                            outputBufferIndex = decoder.dequeueOutputBuffer(bufferInfo, 0);

                        }



                        //===========

                    }
                    catch (IOException e)
                    {
                    }
                }

                decoder.stop();

            }
            catch (Exception e)
            {
            }
        }
    });

完整的代码:

https://gist.github.com/kenokabe/9029256

还需要得到许可:

 <uses-permission android:name="android.permission.INTERNET"></uses-permission>
 <uses-permission android:name="android.permission.RECORD_AUDIO"></uses-permission>

所以我的问题是

  1. 能正确地优化我的示例代码以使其正常工作吗?
  2. 这是一个正确的方式来使用AudioTrack API来动态播放解码的PCM原始数据,并且可以告诉我正确的方法吗?
EN

Stack Overflow用户

发布于 2018-03-13 14:13:33

我已经尝试了上面的代码,它没有正常工作。我得到了很多沉默注入解码输出。 问题没有为解码器设置适当的“csd”值。

因此,如果在日志或解码器投掷错误中看到“沉默”,请确保已将以下内容添加到媒体解码器格式

int profile = 2;  //AAC LC
int freqIdx = 11;  //8KHz
int chanCfg = 1;  //Mono

ByteBuffer csd = ByteBuffer.allocate(2);
csd.put(0, (byte) (profile << 3 | freqIdx >> 1));
csd.put(1, (byte)((freqIdx & 0x01) << 7 | chanCfg << 3));
mediaFormat.setByteBuffer("csd-0", csd);
票数 0
EN
查看全部 6 条回答
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/-100004249

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档