Ejemplo n.º 1
0
static GstClockTime
gst_alsasrc_get_timestamp (GstAlsaSrc * asrc)
{
  snd_pcm_status_t *status;
  snd_htimestamp_t tstamp;
  GstClockTime timestamp;
  snd_pcm_uframes_t avail;
  gint err = -EPIPE;

  if (G_UNLIKELY (!asrc)) {
    GST_ERROR_OBJECT (asrc, "No alsa handle created yet !");
    return GST_CLOCK_TIME_NONE;
  }

  if (G_UNLIKELY (snd_pcm_status_malloc (&status) != 0)) {
    GST_ERROR_OBJECT (asrc, "snd_pcm_status_malloc failed");
    return GST_CLOCK_TIME_NONE;
  }

  if (G_UNLIKELY (snd_pcm_status (asrc->handle, status) != 0)) {
    GST_ERROR_OBJECT (asrc, "snd_pcm_status failed");
    return GST_CLOCK_TIME_NONE;
  }

  /* in case an xrun condition has occured we need to handle this */
  if (snd_pcm_status_get_state (status) != SND_PCM_STATE_RUNNING) {
    if (xrun_recovery (asrc, asrc->handle, err) < 0) {
      GST_WARNING_OBJECT (asrc, "Could not recover from xrun condition !");
    }
    /* reload the status alsa status object, since recovery made it invalid */
    if (G_UNLIKELY (snd_pcm_status (asrc->handle, status) != 0)) {
      GST_ERROR_OBJECT (asrc, "snd_pcm_status failed");
    }
  }

  /* get high resolution time stamp from driver */
  snd_pcm_status_get_htstamp (status, &tstamp);
  timestamp = GST_TIMESPEC_TO_TIME (tstamp);

  /* max available frames sets the depth of the buffer */
  avail = snd_pcm_status_get_avail (status);

  /* calculate the timestamp of the next sample to be read */
  timestamp -= gst_util_uint64_scale_int (avail, GST_SECOND, asrc->rate);

  /* compensate for the fact that we really need the timestamp of the
   * previously read data segment */
  timestamp -= asrc->period_time * 1000;

  snd_pcm_status_free (status);

  GST_LOG_OBJECT (asrc, "ALSA timestamp : %" GST_TIME_FORMAT
      ", delay %lu", GST_TIME_ARGS (timestamp), avail);

  return timestamp;
}
Ejemplo n.º 2
0
static void
alsa_prefill( void )
{
	snd_pcm_status_t *status;
	char buf[512];
	int frames, cnt;

	snd_pcm_status_malloc( &status );
	snd_pcm_status( alsa.pcm, status );
	frames = snd_pcm_status_get_avail(status);
	snd_pcm_status_free( status );

	memset( buf, 0, sizeof(buf) );
	cnt = sizeof(buf)/alsa.bpf;
	for( ; frames > 0; frames -= cnt  ) {
		if( cnt > frames )
			cnt = frames;
		snd_pcm_writei( alsa.pcm, buf, sizeof(buf)/alsa.bpf );
	}
}
void* DAUDIO_Open(INT32 mixerIndex, INT32 deviceID, int isSource,
                  int encoding, float sampleRate, int sampleSizeInBits,
                  int frameSize, int channels,
                  int isSigned, int isBigEndian, int bufferSizeInBytes) {
    snd_pcm_format_mask_t* formatMask;
    snd_pcm_format_t format;
    int dir;
    int ret = 0;
    AlsaPcmInfo* info = NULL;
    /* snd_pcm_uframes_t is 64 bit on 64-bit systems */
    snd_pcm_uframes_t alsaPeriodSize = 0;
    snd_pcm_uframes_t alsaBufferSizeInFrames = 0;


    TRACE0("> DAUDIO_Open\n");
#ifdef USE_TRACE
    // for using ALSA debug dump methods
    if (ALSA_OUTPUT == NULL) {
        snd_output_stdio_attach(&ALSA_OUTPUT, stdout, 0);
    }
#endif

    info = (AlsaPcmInfo*) malloc(sizeof(AlsaPcmInfo));
    if (!info) {
        ERROR0("Out of memory\n");
        return NULL;
    }
    memset(info, 0, sizeof(AlsaPcmInfo));

    ret = openPCMfromDeviceID(deviceID, &(info->handle), isSource, FALSE /* do open device*/);
    if (ret == 0) {
        // set to blocking mode
        snd_pcm_nonblock(info->handle, 0);
        ret = snd_pcm_hw_params_malloc(&(info->hwParams));
        if (ret != 0) {
            ERROR1("  snd_pcm_hw_params_malloc returned error %d\n", ret);
        } else {
            ret = -1;
            if (getAlsaFormatFromFormat(&format, frameSize / channels, sampleSizeInBits,
                                        isSigned, isBigEndian, encoding)) {
                if (setHWParams(info,
                                sampleRate,
                                channels,
                                bufferSizeInBytes / frameSize,
                                format)) {
                    info->frameSize = frameSize;
#ifdef ALSA_PCM_NEW_HW_PARAMS_API
                    ret = snd_pcm_hw_params_get_period_size(info->hwParams, &alsaPeriodSize, &dir);
                    info->periodSize = (int) alsaPeriodSize;
                    if (ret < 0) {
                        ERROR1("ERROR: snd_pcm_hw_params_get_period: %s\n", snd_strerror(ret));
                    }
                    snd_pcm_hw_params_get_periods(info->hwParams, &(info->periods), &dir);
                    snd_pcm_hw_params_get_buffer_size(info->hwParams, &alsaBufferSizeInFrames);
                    info->bufferSizeInBytes = (int) alsaBufferSizeInFrames * frameSize;
#else
                    info->periodSize = snd_pcm_hw_params_get_period_size(info->hwParams, &dir);
                    info->periods = snd_pcm_hw_params_get_periods(info->hwParams, &dir);
                    info->bufferSizeInBytes = snd_pcm_hw_params_get_buffer_size(info->hwParams) * frameSize;
                    ret = 0;
#endif
                    TRACE3("  DAUDIO_Open: period size = %d frames, periods = %d. Buffer size: %d bytes.\n",
                           (int) info->periodSize, info->periods, info->bufferSizeInBytes);
                }
            }
        }
        if (ret == 0) {
            // set software parameters
            ret = snd_pcm_sw_params_malloc(&(info->swParams));
            if (ret != 0) {
                ERROR1("snd_pcm_hw_params_malloc returned error %d\n", ret);
            } else {
                if (!setSWParams(info)) {
                    ret = -1;
                }
            }
        }
        if (ret == 0) {
            // prepare device
            ret = snd_pcm_prepare(info->handle);
            if (ret < 0) {
                ERROR1("ERROR: snd_pcm_prepare: %s\n", snd_strerror(ret));
            }
        }

#ifdef GET_POSITION_METHOD2
        if (ret == 0) {
            ret = snd_pcm_status_malloc(&(info->positionStatus));
            if (ret != 0) {
                ERROR1("ERROR in snd_pcm_status_malloc: %s\n", snd_strerror(ret));
            }
        }
#endif
    }
    if (ret != 0) {
        DAUDIO_Close((void*) info, isSource);
        info = NULL;
    } else {
        // set to non-blocking mode
        snd_pcm_nonblock(info->handle, 1);
        TRACE1("< DAUDIO_Open: Opened device successfully. Handle=%p\n",
               (void*) info->handle);
    }
    return (void*) info;
}
Ejemplo n.º 4
0
/* return 0 on success */
int alsa_open_audio(int naudioindev, int *audioindev, int nchindev,
                    int *chindev, int naudiooutdev, int *audiooutdev, int nchoutdev,
                    int *choutdev, int rate)
{
    int err, inchans = 0, outchans = 0, subunitdir;
    char devname[512];
    snd_output_t* out;
    int frag_size = (sys_blocksize ? sys_blocksize : ALSA_DEFFRAGSIZE);
    int nfrags, i, iodev, dev2;
    int wantinchans, wantoutchans, device;

    nfrags = sys_schedadvance * (float)rate / (1e6 * frag_size);
    /* save our belief as to ALSA's buffer size for later */
    alsa_buf_samps = nfrags * frag_size;
    alsa_nindev = alsa_noutdev = 0;
    alsa_jittermax = ALSA_DEFJITTERMAX;

    if (sys_verbose)
        post("audio buffer set to %d", (int)(0.001 * sys_schedadvance));

    for (iodev = 0; iodev < naudioindev; iodev++)
    {
        alsa_numbertoname(audioindev[iodev], devname, 512);
        err = snd_pcm_open(&alsa_indev[alsa_nindev].a_handle, devname,
                           SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK);
        check_error(err, "snd_pcm_open (input)");
        if (err < 0)
            continue;
        alsa_indev[alsa_nindev].a_devno = audioindev[iodev];
        snd_pcm_nonblock(alsa_indev[alsa_nindev].a_handle, 1);
        if (sys_verbose)
            post("opened input device name %s", devname);
        alsa_nindev++;
    }
    for (iodev = 0; iodev < naudiooutdev; iodev++)
    {
        alsa_numbertoname(audiooutdev[iodev], devname, 512);
        err = snd_pcm_open(&alsa_outdev[alsa_noutdev].a_handle, devname,
                           SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK);
        check_error(err, "snd_pcm_open (output)");
        if (err < 0)
            continue;
        alsa_outdev[alsa_noutdev].a_devno = audiooutdev[iodev];
        snd_pcm_nonblock(alsa_outdev[alsa_noutdev].a_handle, 1);
        alsa_noutdev++;
    }
    if (!alsa_nindev && !alsa_noutdev)
        goto blewit;

    /* If all the open devices support mmap_noninterleaved, let's call
    Wini's code in s_audio_alsamm.c */
    alsa_usemmap = 1;
    for (iodev = 0; iodev < alsa_nindev; iodev++)
        if (!alsaio_canmmap(&alsa_indev[iodev]))
            alsa_usemmap = 0;
    for (iodev = 0; iodev < alsa_noutdev; iodev++)
        if (!alsaio_canmmap(&alsa_outdev[iodev]))
            alsa_usemmap = 0;
    if (alsa_usemmap)
    {
        post("using mmap audio interface");
        if (alsamm_open_audio(rate))
            goto blewit;
        else return (0);
    }
    for (iodev = 0; iodev < alsa_nindev; iodev++)
    {
        int channels = chindev[iodev];
        if (alsaio_setup(&alsa_indev[iodev], 0, &channels, &rate,
                         nfrags, frag_size) < 0)
            goto blewit;
        inchans += channels;
    }
    for (iodev = 0; iodev < alsa_noutdev; iodev++)
    {
        int channels = choutdev[iodev];
        if (alsaio_setup(&alsa_outdev[iodev], 1, &channels, &rate,
                         nfrags, frag_size) < 0)
            goto blewit;
        outchans += channels;
    }
    if (!inchans && !outchans)
        goto blewit;

    for (iodev = 0; iodev < alsa_nindev; iodev++)
        snd_pcm_prepare(alsa_indev[iodev].a_handle);
    for (iodev = 0; iodev < alsa_noutdev; iodev++)
        snd_pcm_prepare(alsa_outdev[iodev].a_handle);

    /* if duplex we can link the channels so they start together */
    for (iodev = 0; iodev < alsa_nindev; iodev++)
        for (dev2 = 0; dev2 < alsa_noutdev; dev2++)
        {
            if (alsa_indev[iodev].a_devno == alsa_outdev[iodev].a_devno)
            {
                snd_pcm_link(alsa_indev[iodev].a_handle,
                             alsa_outdev[iodev].a_handle);
            }
        }

    /* allocate the status variables */
    if (!alsa_status)
    {
        err = snd_pcm_status_malloc(&alsa_status);
        check_error(err, "snd_pcm_status_malloc");
    }

    /* fill the buffer with silence */
    memset(alsa_snd_buf, 0, alsa_snd_bufsize);

    if (outchans)
    {
        i = (frag_size * nfrags)/DEFDACBLKSIZE + 1;
        while (i--)
        {
            for (iodev = 0; iodev < alsa_noutdev; iodev++)
                snd_pcm_writei(alsa_outdev[iodev].a_handle, alsa_snd_buf,
                               DEFDACBLKSIZE);
        }
    }
    else if (inchans)
    {
        for (iodev = 0; iodev < alsa_nindev; iodev++)
            if ((err = snd_pcm_start(alsa_indev[iodev].a_handle)) < 0)
                check_error(err, "input start failed\n");
    }
    return (0);
blewit:
    sys_inchannels = 0;
    sys_outchannels = 0;
    alsa_close_audio();
    return (1);
}