Подтвердить что ты не робот

Декодирование AAC с использованием MediaCodec API на Android

Я пытаюсь использовать API MediaCodec на Android для декодирования потока AAC. (Это необработанный AAC.) Я попытался использовать MediaFormat.createAudioFormat(), чтобы создать объект формата для передачи в MediaCodec.configure(), но я продолжал получать ошибки при использовании AAC (audio/mp4a-latm). (Он работает с MP3 (аудио/mpeg), хотя...)

Наконец, я создал MediaExtractor для файла AAC и посмотрел на объект формата, который он создавал. Я видел, что он включал ключ "csd-0" для ByteBuffer, состоящий из двух байтов как со значением 0x12. Если я включу этот ключ и значение в объект формата, который я использовал для настройки кодека AAC, все работает.

Кто-нибудь есть идея, что происходит? В документации указано, что я не должен настраивать этот ключ. Кто-нибудь имеет указатель на примеры MediaCodec для декодирования файлов AAC без использования MediaExtractor для создания объекта формата?

4b9b3361

Ответ 1

Да, конфигурация кодека 2 байта - это начальное значение, которое вы получаете. И да, это необработанные блоки данных aac. Вы можете увидеть, как я получаю формат ниже при кодировании. Сначала я попытался выполнить документацию, в которой говорилось, что они находятся в широтном формате, и попытался разобрать это. Затем я нашел некоторую "diff" в документации по Android, в которой говорилось, что выход действительно был сырым блоками. Зная, что тогда это просто вопрос выбора контейнера для моих нужд. В частности, мне нужен контейнер adts, а не flv или mp4.

Копирование данных полезной нагрузки в массив, достаточно большой для вашего контейнера, просто добавьте свои биты. Поэтому после очистки Интернета для моего решения я подготовил следующий код:

profile = (configParams[0]>>3)&0x1f;

frequency_index = (this.configParams[0]&0x7) <<1 | (this.configParams[1]>>7) &0x1;

channel_config = (this.configParams[1]>>3) &0xf;

int finallength = encoded_length + 7;       
ENCodedByteArray[0] = (byte) 0xff;
ENCodedByteArray[1] = (byte) 0xf1;
ENCodedByteArray[2] = (byte) ( ((profile - 1) << 6) + (frequency_index << 2) +(channel_config >> 2));
ENCodedByteArray[3] = (byte) (((channel_config & 0x3) << 6) + (finallength >> 11));
ENCodedByteArray[4] = (byte)( (finallength & 0x7ff) >> 3);
ENCodedByteArray[5] = (byte) (((finallength & 7) << 5) + 0x1f) ;
ENCodedByteArray[6] = (byte) 0xfc;

Используя что-то вроде этого:

byte chunkADTS[]=new byte[info.size + 7];
fillInADTSHeader(chunkADTS,info.size);
outputBuffers[bR].get(chunkADTS,7,info.size);
buffer.pushData(chunkADTS);

Ответ 2

Я использовал следующий код и добавил ES, который удалил заголовок ADTS, он мог бы работать хорошо, но я действительно не знаю, почему нужно устанавливать "csd-0", или будет происходить ошибка кодека

      decoder = MediaCodec.createDecoderByType("audio/mp4a-latm");
      mMediaFormat = MediaFormat.createAudioFormat("audio/mp4a-latm", 44100,2);
      byte[] bytes = new byte[]{(byte) 0x12, (byte)0x12};
      ByteBuffer bb = ByteBuffer.wrap(bytes);
      mMediaFormat.setByteBuffer("csd-0", bb);

Ответ 3

У меня не было проблем с декодированием/воспроизведением содержимого AAC на нескольких проверенных мной устройствах. Мой подход состоял в том, чтобы сначала использовать MediaExtractor для установки источника данных, затем инициализировать MediaFormat и, наконец, выполнить работу в цикле с буферами, отправленными в/из MediaCodec. Для поверхности я использовал null, так как это просто аудиоплеер, поэтому ничего не видно.

Я также собрал образец кода в виде библиотеки Android, который доступен в моем блоге: http://www.pocketmagic.net/2014/06/android-audio-player-using-mediacodec-mediaextractor/