⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ao_alsa.c

📁 DawnLightPlayer,一个新的基于ffmpeg的全功能播放器
💻 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 + -