Mplayer源码分析2
更新时间:2024-06-29 02:57:01 阅读量: 综合文库 文档下载
- mplayer源码分析推荐度:
- 相关推荐
MPlayer流程
int c_mplay_main(int argc,char* argv[]) {
**调用 AddExcept()注册异常处理函数
** initmplayer(); //初始化,创建快进和暂停的信号量 **InitTimer();初始化计时器
**mp_msg_init();初始化消息系统 **set_path_env();设置路径、环境 **ipu_image_start();ipu初始化
**mplayer_showmode(1);设置显示模式
**parse_codec_cfg(NULL);解析codec配置寄存器 **打开数据流 **分析播放树 **添加播放树列表 **初始化预填充缓存 **打开播放的文件 **创建buffer **打开数据流
**检测数据流类型(音频格式和视频格式)
**分析音频流视频流的信息(原始视频尺寸、分辨率、帧频率、码流大小) **启动相应的分离器 **分析剪辑信息
**初始化codec(多媒体数字信号编解码器) **选择打开相应的视频解码器
**初始化视频解码器,分析视频流信息 **选择打开相应的音频解码器
**初始化音频解码器、PCM,分析音频信息 **同步音频视频输出 **开始播放 }
main函数中的入口如下~
/*========================== PLAY AUDIO ============================*/ if (mpctx->sh_audio)
if (!fill_audio_out_buffers())
// at eof, all audio at least written to ao
//由mpctx->sh_audio引出,我想重点强调一下sh_audio_t结构,这是音频流头部结构~
// Stream headers: typedef struct { int aid;
demux_stream_t *ds; struct codecs_st *codec; unsigned int format;
int initialized;
float stream_delay; // number of seconds stream should be delayed (according to dwStart or similar) // output format: int sample_format; int samplerate; int samplesize; int channels;
int o_bps; // == samplerate*samplesize*channels (uncompr. bytes/sec) int i_bps; // == bitrate (compressed bytes/sec) // in buffers:
int audio_in_minsize; // max. compressed packet size (== min. in buffer size )
char* a_in_buffer; int a_in_buffer_len; int a_in_buffer_size; // decoder buffers:
int audio_out_minsize; // max. uncompressed packet size (==min. out buffsize )
char* a_buffer; int a_buffer_len; int a_buffer_size; // output buffers: char* a_out_buffer; int a_out_buffer_len; int a_out_buffer_size;
struct af_stream_s *afilter; // the audio filter stream struct ad_functions_s* ad_driver; #ifdef DYNAMIC_PLUGINS void *dec_handle; #endif
// win32-compatible codec parameters: AVIStreamHeader audio; WAVEFORMATEX* wf; // codec-specific:
void* context; // codec-specific stuff (usually HANDLE or struct pointer)
unsigned char* codecdata; // extra header data passed from demuxer to codec
int codecdata_len;
double pts; // last known pts value in output from decoder int pts_bytes; // bytes output by decoder after last known pts char* lang; // track language int default_track; } sh_audio_t;
三.step by step
1.下面我们来分析fill_audio_out_buffers()函数 static int fill_audio_out_buffers(void)
1.1查看音频驱动有多大的空间可以填充解码后的音频数据 bytes_to_write = mpctx->audio_out->get_space();
这里是查看音频驱动还有多少空闲空间(即pcm缓冲区队列的可用空间),如果有空闲的空间,就调用ao->play()
函数来填充这个buffer,并播放音频数据。(pcm缓冲区的数据会被dma自动送去播放,我们不能让pcm缓冲区为空,否则声音就没了!)这个音频驱动的buffer的大小要设置合适,太小会导致一帧图像还没播放完,buffer就已经空了,会导致音视频严重不同步;太大会导致Mplayer需要不停地解析媒体文件来填充这个音频buffer,而视频可能还来不及播放。。。
1.2 对音频流进行解码
if (decode_audio(sh_audio, playsize) < 0)
注:这里的decode_audio只是一个接口,并不是具体的解码api。这个函数从sh_audio->a_out_buffer获得至少playsize bytes的解码或过滤后的音频数据,成功返回0,失败返回-1
1.3 将解码后的音频数据进行播放
playsize = mpctx->audio_out->play(sh_audio->a_out_buffer, playsize, playflags); 注:从sh_audio->a_out_buffer中copy playsize bytes数据,注意这里一定要copy出来,因为当play调用后,这部分数据就会被覆盖了。这些数据不一定要用完,返回的值是用掉的数据长度。另外当flags|AOPLAY_FINAL_CHUNK的值是真时,说明音频文件快结束了。(play()函数把音频数据写到pcm缓冲区 。)
1.4 if (playsize > 0) {
sh_audio->a_out_buffer_len -= playsize;
memmove(sh_audio->a_out_buffer, &sh_audio->a_out_buffer[playsize], sh_audio->a_out_buffer_len);
mpctx->delay += playback_speed*playsize/(double)ao_data.bps; }
播放成功后就从sh_audio->a_out_buffer中移出这段数据,同时减去sh_audio->a_out_buffer_len的长度 .
2.刚才说了,decode_audio()函数并不是真正的解码函数,它只是提供一个接口,下面我们就来看看这个函数到底做了哪些事情.
int decode_audio(sh_audio_t *sh_audio, int minlen)
2.1 解码后的视频数据都被cut成大小相同的一个个区间~
int unitsize = sh_audio->channels * sh_audio->samplesize * 16;
2.2 如果解码器设置了audio_out_minsize,解码可以等价于 while (output_len < target_len) output_len += audio_out_minsize;
因此我们必需保证a_buffer_size大于我们需要的解码数据长度加上audio_out_minsize,所以我们最大解码长度也就有了如下的限制:(是不是有点绕口?~~)
int max_decode_len = sh_audio->a_buffer_size - sh_audio->audio_out_minsize;
2.3 如果a_out_buffer中没有我们需要的足够多的解码后数据,我们当然要继续解码撒~ 只不过我们要注意,
a_out_buffer中的数据是经过filter过滤了的(长度发生了变化),这里会有一个过滤系数,我们反方向求过滤前的数据长度,所以要除以这个系数。 while (sh_audio->a_out_buffer_len < minlen) {
int declen = (minlen - sh_audio->a_out_buffer_len) / filter_multiplier + (unitsize << 5); // some extra for possible filter buffering declen -= declen % unitsize;
if (filter_n_bytes(sh_audio, declen) < 0) return -1; }
3.我们来看看这个filter_n_bytes函数
static int filter_n_bytes(sh_audio_t *sh, int len)
3.1 还记得我们刚才说的那个最大解码长度吗? 这里是要确保不会发生解码后数据溢出。
assert(len-1 + sh->audio_out_minsize <= sh->a_buffer_size);
3.2 按需要解码更多的数据 while (sh->a_buffer_len < len) {
unsigned char *buf = sh->a_buffer + sh->a_buffer_len; int minlen = len - sh->a_buffer_len;
int maxlen = sh->a_buffer_size - sh->a_buffer_len;
//这里才是调用之前确定的音频解码器进行真正音频解码 int ret = sh->ad_driver->decode_audio(sh, buf, minlen, maxlen); if (ret <= 0) { error = -1;
len = sh->a_buffer_len; break; }
//解码之后a_buffer_len增加 sh->a_buffer_len += ret; }
3.3 在前面我们提到过过滤这个步骤,下面的图描述了整个过程 filter_output = af_play(sh->afilter, &filter_input); 注:这里实际上做的是过滤这部分的工作
------------ ---------- ------------
| | 解码 | | 过滤 | | 播放 | 未解码数据 | ----->|解码后数据| ------>| 播放的数据 | ------> | a_in_buffer| | a_buffer | |a_out_buffer| ------------ ---------- ------------
3.4 if (sh->a_out_buffer_size < sh->a_out_buffer_len + filter_output->len) 注:如果过滤后的数据长度太长,需要扩展a_out_buffer_size
3.5 将过滤后的数据从decoder buffer移除: sh->a_buffer_len -= len;
memmove(sh->a_buffer, sh->a_buffer + len, sh->a_buffer_len);
libavcodec libavformat libavutil三个文件夹来自ffmpeg的库 ;
libfaad2 libao2 liba52 libmpg2 mp3lib vidix几个文件夹是其它的三方库 ; libmpcodecs libmpdemux 文件夹中为mplayer 的 demux 和codecs。 ; 其中demux_XXX.c为处理各种不同的container.
vd_XXX.c为mplayer的内置视频解码器,ad_xxx.c是音频解码器。 vf_XXX.c 和af_XXX.c 为视,音频的各种filter。 vo_XXX.c 为解码后视频输出。
libvo 视频输出模块的 Make 文件配置部分头 libao2 音频输出模块的 Make 文件配置部分头
drivers 使用 VIDIX 技术用到的直接硬件访问驱动程序
vo_XXX.c是在libvo下
正在阅读:
Mplayer源码分析206-29
科学探究题解题策略05-09
018办理雨伞寄存、租借服务03-14
My attitude04-16
基础物理电磁学第二章07-29
路缘石安装质量评定表07-11
国际会展场馆经营管理特点12-08
- 多层物业服务方案
- (审判实务)习惯法与少数民族地区民间纠纷解决问题(孙 潋)
- 人教版新课标六年级下册语文全册教案
- 词语打卡
- photoshop实习报告
- 钢结构设计原理综合测试2
- 2014年期末练习题
- 高中数学中的逆向思维解题方法探讨
- 名师原创 全国通用2014-2015学年高二寒假作业 政治(一)Word版
- 北航《建筑结构检测鉴定与加固》在线作业三
- XX县卫生监督所工程建设项目可行性研究报告
- 小学四年级观察作文经典评语
- 浅谈110KV变电站电气一次设计-程泉焱(1)
- 安全员考试题库
- 国家电网公司变电运维管理规定(试行)
- 义务教育课程标准稿征求意见提纲
- 教学秘书面试技巧
- 钢结构工程施工组织设计
- 水利工程概论论文
- 09届九年级数学第四次模拟试卷
- 源码
- Mplayer
- 分析
- 2015-2016学年鲁教版英语七年级上学期期中教学质量检测试题word
- 软件实训心得体会
- 中草药在肉牛养殖疾病防治中的应用
- 云南农业大学2012年植保期末复习资料
- 莒南三中第89期
- 电路各章习题及答案
- 中考语文话题作文指导及范文点评:我很重要
- 黄凤丽八年级下册英语计划
- 油气田工程建设项目监理管理实施细则
- 南京工业大学过程设备设计期末试题
- 机电一体化的发展趋势
- 2017年高考新课标卷理数试题解析(解析版) - 图文
- 2018年高考浙江卷第9题(平面向量)-2018年高考数学经典题分析及针
- 2014-2019年中国莱卡布产业发展前景及供需格局预测报告
- 孔敬大学国际学院特色是什么
- 用模拟退火算法或者遗传算法解决TSP问题程序
- 作文材料的来源
- 人力师201711一级理论和技能真题试卷和答案
- 华为时间管理培训资料
- 高中生物课时提升作业(一) - 图文