Android MediaCodec AAC-Encoder
Ich die MediaCodec
Klasse von der Android-SDK-seit API-level 16 mit den OMX.SEC.aac.enc
encoder zum Kodieren der Audiodaten in eine Datei. Bekomme ich die audio
Eingang von der AudioRecord
Klasse. Mein Beispiel von der AudioRecord
Klasse ist so konfiguriert:
bufferSize = AudioRecord.getMinBufferSize(44100, AudioFormat.CHANNEL_IN_STEREO, AudioFormat.ENCODING_PCM_16BIT);
recorder = new AudioRecord(MediaRecorder.AudioSource.MIC, 44100, AudioFormat.CHANNEL_IN_STEREO, AudioFormat.ENCODING_DEFAULT, bufferSize);
Ich bin in der Lage zu spielen, die raw-Daten aus der AudioRecord
Instanz, also das problem nicht dort zu wohnen.
Schreibe ich die Ausgabe von der AudioRecord
Instanz zu einer ByteBuffer
- Instanz, und übergeben Sie es an einen verfügbaren input-buffer aus dem encoder. Die Ausgabe des encoders in eine Datei geschrieben werden, die auf der SD-Karte.
Diese sind die Konfigurationsparameter für meine MediaCodec
Beispiel:
codec = MediaCodec.createEncoderByType("audio/mp4a-latm");
MediaFormat format = new MediaFormat();
format.setString(MediaFormat.KEY_MIME, "audio/mp4a-latm");
format.setInteger(MediaFormat.KEY_BIT_RATE, 64 * 1024);
format.setInteger(MediaFormat.KEY_CHANNEL_COUNT, 2);
format.setInteger(MediaFormat.KEY_SAMPLE_RATE, 44100);
format.setInteger(MediaFormat.KEY_AAC_PROFILE, MediaCodecInfo.CodecProfileLevel.AACObjectHE);
codec.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
VLC sagt mir, dass es keine streams in meine aac-Datei. Der Befehl FFMPEG -i @filename@
gibt mir die folgende Fehlermeldung: Ungültige Daten gefunden, bei der Verarbeitung von input -. Keiner des Mediaplayers muss ich getestet, sind in der Lage zu spielen, meine Datei.
Warum bin ich nicht in der Lage zu spielen, meine Datei? Ich erhalte keine OpenMAX
Fehler in LogCat
und die Anwendung stürzt nicht mehr ab, wenn die Codierung. Ich schrieb ein video-encoder, der funktioniert nach dem gleichen Prinzip und es funktioniert.
Dies ist der code zum Lesen der Daten aus der AudioRecord
Beispiel zu einem buffer:
new Thread() {
public void run() {
ByteBuffer byteBuffer = ByteBuffer.allocateDirect(bufferSize);
int read = 0;
while (isRecording) {
read = recorder.read(byteBuffer, bufferSize);
if(AudioRecord.ERROR_INVALID_OPERATION != read){
encoder.add(byteBuffer);
}
}
recorder.stop();
}
}.start();
Die Funktion add aus meiner encoder kopiert den Inhalt von einem Puffer zu einem anderen:
public void add(ByteBuffer input) {
if (!isRunning)
return;
if (tmpInputBuffer == null)
tmpInputBuffer = ByteBuffer.allocate(input.capacity());
if (!tmpBufferClear)
Log.e("audio encoder", "deadline missed"); //TODO lower bit rate
synchronized (tmpInputBuffer) {
tmpInputBuffer.clear();
tmpInputBuffer.put(input);
tmpInputBuffer.notifyAll();
Log.d("audio encoder", "pushed data into tmpInputBuffer");
}
}
Dem folgenden code wird verwendet, um zu besetzen, die den Eingabepuffer des Codierers:
new Thread() {
public void run() {
while (isRunning) {
if (tmpInputBuffer == null)
continue;
synchronized (tmpInputBuffer) {
if (tmpBufferClear) {
try {
Log.d("audio encoder", "falling asleep");
tmpInputBuffer.wait(); //wait when no input is available
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
ByteBuffer[] inputBuffers = codec.getInputBuffers();
int inputBufferIndex;
do
inputBufferIndex = codec.dequeueInputBuffer(-1);
while (inputBufferIndex < 0);
ByteBuffer inputBuffer = inputBuffers[inputBufferIndex];
inputBuffer.clear();
Log.d("input buffer size", String.valueOf(inputBuffer.capacity()));
Log.d("tmp input buffer size", String.valueOf(tmpInputBuffer.capacity()));
inputBuffer.put(tmpInputBuffer.array());
tmpInputBuffer.clear();
codec.queueInputBuffer(inputBufferIndex, 0, tmpInputBuffer.capacity(), 0, 0);
tmpBufferClear = true;
Log.d("audio encoder", "added to input buffer");
}
}
}
}.start();
Schreibe ich die Ausgabe des encoders in eine lokale Datei wie dieser:
new Thread() {
public void run() {
while (isRunning) {
ByteBuffer[] outputBuffers = codec.getOutputBuffers();
MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();
int outputBufferIndex = codec.dequeueOutputBuffer(bufferInfo, -1);
while (outputBufferIndex >= 0) {
ByteBuffer outputBuffer = outputBuffers[outputBufferIndex];
byte[] outData = new byte[bufferInfo.size];
outputBuffer.get(outData);
try {
fileWriter.write(outData, 0, outData.length);
}
catch (IOException e) {
e.printStackTrace();
}
codec.releaseOutputBuffer(outputBufferIndex, false);
outputBufferIndex = codec.dequeueOutputBuffer(bufferInfo, 0);
Log.d("audio encoder", "removed from output buffer");
}
}
codec.stop();
try {
fileWriter.close();
}
catch (IOException e) {
e.printStackTrace();
}
}
}.start();
tmpBufferClear = true;
Log.d("audio encoder", "added to input buffer");
}
}
}
}.start();
InformationsquelleAutor der Frage Bas Palmer | 2013-03-07
Du musst angemeldet sein, um einen Kommentar abzugeben.
Ich denke, du verpasst die MediaMauxer Klasse. Sie benötigen Sie, wenn Sie wollen, etwas zu schreiben, bekam von MediaCodec in eine Datei zum Beispiel.
InformationsquelleAutor der Antwort Mimmo Grottoli