Декодированный звук AAC в AudioTrack Weird Sound

Я декодирую 44100 Гц моно 64 кбит звука AAC-LC в пкм сырой. Таким образом, я могу играть в PCM сырье с AudioTrack.

Вот класс:

package com.sametaylak.cstudio.lib;

import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioTrack;
import android.media.MediaCodec;
import android.media.MediaCodecInfo;
import android.media.MediaFormat;
import android.util.Log;

import net.butterflytv.rtmp_client.RtmpClient;

import java.io.IOException;
import java.nio.ByteBuffer;

public class AudioDecoder extends Thread {
private MediaCodec decoder;
private RtmpClient client;
private AudioTrack track;

public boolean startDecoder() {
    try {
        int bufferSizePlayer = AudioTrack.getMinBufferSize(44100, AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT);
        track = new AudioTrack(AudioManager.STREAM_MUSIC, 44100, AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT, bufferSizePlayer, AudioTrack.MODE_STREAM);
        client = new RtmpClient();
        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);
        format.setInteger(MediaFormat.KEY_AAC_PROFILE, MediaCodecInfo.CodecProfileLevel.AACObjectLC);

        int profile = 2;
        int freqIdx = 4;
        int chanCfg = 1;
        ByteBuffer csd = ByteBuffer.allocate(2);
        csd.put(0, (byte) (profile << 3 | freqIdx >> 1));
        csd.put(1, (byte)((freqIdx & 0x01) << 7 | chanCfg << 3));
        format.setByteBuffer("csd-0", csd);

        decoder.configure(format, null, null, 0);
        client.open("rtmp://192.168.1.41/live/samet live=1", false);
        track.play();
        start();
        return true;
    } catch (IOException e) {
        e.printStackTrace();
    }
    return false;
}

@Override
public void run() {
    byte[] data;

    ByteBuffer[] inputBuffers;
    ByteBuffer[] outputBuffers;

    ByteBuffer inputBuffer;
    ByteBuffer outputBuffer;

    MediaCodec.BufferInfo bufferInfo;
    int inputBufferIndex;
    int outputBufferIndex;

    byte[] outData;

    decoder.start();

    try {
        for (;;) {
            data = new byte[1024];
            client.read(data, 0, data.length);

            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");
                track.write(outData, 0, outData.length);

                decoder.releaseOutputBuffer(outputBufferIndex, false);
                outputBufferIndex = decoder.dequeueOutputBuffer(bufferInfo, 0);
            }
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
  }
}

Logcat говорит:

    Декодировано 2048 байт

И время от времени я получал странные звуки. Я думаю, что декодирование нормально. Мое мнение вопрос из размера буфера. Но я не знаю, что делать! Все вроде хорошо.

Я пытался изменить размер аудиотрека в буфере и входящие данные, но без изменений.

Есть идеи?

1 ответ

Я думаю, что вы не настроили декодер до вызова метода декодирования.

public boolean prepare() {
            mBufferInfo = new MediaCodec.BufferInfo();
            //开始播放
            mPlayer = new AudioTrack(AudioManager.STREAM_MUSIC, KEY_SAMPLE_RATE, CHANNEL_OUT, AUDIO_FORMAT, BUFFFER_SIZE, AudioTrack.MODE_STREAM);
            mPlayer.play();
            try {
                mDecoder = MediaCodec.createDecoderByType(MIME_TYPE);
                MediaFormat format = new MediaFormat();
                //解码配置
                format.setString(MediaFormat.KEY_MIME, MIME_TYPE);
                format.setInteger(MediaFormat.KEY_CHANNEL_COUNT, KEY_CHANNEL_COUNT);
                format.setInteger(MediaFormat.KEY_SAMPLE_RATE, KEY_SAMPLE_RATE);
                format.setInteger(MediaFormat.KEY_BIT_RATE, KEY_BIT_RATE);
                format.setInteger(MediaFormat.KEY_IS_ADTS, 1);
                format.setInteger(MediaFormat.KEY_AAC_PROFILE, KEY_AAC_PROFILE);

                int profile = KEY_AAC_PROFILE;  //AAC LC
                int freqIdx = FREQ_IDX;  //44.1KHz
                int chanCfg = CHAN_CFG;  //CPE
                ByteBuffer csd = ByteBuffer.allocate(2);
                csd.put(0, (byte) (profile << 3 | freqIdx >> 1));
                csd.put(1, (byte)((freqIdx & 0x01) << 7 | chanCfg << 3));
                format.setByteBuffer("csd-0", csd);

                mDecoder.configure(format, null, null, 0);
            } catch (IOException e) {
                e.printStackTrace();
                return false;
            }
            if (mDecoder == null) {
                Log.e(TAG, "create mediaDecode failed");
                return false;
            }
            mDecoder.start();
            return true;
        }

Декодирование и воспроизведение должны выполняться в потоке в порядке, указанном ниже. Decode () аналогичен методу декодирования.

public void run() {
            super.run();
            if (!prepare()) {
                isRunning = false;
                Log.d(TAG, "音频解码器初始化失败");
            }
            if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
                inputBuffers = mDecoder.getInputBuffers();
                outputBuffers = mDecoder.getOutputBuffers();
            }
            while (isRunning) {
                decode();
            }
            release();
        }
Другие вопросы по тегам