ao_sgi.c
来自「君正早期ucos系统(只有早期的才不没有打包成库),MPLAYER,文件系统,图」· C语言 代码 · 共 301 行
C
301 行
/* ao_sgi - sgi/irix output plugin for MPlayer 22oct2001 oliver.schoenbrunner@jku.at */#include <mplaylib.h>#include "mplaylib.h"#include <errno.h>#include <dmedia/audio.h>#include "audio_out.h"#include "audio_out_internal.h"#include "mp_msg.h"#include "help_mp.h"#include "libaf/af_format.h"static ao_info_t info = { "sgi audio output", "sgi", "Oliver Schoenbrunner", ""};LIBAO_EXTERN(sgi)static ALconfig ao_config;static ALport ao_port;static int sample_rate;static int queue_size;static int bytes_per_frame;/** * \param [in/out] format * \param [out] width * * \return the closest matching SGI AL sample format * * \note width is set to required per-channel sample width * format is updated to match the SGI AL sample format */static int fmt2sgial(int *format, int *width) { int smpfmt = AL_SAMPFMT_TWOSCOMP; /* SGI AL only supports float and signed integers in native * endianness. If this is something else, we must rely on the audio * filter to convert it to a compatible format. */ /* 24-bit audio is supported, but only with 32-bit alignment. * mplayer's 24-bit format is packed, unfortunately. * So we must upgrade 24-bit requests to 32 bits. Then we drop the * lowest 8 bits during playback. */ switch(*format) { case AF_FORMAT_U8: case AF_FORMAT_S8: *width = AL_SAMPLE_8; *format = AF_FORMAT_S8; break; case AF_FORMAT_U16_LE: case AF_FORMAT_U16_BE: case AF_FORMAT_S16_LE: case AF_FORMAT_S16_BE: *width = AL_SAMPLE_16; *format = AF_FORMAT_S16_NE; break; case AF_FORMAT_U24_LE: case AF_FORMAT_U24_BE: case AF_FORMAT_S24_LE: case AF_FORMAT_S24_BE: case AF_FORMAT_U32_LE: case AF_FORMAT_U32_BE: case AF_FORMAT_S32_LE: case AF_FORMAT_S32_BE: *width = AL_SAMPLE_24; *format = AF_FORMAT_S32_NE; break; case AF_FORMAT_FLOAT_LE: case AF_FORMAT_FLOAT_BE: *width = 4; *format = AF_FORMAT_FLOAT_NE; smpfmt = AL_SAMPFMT_FLOAT; break; default: *width = AL_SAMPLE_16; *format = AF_FORMAT_S16_NE; break; } return smpfmt;}// to set/get/query special features/parametersstatic int control(int cmd, void *arg){ mp_msg(MSGT_AO, MSGL_INFO, MSGTR_AO_SGI_INFO); switch(cmd) { case AOCONTROL_QUERY_FORMAT: /* Do not reject any format: return the closest matching * format if the request is not supported natively. */ return CONTROL_TRUE; } return CONTROL_UNKNOWN;}// open & setup audio device// return: 1=success 0=failstatic int init(int rate, int channels, int format, int flags) { int smpwidth, smpfmt; int rv = AL_DEFAULT_OUTPUT; smpfmt = fmt2sgial(&format, &smpwidth); mp_msg(MSGT_AO, MSGL_INFO, MSGTR_AO_SGI_InitInfo, rate, (channels > 1) ? "Stereo" : "Mono", af_fmt2str_short(format)); { /* from /usr/share/src/dmedia/audio/setrate.c */ double frate, realrate; ALpv x[2]; if(ao_subdevice) { rv = alGetResourceByName(AL_SYSTEM, ao_subdevice, AL_OUTPUT_DEVICE_TYPE); if (!rv) { mp_msg(MSGT_AO, MSGL_ERR, MSGTR_AO_SGI_InvalidDevice); return 0; } } frate = rate; x[0].param = AL_RATE; x[0].value.ll = alDoubleToFixed(rate); x[1].param = AL_MASTER_CLOCK; x[1].value.i = AL_CRYSTAL_MCLK_TYPE; if (alSetParams(rv,x, 2)<0) { mp_msg(MSGT_AO, MSGL_WARN, MSGTR_AO_SGI_CantSetParms_Samplerate, alGetErrorString(oserror())); } if (x[0].sizeOut < 0) { mp_msg(MSGT_AO, MSGL_WARN, MSGTR_AO_SGI_CantSetAlRate); } if (alGetParams(rv,x, 1)<0) { mp_msg(MSGT_AO, MSGL_WARN, MSGTR_AO_SGI_CantGetParms, alGetErrorString(oserror())); } realrate = alFixedToDouble(x[0].value.ll); if (frate != realrate) { mp_msg(MSGT_AO, MSGL_INFO, MSGTR_AO_SGI_SampleRateInfo, realrate, frate); } sample_rate = (int)realrate; } bytes_per_frame = channels * smpwidth; ao_data.samplerate = sample_rate; ao_data.channels = channels; ao_data.format = format; ao_data.bps = sample_rate * bytes_per_frame; ao_data.buffersize=131072; ao_data.outburst = ao_data.buffersize/16; ao_config = alNewConfig(); if (!ao_config) { mp_msg(MSGT_AO, MSGL_ERR, MSGTR_AO_SGI_InitConfigError, alGetErrorString(oserror())); return 0; } if(alSetChannels(ao_config, channels) < 0 || alSetWidth(ao_config, smpwidth) < 0 || alSetSampFmt(ao_config, smpfmt) < 0 || alSetQueueSize(ao_config, sample_rate) < 0 || alSetDevice(ao_config, rv) < 0) { mp_msg(MSGT_AO, MSGL_ERR, MSGTR_AO_SGI_InitConfigError, alGetErrorString(oserror())); return 0; } ao_port = alOpenPort("mplayer", "w", ao_config); if (!ao_port) { mp_msg(MSGT_AO, MSGL_ERR, MSGTR_AO_SGI_InitOpenAudioFailed, alGetErrorString(oserror())); return 0; } // printf("ao_sgi, init: port %d config %d\n", ao_port, ao_config); queue_size = alGetQueueSize(ao_config); return 1; }// close audio devicestatic void uninit(int immed) { /* TODO: samplerate should be set back to the value before mplayer was started! */ mp_msg(MSGT_AO, MSGL_INFO, MSGTR_AO_SGI_Uninit); if (ao_config) { alFreeConfig(ao_config); ao_config = NULL; } if (ao_port) { if (!immed) while(alGetFilled(ao_port) > 0) sginap(1); alClosePort(ao_port); ao_port = NULL; } }// stop playing and empty buffers (for seeking/pause)static void reset(void) { mp_msg(MSGT_AO, MSGL_INFO, MSGTR_AO_SGI_Reset); alDiscardFrames(ao_port, queue_size);}// stop playing, keep buffers (for pause)static void audio_pause(void) { mp_msg(MSGT_AO, MSGL_INFO, MSGTR_AO_SGI_PauseInfo); }// resume playing, after audio_pause()static void audio_resume(void) { mp_msg(MSGT_AO, MSGL_INFO, MSGTR_AO_SGI_ResumeInfo);}// return: how many bytes can be played without blockingstatic int get_space(void) { // printf("ao_sgi, get_space: (ao_outburst %d)\n", ao_data.outburst); // printf("ao_sgi, get_space: alGetFillable [%d] \n", alGetFillable(ao_port)); return alGetFillable(ao_port) * bytes_per_frame; }// plays 'len' bytes of 'data'// it should round it down to outburst*n// return: number of bytes playedstatic int play(void* data, int len, int flags) { /* Always process data in quadword-aligned chunks (64-bits). */ const int plen = len / (sizeof(uint64_t) * bytes_per_frame); const int framecount = plen * sizeof(uint64_t); // printf("ao_sgi, play: len %d flags %d (%d %d)\n", len, flags, ao_port, ao_config); // printf("channels %d\n", ao_data.channels); if(ao_data.format == AF_FORMAT_S32_NE) { /* The zen of this is explained in fmt2sgial() */ int32_t *smpls = data; const int32_t *smple = smpls + (framecount * ao_data.channels); while(smpls < smple) *smpls++ >>= 8; } alWriteFrames(ao_port, data, framecount); return framecount * bytes_per_frame; }// return: delay in seconds between first and last sample in bufferstatic float get_delay(void){ // printf("ao_sgi, get_delay: (ao_buffersize %d)\n", ao_buffersize); // return (float)queue_size/((float)sample_rate); const int outstanding = alGetFilled(ao_port); return (float)((outstanding < 0) ? queue_size : outstanding) / ((float)sample_rate);}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?