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

📄 ao_sun.c

📁 自己移植的linux下的流媒体播放器原代码,支持mms协议,支持ftp和http协议.
💻 C
📖 第 1 页 / 共 2 页
字号:
#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <fcntl.h>#include <errno.h>#include <sys/ioctl.h>#include <sys/time.h>#include <sys/types.h>#include <sys/stat.h>#include <sys/audioio.h>#ifdef	AUDIO_SWFEATURE_MIXER	/* solaris8 or newer? */# define HAVE_SYS_MIXER_H 1#endif#if	HAVE_SYS_MIXER_H# include <sys/mixer.h>#endif#ifdef	__svr4__#include <stropts.h>#endif#include "config.h"#include "mixer.h"#include "audio_out.h"#include "audio_out_internal.h"#include "libaf/af_format.h"#include "mp_msg.h"#include "help_mp.h"static ao_info_t info = {    "Sun audio output",    "sun",    "Juergen Keil",    ""};LIBAO_EXTERN(sun)/* These defines are missing on NetBSD */#ifndef	AUDIO_PRECISION_8#define AUDIO_PRECISION_8	8#define AUDIO_PRECISION_16	16#endif#ifndef	AUDIO_CHANNELS_MONO#define	AUDIO_CHANNELS_MONO	1#define	AUDIO_CHANNELS_STEREO	2#endifstatic char *sun_mixer_device = NULL;static char *audio_dev = NULL;static int queued_bursts = 0;static int queued_samples = 0;static int bytes_per_sample = 0;static int byte_per_sec = 0;static int audio_fd = -1;static enum {    RTSC_UNKNOWN = 0,    RTSC_ENABLED,    RTSC_DISABLED} enable_sample_timing;extern int verbose;// convert an OSS audio format specification into a sun audio encodingstatic int af2sunfmt(int format){    switch (format){    case AF_FORMAT_MU_LAW:	return AUDIO_ENCODING_ULAW;    case AF_FORMAT_A_LAW:	return AUDIO_ENCODING_ALAW;    case AF_FORMAT_S16_NE:	return AUDIO_ENCODING_LINEAR;#ifdef	AUDIO_ENCODING_LINEAR8	// Missing on SunOS 5.5.1...    case AF_FORMAT_U8:	return AUDIO_ENCODING_LINEAR8;#endif    case AF_FORMAT_S8:	return AUDIO_ENCODING_LINEAR;#ifdef	AUDIO_ENCODING_DVI	// Missing on NetBSD...    case AF_FORMAT_IMA_ADPCM:	return AUDIO_ENCODING_DVI;#endif    default:	return AUDIO_ENCODING_NONE;  }}// try to figure out, if the soundcard driver provides usable (precise)// sample counter informationstatic int realtime_samplecounter_available(char *dev){    int fd = -1;    audio_info_t info;    int rtsc_ok = RTSC_DISABLED;    int len;    void *silence = NULL;    struct timeval start, end;    struct timespec delay;    int usec_delay;    unsigned last_samplecnt;    unsigned increment;    unsigned min_increment;    len = 44100 * 4 / 4;    /* amount of data for 0.25sec of 44.1khz, stereo,			     * 16bit.  44kbyte can be sent to all supported			     * sun audio devices without blocking in the			     * "write" below.			     */    silence = calloc(1, len);    if (silence == NULL)	goto error;        if ((fd = open(dev, O_WRONLY)) < 0)	goto error;    AUDIO_INITINFO(&info);    info.play.sample_rate = 44100;    info.play.channels = AUDIO_CHANNELS_STEREO;    info.play.precision = AUDIO_PRECISION_16;    info.play.encoding = AUDIO_ENCODING_LINEAR;    info.play.samples = 0;    if (ioctl(fd, AUDIO_SETINFO, &info)) {	if (verbose>0)	    mp_msg(MSGT_AO, MSGL_ERR, MSGTR_AO_SUN_RtscSetinfoFailed);	goto error;    }        if (write(fd, silence, len) != len) {	if (verbose>0)	    mp_msg(MSGT_AO, MSGL_ERR, MSGTR_AO_SUN_RtscWriteFailed);	goto error;    }    if (ioctl(fd, AUDIO_GETINFO, &info)) {	if (verbose>0)	    perror("rtsc: GETINFO1");	goto error;    }    last_samplecnt = info.play.samples;    min_increment = ~0;    gettimeofday(&start, NULL);    for (;;) {	delay.tv_sec = 0;	delay.tv_nsec = 10000000;	nanosleep(&delay, NULL);	gettimeofday(&end, NULL);	usec_delay = (end.tv_sec - start.tv_sec) * 1000000	    + end.tv_usec - start.tv_usec;	// stop monitoring sample counter after 0.2 seconds	if (usec_delay > 200000)	    break;	if (ioctl(fd, AUDIO_GETINFO, &info)) {	    if (verbose>0)		perror("rtsc: GETINFO2 failed");	    goto error;	}	if (info.play.samples < last_samplecnt) {	    if (verbose>0)		printf("rtsc: %d > %d?\n", last_samplecnt, info.play.samples);	    goto error;	}	if ((increment = info.play.samples - last_samplecnt) > 0) {	    if (verbose>0)		printf("ao_sun: sample counter increment: %d\n", increment);	    if (increment < min_increment) {		min_increment = increment;		if (min_increment < 2000)		    break;	// looks good	    }	}	last_samplecnt = info.play.samples;    }    /*     * For 44.1kkz, stereo, 16-bit format we would send sound data in 16kbytes     * chunks (== 4096 samples) to the audio device.  If we see a minimum     * sample counter increment from the soundcard driver of less than     * 2000 samples,  we assume that the driver provides a useable realtime     * sample counter in the AUDIO_INFO play.samples field.  Timing based     * on sample counts should be much more accurate than counting whole      * 16kbyte chunks.     */    if (min_increment < 2000)	rtsc_ok = RTSC_ENABLED;    if (verbose>0)	printf("ao_sun: minimum sample counter increment per 10msec interval: %d\n"	       "\t%susing sample counter based timing code\n",	       min_increment, rtsc_ok == RTSC_ENABLED ? "" : "not ");    error:    if (silence != NULL) free(silence);    if (fd >= 0) {#ifdef	__svr4__	// remove the 0 bytes from the above measurement from the	// audio driver's STREAMS queue	ioctl(fd, I_FLUSH, FLUSHW);#endif	//ioctl(fd, AUDIO_DRAIN, 0);	close(fd);    }    return rtsc_ok;}// match the requested sample rate |sample_rate| against the// sample rates supported by the audio device |dev|.  Return// a supported sample rate,  if that sample rate is close to// (< 1% difference) the requested rate; return 0 otherwise.#define	MAX_RATE_ERR	1static unsignedfind_close_samplerate_match(int dev, unsigned sample_rate){#if	HAVE_SYS_MIXER_H    am_sample_rates_t *sr;    unsigned i, num, err, best_err, best_rate;    for (num = 16; num < 1024; num *= 2) {	sr = malloc(AUDIO_MIXER_SAMP_RATES_STRUCT_SIZE(num));	if (!sr)	    return 0;	sr->type = AUDIO_PLAY;	sr->flags = 0;	sr->num_samp_rates = num;	if (ioctl(dev, AUDIO_MIXER_GET_SAMPLE_RATES, sr)) {	    free(sr);	    return 0;	}	if (sr->num_samp_rates <= num)	    break;	free(sr);    }    if (sr->flags & MIXER_SR_LIMITS) {	/*	 * HW can playback any rate between 	 * sr->samp_rates[0] .. sr->samp_rates[1]	 */	free(sr);	return 0;    } else {	/* HW supports fixed sample rates only */	best_err = 65535;	best_rate = 0;	for (i = 0; i < sr->num_samp_rates; i++) {	    err = abs(sr->samp_rates[i] - sample_rate);	    if (err == 0) {		/*		 * exact supported sample rate match, no need to		 * retry something else		 */		best_rate = 0;		break;	    }	    if (err < best_err) {		best_err = err;		best_rate = sr->samp_rates[i];	    }	}	free(sr);	if (best_rate > 0 && (100/MAX_RATE_ERR)*best_err < sample_rate) {	    /* found a supported sample rate with <1% error? */	    return best_rate;	}	return 0;    }#else	/* old audioio driver, cannot return list of supported rates */    /* XXX: hardcoded sample rates */    unsigned i, err;    unsigned audiocs_rates[] = {	5510, 6620, 8000, 9600, 11025, 16000, 18900, 22050,	27420, 32000, 33075, 37800, 44100, 48000, 0    };    for (i = 0; audiocs_rates[i]; i++) {	err = abs(audiocs_rates[i] - sample_rate);	if (err == 0) {	    /* 	     * exact supported sample rate match, no need to	     * retry something elise	     */	    return 0;	}	if ((100/MAX_RATE_ERR)*err < audiocs_rates[i]) {	    /* <1% error? */	    return audiocs_rates[i];	}    }    return 0;#endif}// return the highest sample rate supported by audio device |dev|.static unsignedfind_highest_samplerate(int dev){#if	HAVE_SYS_MIXER_H    am_sample_rates_t *sr;    unsigned i, num, max_rate;    for (num = 16; num < 1024; num *= 2) {	sr = malloc(AUDIO_MIXER_SAMP_RATES_STRUCT_SIZE(num));	if (!sr)	    return 0;	sr->type = AUDIO_PLAY;	sr->flags = 0;	sr->num_samp_rates = num;	if (ioctl(dev, AUDIO_MIXER_GET_SAMPLE_RATES, sr)) {	    free(sr);	    return 0;	}	if (sr->num_samp_rates <= num)	    break;	free(sr);    }    if (sr->flags & MIXER_SR_LIMITS) {	/*	 * HW can playback any rate between 	 * sr->samp_rates[0] .. sr->samp_rates[1]	 */	max_rate = sr->samp_rates[1];    } else {	/* HW supports fixed sample rates only */	max_rate = 0;	for (i = 0; i < sr->num_samp_rates; i++) {	    if (sr->samp_rates[i] > max_rate)		max_rate = sr->samp_rates[i];	}    }    free(sr);    return max_rate;#else	/* old audioio driver, cannot return list of supported rates */    return 44100;	/* should be supported even on old ISA SB cards */#endif}static void setup_device_paths(){    if (audio_dev == NULL) {	if ((audio_dev = getenv("AUDIODEV")) == NULL)	    audio_dev = "/dev/audio";    }    if (sun_mixer_device == NULL) {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -