Декодированный звук 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();
}