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

Alsa support: demuxer

______________________________________________________
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 audio_read_close(AVFormatContext *s1)
{
    AlsaData *s = s1->priv_data;

    ff_alsa_close(s);
    return 0;
}

static int audio_read_header(AVFormatContext *s1, AVFormatParameters *ap)
{
    AlsaData *s = s1->priv_data;
    AVStream *st;
    int ret;

    if (ap->sample_rate <= 0 || ap->channels <= 0) {
        av_log(s1, AV_LOG_ERROR, "Bad sample rate %d or channels number %d\n",
                   ap->sample_rate, ap->channels);

        return AVERROR(EIO);
    }

    st = av_new_stream(s1, 0);
    if (st == NULL) {
        av_log(s1, AV_LOG_ERROR, "Cannot add stream\n");

        return AVERROR(ENOMEM);
    }
    s->sample_rate = ap->sample_rate;
    s->channels = ap->channels;
    if (ff_alsa_supported_codec_id(ap->audio_codec_id)) {
        s->codec_id = ap->audio_codec_id;
    } else {
        s->codec_id = DEFAULT_CODEC_ID;
    }

    ret = ff_alsa_open(s1, SND_PCM_STREAM_CAPTURE);
    if (ret < 0) {
        av_free(st);

        return AVERROR(EIO);
    }

    /* take real parameters */
    st->codec->codec_type = CODEC_TYPE_AUDIO;
    st->codec->codec_id = s->codec_id;
    st->codec->sample_rate = s->sample_rate;
    st->codec->channels = s->channels;

    av_set_pts_info(st, 64, 1, 1000000);  /* 64 bits pts in us */

    return 0;
}

static int audio_read_packet(AVFormatContext *s1, AVPacket *pkt)
{
    AlsaData *s = s1->priv_data;
    int res;

    if (av_new_packet(pkt, s->frame_size) < 0) {
        return AVERROR(EIO);
    }
    while ((res = snd_pcm_readi(s->h, pkt->data, pkt->size / (av_get_bits_per_sample(s->codec_id) / 8 * s->channels))) < 0) {
        if (res == -EAGAIN) {
            pkt->size = 0;
            av_free_packet(pkt);

            return AVERROR(EAGAIN);
        }
	if (ff_alsa_xrun_recover(s1, res) < 0) {
                av_log(s1, AV_LOG_ERROR, "Alsa read error: %s\n",
                                   snd_strerror(res));
                av_free_packet(pkt);

                return AVERROR(EIO);
        }
    }
    pkt->size = res * (av_get_bits_per_sample(s->codec_id) / 8 * s->channels);
    pkt->pts = av_gettime();   /* FIXME: We might need something better... */

    return 0;
}

AVInputFormat alsa_demuxer = {
    "alsa",
    "Alsa audio input",
    sizeof(AlsaData),
    NULL,
    audio_read_header,
    audio_read_packet,
    audio_read_close,
    .flags = AVFMT_NOFILE,
};

Reply via email to