Android PCM->;AAC(编码器)——>;PCM(译码器)实时优化

Android PCM->;AAC(编码器)——>;PCM(译码器)实时优化,android,pcm,aac,android-mediacodec,audiorecord,Android,Pcm,Aac,Android Mediacodec,Audiorecord,我正在努力实现 AudioRecord (MIC) -> PCM -> AAC Encoder AAC -> PCM Decode -> AudioTrack?? (SPEAKER) 使用Android 4.1+(API16)上的MediaCodec 首先,我通过MediaCodec成功地实现了PCM->AAC编码器(但不确定是否正确优化),如下所示 private boolean setEncoder(int rate) { encoder = Medi

我正在努力实现

AudioRecord (MIC) ->

PCM -> AAC Encoder
AAC -> PCM Decode

-> AudioTrack??  (SPEAKER)
使用Android 4.1+(API16)上的
MediaCodec

首先,我通过
MediaCodec
成功地实现了
PCM->AAC编码器
(但不确定是否正确优化),如下所示

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比特率=64 x 1024(位)=65536位/s

因此,数据大小大约被压缩
x11
,我通过观察日志确认了这一点

  • 录音记录器﹕ 读取4096字节
  • 音频编码器﹕ 369字节编码
数据大小大约是压缩的
x11
,到目前为止还不错

现在,我有一个UDP服务器来接收编码数据,然后对其进行解码

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

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;
}
    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)
            {
            }
        }
    });
由于UDPserver数据包缓冲区大小为
1024

  • UDPserver﹕ 接收到1024字节
由于这是压缩的AAC数据,我希望解码的大小是

大约1024个
x11
,但实际结果是

  • 音频解码器﹕ 已解码8192字节
大约是
x8
,我感觉有点不对劲

解码器代码如下所示:

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;
}
    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)
            {
            }
        }
    });
完整代码:

还需要许可:

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

然而,结果是一样的

现在,我想,错误是:
W/SoftAAC2﹕ AAC解码器返回错误16388,替换为静默。
表示此解码器从第一个开始就完全失败。又是数据不可查找的问题。如果AAC解码器不能以这种方式处理流式数据,而只是添加一些头,那将非常令人失望。


UPDATE2:UDP接收器出错,因此进行了修改

现在,错误来了

W/SoftAAC2﹕ AAC解码器返回错误16388,替换为静默。
消失了

因此,它表明解码器至少可以正常工作

但是,这是1个周期的日志:

D/AudioRecoder﹕ 4096 bytes read
D/AudioEncoder﹕ 360 bytes encoded
D/UDP Receiver﹕ received !!! from /127.0.0.1:39000
D/UDP Receiver﹕ 360 bytes received
D/AudioDecoder﹕ 8192 bytes decoded
PCM(4096)->AACencoded(360)->UDP-AAC(360)->(应该是)PCM(8192)

最终的结果是原PCM的2倍大小,但仍有问题


