Luca Abeni <[EMAIL PROTECTED]> added the comment:

Alsa support: common functions

----------
status: new -> open
substatus: new -> needs_changes

______________________________________________________
FFmpeg issue tracker <[EMAIL PROTECTED]>
<https://roundup.mplayerhq.hu/roundup/ffmpeg/issue247>
______________________________________________________
#include "avformat.h"
#include <alsa/asoundlib.h>

#include "alsa-audio.h"

static int alsa_codec_id(int codec_id)
{
    switch(codec_id) {
        case CODEC_ID_PCM_S16LE:
            return SND_PCM_FORMAT_S16_LE;
        case CODEC_ID_PCM_S16BE:
            return SND_PCM_FORMAT_S16_BE;
        default:
            return -1;
    }
}

int ff_alsa_supported_codec_id(enum CodecID codec_id)
{
    switch (codec_id) {
        case DEFAULT_CODEC_ID:
            return 1;
        default:
            return 0;
    }
}

int ff_alsa_open(AVFormatContext *ctx, int mode)
{
    AlsaData *s = ctx->priv_data;
    const char *audio_device;
    int res, flags = 0;
    snd_pcm_t *h;
    snd_pcm_hw_params_t *hw_params;

    if (ctx->filename[0] == 0) {
        audio_device = DEFAULT_DEVICE;
    } else {
        audio_device = ctx->filename;
    }

    if (ctx->flags & AVFMT_FLAG_NONBLOCK) {
        flags = O_NONBLOCK;
    }
    res = snd_pcm_open(&h, audio_device, mode, flags);
    if (res < 0) {
        av_log(NULL, AV_LOG_ERROR, "cannot open audio device %s (%s)\n",
                     audio_device, snd_strerror(res));

        return AVERROR_IO;
    }

    res = snd_pcm_hw_params_malloc(&hw_params);
    if (res < 0) {
        av_log(NULL, AV_LOG_ERROR, "cannot allocate hardware parameter structure (%s)\n",
                         snd_strerror(res));
        goto fail1;
    }

    res = snd_pcm_hw_params_any(h, hw_params);
    if (res < 0) {
        av_log(NULL, AV_LOG_ERROR, "cannot initialize hardware parameter structure (%s)\n",
                         snd_strerror(res));
        goto fail;
    }

    res = snd_pcm_hw_params_set_access(h, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED);
    if (res < 0) {
        av_log(NULL, AV_LOG_ERROR, "cannot set access type (%s)\n",
                         snd_strerror(res));
        goto fail;
    }

    res = snd_pcm_hw_params_set_format(h, hw_params, alsa_codec_id(s->codec_id));
    if (res < 0) {
        av_log(NULL, AV_LOG_ERROR, "cannot set sample format %d %d (%s)\n",
                         s->codec_id, alsa_codec_id(s->codec_id), snd_strerror(res));
        goto fail;
    }

    res = snd_pcm_hw_params_set_rate_near(h, hw_params, &s->sample_rate, 0);
    if (res < 0) {
        av_log(NULL, AV_LOG_ERROR, "cannot set sample rate (%s)\n",
                         snd_strerror(res));
        goto fail;
    }

    res = snd_pcm_hw_params_set_period_size(h, hw_params, AUDIO_BLOCK_SIZE / (av_get_bits_per_sample(s->codec_id) / 8 * s->channels), 0);
    if (res < 0) {
        av_log(NULL, AV_LOG_ERROR, "cannot set ALSA period size (%s)\n",
                         snd_strerror(res));
        goto fail;
    }
    s->frame_size = AUDIO_BLOCK_SIZE;

    res = snd_pcm_hw_params_set_channels(h, hw_params, s->channels);
    if (res < 0) {
        av_log(NULL, AV_LOG_ERROR, "cannot set channel count to %d (%s)\n",
                         s->channels, snd_strerror(res));
        goto fail;
    }

    res = snd_pcm_hw_params(h, hw_params);
    if (res < 0) {
        av_log(NULL, AV_LOG_ERROR, "cannot set parameters (%s)\n",
                         snd_strerror(res));
        goto fail;
    }
    
    snd_pcm_hw_params_free(hw_params);

    s->h = h;

    return 0;

fail:
    snd_pcm_hw_params_free(hw_params);
fail1:
    snd_pcm_close(h);
    return AVERROR_IO;

}

int ff_alsa_close(AlsaData *s)
{
    snd_pcm_close(s->h);

    return 0;
}

int ff_alsa_xrun_recover(AVFormatContext *s1, int err)
{
    AlsaData *s = s1->priv_data;
    snd_pcm_t *handle = s->h;

    av_log(s1, AV_LOG_ERROR, "XRUN!!!\n");
    if (err == -EPIPE) {
        err = snd_pcm_prepare(handle);
        if (err < 0) {
            av_log(NULL, AV_LOG_ERROR, "cannot recover from underrun (snd_pcm_prepare failed: %s)\n", snd_strerror(err));

            return 0;
        }
    } else if (err == -ESTRPIPE) {
        av_log(NULL, AV_LOG_ERROR, "-ESTPIPE... Unsupported!\n");

        return -1;
    }
    return err;
}

Reply via email to