Android,解码mp3,混合少量音频和编码到pcm(输出太快)

时间:2014-11-05 08:22:16

标签: java android algorithm audio mixing

我对Android解码mp3有疑问,混合少量音频并编码为m4a(aac)。为此,我使用Jlayer for android解码mp3,audiotrack播放歌曲,MediaCodec使用mediaformat编码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();
    }
}
}

0 个答案:

没有答案