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

📄 ao_alsa.c

📁 自己移植的linux下的流媒体播放器原代码,支持mms协议,支持ftp和http协议.
💻 C
📖 第 1 页 / 共 3 页
字号:
    }}/* stop playing and empty buffers (for seeking/pause) */static void reset(){    int err;    if ((err = snd_pcm_drop(alsa_handler)) < 0)    {	mp_msg(MSGT_AO,MSGL_ERR,"alsa-reset: pcm drop error: %s\n", snd_strerror(err));	return;    }    if ((err = snd_pcm_prepare(alsa_handler)) < 0)    {	mp_msg(MSGT_AO,MSGL_ERR,"alsa-reset: pcm prepare error: %s\n", snd_strerror(err));	return;    }    return;}#ifdef USE_POLLstatic int wait_for_poll(snd_pcm_t *handle, struct pollfd *ufds, unsigned int count){  unsigned short revents;  while (1) {    poll(ufds, count, -1);    snd_pcm_poll_descriptors_revents(handle, ufds, count, &revents);    if (revents & POLLERR)      return -EIO;    if (revents & POLLOUT)      return 0;  }} #endif#ifndef timersub#define timersub(a, b, result) \do { \	(result)->tv_sec = (a)->tv_sec - (b)->tv_sec; \  (result)->tv_usec = (a)->tv_usec - (b)->tv_usec; \  if ((result)->tv_usec < 0) { \		--(result)->tv_sec; \		(result)->tv_usec += 1000000; \	} \} while (0)#endif/* I/O error handler */static int xrun(u_char *str_mode){  int err;  snd_pcm_status_t *status;  snd_pcm_status_alloca(&status);    if ((err = snd_pcm_status(alsa_handler, status))<0) {    mp_msg(MSGT_AO,MSGL_ERR,"status error: %s", snd_strerror(err));    return(0);  }  if (snd_pcm_status_get_state(status) == SND_PCM_STATE_XRUN) {    struct timeval now, diff, tstamp;    gettimeofday(&now, 0);    snd_pcm_status_get_trigger_tstamp(status, &tstamp);    timersub(&now, &tstamp, &diff);    mp_msg(MSGT_AO,MSGL_INFO,"alsa-%s: xrun of at least %.3f msecs. resetting stream\n",	   str_mode,	   diff.tv_sec * 1000 + diff.tv_usec / 1000.0);  }  if ((err = snd_pcm_prepare(alsa_handler))<0) {    mp_msg(MSGT_AO,MSGL_ERR,"xrun: prepare error: %s", snd_strerror(err));    return(0);  }  return(1); /* ok, data should be accepted again */}static int play_normal(void* data, int len);static int play_mmap(void* data, int len);static int play(void* data, int len, int flags){  int result;  if (ao_mmap)    result = play_mmap(data, len);  else    result = play_normal(data, len);  return result;}/*    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_normal(void* data, int len){  //bytes_per_sample is always 4 for 2 chn S16_LE  int num_frames = len / bytes_per_sample;  char *output_samples = (char *)data;  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,"alsa-play: device configuration error");    return 0;  }  while (num_frames > 0) {    res = snd_pcm_writei(alsa_handler, (void *)output_samples, num_frames);      if (res == -EAGAIN) {	snd_pcm_wait(alsa_handler, 1000);      }      else if (res == -EPIPE) {  /* underrun */	if (xrun("play") <= 0) {	  mp_msg(MSGT_AO,MSGL_ERR,"alsa-play: xrun reset error");	  return(0);	}      }      else if (res == -ESTRPIPE) {	/* suspend */	mp_msg(MSGT_AO,MSGL_INFO,"alsa-play: pcm in suspend mode. trying to resume\n");	while ((res = snd_pcm_resume(alsa_handler)) == -EAGAIN)	  sleep(1);      }      else if (res < 0) {	mp_msg(MSGT_AO,MSGL_INFO,"alsa-play: unknown status, trying to reset soundcard\n");	if ((res = snd_pcm_prepare(alsa_handler)) < 0) {	   mp_msg(MSGT_AO,MSGL_ERR,"alsa-play: snd prepare error");	  return(0);	  break;	}      }      if (res > 0) {	/* output_samples += ao_data.channels * res; */	output_samples += res * bytes_per_sample;	num_frames -= res;      }  } //end while  if (res < 0) {    mp_msg(MSGT_AO,MSGL_ERR,"alsa-play: write error %s", snd_strerror(res));    return 0;  }  return len - len % bytes_per_sample;}/* mmap-mode mainly based on descriptions by Joshua Haberman <joshua@haberman.com> * 'An overview of the ALSA API' http://people.debian.org/~joshua/x66.html * and some help by Paul Davis <pbd@op.net> */static int play_mmap(void* data, int len){  snd_pcm_sframes_t commitres, frames_available;  snd_pcm_uframes_t frames_transmit, size, offset;  const snd_pcm_channel_area_t *area;  void *outbuffer;  int result;#ifdef USE_POLL //seems not really be needed  struct pollfd *ufds;  int count;  count = snd_pcm_poll_descriptors_count (alsa_handler);  ufds = malloc(sizeof(struct pollfd) * count);  snd_pcm_poll_descriptors(alsa_handler, ufds, count);  //first wait_for_poll    if (err = (wait_for_poll(alsa_handler, ufds, count) < 0)) {      if (snd_pcm_state(alsa_handler) == SND_PCM_STATE_XRUN || 	  snd_pcm_state(alsa_handler) == SND_PCM_STATE_SUSPENDED) {        xrun("play");      }    }#endif  outbuffer = alloca(ao_data.buffersize);  //don't trust get_space() ;)  frames_available = snd_pcm_avail_update(alsa_handler) * bytes_per_sample;  if (frames_available < 0)    xrun("play");  if (frames_available < 4) {    if (first) {      first = 0;      snd_pcm_start(alsa_handler);    }    else { //FIXME should break and return 0?      snd_pcm_wait(alsa_handler, -1);      first = 1;    }  }  /* len is simply the available bufferspace got by get_space()    * but real avail_buffer in frames is ab/bytes_per_sample */  size = len / bytes_per_sample;  //mp_msg(MSGT_AO,MSGL_V,"len: %i size %i, f_avail %i, bps %i ...\n", len, size, frames_available, bytes_per_sample);  frames_transmit = size;  /* prepare areas and set sw-pointers   * frames_transmit returns the real available buffer-size   * sometimes != frames_available cause of ringbuffer 'emulation' */  snd_pcm_mmap_begin(alsa_handler, &area, &offset, &frames_transmit);  /* this is specific to interleaved streams (or non-interleaved   * streams with only one channel) */  outbuffer = ((char *) area->addr + (area->first + area->step * offset) / 8); //8  //write data  memcpy(outbuffer, data, (frames_transmit * bytes_per_sample));  commitres = snd_pcm_mmap_commit(alsa_handler, offset, frames_transmit);  if (commitres < 0 || commitres != frames_transmit) {    if (snd_pcm_state(alsa_handler) == SND_PCM_STATE_XRUN || 	snd_pcm_state(alsa_handler) == SND_PCM_STATE_SUSPENDED) {      xrun("play");    }  }  //mp_msg(MSGT_AO,MSGL_V,"mmap ft: %i, cres: %i\n", frames_transmit, commitres);  /* 	err = snd_pcm_area_copy(&area, offset, &data, offset, len, alsa_format); */  /* 	if (err < 0) { */  /* 	  mp_msg(MSGT_AO,MSGL_ERR,"area-copy-error\n"); */  /* 	  return 0; */  /* 	} */  //calculate written frames!  result = commitres * bytes_per_sample;  /* if (verbose) { */  /* if (len == result) */  /* mp_msg(MSGT_AO,MSGL_V,"result: %i, frames written: %i ...\n", result, frames_transmit); */  /* else */  /* mp_msg(MSGT_AO,MSGL_V,"result: %i, frames written: %i, result != len ...\n", result, frames_transmit); */  /* } */  //mplayer doesn't like -result  if (result < 0)    result = 0;#ifdef USE_POLL  free(ufds);#endif  return result;}/* how many byes are free in the buffer */static int get_space(){    snd_pcm_status_t *status;    int ret;    char *str_status;    //snd_pcm_sframes_t avail_frames = 0;        snd_pcm_status_alloca(&status);        if ((ret = snd_pcm_status(alsa_handler, status)) < 0)    {	mp_msg(MSGT_AO,MSGL_ERR,"alsa-space: cannot get pcm status: %s\n", snd_strerror(ret));	return(0);    }        switch(snd_pcm_status_get_state(status))    {    case SND_PCM_STATE_OPEN:      str_status = "open";      ret = snd_pcm_status_get_avail(status) * bytes_per_sample;      break;    case SND_PCM_STATE_PREPARED:	str_status = "prepared";	first = 1;	ret = snd_pcm_status_get_avail(status) * bytes_per_sample;	if (ret == 0) //ugly workaround for hang in mmap-mode	  ret = 10;	break;    case SND_PCM_STATE_RUNNING:      ret = snd_pcm_status_get_avail(status) * bytes_per_sample;      //avail_frames = snd_pcm_avail_update(alsa_handler) * bytes_per_sample;      if (str_status != "open" && str_status != "prepared")	str_status = "running";      break;    case SND_PCM_STATE_PAUSED:      mp_msg(MSGT_AO,MSGL_V,"alsa-space: paused");      str_status = "paused";      ret = 0;      break;    case SND_PCM_STATE_XRUN:      xrun("space");      str_status = "xrun";      first = 1;      ret = 0;      break;    default:      str_status = "undefined";      ret = snd_pcm_status_get_avail(status) * bytes_per_sample;      if (ret <= 0) {	xrun("space");      }    }    if (snd_pcm_status_get_state(status) != SND_PCM_STATE_RUNNING)      mp_msg(MSGT_AO,MSGL_V,"alsa-space: free space = %i, %s --\n", ret, str_status);        if (ret < 0) {      mp_msg(MSGT_AO,MSGL_ERR,"negative value!!\n");      ret = 0;    }     // workaround for too small value returned    if (ret < MIN_CHUNK_SIZE)      ret = 0;    return(ret);}/* delay in seconds between first and last sample in buffer */static float get_delay(){  if (alsa_handler) {    snd_pcm_status_t *status;    float ret;        snd_pcm_status_alloca(&status);        if ((ret = snd_pcm_status(alsa_handler, status)) < 0)    {	mp_msg(MSGT_AO,MSGL_ERR,"alsa-delay: cannot get pcm status: %s\n", snd_strerror(ret));    }        switch(snd_pcm_status_get_state(status))    {	case SND_PCM_STATE_OPEN:	case SND_PCM_STATE_PREPARED:	case SND_PCM_STATE_RUNNING:	    ret = (float)snd_pcm_status_get_delay(status)/(float)ao_data.samplerate;	    break;	default:	    ret = 0;    }        if (ret < 0)      ret = 0;    return(ret);      } else {    return(0);  }}

⌨️ 快捷键说明

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