• Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • File List
  • Globals

libavdevice/alsa-audio-dec.c

Go to the documentation of this file.
00001 /*
00002  * ALSA input and output
00003  * Copyright (c) 2007 Luca Abeni ( lucabe72 email it )
00004  * Copyright (c) 2007 Benoit Fouet ( benoit fouet free fr )
00005  *
00006  * This file is part of FFmpeg.
00007  *
00008  * FFmpeg is free software; you can redistribute it and/or
00009  * modify it under the terms of the GNU Lesser General Public
00010  * License as published by the Free Software Foundation; either
00011  * version 2.1 of the License, or (at your option) any later version.
00012  *
00013  * FFmpeg is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00016  * Lesser General Public License for more details.
00017  *
00018  * You should have received a copy of the GNU Lesser General Public
00019  * License along with FFmpeg; if not, write to the Free Software
00020  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
00021  */
00022 
00048 #include <alsa/asoundlib.h>
00049 #include "libavformat/avformat.h"
00050 
00051 #include "alsa-audio.h"
00052 
00053 static av_cold int audio_read_header(AVFormatContext *s1,
00054                                      AVFormatParameters *ap)
00055 {
00056     AlsaData *s = s1->priv_data;
00057     AVStream *st;
00058     int ret;
00059     unsigned int sample_rate;
00060     enum CodecID codec_id;
00061     snd_pcm_sw_params_t *sw_params;
00062 
00063     if (ap->sample_rate <= 0) {
00064         av_log(s1, AV_LOG_ERROR, "Bad sample rate %d\n", ap->sample_rate);
00065 
00066         return AVERROR(EIO);
00067     }
00068 
00069     if (ap->channels <= 0) {
00070         av_log(s1, AV_LOG_ERROR, "Bad channels number %d\n", ap->channels);
00071 
00072         return AVERROR(EIO);
00073     }
00074 
00075     st = av_new_stream(s1, 0);
00076     if (!st) {
00077         av_log(s1, AV_LOG_ERROR, "Cannot add stream\n");
00078 
00079         return AVERROR(ENOMEM);
00080     }
00081     sample_rate = ap->sample_rate;
00082     codec_id    = s1->audio_codec_id;
00083 
00084     ret = ff_alsa_open(s1, SND_PCM_STREAM_CAPTURE, &sample_rate, ap->channels,
00085         &codec_id);
00086     if (ret < 0) {
00087         return AVERROR(EIO);
00088     }
00089 
00090     if (snd_pcm_type(s->h) != SND_PCM_TYPE_HW)
00091         av_log(s1, AV_LOG_WARNING,
00092                "capture with some ALSA plugins, especially dsnoop, "
00093                "may hang.\n");
00094 
00095     ret = snd_pcm_sw_params_malloc(&sw_params);
00096     if (ret < 0) {
00097         av_log(s1, AV_LOG_ERROR, "cannot allocate software parameters structure (%s)\n",
00098                snd_strerror(ret));
00099         goto fail;
00100     }
00101 
00102     snd_pcm_sw_params_current(s->h, sw_params);
00103     snd_pcm_sw_params_set_tstamp_mode(s->h, sw_params, SND_PCM_TSTAMP_ENABLE);
00104 
00105     ret = snd_pcm_sw_params(s->h, sw_params);
00106     snd_pcm_sw_params_free(sw_params);
00107     if (ret < 0) {
00108         av_log(s1, AV_LOG_ERROR, "cannot install ALSA software parameters (%s)\n",
00109                snd_strerror(ret));
00110         goto fail;
00111     }
00112 
00113     /* take real parameters */
00114     st->codec->codec_type  = AVMEDIA_TYPE_AUDIO;
00115     st->codec->codec_id    = codec_id;
00116     st->codec->sample_rate = sample_rate;
00117     st->codec->channels    = ap->channels;
00118     av_set_pts_info(st, 64, 1, 1000000);  /* 64 bits pts in us */
00119 
00120     return 0;
00121 
00122 fail:
00123     snd_pcm_close(s->h);
00124     return AVERROR(EIO);
00125 }
00126 
00127 static int audio_read_packet(AVFormatContext *s1, AVPacket *pkt)
00128 {
00129     AlsaData *s  = s1->priv_data;
00130     AVStream *st = s1->streams[0];
00131     int res;
00132     snd_htimestamp_t timestamp;
00133     snd_pcm_uframes_t ts_delay;
00134 
00135     if (av_new_packet(pkt, s->period_size) < 0) {
00136         return AVERROR(EIO);
00137     }
00138 
00139     while ((res = snd_pcm_readi(s->h, pkt->data, pkt->size / s->frame_size)) < 0) {
00140         if (res == -EAGAIN) {
00141             av_free_packet(pkt);
00142 
00143             return AVERROR(EAGAIN);
00144         }
00145         if (ff_alsa_xrun_recover(s1, res) < 0) {
00146             av_log(s1, AV_LOG_ERROR, "ALSA read error: %s\n",
00147                    snd_strerror(res));
00148             av_free_packet(pkt);
00149 
00150             return AVERROR(EIO);
00151         }
00152     }
00153 
00154     snd_pcm_htimestamp(s->h, &ts_delay, &timestamp);
00155     ts_delay += res;
00156     pkt->pts = timestamp.tv_sec * 1000000LL
00157                + (timestamp.tv_nsec * st->codec->sample_rate
00158                   - ts_delay * 1000000000LL + st->codec->sample_rate * 500LL)
00159                / (st->codec->sample_rate * 1000LL);
00160 
00161     pkt->size = res * s->frame_size;
00162 
00163     return 0;
00164 }
00165 
00166 AVInputFormat alsa_demuxer = {
00167     "alsa",
00168     NULL_IF_CONFIG_SMALL("ALSA audio input"),
00169     sizeof(AlsaData),
00170     NULL,
00171     audio_read_header,
00172     audio_read_packet,
00173     ff_alsa_close,
00174     .flags = AVFMT_NOFILE,
00175 };

Generated on Fri Sep 16 2011 17:17:47 for FFmpeg by  doxygen 1.7.1