Я пытаюсь декодировать аудио на Android и получить необработанные данные для применения фильтра.
Я использую MediaExtractor
для извлечения закодированных данных из файла, и это, похоже, работает,Затем я попытался перепутать код из MediaExtractor docs плюс MediaCodec при синхронной обработке с использованием буферов для извлечения данных и их декодирования в блоках.
Итак, я сначала настроилдекодер с форматом, взятым из extractor.getTrackFormat(0);
MediaExtractor extractor = new MediaExtractor();
String path = "...";
extractor.setDataSource(path);
MediaFormat format = extractor.getTrackFormat(0);
mAudioKeyMine = format.getString(MediaFormat.KEY_MIME);
extractor.selectTrack(0);
MediaCodec decoder;
decoder = MediaCodec.createDecoderByType(mAudioKeyMine);
decoder.configure(format, null, null, 0);
А затем попытался получить данные:
public void getData(MediaExtractor extractor)
{
int offset = 0;
ByteBuffer inputBuffer = ByteBuffer.allocate(2048);
MediaFormat outputFormat = decoder.getOutputFormat();
Log.v(TAG, "outputFormat: " + outputFormat.toString());
decoder.start();
int index = decoder.dequeueInputBuffer(1000);
boolean sawInputEOS = false;
int sample = 0;
while (sample >= 0)
{
int inputBufferId = decoder.dequeueInputBuffer(1000);
if (inputBufferId >= 0)
{
inputBuffer = decoder.getInputBuffer(index);
sample = extractor.readSampleData(inputBuffer, 0);
long presentationTimeUs = 0;
if (sample < 0)
{
sawInputEOS = true;
sample = 0;
}
else
{
int trackIndex = extractor.getSampleTrackIndex();
presentationTimeUs = extractor.getSampleTime();
Log.v(TAG, "trackIndex: " + trackIndex + ", presentationTimeUs: " + presentationTimeUs);
Log.v(TAG, "sample: " + sample + ", offset: " + offset);
Log.v(TAG, "inputBuffer: " + inputBuffer.toString());
}
decoder.queueInputBuffer(inputBufferId, 0, sample, presentationTimeUs, sawInputEOS ? MediaCodec.BUFFER_FLAG_END_OF_STREAM : 0);
if (!sawInputEOS)
{
extractor.advance();
}
}
MediaCodec.BufferInfo info = new MediaCodec.BufferInfo();
int outputBufferId = decoder.dequeueOutputBuffer(info, 1000);
Log.v(TAG, "info: " + info.toString());
if (outputBufferId >= 0)
{
ByteBuffer outputBuffer = decoder.getOutputBuffer(outputBufferId);
MediaFormat bufferFormat = decoder.getOutputFormat(outputBufferId);
Log.v(TAG, "option A");
Log.v(TAG, "outputBufferId: " + outputBufferId);
if (outputBuffer != null)
{
Log.v(TAG, "outputBuffer: " + outputBuffer.toString());
}
else
{
Log.v(TAG, "outputBuffer: null");
}
Log.v(TAG, "bufferFormat: " + bufferFormat.toString());
if (outputBuffer != null)
{
int cont = 0;
while (outputBuffer.hasRemaining())
{
int pos = outputBuffer.position();
byte data = outputBuffer.get();
// do something with the data
if (cont < 10)
{
Log.v(TAG, "outputBuffer: " + pos + " -> " + data);
}
cont++;
}
}
else
{
Log.v(TAG, "outputBuffer: null");
}
decoder.releaseOutputBuffer(outputBufferId, 0);
}
else if (outputBufferId == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED)
{
Log.v(TAG, "option B");
outputFormat = decoder.getOutputFormat();
Log.v(TAG, "outputFormat: " + outputFormat.toString());
}
Log.v(TAG, "extractor.advance()");
offset += sample;
}
Log.v(TAG, "end of track");
extractor.release();
extractor = null;
decoder.stop();
decoder.release();
}
Но я получаю ошибку IllegalStateException
в строке int outputBufferId = decoder.dequeueOutputBuffer(info, 1000);
.
Я искал ошибку и как правильно декодировать m4a, но большинство решений устарело на API 21, и теперь я застрял на этой ошибке.
Так что естьПример декодирования звука для API 26/28, или, пожалуйста, кто-нибудь может объяснить, как это сделать правильно?
Весь проект размещен на GitHub .