音频文件格式–MP3 代码走读

上一篇《音频格式–MP3格式介绍》我们大概了解了MP3的发展历程,文件结构和关键点等内容,本文我们在FFMPEG中进行代码走读,更加全面和深入的学习和掌握MP3。

FFPlay 播放

看代码之前,先尝试用FFplay进行播放一下,大概如下:

音频文件格式--MP3 代码走读

ID3v1

ID3v1 是 MP3 文件中使用的元数据标记格式。ID3v1标签的具体功能是存储有关MP3文件的元数据。播放器可以使用此元数据来显示有关文件的信息,例如标题、艺术家、专辑和曲目编号。搜索引擎还可以使用元数据来索引 MP3 文件。

ID3v1 标签存储在 MP3 文件的标头中,其长度通常为 128 字节,但也可以更短或更长。ID3v1 标签的格式有详细记录,因此可以通过软件轻松读取和写入。

ID3v1 标签并不是 MP3 文件中使用的唯一元数据标签格式。还有ID3v2标签,更加灵活,可以存储更多信息。然而,ID3v1 标签仍然受到广泛支持,并且经常在 MP3 文件中使用。

音频文件格式--MP3 代码走读

ff_mp3_demuxer

FFmpeg 使用 `ff_mp3_demuxer` 结构来解复用 MP3 文件。当 FFmpeg 遇到认为是 MP3 格式的文件时,调用 `read_probe` 函数来确定该文件是否实际上是 MP3 格式。如果文件是MP3格式,FFmpeg会调用`read_header`函数读取文件头。`read_header` 函数将返回指向 `AVFormatContext` 结构的指针,该结构包含有关文件的信息,例如文件中的流数和用于每个流的编解码器。然后 FFmpeg 将调用 read_packet 函数从文件中读取数据包。`read_packet` 函数将返回指向 `AVPacket` 结构的指针,其中包含数据包的数据。然后 FFmpeg 将解码数据包中的数据并播放该文件。

`ff_mp3_demuxer` 结构是 FFmpeg 的一个非常重要的部分。允许 FFmpeg 解复用 MP3 文件并播放这些文件。

音频文件格式--MP3 代码走读
音频文件格式--MP3 代码走读

ff_id3v1_read

ff_id3v1_read() 函数用于从音频文件中读取 ID3v1 标签。该函数将 AVFormatContext 指针作为其唯一参数。AVFormatContext 结构包含有关音频文件的信息,例如其大小、持续时间和流的数量。

ff_id3v1_read() 函数首先检查音频文件是否可搜索。如果音频文件不可搜索,则函数返回。

如果音频文件是可搜索的,则该函数会获取音频文件的大小。该函数然后查找音频文件的末尾并读取 128 字节的数据。128 字节的数据是 ID3v1 标签。

音频文件格式--MP3 代码走读

mp3_read_probe

mp3_read_probe()函数是一个用于探测文件以查看其是否为 MP3 格式的函数。该函数将指向 AVProbeData 结构的指针作为其唯一参数。AVProbeData 结构包含有关文件的信息,例如文件的大小和文件的前几个字节。

mp3_read_probe() 函数首先查找 MPEG-1 第 3 层 (MP3) 标头。MP3 标头是一个 12 字节的标头,位于每个 MP3 文件的开头。如果该函数找到 MP3 标头,就会读取文件接下来的几个字节以查看是否与 MP3 文件一致。如果接下来的几个字节与 MP3 文件一致,则函数返回一个正值。该函数返回的值表示该文件为 MP3 格式的可能性有多大,较高的值表示较高的可能性。

如果函数没有找到 MP3 文件头或者文件接下来的几个字节与 MP3 文件不一致,则函数返回一个负值,一般负值表示文件不是 MP3 格式。

mp3_read_header

mp3_read_header() 函数是一个用来读取 MP3 文件头的函数。该函数将指向 AVFormatContext 结构的指针作为其唯一参数。AVFormatContext 结构包含有关文件的信息,例如文件的大小和文件中的流数。

mp3_read_header() 函数首先读取文件的前几个字节。这些字节包含 MP3 标头。如果该函数成功读取 MP3 标头,它将读取文件的其余部分,寻找其他 MP3 标头。如果该函数找到其他 MP3 标头,它会将有关标头的信息存储在 AVFormatContext 结构中。

如果该函数未找到任何 MP3 标头,则返回负值。负值表示该文件不是 MP3 文件。

mp3_read_packet

mp3_read_packet()该函数用于从 MP3 文件读取数据包。该函数首先检查数据包的大小。如果该大小大于文件的剩余大小,则该函数将数据包的大小减小到文件的剩余大小。然后该函数调用 av_get_packet() 函数从文件中读取数据包。

音频文件格式--MP3 代码走读

mp3_seek

mp3_seek()该函数首先检查 MP3 文件是否有 Xing TOC。 如果是,该函数将使用 TOC 查找时间戳之前最接近的索引条目。 如果 MP3 文件没有 Xing TOC,则该函数使用简单的缩放算法来估计时间戳的位置。

一旦函数找到时间戳的位置,它就会调用 mp3_sync() 函数以确保位置准确。 如果 mp3_sync() 函数返回错误,则该函数返回该错误。

最后,该函数更新流的当前 DTS 并返回 0。

音频文件格式--MP3 代码走读

mp3_sync

mp3_sync()该函数首先寻找目标位置。 如果查找成功,该函数将检查接下来的几帧以查看它们是否是同步帧。 如果是,该函数返回第一个同步帧的位置。 如果不是,该函数将继续向前查找,直到找到同步帧。其中分数是衡量位置与目标位置的接近程度的指标。

音频文件格式--MP3 代码走读

该函数返回它找到的第一个同步帧的位置。 如果没有找到同步帧,该函数返回-1。

check

check()函数用于检查 MP3 文件中的位置是否是同步帧。

音频文件格式--MP3 代码走读

我是一枚爱跑步的程序猿,维护公众号和知乎专栏《MediaStack》,有兴趣可以关注,一起学习音视频知识,时不时分享实战经验。

版权声明:本文内容转自互联网,本文观点仅代表作者本人。本站仅提供信息存储空间服务,所有权归原作者所有。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至1393616908@qq.com 举报,一经查实,本站将立刻删除。

(0)

相关推荐

发表回复

登录后才能评论