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

  • Korrigieren Sie wav zu AAC auf Android
  • PCM zur AAC-Konvertierung mit mediacodec
  • Stream und Play .m4a Stream (Itunes Vorschau Url) in Android
  • Streaming AAC Audio mit Android
  • Decodierung von AAC mit MediaCodec API auf Android
  • Android MediaCodec AAC Encoder
  •   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(); } } } 

  • Wie man LinearLayout in der Mitte seines Elternteils ausrichtet?
  • ADT 22.3 (android 4.4) - Fehler bekommen "Nach der Szenenerstellung muss #init ()"
  • Nicht in der Lage, App auf Android-Gerät zu debuggen - Android Studio 2.0
  • Kamera Fehler 100
  • Ausnahme - Fehler beim Auflösen des Attributs bei Index 6: TypedValue
  • Android-In-App-Kauf-Flow gebrochen
  • 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.