alsa sample rate跟踪 <3>

来源:互联网 发布:阿尔法营创意编程 编辑:程序博客网 时间:2024/05/23 17:16

alsa sample rate跟踪 <3>

接着看。
还有一个疑问点,按照之前的分析,如果想要snd_pcm_hw_params被调用,需要调用snd_pcm_rate_open。
但是从上面列出来的函数调用关系没有调用snd_pcm_rate_open,那么这个东东是什么时候被调用的呢?
原来在函数snd_pcm_plug_hw_params中有个判断,如果client params中的参数与slave params中的不一致,将调用snd_pcm_plug_insert_plugins函数。

static int snd_pcm_plug_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t *params){ snd_pcm_plug_t *plug = pcm->private_data; snd_pcm_t *slave = plug->req_slave; snd_pcm_plug_params_t clt_params, slv_params; snd_pcm_hw_params_t sparams; int err; err = snd_pcm_plug_hw_refine_sprepare(pcm, &sparams); if (err < 0)  return err; err = snd_pcm_plug_hw_refine_schange(pcm, params, &sparams); if (err < 0)  return err; err = snd_pcm_hw_refine_soft(slave, &sparams); if (err < 0)  return err; INTERNAL(snd_pcm_hw_params_get_access)(params, &clt_params.access); INTERNAL(snd_pcm_hw_params_get_format)(params, &clt_params.format); INTERNAL(snd_pcm_hw_params_get_channels)(params, &clt_params.channels); INTERNAL(snd_pcm_hw_params_get_rate)(params, &clt_params.rate, 0); INTERNAL(snd_pcm_hw_params_get_format)(&sparams, &slv_params.format); INTERNAL(snd_pcm_hw_params_get_channels)(&sparams, &slv_params.channels); INTERNAL(snd_pcm_hw_params_get_rate)(&sparams, &slv_params.rate, 0); snd_pcm_plug_clear(pcm); if (!(clt_params.format == slv_params.format &&       clt_params.channels == slv_params.channels &&       clt_params.rate == slv_params.rate &&       !plug->ttable &&       snd_pcm_hw_params_test_access(slave, &sparams,         clt_params.access) >= 0)) {  INTERNAL(snd_pcm_hw_params_set_access_first)(slave, &sparams, &slv_params.access);  err = snd_pcm_plug_insert_plugins(pcm, &clt_params, &slv_params);  if (err < 0)   return err; } slave = plug->gen.slave; err = _snd_pcm_hw_params(slave, params); if (err < 0) {  snd_pcm_plug_clear(pcm);  return err; } snd_pcm_unlink_hw_ptr(pcm, plug->req_slave); snd_pcm_unlink_appl_ptr(pcm, plug->req_slave); snd_pcm_link_hw_ptr(pcm, slave); snd_pcm_link_appl_ptr(pcm, slave); return 0;}


 

函数snd_pcm_plug_insert_plugins中会通过一个while循环,依次调用plugin进行处理,知道client params和slave params完全一致。

static int snd_pcm_plug_insert_plugins(snd_pcm_t *pcm,           snd_pcm_plug_params_t *client,           snd_pcm_plug_params_t *slave){ snd_pcm_plug_t *plug = pcm->private_data; static int (*const funcs[])(snd_pcm_t *_pcm, snd_pcm_t **new, snd_pcm_plug_params_t *s, snd_pcm_plug_params_t *d) = {#ifdef BUILD_PCM_PLUGIN_MMAP_EMUL  snd_pcm_plug_change_mmap,#endif  snd_pcm_plug_change_format,#ifdef BUILD_PCM_PLUGIN_ROUTE  snd_pcm_plug_change_channels,#endif#ifdef BUILD_PCM_PLUGIN_RATE  snd_pcm_plug_change_rate,#endif#ifdef BUILD_PCM_PLUGIN_ROUTE  snd_pcm_plug_change_channels,#endif  snd_pcm_plug_change_format,  snd_pcm_plug_change_access }; snd_pcm_plug_params_t p = *slave; unsigned int k = 0; plug->ttable_ok = plug->ttable_last = 0; while (client->format != p.format ||        client->channels != p.channels ||        client->rate != p.rate ||        client->access != p.access) {  snd_pcm_t *new;  int err;  if (k >= sizeof(funcs)/sizeof(*funcs))   return -EINVAL;  err = funcs[k](pcm, &new, client, &p);  if (err < 0) {   snd_pcm_plug_clear(pcm);   return err;  }  if (err) {   plug->gen.slave = new;   pcm->fast_ops = new->fast_ops;   pcm->fast_op_arg = new->fast_op_arg;  }  k++; }...}


 

其中的snd_pcm_plug_change_rate函数调用了snd_pcm_rate_open函数。
函数snd_pcm_plug_insert_plugins中定义了一个snd_pcm_t指针:snd_pcm_t *new,并将其传给了snd_pcm_plug_change_rate。
snd_pcm_plug_change_rate又将new传给了snd_pcm_rate_open函数。
snd_pcm_rate_open函数中将snd_pcm_rate_ops赋值给了new的ops成员:

 pcm->ops = &snd_pcm_rate_ops;



snd_pcm_plug_insert_plugins中判断如果处理都成功,将new赋值给plug->gen.slave:

 snd_pcm_plug_t *plug = pcm->private_data;   plug->gen.slave = new;



再回到函数snd_pcm_plug_hw_params,其中在调用过snd_pcm_plug_insert_plugins之后,将plug->gen.slave赋值给了slave。
然后以slave为参数调用了函数_snd_pcm_hw_params:

 snd_pcm_plug_t *plug = pcm->private_data; slave = plug->gen.slave; err = _snd_pcm_hw_params(slave, params);



函数_snd_pcm_hw_params中会调用slave中ops的hw_params函数:

 err = pcm->ops->hw_params(pcm->op_arg, params);



 
看到这儿,发现alsa lib中通常是以pcm为媒介,在open的时候将根据需要将函数指针挂到pcm上。
后面要用的时候再调用pcm上的函数指针。
既然这样,我们就看看在前面的open流程中都往pcm上挂了哪些东东。

0 0