首页 > 解决方案 > 实施 RFC 5219(RTP 的 MPA-Robust 有效负载):如何知道他们已经阅读了整个 ADU?

问题描述

我正在尝试实现RFC 5219: A More Loss-Tolerant RTP Payload Format for MP3 Audio

我知道,对于给定的 MP3 帧,您可以通过解析“main_data_begin”反向指针并从“位存储库”(即前几帧中的音频数据)读取来识别相应 ADU 的开始位置。

但是,我无法理解,对于给定的 MP3 帧,您如何知道 ADU 何时完成?

例如,考虑以下 2 个 MP3 帧:

因此,ADU1 的长度为

Frame1.Length - Frame1.HeaderLength - 20 bytes

但是我怎么知道呢?我是否能够从 Frame1 生成 ADU1,还是必须先读取 Frame2,然后才能确定 Frame1 已完成并生成 ADU1?

请注意,RFC 5219 附录 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 位结构,它会给我一个太高而无法成为帧大小的值。

标签: parsingmp3

解决方案


最终我们在 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的解析在这里解释有点繁琐,但是在MP3Internals.cpp的getSideInfo1andgetSideInfo2方法中有很好的解释(例如,这里);


推荐阅读