Android, декодируйте mp3, смешайте немного аудио и закодируйте в pcm (вывод слишком быстрый)
У меня есть вопрос о Android декодировать mp3, смешать немного аудио и кодировать в M4A (AAC). Для этого я использую Jlayer для Android для декодирования mp3, аудиотрек для воспроизведения песни и MediaCodec с медиаформатом для кодирования pcm. Проблема в том, что мой вывод после того, как кодирование слишком быстрое, например: у меня должно быть 5 секундное микширование звука, но вместо этого я получил ~ 1,5 секунды. Я думаю, что я теряю где-то аудио кадры, но я не уверен в этом. Спасибо за ответ.
(выходной файл примерно на 25% быстрее, чем должно быть)
Расшифровать mp3 код:
public void decodeMP3toPCM(Resources res, int resource) throws BitstreamException, DecoderException, IOException {
InputStream inputStream = new BufferedInputStream(res.openRawResource(resource), 1152);
Bitstream bitstream = new Bitstream(inputStream);
Decoder decoder = new Decoder();
boolean done = false;
while (!done) {
Header frameHeader = bitstream.readFrame();
if (frameHeader == null) {
done = true;
} else {
SampleBuffer output = (SampleBuffer) decoder.decodeFrame(frameHeader, bitstream);
mTimeCount += frameHeader.ms_per_frame();
short[] pcm = output.getBuffer();
mDataBuffer.addFrame(mViewId, pcm);
mReadedFrames++;
mAudioTrack.write(pcm, 0, pcm.length);
}
bitstream.closeFrame();
}
inputStream.close();
}
закодировать:
public class AudioEncoder {
private MediaCodec mediaCodec;
private BufferedOutputStream outputStream;
private String mediaType = "audio/mp4a-latm";
public AudioEncoder(String filePath) throws IOException {
File f = new File(filePath);
touch(f);
try {
outputStream = new BufferedOutputStream(new FileOutputStream(f));
} catch (Exception e) {
e.printStackTrace();
}
try {
//mediaCodec = MediaCodec.createEncoderByType(mediaType);
mediaCodec = MediaCodec.createByCodecName("OMX.google.aac.encoder");
} catch (IOException e) {
e.printStackTrace();
}
mediaCodec = MediaCodec.createEncoderByType(mediaType);
final int kSampleRates[] = { 8000, 11025, 22050, 44100, 48000 };
final int kBitRates[] = { 64000, 128000 };
MediaFormat mediaFormat = MediaFormat.createAudioFormat(mediaType,kSampleRates[3],2);
mediaFormat.setInteger(MediaFormat.KEY_AAC_PROFILE, MediaCodecInfo.CodecProfileLevel.AACObjectLC);
mediaFormat.setInteger(MediaFormat.KEY_MAX_INPUT_SIZE, 4608);
mediaFormat.setInteger(MediaFormat.KEY_BIT_RATE, kBitRates[1]);
mediaCodec.configure(mediaFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
mediaCodec.start();
}
public void close() {
try {
mediaCodec.stop();
mediaCodec.release();
outputStream.flush();
outputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
}
public synchronized void offerEncoder(byte[] input) {
Log.e("synchro ", input.length + " is coming");
try {
ByteBuffer[] inputBuffers = mediaCodec.getInputBuffers();
ByteBuffer[] outputBuffers = mediaCodec.getOutputBuffers();
int inputBufferIndex = mediaCodec.dequeueInputBuffer(-1);
if (inputBufferIndex >= 0) {
ByteBuffer inputBuffer = inputBuffers[inputBufferIndex];
inputBuffer.clear();
inputBuffer.put(input);
mediaCodec.queueInputBuffer(inputBufferIndex, 0, input.length, 0, 0);
}
MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();
int outputBufferIndex = mediaCodec.dequeueOutputBuffer(bufferInfo, 0);
while (outputBufferIndex >= 0) {
int outBitsSize = bufferInfo.size;
int outPacketSize = outBitsSize + 7; // 7 is ADTS size
ByteBuffer outputBuffer = outputBuffers[outputBufferIndex];
outputBuffer.position(bufferInfo.offset);
outputBuffer.limit(bufferInfo.offset + outBitsSize);
byte[] outData = new byte[outPacketSize];
addADTStoPacket(outData, outPacketSize);
outputBuffer.get(outData, 7, outBitsSize);
outputBuffer.position(bufferInfo.offset);
outputStream.write(outData, 0, outData.length);
mediaCodec.releaseOutputBuffer(outputBufferIndex, false);
outputBufferIndex = mediaCodec.dequeueOutputBuffer(bufferInfo, 0);
}
} catch (Throwable t) {
t.printStackTrace();
}
}
private void addADTStoPacket(byte[] packet, int packetLen) {
int profile = 2; //AAC LC
//39=MediaCodecInfo.CodecProfileLevel.AACObjectELD;
int freqIdx = 4; //44.1KHz
int chanCfg = 2; //CPE
// fill in ADTS data
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 void touch(File f) {
try {
if (!f.exists())
f.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
}