📄 ao_alsa.c
字号:
IEC958_AES1_CON_PCM_CODER; s[2] = 0; s[3] = IEC958_AES3_CON_FS_48000; snprintf(alsa_device, ALSA_DEVICE_SIZE, "iec958:{CARD 0 AES0 0x%02x AES1 0x%02x AES2 0x%02x AES3 0x%02x}", s[0], s[1], s[2], s[3]); device.str = alsa_device; mp_msg(MSGT_AO,MSGL_V,"alsa-spdif-init: playing AC3, %i channels\n", channels); } else /* in any case for multichannel playback we should select * appropriate device */ switch (channels) { case 1: case 2: device.str = "default"; mp_msg(MSGT_AO,MSGL_V,"alsa-init: setup for 1/2 channel(s)\n"); break; case 4: if (alsa_format == SND_PCM_FORMAT_FLOAT_LE) // hack - use the converter plugin device.str = "plug:surround40"; else device.str = "surround40"; mp_msg(MSGT_AO,MSGL_V,"alsa-init: device set to surround40\n"); break; case 6: if (alsa_format == SND_PCM_FORMAT_FLOAT_LE) device.str = "plug:surround51"; else device.str = "surround51"; mp_msg(MSGT_AO,MSGL_V,"alsa-init: device set to surround51\n"); break; default: device.str = "default"; mp_msg(MSGT_AO,MSGL_ERR,"alsa-init: %d channels are not supported\n",channels); } device.len = strlen(device.str); if (subopt_parse(ao_subdevice, subopts) != 0) { print_help(); return 0; } ao_noblock = !block; parse_device(alsa_device, device.str, device.len); mp_msg(MSGT_AO,MSGL_INFO,"alsa-init: %d soundcard%s found, using: %s\n", cards+1,(cards >= 0) ? "" : "s", alsa_device); //setting modes for block or nonblock-mode if (ao_noblock) { open_mode = SND_PCM_NONBLOCK; set_block_mode = 1; str_block_mode = "nonblock-mode"; } else { open_mode = 0; set_block_mode = 0; str_block_mode = "block-mode"; } //sets buff/chunksize if its set manually if (ao_data.buffersize) { switch (ao_data.buffersize) { case 1: alsa_fragcount = 16; chunk_size = 512; mp_msg(MSGT_AO,MSGL_V,"alsa-init: buffersize set manually to 8192\n"); mp_msg(MSGT_AO,MSGL_V,"alsa-init: chunksize set manually to 512\n"); break; case 2: alsa_fragcount = 8; chunk_size = 1024; mp_msg(MSGT_AO,MSGL_V,"alsa-init: buffersize set manually to 8192\n"); mp_msg(MSGT_AO,MSGL_V,"alsa-init: chunksize set manually to 1024\n"); break; case 3: alsa_fragcount = 32; chunk_size = 512; mp_msg(MSGT_AO,MSGL_V,"alsa-init: buffersize set manually to 16384\n"); mp_msg(MSGT_AO,MSGL_V,"alsa-init: chunksize set manually to 512\n"); break; case 4: alsa_fragcount = 16; chunk_size = 1024; mp_msg(MSGT_AO,MSGL_V,"alsa-init: buffersize set manually to 16384\n"); mp_msg(MSGT_AO,MSGL_V,"alsa-init: chunksize set manually to 1024\n"); break; default: alsa_fragcount = 16; if (ao_mmap) chunk_size = 512; else chunk_size = 1024; break; } } if (!alsa_handler) { //modes = 0, SND_PCM_NONBLOCK, SND_PCM_ASYNC if ((err = snd_pcm_open(&alsa_handler, alsa_device, SND_PCM_STREAM_PLAYBACK, open_mode)) < 0) { if (err != -EBUSY && ao_noblock) { mp_msg(MSGT_AO,MSGL_INFO,"alsa-init: open in nonblock-mode failed, trying to open in block-mode\n"); if ((err = snd_pcm_open(&alsa_handler, alsa_device, SND_PCM_STREAM_PLAYBACK, 0)) < 0) { mp_msg(MSGT_AO,MSGL_ERR,"alsa-init: playback open error: %s\n", snd_strerror(err)); return(0); } else { set_block_mode = 0; str_block_mode = "block-mode"; } } else { mp_msg(MSGT_AO,MSGL_ERR,"alsa-init: playback open error: %s\n", snd_strerror(err)); return(0); } } if ((err = snd_pcm_nonblock(alsa_handler, set_block_mode)) < 0) { mp_msg(MSGT_AO,MSGL_ERR,"alsa-init: error set block-mode %s\n", snd_strerror(err)); } else { mp_msg(MSGT_AO,MSGL_V,"alsa-init: pcm opend in %s\n", str_block_mode); } snd_pcm_hw_params_alloca(&alsa_hwparams); snd_pcm_sw_params_alloca(&alsa_swparams); // setting hw-parameters if ((err = snd_pcm_hw_params_any(alsa_handler, alsa_hwparams)) < 0) { mp_msg(MSGT_AO,MSGL_ERR,"alsa-init: unable to get initial parameters: %s\n", snd_strerror(err)); return(0); } if (ao_mmap) { snd_pcm_access_mask_t *mask = alloca(snd_pcm_access_mask_sizeof()); snd_pcm_access_mask_none(mask); snd_pcm_access_mask_set(mask, SND_PCM_ACCESS_MMAP_INTERLEAVED); snd_pcm_access_mask_set(mask, SND_PCM_ACCESS_MMAP_NONINTERLEAVED); snd_pcm_access_mask_set(mask, SND_PCM_ACCESS_MMAP_COMPLEX); err = snd_pcm_hw_params_set_access_mask(alsa_handler, alsa_hwparams, mask); mp_msg(MSGT_AO,MSGL_INFO,"alsa-init: mmap set\n"); } else { err = snd_pcm_hw_params_set_access(alsa_handler, alsa_hwparams, SND_PCM_ACCESS_RW_INTERLEAVED); } if (err < 0) { mp_msg(MSGT_AO,MSGL_ERR,"alsa-init: unable to set access type: %s\n", snd_strerror(err)); return (0); } /* workaround for nonsupported formats sets default format to S16_LE if the given formats aren't supported */ if ((err = snd_pcm_hw_params_test_format(alsa_handler, alsa_hwparams, alsa_format)) < 0) { mp_msg(MSGT_AO,MSGL_INFO, "alsa-init: format %s are not supported by hardware, trying default\n", af_fmt2str_short(format)); alsa_format = SND_PCM_FORMAT_S16_LE; ao_data.format = AF_FORMAT_S16_LE; ao_data.bps = channels * rate_hz * 2; } bytes_per_sample = ao_data.bps / ao_data.samplerate; //it should be here if ((err = snd_pcm_hw_params_set_format(alsa_handler, alsa_hwparams, alsa_format)) < 0) { mp_msg(MSGT_AO,MSGL_ERR,"alsa-init: unable to set format: %s\n", snd_strerror(err)); } if ((err = snd_pcm_hw_params_set_channels(alsa_handler, alsa_hwparams, ao_data.channels)) < 0) { mp_msg(MSGT_AO,MSGL_ERR,"alsa-init: unable to set channels: %s\n", snd_strerror(err)); } if ((err = snd_pcm_hw_params_set_rate_near(alsa_handler, alsa_hwparams, &ao_data.samplerate, &dir)) < 0) { mp_msg(MSGT_AO,MSGL_ERR,"alsa-init: unable to set samplerate-2: %s\n", snd_strerror(err)); return(0); }#ifdef BUFFERTIME { int alsa_buffer_time = 500000; /* original 60 */ int alsa_period_time; alsa_period_time = alsa_buffer_time/4; if ((err = snd_pcm_hw_params_set_buffer_time_near(alsa_handler, alsa_hwparams, &alsa_buffer_time, &dir)) < 0) { mp_msg(MSGT_AO,MSGL_ERR,"alsa-init: unable to set buffer time near: %s\n", snd_strerror(err)); return(0); } else alsa_buffer_time = err; if ((err = snd_pcm_hw_params_set_period_time_near(alsa_handler, alsa_hwparams, &alsa_period_time, &dir)) < 0) /* original: alsa_buffer_time/ao_data.bps */ { mp_msg(MSGT_AO,MSGL_ERR,"alsa-init: unable to set period time: %s\n", snd_strerror(err)); } mp_msg(MSGT_AO,MSGL_INFO,"alsa-init: buffer_time: %d, period_time :%d\n", alsa_buffer_time, err); } #endif//end SET_BUFFERTIME#ifdef SET_CHUNKSIZE { //set chunksize dir=0; if ((err = snd_pcm_hw_params_set_period_size_near(alsa_handler, alsa_hwparams, &chunk_size, &dir)) < 0) { mp_msg(MSGT_AO,MSGL_ERR,"alsa-init: unable to set periodsize(%d): %s\n", chunk_size, snd_strerror(err)); } else { mp_msg(MSGT_AO,MSGL_V,"alsa-init: chunksize set to %i\n", chunk_size); } if ((err = snd_pcm_hw_params_set_periods_near(alsa_handler, alsa_hwparams, &alsa_fragcount, &dir)) < 0) { mp_msg(MSGT_AO,MSGL_ERR,"alsa-init: unable to set periods: %s\n", snd_strerror(err)); } else { mp_msg(MSGT_AO,MSGL_V,"alsa-init: fragcount=%i\n", alsa_fragcount); } }#endif//end SET_CHUNKSIZE /* finally install hardware parameters */ if ((err = snd_pcm_hw_params(alsa_handler, alsa_hwparams)) < 0) { mp_msg(MSGT_AO,MSGL_ERR,"alsa-init: unable to set hw-parameters: %s\n", snd_strerror(err)); } // end setting hw-params // gets buffersize for control if ((err = snd_pcm_hw_params_get_buffer_size(alsa_hwparams, &bufsize)) < 0) { mp_msg(MSGT_AO,MSGL_ERR,"alsa-init: unable to get buffersize: %s\n", snd_strerror(err)); } else { ao_data.buffersize = bufsize * bytes_per_sample; mp_msg(MSGT_AO,MSGL_V,"alsa-init: got buffersize=%i\n", ao_data.buffersize); } // setting sw-params (only avail-min) if noblocking mode was choosed if (ao_noblock) { if ((err = snd_pcm_sw_params_current(alsa_handler, alsa_swparams)) < 0) { mp_msg(MSGT_AO,MSGL_ERR,"alsa-init: unable to get parameters: %s\n", snd_strerror(err)); } //set min available frames to consider pcm ready (4) //increased for nonblock-mode should be set dynamically later if ((err = snd_pcm_sw_params_set_avail_min(alsa_handler, alsa_swparams, 4)) < 0) { mp_msg(MSGT_AO,MSGL_ERR,"alsa-init: unable to set avail_min %s\n", snd_strerror(err)); } if ((err = snd_pcm_sw_params(alsa_handler, alsa_swparams)) < 0) { mp_msg(MSGT_AO,MSGL_ERR,"alsa-init: unable to install sw-params\n"); } bits_per_sample = snd_pcm_format_physical_width(alsa_format); bits_per_frame = bits_per_sample * channels; chunk_bytes = chunk_size * bits_per_frame / 8; mp_msg(MSGT_AO,MSGL_V,"alsa-init: bits per sample (bps)=%i, bits per frame (bpf)=%i, chunk_bytes=%i\n",bits_per_sample,bits_per_frame,chunk_bytes);} //end swparams if ((err = snd_pcm_prepare(alsa_handler)) < 0) { mp_msg(MSGT_AO,MSGL_ERR,"alsa-init: pcm prepare error: %s\n", snd_strerror(err)); } mp_msg(MSGT_AO,MSGL_INFO,"alsa: %d Hz/%d channels/%d bpf/%d bytes buffer/%s\n", ao_data.samplerate, ao_data.channels, bytes_per_sample, ao_data.buffersize, snd_pcm_format_description(alsa_format)); } // end switch alsa_handler (spdif) alsa_can_pause = snd_pcm_hw_params_can_pause(alsa_hwparams); return(1);} // end init/* close audio device */static void uninit(int immed){ if (alsa_handler) { int err; if (!immed) snd_pcm_drain(alsa_handler); if (!ao_noblock) { if ((err = snd_pcm_drop(alsa_handler)) < 0) { mp_msg(MSGT_AO,MSGL_ERR,"alsa-uninit: pcm drop error: %s\n", snd_strerror(err)); return; } } if ((err = snd_pcm_close(alsa_handler)) < 0) { mp_msg(MSGT_AO,MSGL_ERR,"alsa-uninit: pcm close error: %s\n", snd_strerror(err)); return; } else { alsa_handler = NULL; mp_msg(MSGT_AO,MSGL_INFO,"alsa-uninit: pcm closed\n"); } } else { mp_msg(MSGT_AO,MSGL_ERR,"alsa-uninit: no handler defined!\n"); }}static void audio_pause(){ int err; if (alsa_can_pause) { if ((err = snd_pcm_pause(alsa_handler, 1)) < 0) { mp_msg(MSGT_AO,MSGL_ERR,"alsa-pause: pcm pause error: %s\n", snd_strerror(err)); return; } mp_msg(MSGT_AO,MSGL_V,"alsa-pause: pause supported by hardware\n"); } else { if ((err = snd_pcm_drop(alsa_handler)) < 0) { mp_msg(MSGT_AO,MSGL_ERR,"alsa-pause: pcm drop error: %s\n", snd_strerror(err)); return; } }}static void audio_resume(){ int err; if (alsa_can_pause) { if ((err = snd_pcm_pause(alsa_handler, 0)) < 0) { mp_msg(MSGT_AO,MSGL_ERR,"alsa-resume: pcm resume error: %s\n", snd_strerror(err)); return; } mp_msg(MSGT_AO,MSGL_V,"alsa-resume: resume supported by hardware\n"); } else { if ((err = snd_pcm_prepare(alsa_handler)) < 0) { mp_msg(MSGT_AO,MSGL_ERR,"alsa-resume: pcm prepare error: %s\n", snd_strerror(err)); return; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -