ao_alsa.c
来自「君正早期ucos系统(只有早期的才不没有打包成库),MPLAYER,文件系统,图」· C语言 代码 · 共 889 行 · 第 1/2 页
C
889 行
mp_msg(MSGT_AO,MSGL_V,"alsa-init: using device %s\n", alsa_device); //setting modes for block or nonblock-mode if (ao_noblock) { open_mode = SND_PCM_NONBLOCK; } else { open_mode = 0; } //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; chunk_size = 1024; break; } } if (!alsa_handler) { //modes = 0, SND_PCM_NONBLOCK, SND_PCM_ASYNC if ((err = try_open_device(alsa_device, open_mode, format == AF_FORMAT_AC3)) < 0) { if (err != -EBUSY && ao_noblock) { mp_msg(MSGT_AO,MSGL_INFO,MSGTR_AO_ALSA_OpenInNonblockModeFailed); if ((err = try_open_device(alsa_device, 0, format == AF_FORMAT_AC3)) < 0) { mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_PlaybackOpenError, snd_strerror(err)); return(0); } } else { mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_PlaybackOpenError, snd_strerror(err)); return(0); } } if ((err = snd_pcm_nonblock(alsa_handler, 0)) < 0) { mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_ErrorSetBlockMode, snd_strerror(err)); } else { mp_msg(MSGT_AO,MSGL_V,"alsa-init: pcm opened in blocking mode\n"); } 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,MSGTR_AO_ALSA_UnableToGetInitialParameters, snd_strerror(err)); return(0); } 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,MSGTR_AO_ALSA_UnableToSetAccessType, 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, MSGTR_AO_ALSA_FormatNotSupportedByHardware, af_fmt2str_short(format)); alsa_format = SND_PCM_FORMAT_S16_LE; ao_data.format = AF_FORMAT_S16_LE; } if ((err = snd_pcm_hw_params_set_format(alsa_handler, alsa_hwparams, alsa_format)) < 0) { mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_UnableToSetFormat, snd_strerror(err)); return(0); } if ((err = snd_pcm_hw_params_set_channels_near(alsa_handler, alsa_hwparams, &ao_data.channels)) < 0) { mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_UnableToSetChannels, snd_strerror(err)); return(0); } /* workaround for buggy rate plugin (should be fixed in ALSA 1.0.11) prefer our own resampler */#if SND_LIB_VERSION >= 0x010009 if ((err = snd_pcm_hw_params_set_rate_resample(alsa_handler, alsa_hwparams, 0)) < 0) { mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_UnableToDisableResampling, snd_strerror(err)); return(0); }#endif if ((err = snd_pcm_hw_params_set_rate_near(alsa_handler, alsa_hwparams, &ao_data.samplerate, NULL)) < 0) { mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_UnableToSetSamplerate2, snd_strerror(err)); return(0); } bytes_per_sample = snd_pcm_format_physical_width(alsa_format) / 8; bytes_per_sample *= ao_data.channels; ao_data.bps = ao_data.samplerate * bytes_per_sample;#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, NULL)) < 0) { mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_UnableToSetBufferTimeNear, 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, NULL)) < 0) /* original: alsa_buffer_time/ao_data.bps */ { mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_UnableToSetPeriodTime, snd_strerror(err)); return 0; } mp_msg(MSGT_AO,MSGL_INFO,MSGTR_AO_ALSA_BufferTimePeriodTime, alsa_buffer_time, err); } #endif//end SET_BUFFERTIME#ifdef SET_CHUNKSIZE { //set chunksize if ((err = snd_pcm_hw_params_set_period_size_near(alsa_handler, alsa_hwparams, &chunk_size, NULL)) < 0) { mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_UnableToSetPeriodSize, chunk_size, snd_strerror(err)); return 0; } else { mp_msg(MSGT_AO,MSGL_V,"alsa-init: chunksize set to %li\n", chunk_size); } if ((err = snd_pcm_hw_params_set_periods_near(alsa_handler, alsa_hwparams, &alsa_fragcount, NULL)) < 0) { mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_UnableToSetPeriods, snd_strerror(err)); return 0; } 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,MSGTR_AO_ALSA_UnableToSetHwParameters, snd_strerror(err)); return 0; } // 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,MSGTR_AO_ALSA_UnableToGetBufferSize, snd_strerror(err)); return 0; } else { ao_data.buffersize = bufsize * bytes_per_sample; mp_msg(MSGT_AO,MSGL_V,"alsa-init: got buffersize=%i\n", ao_data.buffersize); } if ((err = snd_pcm_hw_params_get_period_size(alsa_hwparams, &chunk_size, NULL)) < 0) { mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_UnableToGetPeriodSize, snd_strerror(err)); return 0; } else { mp_msg(MSGT_AO,MSGL_V,"alsa-init: got period size %li\n", chunk_size); } ao_data.outburst = chunk_size * bytes_per_sample; /* setting software parameters */ if ((err = snd_pcm_sw_params_current(alsa_handler, alsa_swparams)) < 0) { mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_UnableToGetSwParameters, snd_strerror(err)); return 0; }#if SND_LIB_VERSION >= 0x000901 if ((err = snd_pcm_sw_params_get_boundary(alsa_swparams, &boundary)) < 0) { mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_UnableToGetBoundary, snd_strerror(err)); return 0; }#else boundary = 0x7fffffff;#endif /* start playing when one period has been written */ if ((err = snd_pcm_sw_params_set_start_threshold(alsa_handler, alsa_swparams, chunk_size)) < 0) { mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_UnableToSetStartThreshold, snd_strerror(err)); return 0; } /* disable underrun reporting */ if ((err = snd_pcm_sw_params_set_stop_threshold(alsa_handler, alsa_swparams, boundary)) < 0) { mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_UnableToSetStopThreshold, snd_strerror(err)); return 0; }#if SND_LIB_VERSION >= 0x000901 /* play silence when there is an underrun */ if ((err = snd_pcm_sw_params_set_silence_size(alsa_handler, alsa_swparams, boundary)) < 0) { mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_UnableToSetSilenceSize, snd_strerror(err)); return 0; }#endif if ((err = snd_pcm_sw_params(alsa_handler, alsa_swparams)) < 0) { mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_UnableToGetSwParameters, snd_strerror(err)); return 0; } /* end setting sw-params */ mp_msg(MSGT_AO,MSGL_V,"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 ((err = snd_pcm_close(alsa_handler)) < 0) { mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_PcmCloseError, snd_strerror(err)); return; } else { alsa_handler = NULL; mp_msg(MSGT_AO,MSGL_V,"alsa-uninit: pcm closed\n"); } } else { mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_NoHandlerDefined); }}static void audio_pause(void){ int err; if (alsa_can_pause) { if ((err = snd_pcm_pause(alsa_handler, 1)) < 0) { mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_PcmPauseError, 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,MSGTR_AO_ALSA_PcmDropError, snd_strerror(err)); return; } }}static void audio_resume(void){ int err; if (alsa_can_pause) { if ((err = snd_pcm_pause(alsa_handler, 0)) < 0) { mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_PcmResumeError, 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,MSGTR_AO_ALSA_PcmPrepareError, snd_strerror(err)); return; } }}/* stop playing and empty buffers (for seeking/pause) */static void reset(void){ int err; if ((err = snd_pcm_drop(alsa_handler)) < 0) { mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_PcmPrepareError, snd_strerror(err)); return; } if ((err = snd_pcm_prepare(alsa_handler)) < 0) { mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_PcmPrepareError, snd_strerror(err)); return; } return;}/* plays 'len' bytes of 'data' returns: number of bytes played modified last at 29.06.02 by jp thanxs for marius <marius@rospot.com> for giving us the light ;)*/static int play(void* data, int len, int flags){ int num_frames = len / bytes_per_sample; snd_pcm_sframes_t res = 0; //mp_msg(MSGT_AO,MSGL_ERR,"alsa-play: frames=%i, len=%i\n",num_frames,len); if (!alsa_handler) { mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_DeviceConfigurationError); return 0; } if (num_frames == 0) return 0; do { res = snd_pcm_writei(alsa_handler, data, num_frames); if (res == -EINTR) { /* nothing to do */ res = 0; } else if (res == -ESTRPIPE) { /* suspend */ mp_msg(MSGT_AO,MSGL_INFO,MSGTR_AO_ALSA_PcmInSuspendModeTryingResume); while ((res = snd_pcm_resume(alsa_handler)) == -EAGAIN) sleep(1); } if (res < 0) { mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_WriteError, snd_strerror(res)); mp_msg(MSGT_AO,MSGL_INFO,MSGTR_AO_ALSA_TryingToResetSoundcard); if ((res = snd_pcm_prepare(alsa_handler)) < 0) { mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_PcmPrepareError, snd_strerror(res)); return(0); break; } } } while (res == 0); return res < 0 ? res : res * bytes_per_sample;}/* how many byes are free in the buffer */static int get_space(void){ snd_pcm_status_t *status; int ret; snd_pcm_status_alloca(&status); if ((ret = snd_pcm_status(alsa_handler, status)) < 0) { mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_CannotGetPcmStatus, snd_strerror(ret)); return(0); } ret = snd_pcm_status_get_avail(status) * bytes_per_sample; if (ret > ao_data.buffersize) // Buffer underrun? ret = ao_data.buffersize; return(ret);}/* delay in seconds between first and last sample in buffer */static float get_delay(void){ if (alsa_handler) { snd_pcm_sframes_t delay; if (snd_pcm_delay(alsa_handler, &delay) < 0) return 0; if (delay < 0) { /* underrun - move the application pointer forward to catch up */#if SND_LIB_VERSION >= 0x000901 /* snd_pcm_forward() exists since 0.9.0rc8 */ snd_pcm_forward(alsa_handler, -delay);#endif delay = 0; } return (float)delay / (float)ao_data.samplerate; } else { return(0); }}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?