流媒体MP3播放器教程
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
基于libmad 的简单MP3流媒体播放器的实现.介绍
本文在Fedora 5 Linux 下实现了一个基于libmad 的mp3 流媒体播放器。此流媒体播放器可以播放基于HTTP 1.1 协议传输的MP3 流媒体数据。
基本原理是:从HTTP 服务器获得MP3 媒体信息,然后通过网络传输把MP3 数据以数据流的形式接收到MP3 流媒体播放器客户端,由客户端通过libmad 解码MP3 数据流,得到PCM 音频数据,写入音频设备,播放音乐。本文的流媒体播放器只是实现了必要的简单功能,没有考虑太多情况。比如,没有考虑实时播放控制,这样的话就不能随意选取播放点进行播放。
本文的MP3 流媒体播放器创建两个线程,使用两个缓冲区保存MP3 数据,可以一边下载数据,一边播放音乐。编译运行此MP3 流媒体播放器需要安装libmad
(/prodUCts/mad/) 以及ALSA(Advanced Linux Sound Architecture)
()相关的软件。ALSA包括4部分,分别是sound driver, sound library , sound utilities 以及tools。至少应该安装sound driver, sound library 。编译程序时连接库的选项是:-lmad -lasound -lpthread。
本文的MP3 流媒体播放器使用双缓冲区,一个是数据接收缓冲区,另一个是数据解码缓冲区。主程序结构如下图所示,图中的蓝色线表示数据流向。
图1:MP3 流媒体播放器主程序结构图
2.libmad简介
MAD (libmad)是一个开源的高精度MPEG 音频解码库,支持MPEG-1(Layer I, Layer II 和LayerIII(也就是MP3)。LIBMAD 提供24-bit 的PCM 输出,完全是定点计算,非常适合没有浮点支持的平台上使用。使用libmad 提供的一系列API,就可以非常简单地实现MP3 数据解码工作。在libmad 的源代码文件目录下的mad.h 文件中,可以看到绝大部分该库的数据结构和API 等。
本文用到的libmad 中的主要数据结构有:struct mad_stream, struct mad_synth, struct mad_frame。它们的定义如下:
清单1:libmad 中的主要数据结构
struct mad_stream {
unsigned char const *buffer; /* input bitstream buffer */ unsigned char const *bufend; /* end of buffer */
unsigned long skiplen; /* bytes to skip before next frame */
int sync; /* stream sync found */
unsigned long freerate; /* free bitrate (fixed) */ unsigned char const *this_frame; /* start of current frame */ unsigned char const *next_frame; /* start of next frame */ struct mad_bitptr ptr; /* current processing bit pointer */
struct mad_bitptr anc_ptr; /* ancillary bits pointer */ unsigned int anc_bitlen; /* number of ancillary bits */ unsigned char (*main_data)[MAD_BUFFER_MDLEN];
/* Layer III main_data() */
unsigned int md_len; /* bytes in main_data */
int options; /* decoding options (see below) */
enum mad_error error; /* error code (see above) */ };
更多内容请看流媒体播放器流媒体文件格式播放技巧专题,或
如果缓冲区最后一个MPEG 数据帧只有部分数据包括在缓冲区中,那么struct
mad_stream中的next_frame域指到不完整数据的开始地址。
∙由于缓冲区的MPEG 数据帧不一定完整,所以不完整的MPEG 帧的数据必须拷贝到下一次解码操作的缓冲区中,进行再次解码。这里我们还看到bufend指向缓冲区数据的最后地址,也就是最后一字节的地址加 1 的位置。mad_stream.bufend –
mad_stream.next_frame就是剩余的未被解码的MPEG 帧的数据的字节数量(假设此帧在缓冲区中不完整)。mad_stream的error域用来记录操作mad_stream得到的错误代码。错误代码在mad.h 中有很详细的定义。
∙清单2:错误代码在mad.h 中的详细定义
∙struct mad_synth {
∙ mad_fixed_t filter[2][2][2][16][8]; /* polyphase filterbank outputs */
∙ /* [ch][eo][peo][s][v] */
∙ unsigned int phase; /* current processing phase */
∙ struct mad_pcm pcm; /* PCM output */
∙};
mad_synth中的关键域pcm保存解码和合成后得到的PCM 数据。
清单3:mad_synth 中的关键域
struct mad_pcm {
unsigned int samplerate; /* sampling frequency (Hz) */ unsigned short channels; /* number of channels */
unsigned short length; /* number of samples per channel */
mad_fixed_t samples[2][1152]; /* PCM output samples
[ch][sample] */
};
struct mad_pcm定义了音频的采样率、每个声道个数以及最后的PCM 采样数据。这些参数可用来初始化音频设备。
清单4:struct mad_pcm
struct mad_frame {
struct mad_header header; /* MPEG audio header */ int options; /* decoding options (from stream) */
mad_fixed_t sbsample[2][36][32]; /* synthesis subband filter samples */
mad_fixed_t (*overlap)[2][32][18]; /* Layer III block overlap data */
};