📄 ao_alsa.c
字号:
/********************************************** * Dawn Light Player * * ao_alsa.c * * Created by maddrone * 17:55:12 02/29/08 CST * * $Id: ao_alsa.c 168 2008-03-21 02:50:01Z kf701 $ **********************************************/#if ENABLE_AO_ALSA#define ALSA_PCM_NEW_HW_PARAMS_API#include <alsa/asoundlib.h>#include "avutil.h"#include "avoutput.h"#include "global.h"static snd_pcm_t *alsa_handle;static int bytes_per_sample;static snd_pcm_format_t format2alsa(int fmt){ switch (fmt) { case SAMPLE_FMT_U8: return SND_PCM_FORMAT_S8; case SAMPLE_FMT_S16: return SND_PCM_FORMAT_S16_LE; case SAMPLE_FMT_S24: return SND_PCM_FORMAT_S24_LE; case SAMPLE_FMT_S32: return SND_PCM_FORMAT_S32_LE; case SAMPLE_FMT_FLT: return SND_PCM_FORMAT_FLOAT_LE; default: return -1; }}static int ao_alsa_init(void){ snd_pcm_hw_params_t *alsa_hwparams = NULL; snd_pcm_sw_params_t *alsa_swparams = NULL; snd_pcm_uframes_t size, boundary; int err, afmt, sr, channels; int buffersize, outburst; afmt = format2alsa(dlpctxp->sample_fmt); channels = dlpctxp->channels; sr = dlpctxp->sample_rate; err = snd_pcm_open(&alsa_handle, "default", SND_PCM_STREAM_PLAYBACK, 0); if ( err < 0 ) { av_log(NULL, AV_LOG_ERROR, "%s,%d: %s\n", __func__, __LINE__, snd_strerror(err)); return -1; } snd_pcm_hw_params_alloca(&alsa_hwparams); snd_pcm_sw_params_alloca(&alsa_swparams); err = snd_pcm_hw_params_any(alsa_handle, alsa_hwparams); if ( err < 0 ) { av_log(NULL, AV_LOG_ERROR, "%s,%d: %s\n", __func__, __LINE__, snd_strerror(err)); return -1; } err = snd_pcm_hw_params_set_access(alsa_handle,alsa_hwparams,SND_PCM_ACCESS_RW_INTERLEAVED); if ( err < 0 ) { av_log(NULL, AV_LOG_ERROR, "%s,%d: %s\n", __func__, __LINE__, snd_strerror(err)); return -1; } err = snd_pcm_hw_params_set_format(alsa_handle, alsa_hwparams, afmt); if ( err < 0 ) { av_log(NULL, AV_LOG_ERROR, "%s,%d: %s\n", __func__, __LINE__, snd_strerror(err)); return -1; } err = snd_pcm_hw_params_set_channels_near(alsa_handle, alsa_hwparams, &channels); if ( err < 0 ) { av_log(NULL, AV_LOG_ERROR, "%s,%d: %s\n", __func__, __LINE__, snd_strerror(err)); return -1; }#if SND_LIB_VERSION >= 0x010009 /* copy from MPlayer */ err = snd_pcm_hw_params_set_rate_resample(alsa_handle, alsa_hwparams, 0); if ( err < 0 ) { av_log(NULL, AV_LOG_ERROR, "%s,%d: %s\n", __func__, __LINE__, snd_strerror(err)); return -1; }#endif err = snd_pcm_hw_params_set_rate_near(alsa_handle,alsa_hwparams,&sr,NULL); if ( err < 0 ) { av_log(NULL, AV_LOG_ERROR, "%s,%d: %s\n", __func__, __LINE__, snd_strerror(err)); return -1; } bytes_per_sample = snd_pcm_format_physical_width(afmt) / 8; bytes_per_sample *= channels; av_log(NULL, AV_LOG_INFO, "sr: %d, ch: %d, afmt: %d\n", sr, channels, dlpctxp->sample_fmt); err = snd_pcm_hw_params(alsa_handle, alsa_hwparams); if ( err < 0 ) { av_log(NULL, AV_LOG_ERROR, "%s,%d: %s\n", __func__, __LINE__, snd_strerror(err)); return -1; } /****************************************************************** * Set HW Params Finish ******************************************************************/ err = snd_pcm_hw_params_get_buffer_size(alsa_hwparams, &size); if ( err < 0 ) { av_log(NULL, AV_LOG_ERROR, "%s,%d: %s\n", __func__, __LINE__, snd_strerror(err)); return -1; } buffersize = size * bytes_per_sample; err = snd_pcm_hw_params_get_period_size(alsa_hwparams, &size, NULL); if ( err < 0 ) { av_log(NULL, AV_LOG_ERROR, "%s,%d: %s\n", __func__, __LINE__, snd_strerror(err)); return -1; } outburst = size * bytes_per_sample; av_log(NULL, AV_LOG_INFO, "outburst: %d, bytes_per_sample: %d, buffersize: %d\n", outburst, bytes_per_sample, buffersize); /****************************************************************** * set sw params ******************************************************************/ err = snd_pcm_sw_params_current(alsa_handle, alsa_swparams); if ( err < 0 ) { av_log(NULL, AV_LOG_ERROR, "%s,%d: %s\n", __func__, __LINE__, snd_strerror(err)); return -1; }#if SND_LIB_VERSION >= 0x000901 err = snd_pcm_sw_params_get_boundary(alsa_swparams, &boundary);#else boundary = 0x7fffffff;#endif err = snd_pcm_sw_params_set_start_threshold(alsa_handle, alsa_swparams, size); if ( err < 0 ) { av_log(NULL, AV_LOG_ERROR, "%s,%d: %s\n", __func__, __LINE__, snd_strerror(err)); return -1; } err = snd_pcm_sw_params_set_stop_threshold(alsa_handle, alsa_swparams, boundary); if ( err < 0 ) { av_log(NULL, AV_LOG_ERROR, "%s,%d: %s\n", __func__, __LINE__, snd_strerror(err)); return -1; }#if SND_LIB_VERSION >= 0x000901 err = snd_pcm_sw_params_set_silence_size(alsa_handle, alsa_swparams, boundary); if ( err < 0 ) { av_log(NULL, AV_LOG_ERROR, "%s,%d: %s\n", __func__, __LINE__, snd_strerror(err)); return -1; }#endif err = snd_pcm_sw_params(alsa_handle, alsa_swparams); if ( err < 0 ) { av_log(NULL, AV_LOG_ERROR, "%s,%d: %s\n", __func__, __LINE__, snd_strerror(err)); return -1; } outburst = size * bytes_per_sample; av_log(NULL, AV_LOG_INFO, "<<<<<<<<<<< alsa init ok >>>>>>>>>>>\n"); return 0;}static int ao_alsa_uninit(void){ if ( alsa_handle ) { snd_pcm_drain(alsa_handle); snd_pcm_close(alsa_handle); } return 0;}static void ao_alsa_play(AVSample *s){ int num_frames = s->size / bytes_per_sample; snd_pcm_sframes_t res = 0; uint8_t *data = s->data; if (!alsa_handle) return ; if (num_frames == 0) return ;rewrite: res = snd_pcm_writei(alsa_handle, data, num_frames); if ( res == -EINTR ) goto rewrite; if ( res < 0 ) { snd_pcm_prepare(alsa_handle); goto rewrite; } if ( res < num_frames ) { data += res * bytes_per_sample; num_frames -= res; goto rewrite; }}static int ao_alsa_control(int cmd, void *arg){ switch (cmd) { case AO_ADD_VOLUME: case AO_SUB_VOLUME: case AO_GET_VOLUME: { int err; long value; snd_mixer_t *handle; snd_mixer_elem_t *elem; snd_mixer_selem_id_t *sid; static char *mix_name = "PCM"; static char *card = "default"; static int mix_index = 0; snd_mixer_selem_id_alloca(&sid); snd_mixer_selem_id_set_index(sid, mix_index); snd_mixer_selem_id_set_name(sid, mix_name); err = snd_mixer_open(&handle, 0); if ( err < 0 ) { av_log(NULL, AV_LOG_ERROR, "%s,%d: line reported!\n", __func__, __LINE__); return -1; } err = snd_mixer_attach(handle, card); if ( err < 0 ) { av_log(NULL, AV_LOG_ERROR, "%s,%d: line reported!\n", __func__, __LINE__); snd_mixer_close(handle); return -1; } err = snd_mixer_selem_register(handle, NULL, NULL); if ( err < 0 ) { av_log(NULL, AV_LOG_ERROR, "%s,%d: line reported!\n", __func__, __LINE__); snd_mixer_close(handle); return -1; } err = snd_mixer_load(handle); if ( err < 0 ) { av_log(NULL, AV_LOG_ERROR, "%s,%d: line reported!\n", __func__, __LINE__); snd_mixer_close(handle); return -1; } elem = snd_mixer_find_selem(handle, sid); if ( !elem ) { av_log(NULL, AV_LOG_ERROR, "%s,%d: line reported!\n", __func__, __LINE__); snd_mixer_close(handle); return -1; } snd_mixer_selem_get_playback_volume(elem, 0, &value); if ( AO_GET_VOLUME == cmd ) { snd_mixer_close(handle); return value; } if ( AO_ADD_VOLUME == cmd ) value += 10; if ( AO_SUB_VOLUME == cmd ) value -= 10; snd_mixer_selem_set_playback_volume(elem, 0, value); snd_mixer_selem_set_playback_volume(elem, 1, value); av_log(NULL, AV_LOG_INFO, "Change Volume to %ld \r", value); snd_mixer_close(handle); break; } default: { av_log(NULL, AV_LOG_INFO, "ALSA control CMD not support\n"); break; } } return 0;}ao_t ao_alsa ={ .id = AO_ID_ALSA, .name = "alsa", .ao_init = ao_alsa_init, .ao_uninit = ao_alsa_uninit, .ao_play = ao_alsa_play, .ao_getspace = NULL, .ao_control = ao_alsa_control,};#endif /* ENABLE_AO_ALSA */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -