当前位置: 首页 > 知识库问答 >
问题:

当我将pcm编码为aac文件时,使用aac分析工具无法正确分析该文件

潘哲
2023-03-14

当采样率为44100时,aac字节数组可以解码,我可以发出声音,但其他字节不能正确解码。我不知道为什么?

在编码之前,我设置了MediaFormat.thecsd-0是从其他示例复制的,并且MediaFormat参数将显示。

private boolean prepare() {
    String codecName = null;
    for (int i = 0; i < MediaCodecList.getCodecCount(); i++) {
        MediaCodecInfo mediaCodecInfo = MediaCodecList.getCodecInfoAt(i);
        for (String type : mediaCodecInfo.getSupportedTypes()) {
            if (TextUtils.equals(type, MIME_TYPE)
                    && mediaCodecInfo.isEncoder()) {
                codecName = mediaCodecInfo.getName();
                break;
            }
        }
        if (null != codecName) {
            break;
        }
    }
    try {
        mBufferInfo = new MediaCodec.BufferInfo();
        mEncoder = MediaCodec.createByCodecName(codecName);
        MediaFormat mediaFormat = MediaFormat.createAudioFormat(MIME_TYPE,
                KEY_SAMPLE_RATE, KEY_CHANNEL_COUNT);
        mediaFormat.setString(MediaFormat.KEY_MIME, MediaFormat.MIMETYPE_AUDIO_AAC);
        mediaFormat.setInteger(MediaFormat.KEY_BIT_RATE, KEY_BIT_RATE);
        mediaFormat.setInteger(MediaFormat.KEY_AAC_PROFILE,
                KEY_AAC_PROFILE);
        mediaFormat.setInteger(MediaFormat.KEY_MAX_INPUT_SIZE, mFrameSize);
        byte[] data = new byte[]{(byte) 0x11, (byte) 0x90};
        ByteBuffer csd_0 = ByteBuffer.wrap(data);
        mediaFormat.setByteBuffer("csd-0", csd_0);
        mEncoder.configure(mediaFormat, null, null,
                MediaCodec.CONFIGURE_FLAG_ENCODE);
        mEncoder.start();
    } catch (IOException e) {
        e.printStackTrace();
        return false;
    }
    mBuffer = new byte[mFrameSize];
    int minBufferSize = AudioRecord.getMinBufferSize(KEY_SAMPLE_RATE, CHANNEL_IN,
            AUDIO_FORMAT);
    mRecord = new AudioRecord(MediaRecorder.AudioSource.MIC,
            KEY_SAMPLE_RATE, CHANNEL_IN, AUDIO_FORMAT, minBufferSize * 2);
    mRecord.startRecording();
    return true;
}

同时使用android MediaCodec api编码到aac。MediaCodec将调用encoderCallback进行解码。

long presentationTimeUs = 0;
    private void encode(byte[] data) {
        //api > 21
        if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP) {

            int inputBufferIndex = mEncoder.dequeueInputBuffer(-1);
            if (inputBufferIndex >= 0) {

                ByteBuffer inputBuffer = mEncoder.getInputBuffer(inputBufferIndex);
                inputBuffer.clear();

                inputBuffer.put(data);
                inputBuffer.limit(data.length);

                mEncoder.queueInputBuffer(inputBufferIndex, 0, data.length,
                        computePresentationTime(presentationTimeUs), BUFFER_FLAG_CODEC_CONFIG);
                presentationTimeUs+=1;
            }

            int outputBufferIndex = mEncoder.dequeueOutputBuffer(mBufferInfo, 0);

            while (outputBufferIndex >= 0) {

                ByteBuffer outputBuffer = mEncoder.getOutputBuffer(outputBufferIndex);

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


                int length = mBufferInfo.size + 7;
                if (mFrameByte == null || mFrameByte.length < length) {
                    mFrameByte = new byte[length];
                }
                addADTStoPacket(mFrameByte, length);

                outputBuffer.get(mFrameByte, 7, mBufferInfo.size);

                if (encoderCallback!=null){
                    encoderCallback.encode(mFrameByte);

                    mFrameByte = null;
                }
                mEncoder.releaseOutputBuffer(outputBufferIndex, false);
                outputBufferIndex = mEncoder.dequeueOutputBuffer(mBufferInfo, 0);
            }
    }

添加adts标题。

private void addADTStoPacket(byte[] packet, int packetLen) {
        int profile = KEY_AAC_PROFILE;  //AAC LC
        int freqIdx = FREQ_IDX;  //44.1KHz
        int chanCfg = CHAN_CFG;  //CPE
        packet[0] = (byte) 0xFF;
        packet[1] = (byte) 0xF9;
        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;
    }

这些是关于采样率的参数。

