madplay源代码导读
来源:互联网 发布:ps4网络nat3转nat2 编辑:程序博客网 时间:2024/06/01 10:30
1. madplay基于libmad的基础上做了一个播放器,该播放器除了目前不支持网络播放以为,其余功能都支持。如快进播放,seek播放,暂停,恢复等
int main(int argc, char *argv[]) //后续如果做二次开发的话,可以将main函数改造成普通函数,普通函数形成传入agrv[].
{
player_init(&player);
初始化player成员变量。
player.options |= PLAYER_OPTION_TTYCONTROL; 默认支持键盘按键操作
get_options(argc,argv, &player);//该函数只解析-或者—开头的选择,其他不能解析
将main函数的传入的参数,解析后并赋值给player结构体中的各个成员。
f(player.verbosity >= 0)
ver_banner(stderr);
输入标题,信息(即文件头信息)默认player.verbosity ,所以输出Verbosity信息
设置播放绝对时间
设置默认输出模块(默认为osss驱动输出,如修改改成其他默认,改makefile或者configure传入或改代码
player_run();进入播放循环中 选项中,除-或—开头的选项坐标播放文件。
player_finish()播放完毕或出错,player_run()退出,完成播放回收
}
player_run(struct player *player, int argc,char const *argv[])
入口参数:player对象这个结构体
节目个数 argc
节目链表的第一个地址:即argv
{
初始化tty setup_tty()
初始化附加数据路径 (没明白这个辅数据是什么)
setup_filters(player) (这个filter是一个链表,建立各自filter指针链表,在解码时,每解一帧后输出到驱动前都要进行filter动作,完成播放控制,如音量调节,暂停,恢复,继续播放等等)
set_gain(player, 0, 0); //设置增益参数,相当于调节音量
初始化音频
播放所有的节目play_all(player); 里面是一个大循环,循环播放所有的节目或异常退出
反初始化音频
}
play_all(struct player *player)
{
初始化节目单
如果是随机模式,则初始化随机节目单
play_one(player) 小循环,必需播完一个节目再退出来
一个节目播放完,或者被滤波打断,小循环跳出播放下一首后上一首歌 等动作。
}
如何实现播放控制:
1. run_sync 解码循环中,每解码一帧后输出前,都要进行filter动作(即decode_filter 函数的执行)。来完成是播放标志控制进而跳出循环或继续输出。
2. filter动作是一个链表,里面可能是设置音量等参数,输出其他信息,这中filter不会打断循环,循环继续讲数据送入驱动;而播放下一首,上一首,进入Mad_FLOW_Stop状态却会从循环中跳出来,并返回result=-1,返回到playall()函数进行下一首的开始播放;如果是暂停的话,就一直在改循环中continue,不会往下送数据,知道resume后才送数据,进行正常解码。
3. decode_filter 每解码一帧,完成filter动作。
4. filter_run()中完成每个filter函数动作,如:mono_filter,gain_filter,mixer_filter,fadein_filter,tty_filter等动作
5. setup_filters 就是建立一个链表,链表数据域为滤波函数指针。
6. addfilter 就是创意一个链表节点,比插入到头节点后面
7. filter_new 就是完成一一个链表节点的创建和插入动作。
8. decode_output 输出配置filter动作完成一些非中断式的特技动作(如调节音量,停止,左右声道选择,停止还是播放,实际的硬件的控制)。
如何显示播放时间:
1.在每帧输出到底层驱动是显示或者键盘按I字母时显示
show_status(&player->stats, header,0, 0);
先将实际独到time_str
mad_timer_string(timer, time_str, "%02lu:%02u:%02u",
MAD_UNITS_HOURS, 0, 0);
再完成打印
message("%s %s", time_str, label? label : stats->label);
状态标签也是在main函数出入的。详见使用方法
如何关联某种驱动的输出。
在main函数中默认为player.output.command = audio_output(0);除非通过main函数出入-o
layer->output.path = optarg;进行转码成wav等格式,否则默认送人底层驱动播放。
送入顶层驱动有有很多中,如OSS,alsa,win32等,
Config.h文件中设置默认为oss
#define AUDIO_DEFAULT audio_oss
可以根据实际情况就行更改。
如果我设备没有oss驱动,而是alsa驱动,就将宏定义改为
#define AUDIO_DEFAULT audio_alsa即可
player.output.command = audio_output(0) 返回输出模型
struct output *output =&player->output;
if(output->command(&control) == -1)
就是调用相应的音频驱动操作函数。
如oss驱动映射到
audio_oss(union audio_control *control)
如alsa驱动就映射到
int audio_alsa(union audio_control*control)
如何实现seek效果.
Stream->skip这个值通过某个线程传入,或者在filter函数中传入,每解码一帧,有一个帧头检测过程,在帧头检测过程中有一个skip动作,可以帮助我们跳过某些帧,实现seek的效果。
Pause和resume实现原理:
接受的pasue按键,读按键是就阻塞,造成底层播放流程无法开展,下一帧解码也无法开展,整个流程就冻结了。按任意非定义的键取消阻塞即可(因为已经定义键,将会走定义流程)。
enum mad_flow flow = MAD_FLOW_CONTINUE; 确保继续该解码循环,恢复播放
Stop和resume实现原理
Stop后,也是进程阻塞,但按任意非定义键重新播放
player->control = PLAYER_CONTROL_REPLAY;
flow = MAD_FLOW_STOP;
确保跳出解码这个循环,并重启播放
- madplay源代码导读
- webkit内核源代码导读
- Android源代码导读
- madplay
- Linux文件系统—源代码导读
- (莱昂氏unix源代码分析导读-1) 引子
- (莱昂氏unix源代码分析导读-26) trace
- (莱昂氏unix源代码分析导读-30) device
- (莱昂氏unix源代码分析导读-47) exec
- 导读
- 导读
- 导读
- 导读
- 导读
- UDA1341声卡驱动与madplay移植播放mp3(第三方源代码移植步骤)
- 《自己动手打造“超高精度浮点数类”》源代码简要导读
- (莱昂氏unix源代码分析导读-5) 中断与陷入初探
- (莱昂氏unix源代码分析导读-7) c语言若干问题
- 1.求两个数的最大公约数
- TreeView绑定数据库
- Git学习系列(三)版本回退和管理文件的修改及删除操作
- 打开(激活)Ubuntu的root帐号
- CDN
- madplay源代码导读
- 【python2.7】raw_input()和input()区别及用法
- java获取对象属性类型、属性名称、属性值
- 构造方法私有化---单例设计模式
- maven 发布jar到私服总失败
- linux中select函数的使用
- TotalCommand快捷键查询
- 快速排序 非递归
- Java学习之路——马士兵老师