Внедрение RFC 5219 (надежная полезная нагрузка MPA для RTP): как узнать, что они прочитали весь ADU? - PullRequest
0 голосов
/ 16 января 2019

Я пытаюсь реализовать RFC 5219: более терпимый к потерям формат полезной нагрузки RTP для аудио MP3 .

Я понимаю, что для данного MP3-кадра вы можете определить, где начинается соответствующий ADU, путем анализа обратного указателя "main_data_begin" и чтения из "битового резервуара" (т. Е. Аудиоданных в предыдущих нескольких кадрах).

Однако я не могу понять, как для данного кадра MP3 вы знаете, когда заканчивается ADU?

Например, рассмотрим следующие 2 кадра MP3:

  • Frame1 имеет main_data_begin = 0.
  • Frame2 имеет main_data_begin = 20

Следовательно, длина ADU1 равна

Frame1.Length - Frame1.HeaderLength - 20 bytes

Но как я могу это знать? Могу ли я сгенерировать ADU1 из Frame1, или я должен прочитать в Frame2, прежде чем я смогу определить, что Frame1 завершен и генерировать ADU1?

Обратите внимание, что в RFC 5219 Appendex A.1 имеется пример алгоритма, который содержит следующий псевдокод:

do
{
     // read a frame
}
while (totalDataSizeBefore < newFrame.backpointer ||
       totalDataSizeAfter < newFrame.aduDataSize);

но нигде он не определяет "aduDataSize" или как он рассчитывается, так что это не супер полезно ...

Единственная другая подсказка, которую я имею, - это смутное предложение, что я могу прочитать part_2_3_length из дополнительной информации, и это скажет мне, как долго ADU - однако я не могу найти действительно эффективный источник для того, как на самом деле анализировать part_2_3_length - я просто знаю, что это 12/24-битная структура, которая даст мне слишком большое значение, чтобы иметь размер кадра.

1 Ответ

0 голосов
/ 16 января 2019

В конце концов мы нашли ответ в исходном коде Live555 (в частности, MP3Internals.cpp).

По сути, вам нужно прочитать part_2_3_lengths для каждой гранулы в каждом канале, а затем вычислить их.

Грубо:

uint numBits = 0;
for (int channelIdx = 0; channelIdx < isMono ? 1 : 2; channelIdx ++)
{
    for (int granuleIdx = 0; granuleIdx < 2; granuleIdx ++)
    {
        numBits += SideInfoGranules[channelIdx][granuleIdx].Part_2_3_Length;
    }
}

// Now maths this number. I don't know where the magic constants 7 and 8 come from though.
var aduDataSize = (numBits + 7) / 8;

Синтаксический анализ part_2_3_length слишком сложен для объяснения здесь, но он хорошо объяснен в getSideInfo1 и getSideInfo2 методах MP3Internals.cpp (например, здесь );

...