public interface AudioCodec {
    String MIME_TYPE = MediaFormat.MIMETYPE_AUDIO_AAC;
    int KEY_CHANNEL_COUNT = 2;
    int KEY_BIT_RATE = 64 * 1024;
    int KEY_SAMPLE_RATE = 44100;
    int CHANNEL_OUT = AudioFormat.CHANNEL_OUT_STEREO;
    int CHANNEL_IN = AudioFormat.CHANNEL_IN_STEREO;
    int KEY_AAC_PROFILE = MediaCodecInfo.CodecProfileLevel.AACObjectLC;
    int WAIT_TIME = 10000;
    int AUDIO_FORMAT = AudioFormat.ENCODING_PCM_16BIT;
    int BUFFFER_SIZE = 2048;
    int FREQ_IDX = 4;
    int CHAN_CFG = 1;
}

共有1个答案

解晟睿
2023-03-14

也许我的英语很差,所以有人听不懂我的描述。现在,我找到了AAC文件不能工作或以半速播放的原因。AAC的csd-0配置决定是否成功。

我将下面的参数设置为MediaCodec,用于编码和解码。抽样率为44100。

int KEY_CHANNEL_COUNT = 2;
int KEY_BIT_RATE = 64*1024;
int KEY_SAMPLE_RATE = 44100;
int CHANNEL_OUT = AudioFormat.CHANNEL_OUT_STEREO;
int CHANNEL_IN = AudioFormat.CHANNEL_IN_STEREO;
int KEY_AAC_PROFILE = MediaCodecInfo.CodecProfileLevel.AACObjectLC;
int WAIT_TIME = 10000;
int AUDIO_FORMAT = AudioFormat.ENCODING_PCM_16BIT;
int BUFFFER_SIZE = 2048;
int FREQ_IDX = 4;
int CHAN_CFG = 2;
byte CSD_0 = 0x12;
byte CSD_1 = (byte) 0x12;

csd-0被设置为通过MediaCodec从pcm编码aac。

byte[] data = new byte[]{CSD_0, CSD_1};
ByteBuffer csd_0 = ByteBuffer.wrap(data);
mediaFormat.setByteBuffer("csd-0", csd_0);

csd-0可根据您的采样率进行更改。例如,你的抽样率是8000。

int KEY_CHANNEL_COUNT = 1;
int KEY_SAMPLE_RATE = 8000;
int KEY_BIT_RATE = 16000;
int CHANNEL_OUT = AudioFormat.CHANNEL_OUT_STEREO;
int CHANNEL_IN = AudioFormat.CHANNEL_IN_STEREO;
int KEY_AAC_PROFILE = MediaCodecInfo.CodecProfileLevel.AACObjectLC;
int WAIT_TIME = 10000;
int AUDIO_FORMAT = AudioFormat.ENCODING_PCM_16BIT;
int BUFFFER_SIZE = 2048;
int FREQ_IDX = 11;
int CHAN_CFG = 1;
byte CSD_0 = 0x15;
byte CSD_1 = (byte) 0x88;
 类似资料:
  • 实际上,我已经使用ffmpeg本机aac编码器将一个音频文件从ac3编码到aac,但问题是该文件没有正确播放,更具体地说,我在不同的媒体播放器中播放了该文件,但大多数都是从19秒开始的,在vlc中,甚至直到我寻求超过19秒的持续时间才开始播放。 我使用的命令是:-ffmpeg-i source。mkv-Map0:a:0-c:aac音频。mp4。

  • 我正在使用MediaCodec将PCM数据转换为AAC,并使用MediaMuxer将此aac数据存储到m4a文件中。没有视频。 该文件会生成,甚至会播放。但是没有声音。如果我将aac文件导入Audacity,它不会显示任何数据。音频的长度甚至是预期的时间。我知道数据正在被编码,尽管我不确定这些数据是否被正确编码。 对pcm数据进行编码: 我已经浏览了大量示例,我所做的一切似乎都是正确的。如果我在o

  • 我尝试通过以下设置将音频编码为AAC,配置文件。 如何选择以获得输出?

  • 我正在使用Android中的一个媒体编解码器类(Jelly Bean)将PCM格式编码为AAC。该文件已编码,但没有音乐播放器能够播放该文件。我在网上找不到任何工作代码或适当的文档。 这是我的代码:

  • 我正在尝试使用使用编解码器对一些音频流进行编码。为此,我使用了google cts ExtractEncodeMust的这个实现。 对于某些aac文件,它会在编码某些帧后抛出。更准确地说,它会在第1030行抛出异常,。 我正在配置如下: 我完全不知道如何解决这个问题。任何形式的帮助都将不胜感激。 带有一些日志的堆栈跟踪: 设备:小米POCO x3 操作系统:Android10 导致溢出的示例文件信

  • 问题很简单,但我没有任何线索来解决它: 我编写一行代码来在我的Nexus 4(Android 4.4.2)上创建AAC编码器 保存在“codec”中的返回值不为空,但我在Logcat中收到一条红色错误消息: 我还尝试了另一条线: 并得到相同的错误结果。 在使用MediaCodec之前,我是否错过了任何初始化步骤?我在官方文档中没有找到有关此的任何信息。 有人遇到过这个问题吗? 实际上,我正在尝试将