所以我的问题是

  • 你能适当地优化我的示例代码以使其正常工作吗

  • 使用
    AudioTrack
    API动态播放解码后的PCM原始数据是否正确,您能告诉我正确的方法吗?欢迎使用示例代码

  • 多谢各位


    另外,我的项目目标是Android4.1+(API16),我读过API18(Android 4.3+)上的东西更简单,但出于明显的兼容性原因,不幸的是,我不得不跳过MediaMuxer等。这里…

    您的网络代码正在组合数据。你得到了369字节的压缩数据,但在接收端你得到了1024字节。这1024字节由两个完整帧和一个部分帧组成。这两个完整的帧再次解码为4096字节,总共8192字节。一旦您向解码器发送足够多的数据,剩余的部分帧可能会被解码,但您通常应该只向解码器发送整个帧


    此外,
    MediaCodec.dequeueOutputBuffer()
    不仅返回(正)缓冲区索引,还返回(负)状态代码。可能的代码之一是
    MediaCodec.INFO\u OUTPUT\u FORMAT\u CHANGED
    ,这表示您需要调用
    MediaCodec.getOutputFormat()
    ,以获取音频数据的格式。即使输入是单声道,也可能会看到编解码器输出立体声。当您发布的代码收到这些状态代码之一时,它就会跳出循环。

    自我回答,以下是我迄今为止所做的最大努力

    package com.example.app;
    
    import android.app.Activity;
    
    import android.media.AudioManager;
    import android.media.MediaCodecInfo;
    import android.media.MediaFormat;
    import android.os.Bundle;
    
    import android.media.AudioFormat;
    import android.media.AudioRecord;
    import android.media.AudioTrack;
    import android.media.MediaCodec;
    
    import android.media.MediaRecorder.AudioSource;
    
    import android.util.Log;
    
    import java.io.IOException;
    import java.net.DatagramPacket;
    import java.net.DatagramSocket;
    import java.net.InetAddress;
    import java.net.SocketAddress;
    import java.net.SocketException;
    import java.nio.ByteBuffer;
    
    public class MainActivity extends Activity
    {
        private AudioRecord recorder;
        private AudioTrack player;
    
        private MediaCodec encoder;
        private MediaCodec decoder;
    
        private short audioFormat = AudioFormat.ENCODING_PCM_16BIT;
        private short channelConfig = AudioFormat.CHANNEL_IN_MONO;
    
        private int bufferSize;
        private boolean isRecording;
        private boolean isPlaying;
    
        private Thread IOrecorder;
    
        private Thread IOudpPlayer;
    
    
        private DatagramSocket ds;
        private final int localPort = 39000;
    
        @Override
        protected void onCreate(Bundle savedInstanceState)
        {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            IOrecorder = new Thread(new Runnable()
            {
                public void run()
                {
                    int read;
                    byte[] buffer1 = new byte[bufferSize];
    
                    ByteBuffer[] inputBuffers;
                    ByteBuffer[] outputBuffers;
    
                    ByteBuffer inputBuffer;
                    ByteBuffer outputBuffer;
    
                    MediaCodec.BufferInfo bufferInfo;
                    int inputBufferIndex;
                    int outputBufferIndex;
    
                    byte[] outData;
    
                    DatagramPacket packet;
                    try
                    {
                        encoder.start();
                        recorder.startRecording();
                        isRecording = true;
                        while (isRecording)
                        {
                            read = recorder.read(buffer1, 0, bufferSize);
                           // Log.d("AudioRecoder", read + " bytes read");
                            //------------------------
    
                            inputBuffers = encoder.getInputBuffers();
                            outputBuffers = encoder.getOutputBuffers();
                            inputBufferIndex = encoder.dequeueInputBuffer(-1);
                            if (inputBufferIndex >= 0)
                            {
                                inputBuffer = inputBuffers[inputBufferIndex];
                                inputBuffer.clear();
    
                                inputBuffer.put(buffer1);
    
                                encoder.queueInputBuffer(inputBufferIndex, 0, buffer1.length, 0, 0);
                            }
    
                            bufferInfo = new MediaCodec.BufferInfo();
                            outputBufferIndex = encoder.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("AudioEncoder", outData.length + " bytes encoded");
                                //-------------
                                packet = new DatagramPacket(outData, outData.length,
                                        InetAddress.getByName("127.0.0.1"), localPort);
                                ds.send(packet);
                                //------------
    
                                encoder.releaseOutputBuffer(outputBufferIndex, false);
                                outputBufferIndex = encoder.dequeueOutputBuffer(bufferInfo, 0);
    
                            }
                            // ----------------------;
    
                        }
                        encoder.stop();
                        recorder.stop();
                    }
                    catch (Exception e)
                    {
                        e.printStackTrace();
                    }
                }
            });
    
    
    
            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
                    {
                        player.play();
                        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");
    
                                    player.write(outData, 0, outData.length);
    
                                    decoder.releaseOutputBuffer(outputBufferIndex, false);
                                    outputBufferIndex = decoder.dequeueOutputBuffer(bufferInfo, 0);
    
                                }
    
                                //===========
    
                            }
                            catch (IOException e)
                            {
                            }
                        }
    
                        decoder.stop();
                        player.stop();
    
                    }
                    catch (Exception e)
                    {
                    }
                }
            });
    
    //===========================================================
            int rate = findAudioRecord();
            if (rate != -1)
            {
                Log.v("=========media ", "ready: " + rate);
                Log.v("=========media channel ", "ready: " + channelConfig);
    
                boolean encoderReady = setEncoder(rate);
                Log.v("=========encoder ", "ready: " + encoderReady);
                if (encoderReady)
                {
                    boolean decoderReady = setDecoder(rate);
                    Log.v("=========decoder ", "ready: " + decoderReady);
                    if (decoderReady)
                    {
                        Log.d("=======bufferSize========", "" + bufferSize);
                        try
                        {
                            setPlayer(rate);
    
                            ds = new DatagramSocket(localPort);
                            IOudpPlayer.start();
    
                            IOrecorder.start();
    
                        }
                        catch (SocketException e)
                        {
                            e.printStackTrace();
                        }
    
    
                    }
    
                }
            }
        }
    
    
        protected void onDestroy()
        {
    
            recorder.release();
            player.release();
            encoder.release();
            decoder.release();
    
        }
    /*
        protected void onResume()
        {
    
            // isRecording = true;
        }
    
        protected void onPause()
        {
    
            isRecording = false;
        }
    */
    
        private int findAudioRecord()
        {
            for (int rate : new int[]{44100})
            {
                try
                {
                    Log.v("===========Attempting rate ", rate + "Hz, bits: " + audioFormat + ", channel: " + channelConfig);
                    bufferSize = AudioRecord.getMinBufferSize(rate, channelConfig, audioFormat);
    
                    if (bufferSize != AudioRecord.ERROR_BAD_VALUE)
                    {
                        // check if we can instantiate and have a success
                        recorder = new AudioRecord(AudioSource.MIC, rate, channelConfig, audioFormat, bufferSize);
    
                        if (recorder.getState() == AudioRecord.STATE_INITIALIZED)
                        {
                            Log.v("===========final rate ", rate + "Hz, bits: " + audioFormat + ", channel: " + channelConfig);
    
                            return rate;
                        }
                    }
                }
                catch (Exception e)
                {
                    Log.v("error", "" + rate);
                }
    
            }
            return -1;
        }
    
        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, rate);
            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;
        }
    
        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, rate);
            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;
        }
    
        private boolean setPlayer(int rate)
        {
            int bufferSizePlayer = AudioTrack.getMinBufferSize(rate, AudioFormat.CHANNEL_OUT_MONO, audioFormat);
            Log.d("====buffer Size player ", String.valueOf(bufferSizePlayer));
    
            player= new AudioTrack(AudioManager.STREAM_MUSIC, rate, AudioFormat.CHANNEL_OUT_MONO, audioFormat, bufferSizePlayer, AudioTrack.MODE_STREAM);
    
    
            if (player.getState() == AudioTrack.STATE_INITIALIZED)
            {
    
                return true;
            }
            else
            {
                return false;
            }
    
        }
    
    
    }
    

    在测试之后,我通过修改您的代码得出了以下结论:

     package com.example.app;
    
        import android.app.Activity;
    
        import android.media.AudioManager;
        import android.media.MediaCodecInfo;
        import android.media.MediaFormat;
        import android.os.Bundle;
    
        import android.media.AudioFormat;
        import android.media.AudioRecord;
        import android.media.AudioTrack;
        import android.media.MediaCodec;
    
        import android.media.MediaRecorder.AudioSource;
    
        import android.util.Log;
    
        import java.io.IOException;
        import java.net.DatagramPacket;
        import java.net.DatagramSocket;
        import java.net.InetAddress;
        import java.net.SocketAddress;
        import java.net.SocketException;
        import java.nio.ByteBuffer;
    
        public class MainActivity extends Activity
        {
            private AudioRecord recorder;
            private AudioTrack player;
    
            private MediaCodec encoder;
            private MediaCodec decoder;
    
            private short audioFormat = AudioFormat.ENCODING_PCM_16BIT;
            private short channelConfig = AudioFormat.CHANNEL_IN_MONO;
    
            private int bufferSize;
            private boolean isRecording;
            private boolean isPlaying;
    
            private Thread IOrecorder;
    
            private Thread IOudpPlayer;
    
    
            private DatagramSocket ds;
            private final int localPort = 39000;
    
            @Override
            protected void onCreate(Bundle savedInstanceState)
            {
                super.onCreate(savedInstanceState);
                setContentView(R.layout.activity_main);
    
                IOrecorder = new Thread(new Runnable()
                {
                    public void run()
                    {
                        int read;
                        byte[] buffer1 = new byte[bufferSize];
    
                        ByteBuffer[] inputBuffers;
                        ByteBuffer[] outputBuffers;
    
                        ByteBuffer inputBuffer;
                        ByteBuffer outputBuffer;
    
                        MediaCodec.BufferInfo bufferInfo;
                        int inputBufferIndex;
                        int outputBufferIndex;
    
                        byte[] outData;
    
                        DatagramPacket packet;
                        try
                        {
                            encoder.start();
                            recorder.startRecording();
                            isRecording = true;
                            while (isRecording)
                            {
                                read = recorder.read(buffer1, 0, bufferSize);
                               // Log.d("AudioRecoder", read + " bytes read");
                                //------------------------
    
                                inputBuffers = encoder.getInputBuffers();
                                outputBuffers = encoder.getOutputBuffers();
                                inputBufferIndex = encoder.dequeueInputBuffer(-1);
                                if (inputBufferIndex >= 0)
                                {
                                    inputBuffer = inputBuffers[inputBufferIndex];
                                    inputBuffer.clear();
    
                                    inputBuffer.put(buffer1);
    
                                    encoder.queueInputBuffer(inputBufferIndex, 0, buffer1.length, 0, 0);
                                }
    
                                bufferInfo = new MediaCodec.BufferInfo();
                                outputBufferIndex = encoder.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("AudioEncoder ", outData.length + " bytes encoded");
                                    //-------------
                                    packet = new DatagramPacket(outData, outData.length,
                                            InetAddress.getByName("127.0.0.1"), localPort);
                                    ds.send(packet);
                                    //------------
    
                                    encoder.releaseOutputBuffer(outputBufferIndex, false);
                                    outputBufferIndex = encoder.dequeueOutputBuffer(bufferInfo, 0);
    
                                }
                                // ----------------------;
    
                            }
                            encoder.stop();
                            recorder.stop();
                        }
                        catch (Exception e)
                        {
                            e.printStackTrace();
                        }
                    }
                });
    
    
    
                IOudpPlayer = new Thread(new Runnable()
                {
                    public void run()
                    {
                        SocketAddress sockAddress;
                        String address;
    
                        int len = 2048
                        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
                        {
                            player.play();
                            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");
    
                                        player.write(outData, 0, outData.length);
    
                                        decoder.releaseOutputBuffer(outputBufferIndex, false);
                                        outputBufferIndex = decoder.dequeueOutputBuffer(bufferInfo, 0..
    

    我已经用你的资源测试过了。 有几点

  • 比特率是K的自然数,但不是计算机K。 64k=64000,但不是64*1024

  • 不建议编写共享某些变量的长代码。 A.将编码器线程和解码器线程分为2个独立类。 B.数据集邮是发送方和接收方共享的,这不好

  • 枚举音频格式需要更多值。 i、 e.抽样率应从8000、11025、22050、44100中选取


  • 我尝试了上面的代码,但它没有正常工作。我在解码输出中注入了大量的静默。问题是没有为解码器设置正确的“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);
    
    int profile=2//AAC信用证
    int-freqIdx=11//8KHz
    int-chanCfg=1//单声道
    ByteBuffer csd=ByteBuffer.allocate(2);
    csd.put(0,(字节)(profile>1));
    
    csd.put(1,(字节)((freqIdx&0x01)D/audiorecord﹕ 读取4096字节 音频编码器﹕ 360字节编码 D/UDP接收机﹕ 收到!!!从/127.0.0.1:39000 D/UDP接收机﹕ 接收到360字节 音频解码器﹕ 已解码8192字节

    这是因为acc解码器始终解码到立体声通道,即使编码数据是单声道。因此,如果您的编码端设置为立体声通道,则如下所示:

    音频记录器﹕ 8192字节读取 音频编码器﹕ 360字节编码 D/UDP接收机﹕ 收到!!!从/127.0.0.1:39000 D/UDP接收机﹕ 接收到360字节
    音频解码器﹕ 8192字节解码

    我不是这方面的专家,但我会假设每个数据包中都有额外的报头信息控制数据,使得原始有效负载小于1024,因此8192可能是合理的。更有趣的是音频听起来像什么?压缩后是否可以播放?是否可以播放