Encoding AAC Audio mit AudioRecord und MediaCodec auf Android

Ich versuche, aac Audio mit Android AudioRecord und MediaCodec zu codieren. Ich habe eine Encoder-Klasse sehr ähnlich ( Encoding H.264 von Kamera mit Android MediaCodec ) erstellt. Mit dieser Klasse habe ich eine Instanz von AudioRecord erstellt und es gemerkt, seine Byte [] Daten an den AudioEncoder (audioEncoder.offerEncoder (Data)) abzulesen.

while(isRecording) { audioRecord.read(Data, 0, Data.length); audioEncoder.offerEncoder(Data); } 

Hier ist meine Einstellung für meine AudioRecord

  • Android MediaCodec AAC Encoder
  • Wie man AAC sucht über http Stream mit Android MediaPlayer?
  • Kann nicht aufgezeichnete Audiodatei von Android in iOS 5+ abspielen
  • Korrigieren Sie wav zu AAC auf Android
  • Android - Include native StageFright-Funktionen in meinem eigenen Projekt
  • PCM zur AAC-Konvertierung mit mediacodec
  •   int audioSource = MediaRecorder.AudioSource.MIC; int sampleRateInHz = 44100; int channelConfig = AudioFormat.CHANNEL_IN_MONO; int audioFormat = AudioFormat.ENCODING_PCM_16BIT; int bufferSizeInBytes = AudioRecord.getMinBufferSize(sampleRateInHz, channelConfig, audioFormat); 

    Ich habe erfolgreich einige Byte [] Array-Daten gesammelt und in eine lokale Datei geschrieben. Leider ist die Datei nicht abspielbar. Ich habe noch mehr online gesucht und einen verwandten Beitrag gefunden ( wie man den AAC ADTS Elementary Stream mit Android MediaCodec generiert ). Also, andere, die ein ähnliches Problem haben, sagen das Hauptproblem: "Der MediaCodec Encoder erzeugt den Roh-AAC-Stream. Der rohe AAC-Stream muss in ein spielbares Format wie den ADTS-Stream konvertiert werden. Also habe ich versucht, den ADTS-Header hinzuzufügen. Trotzdem, nachdem ich den ADTS-Header hinzugefügt habe (ich habe in dem unten stehenden Code kommentiert), würde mein AudioEncoder nicht einmal die Audioausgabe schreiben. Gibt es irgendetwas, das mir fehlt? Ist mein Setup richtig?

    Irgendwelche Vorschläge, Kommentare und Meinungen sind willkommen und sehr geschätzt. danke Leute!

     import android.media.MediaCodec; import android.media.MediaCodecInfo; import android.media.MediaFormat; import android.os.Environment; import android.util.Log; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.nio.ByteBuffer; public class AudioEncoder { private MediaCodec mediaCodec; private BufferedOutputStream outputStream; private String mediaType = "audio/mp4a-latm"; public AudioEncoder() { File f = new File(Environment.getExternalStorageDirectory(), "Download/audio_encoded.aac"); touch(f); try { outputStream = new BufferedOutputStream(new FileOutputStream(f)); Log.e("AudioEncoder", "outputStream initialized"); } catch (Exception 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],1); mediaFormat.setInteger(MediaFormat.KEY_AAC_PROFILE, MediaCodecInfo.CodecProfileLevel.AACObjectLC); 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(); } } // called AudioRecord's read public synchronized void offerEncoder(byte[] input) { Log.e("AudioEncoder", 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); ////trying to add a ADTS // 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); // //// byte[] outData = new byte[bufferInfo.size]; // outputStream.write(outData, 0, outData.length); // Log.e("AudioEncoder", outData.length + " bytes written"); // // mediaCodec.releaseOutputBuffer(outputBufferIndex, false); // outputBufferIndex = mediaCodec.dequeueOutputBuffer(bufferInfo, 0); // // } //Without ADTS header while (outputBufferIndex >= 0) { ByteBuffer outputBuffer = outputBuffers[outputBufferIndex]; byte[] outData = new byte[bufferInfo.size]; outputBuffer.get(outData); outputStream.write(outData, 0, outData.length); Log.e("AudioEncoder", outData.length + " bytes written"); mediaCodec.releaseOutputBuffer(outputBufferIndex, false); outputBufferIndex = mediaCodec.dequeueOutputBuffer(bufferInfo, 0); } } catch (Throwable t) { t.printStackTrace(); } } /** * Add ADTS header at the beginning of each and every AAC packet. * This is needed as MediaCodec encoder generates a packet of raw * AAC data. * * Note the packetLen must count in the ADTS header itself. **/ 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(); } } } 

  • Meldung in Protokollen sehen: "App: Thema ist veraltet"?
  • IOS / Android: Entwerfen von App, All-Native oder PhoneGap?
  • Wie kann ich JavaScript auf Android ausführen?
  • Benutzerdefinierte Schrift für Textansicht in ArrayAdapter
  • Benutzerdefinierte Ansicht mit Layout
  • RecyclerView Mehrere Layout-View (s) in einer Adapter-Klasse
  • 2 Solutions collect form web for “Encoding AAC Audio mit AudioRecord und MediaCodec auf Android”

    Sie können Android MediaMuxer verwenden, um die von MediaCodec erstellten Rohströme in eine .mp4-Datei zu packen . Bonus: AAC-Pakete, die in einem .mp4 enthalten sind, benötigen den ADTS-Header nicht.

    Ich habe ein funktionierendes Beispiel für diese Technik auf Github .

    Überprüfen Sie hier die Methode "testEncoder", wie Sie MediaCodec als Encoder richtig verwenden können.

    Danach in deinem code,

    Ihr Eingang (Audio Recorder) ist für einen einzelnen Audiokanal konfiguriert, während Ihr Ausgang (ADTS Paketkopf) für zwei Kanäle eingestellt ist (chanCfg = 2).

    Auch wenn du deine Eingabe Samplerate (derzeit 44.1khz) ändern musst du auch freqIdx Flag im ADTS Paket Header ändern. Überprüfen Sie diesen Link auf gültige Werte.

    Und das ADTS-Header-Profil-Flag auf "AAC LC" gesetzt ist, können Sie das auch unter MediaCodecInfo.CodecProfileLevel finden . Du hast das Profil = 2 gesetzt, das ist MediaCodecInfo.CodecProfileLevel.AACObjectLC

    Das Android ist ein Google Android Fan-Website, Alles ├╝ber Android Phones, Android Wear, Android Dev und Android Spiele Apps und so weiter.