Linux中国 Linux中国门户站!
设为主页 设为主页
收藏本站 收藏本站
 
当前位置 :首页 ->Linux技术 ->Linux程序设计 ->正文

基于libmad 的简单MP3流媒体播放器的实现

来源:linux.chinaunix.net 作者:李 素科  时间:2007-04-22 点击: [收藏] [投稿]

GARD_SIZE 是一次从 socket 读取数据字节数的最大值,而解码缓冲区的大小应该是比 GARD_SIZE 大 8192 字节,因此定义 DECODE_BUF_SIZE(8192*11)recv_buf 是数据接收缓冲区,decode_buf 是数据解码缓冲区。在拷贝数据到解码缓冲区的时候,上次未解码的数据,还被保存在解码缓冲区的开始部分,故拷贝数据的时候,必须拷贝到剩余数据的后面,程序例子如下:

memcpy(decode_buf + current_remain, recv_buf, current_read);
current_read += current_remain;

这里的 current_remain 表示上次解码线程中未解码的不完整 MP3 帧的数据字节数,current_read 表示当前接收线程接收到的实际数据字节数。两个缓冲区之间的数据拷贝操作如下图所示。


图 2:缓冲区之间的数据拷贝操作
缓冲区之间的数据拷贝操作

数据接收线程和音乐播放线程之间的同步

由于使用了双缓冲区保存数据,所以,在音乐播放线程播放音乐的时候,数据接收线程不能把数据拷贝到数据解码缓冲区,而是需要等待。当数据接收缓冲区满的时候,接收线程自己也需要等待。本文用到了 POSIX 信号量处理函数,实现了线程之间的同步。它们分别是:

#include <semaphore.h>
int sem_init(sem_t *sem, int pshared, unsigned int value); 

初始化信号量,第三个参数表示初始的信号量的计数。

int sem_wait(sem_t * sem);

sem_wait 阻塞当前线程的执行,直到信号量的计数非 0;然后,它会把信号量计数减 1,然后程序继续执行。相当于 P 操作。

int sem_post(sem_t * sem);

sem 指向的信号量计数加 1。相当于 V 操作。

int sem_destroy(sem_t * sem);

释放信号量对象。

在程序中,信号量定义及初始化为:

static sem_t empty_sem;
static sem_t decode_sem;
static sem_t copy_sem;
sem_init(&empty_sem, 0, 1);
sem_init(&decode_sem, 0, 0);
sem_init(&copy_sem, 0, 1);

empty_sem 信号量的计数表示接收缓冲是否为空,其中如果是 1,表示为空;如果为 0 表示不为空。decode_sem 信号量的计数表示音乐播放线程是否正在对数据解码缓冲区的数据进行解码,如果是 1 表示正在进行解码,如果是 0 表示没有解码;copy_sem 信号量的计数表示是否可以从数据接收缓冲区拷贝数据到数据解码缓冲区,如果是 1 表示可以,如果是 0 表示不能。

两个线程的同步操作或者说是 PV 操作流程如下图所示:


图 3:PV 操作流程示意图
PV 操作流程示意图

7.程序运行实例


图 4:程序运行实例
程序运行实例

8.小结

在实现基于 libmad 的 MP3 流媒体播放器中,我们用到了 libmad 的 API、网络 socket 编程技术、在音频设备上播放 PCM 数据技术、POSIX 信号量以及 POSIX 线程。数据接收线程和音乐播放线程通过信号量和共享数据通信,相比单缓冲操作,通过双缓冲数据操作有效地提高了程序执行效率。同时,通过简单的信号量操作,线程不必使用轮询的方法来处理数据,也进一步减少了对 CPU 资源的浪费。

本文的意义在于给出了一个简单、明了的 MP3 流媒体播放器的实现。但是不足之处在于没有实现流媒体播放的控制协议,不能动态实现播放拖放操作。

原文链接:http://www.ibm.com/developerworks/cn/linux/l-cn-libmadmp3player/index.html



 如果您对本文有任何疑问或者建议,请到讨论区发表您的意见: >> 论坛入口 <<

上一页 1 2 3 4 5 6下一页


上一篇:Java 2007:新年展望   下一篇:UNIX 目标文件初探

文章评论】 【收藏本文】 【推荐好友】 【打印本文】 【我要投稿】 【论坛讨论
更多相关文章
·快速编辑Shell命令行
·从2.4到2.6内核发展中的改进
·两个很详细的shell实例
·内核设计篇
·shell技巧
·批量添加用户
·HowtoCreatingandBootingaNewKernelWithautoconf
·利用ip_conntrack表实现封ip的shell脚本,并有简
·30分钟搞定BASH脚本编程!
·Shell初学者的入门知识
推荐文章
·使用 Git 管理源代码
·GTK+与MFC不完全对比
·Linux程式设计-11.ShellScript(bash
·linux Shell编程入门 实例讲解详解
·PHP 配置模式
·Linux设备驱动编程之阻塞与非阻塞
·Apache和Subversion 搭建安全CVS
·一个 Shell 程序的性能优化
精彩文章
·DIY乐园 编写Linux系统的设备驱动程
·在 C/C++中怎么样构造通用的对象链
·深入浅出 Linux设备驱动中断处理介
·学会Linux下C语言编程--基础知识
·shell实现Unix进程间信息交换的几种
·Linux系统下C语言编程--进程的创建
·Linux操作系统的Shell编程脚本欣赏
·Linux操作系统内核编程实现调度任务
·用开源软件Subversion进行个人文档
·UNIX 目标文件初探
·Linux操作系统网桥源码框架初步分析
·Linux编程:把PHP作为Shell脚本使用
·Linux入门普及读物 解读Linux编程库
·SCO unix 系统下定时备份oracle数据
·告别无声世界 Linux声音设备编程实
·怎么样在Unix/Linux下调试脚本程序
·Linux操作系统下的汇编程序设计简介
·Linux操作系统下C语言编程的时间概
·Linux操作系统的编程环境详细介绍
·使用 Flex 和 Bison 更好地进行错误
·C 语言中的指针和内存泄漏
·一个 Shell 程序的性能优化
·Bash中对变量的操作
·Linux编程Shell基本工作原理方案
·如何在.cshrc中判断是否在loginshel
·教你提高Linux上小型数据库的速度
Power by linux-cn.com 粤ICP备05006655号