Codierung AAC-Audio mit AudioRecord und MediaCodec auf Android
Ich versuche zum codieren von aac-audio mit android-AudioRecord und MediaCodec. Habe ich einen encoder-Klasse sehr ähnlich (Codierung H. 264 aus der Kamera mit Android MediaCodec). Mit dieser Klasse, die ich erstellt eine Instanz von AudioRecord und sagen, es zu Lesen aus byte[] Daten zu den AudioEncoder (audioEncoder.offerEncoder(Daten)).
while(isRecording)
{
audioRecord.read(Data, 0, Data.length);
audioEncoder.offerEncoder(Data);
}
Hier ist meine Einstellung für meine AudioRecord
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);
Habe ich erfolgreich gesammelt byte [] - array-Daten und schreiben einer lokalen Datei. Leider ist die Datei nicht spielbar ist. Ich habe einige weitere online-Suche und fand einen entsprechenden post (Wie generieren Sie die AAC-ADTS-elementary-stream mit Android MediaCodec). So, andere, die mit ähnlichen problem zu sagen, das Hauptproblem ist "Der MediaCodec-encoder generiert die raw-AAC-stream. Die raw-AAC-stream konvertiert werden muss, in ein abspielbares format, wie die ADTS stream". So ich versucht, um die ADTS-header. Dennoch, nachdem ich fügte der ADTS-header(ich auskommentiert im code unten), meine AudioEncoder gar nicht schreiben, der die Ausgabe von audio-Datei.
Ist es etwas, was ich bin fehlt? Ist meine Einstellung richtig?
Vorschläge, Kommentare und Meinungen sind willkommen und sehr geschätzt. danke Jungs!
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();
}
}
}
Haben Sie jemals herausfinden? Es gibt anscheinend keine funktionierende Beispiele der Codierung von audio mit MediaCodec API-es sei denn, >= 18.
InformationsquelleAutor xiaowoo | 2013-11-07
Du musst angemeldet sein, um einen Kommentar abzugeben.
Können Sie die Android MediaMuxer Verpacken Sie die raw-streams erstellt von MediaCodec in einem .mp4-Datei. Bonus: AAC-Pakete enthalten .mp4 ist nicht erforderlich-die ADTS-header.
Habe ich eine Beispiel für diese Technik ist auf Github.
Ich habe Probleme beim konfigurieren der audio-encoder. Ich erhalte Fehler
android.media.MediaCodec$CodecException: Error 0x80001001
mit der exakt gleichen Parameter für die audio-MediaEncoder in die Lösung über. Übersehe ich hier etwas offensichtliches?InformationsquelleAutor dbro
Check "testEncoder" Methode hier, wie MediaCodec als Encoder richtig.
danach
In Ihrem code,
Ihre Eingabe(audio recorder) so konfiguriert ist, dass Sie einzelne audio-Kanal, während Ihr Ausgang(ADTS-packet-header), ist für zwei Kanäle(chanCfg = 2).
auch wenn Sie ändern Sie Ihre Eingabe mit der samplerate (derzeit 44,1 khz) Sie haben auch zu ändern freqIdx fahne in der ADTS-Paket-header. überprüfen Sie diese link gültige Werte.
Und ADTS header-Profil-Kennzeichen auf "AAC-LC", Sie können auch gefunden unter
MediaCodecInfo.CodecProfileLevel.
Sie haben Profil = 2, MediaCodecInfo.CodecProfileLevel.AACObjectLC
InformationsquelleAutor Ankit