MediaCodec — звук с пониженной дискретизацией от 48 Кбит / с до 44,1 Кбит / с по-прежнему воспроизводится с меньшей скоростью

#android #audio #android-mediacodec

#Android #Аудио #android-mediacodec

Вопрос:

До сих пор в моих поисках объединения видео с MediaCodec мне, наконец, удалось выполнить повторную дискретизацию звука с частотой 48 Кбит / с до 44,1 Кбит / с.

Я тестировал объединение видео вместе с двумя видео, первое из которых содержит звуковую дорожку с 2-канальным форматом 22050 Гц, а второе — звуковую дорожку с 1-канальным форматом 24000 Гц. Поскольку мой декодер выдает только 44100 Гц 2 канала необработанного звука для первого видео и 48000 Гц 2 канала необработанного звука для второго, я пересчитал ByteBuffers то, что декодер второго видео выводит с 48000 Гц до 44100 Гц, используя этот метод:

 private byte[] minorDownsamplingFrom48kTo44k(byte[] origByteArray)
{
    int origLength = origByteArray.length;
    int moddedLength = origLength * 147/160;
    //int moddedLength = 187*36;
    int delta = origLength - moddedLength;
    byte[] resultByteArray = new byte[moddedLength];
    int arrayIndex = 0;
    for(int i = 0; i < origLength; i =44)
    {
        for(int j = i; j < (i 40 > origLength ? origLength : i   40); j  )
        {
            resultByteArray[arrayIndex] = origByteArray[j];
            arrayIndex  ;
        }
        //Log.i("array_iter", i " " arrayIndex);
    }
    //smoothArray(resultByteArray, 3);
    return resultByteArray;
}
  

Однако в выходном видеофайле видео воспроизводится с меньшей скоростью при достижении второго видео с пониженной дискретизацией звуковой дорожки. Высота звука осталась прежней, а шум исчез, но звуковые сэмплы просто воспроизводятся медленнее.

Мой выходной формат на самом деле 22050 Гц 2 канала, после первого видео.

РЕДАКТИРОВАТЬ: как будто проигрыватель продолжает воспроизводить звук так, как будто у него частота дискретизации 48000 Гц, даже после того, как он уменьшен до 44100 Гц.

Мои вопросы:

  1. Как мне решить эту проблему? Потому что я не думаю, что изменение временных меток работает в этом случае. Я просто использую временные метки, предоставляемые декодером, с некоторым смещением, основанным на последней временной метке первого видео.
  2. Проблема связана с CSD-0 ByteBuffer s?
  3. Если MediaCodec есть возможность изменять битрейт видео «на лету», будет ли возможна новая функция изменения частоты дискретизации звука или количества каналов «на лету»?

Ответ №1:

Оказывается, это было так просто, как ограничение размера моих байт-буферов.

Декодер выдает 8192 байта (2048 сэмплов).

После понижающей дискретизации данные становятся 7524 байтами (1881 сэмпл) — первоначально 7526 байт, но это составляет 1881,5 сэмпла, поэтому я округлил его в меньшую сторону.

Основная ошибка заключалась в этом коде, где я должен приблизить частоту дискретизации к исходной:

 byte[] finalByteBufferContent = new byte[size / 2]; //here

for (int i = 0; i < bufferSize; i  = 2) {
    if ((i   1) * ((int) samplingFactor) > testBufferContents.length) {
        finalByteBufferContent[i] = 0;
        finalByteBufferContent[i   1] = 0;
    } else {
        finalByteBufferContent[i] = testBufferContents[i * ((int) samplingFactor)];
        finalByteBufferContent[i   1] = testBufferContents[i * ((int) samplingFactor)   1];
    }
}

bufferSize = finalByteBufferContent.length;
  

Где size ByteBuffer — длина выходного сигнала декодера и testBufferContents массив байтов, который я использую для изменения его содержимого (и тот, который был уменьшен до 7524 байт).

Длина результирующего массива байтов по-прежнему составляла 4096 байт вместо 3762 байт.

Переход new byte[size / 2] на new byte[testBufferContents.length / 2] эту проблему решен.