1. 前言
折腾了也有差不多一个来月,之前没怎么上手过linux下的C,很多东西都是想当然的状态就开始东看看西敲敲了。这篇本章意在让一个小白学会做一个流媒体播放器。我最开始就是个小白。
2. 准备工作
2.1 系统环境
系统环境: ubuntu 12.04
编辑器: code::blocks
2.2 相关库
libmad: mp3解码库 下载地址: libmad-0.15.1b.tar.gz
alsa-lib: 用户空间的声卡接口(不知道这么描述对不对,其实ubuntu里alsa声卡驱动已经有了,这个库则是提供一个可使用的API)。下载地址: alsa-lib-1.0.25.tar.bz2
关于libmad和alsa的详细介绍建议搜搜看下。
2.2 库的安装
一般步骤
解压 - 进入解压目录,然后
./configure
make
sudo make instal
在make libmad的时候,由于gcc版本问题,可能编译不过,打开跟目录下的Makefile去掉里面出现的"-fforce-mem"即可解决。
3. 总体设计
3.1 概述
大致思想有接触过socket编程应该很明了,问题在于如何边接收mp3数据边播放。
有兴趣可以看一下下面几篇文章,我也是看了这几篇文章才知道怎么做的。
关于文中提到的minimad.c文件在编译完的libmad库里面就有,看懂这个程序对之后工作的开展有很大益处。
3.2 需求分析
这个程序是别人的课程设计,我拿来练练手。
主要需求有以下几个点:
1. Mp3文件以帧为单位进行发送,数据包格式可参照RTP。
2. 可手动建立多条socket进行传输,socket的传输率从10%~100%可自动以。eg. 传输率为80%的socket,每10个包中发送8个包,另2个包丢弃。
3. 接收端有一个适当大小的缓存,讲包按顺序排满后即可播放,缺失的包需要打印出来。eg. 缓存[1,2,3,5,6]已排满,进行播放,缺少序号为4的包,打印提示。
4. 可双向播放。
3.3 核心问题
1. Mp3文件的分割,打包以及传输。
2. BSD socket的创建和传输。
3. 数据包的重组及播放。
4. 合理的创建、删除线程。
5. 线程同步
我这篇文章想写的是1和3,其他的打算另外写文章来自我总结。
3.3 问题分析
3.3.1 MP3的文件格式
想要分割和重组MP3自然需要了解其文件格式
首先,MP3文件格式解析 已经讲得很细致了。
然后再画个图吧。
关于ID3V2,虚线之间的部分为一个标签帧,一个IDV3V2可以有多个标签帧。标签帧记录着专辑名称,专辑封面,歌手信息等等。
3.3.2 ID3V2头的解析。
实际上我并不需要解析出所有数据,我只想将ID3V2的信息跳过,知道哪里是MP3帧数据(也就是声音数据主体内容)的开始,然后分隔出每个帧进行打包就好了。
当然以学习的心态还是写了简单的解析代码,标签帧就没有解析了,利用Size[4]记录的标签大小直接跳过。
关于标签大小的计算,如果看了3.3.1链接里的那篇文章应该就会明白了。这里将公式再写一下。
total_size = (Size[0]&0x7F)*0x200000 + (Size[1]&0x7F)*0x400 + (Size[2]&0x7F)*0x80 + (Size[3]&0x7F)
将每一位的最高位舍弃,只取低七位,然后带入公式进行计算。
3.3.2 Frame Header的解析
这个部分就按照结构体头部的格式细心的进行位操作即可。刚开始写的时候自己给自己开了不少玩笑,一个字节的高位低位愣是搞了半天才搞清楚。
解析完头部,一帧的大小就可以比对着下表进行计算。
表1 MP3 帧头字节说明表
名称
|
位长
|
说
明
|
||||||||||||||
同步信息 | 11 | 第1、2字节 | 所有位均为1,第1字节恒为FF。 | |||||||||||||
版本 | 2 | 00-MPEG 2.5 01-未定义 10-MPEG 2 11-MPEG 1 | ||||||||||||||
层 | 2 | 00-未定义 01-Layer 3 10-Layer 2 11-Layer 1 | ||||||||||||||
CRC校验 | 1 | 0-校验 1-不校验 | ||||||||||||||
位率 | 4 | 第3字节 |
取样率,单位是
kbps
,例如采用
MPEG-1 Layer 3
,
64kbps
是,值为
0101
。
|