2017-10-22 3 views
1

Ich bin decodieren 44100Hz Mono 64kbit AAC-LC-Sound zu PCM roh. Auf diese Weise kann ich pcm root mit AudioTrack spielen. HierDekodierte AAC-Sound zu AudioTrack Weird Sound

ist die Klasse:

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 sagt:

 
    2048 bytes decoded 

Und ich habe seltsame Klang Zeit zu Zeit. Decoding scheint okay, denke ich. Mein Meinungsproblem von der Puffergröße. Aber ich weiß nicht, was ich tun soll! Alles scheint gut zu sein.

Ich habe versucht, Puffergröße Audiospur und eingehende Daten zu ändern, aber keine Änderungen.

Irgendwelche Ideen?

Antwort

-1

Ich denke, Sie haben Decoder-Konfiguration nicht festgelegt, bevor Ihre Decodierungsmethode aufgerufen wird.

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 und playtrack als below.The decode in Gewinde in Reihenfolge durchgeführt werden() ist gleich Ihre Dekodierungsverfahren.

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(); 
     } 
Verwandte Themen