• Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • Examples
  • 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 "libavutil/opt.h"
00050 
00051 #include "avdevice.h"
00052 #include "alsa-audio.h"
00053 
00054 static av_cold int audio_read_header(AVFormatContext *s1,
00055                                      AVFormatParameters *ap)
00056 {
00057     AlsaData *s = s1->priv_data;
00058     AVStream *st;
00059     int ret;
00060     enum CodecID codec_id;
00061     snd_pcm_sw_params_t *sw_params;
00062 
00063 #if FF_API_FORMAT_PARAMETERS
00064     if (ap->sample_rate > 0)
00065         s->sample_rate = ap->sample_rate;
00066 
00067     if (ap->channels > 0)
00068         s->channels = ap->channels;
00069 #endif
00070 
00071     st = av_new_stream(s1, 0);
00072     if (!st) {
00073         av_log(s1, AV_LOG_ERROR, "Cannot add stream\n");
00074 
00075         return AVERROR(ENOMEM);
00076     }
00077     codec_id    = s1->audio_codec_id;
00078 
00079     ret = ff_alsa_open(s1, SND_PCM_STREAM_CAPTURE, &s->sample_rate, s->channels,
00080         &codec_id);
00081     if (ret < 0) {
00082         return AVERROR(EIO);
00083     }
00084 
00085     if (snd_pcm_type(s->h) != SND_PCM_TYPE_HW)
00086         av_log(s1, AV_LOG_WARNING,
00087                "capture with some ALSA plugins, especially dsnoop, "
00088                "may hang.\n");
00089 
00090     ret = snd_pcm_sw_params_malloc(&sw_params);
00091     if (ret < 0) {
00092         av_log(s1, AV_LOG_ERROR, "cannot allocate software parameters structure (%s)\n",
00093                snd_strerror(ret));
00094         goto fail;
00095     }
00096 
00097     snd_pcm_sw_params_current(s->h, sw_params);
00098     snd_pcm_sw_params_set_tstamp_mode(s->h, sw_params, SND_PCM_TSTAMP_ENABLE);
00099 
00100     ret = snd_pcm_sw_params(s->h, sw_params);
00101     snd_pcm_sw_params_free(sw_params);
00102     if (ret < 0) {
00103         av_log(s1, AV_LOG_ERROR, "cannot install ALSA software parameters (%s)\n",
00104                snd_strerror(ret));
00105         goto fail;
00106     }
00107 
00108     /* take real parameters */
00109     st->codec->codec_type  = AVMEDIA_TYPE_AUDIO;
00110     st->codec->codec_id    = codec_id;
00111     st->codec->sample_rate = s->sample_rate;
00112     st->codec->channels    = s->channels;
00113     av_set_pts_info(st, 64, 1, 1000000);  /* 64 bits pts in us */
00114 
00115     return 0;
00116 
00117 fail:
00118     snd_pcm_close(s->h);
00119     return AVERROR(EIO);
00120 }
00121 
00122 static int audio_read_packet(AVFormatContext *s1, AVPacket *pkt)
00123 {
00124     AlsaData *s  = s1->priv_data;
00125     AVStream *st = s1->streams[0];
00126     int res;
00127     snd_htimestamp_t timestamp;
00128     snd_pcm_uframes_t ts_delay;
00129 
00130     if (av_new_packet(pkt, s->period_size) < 0) {
00131         return AVERROR(EIO);
00132     }
00133 
00134     while ((res = snd_pcm_readi(s->h, pkt->data, pkt->size / s->frame_size)) < 0) {
00135         if (res == -EAGAIN) {
00136             av_free_packet(pkt);
00137 
00138             return AVERROR(EAGAIN);
00139         }
00140         if (ff_alsa_xrun_recover(s1, res) < 0) {
00141             av_log(s1, AV_LOG_ERROR, "ALSA read error: %s\n",
00142                    snd_strerror(res));
00143             av_free_packet(pkt);
00144 
00145             return AVERROR(EIO);
00146         }
00147     }
00148 
00149     snd_pcm_htimestamp(s->h, &ts_delay, &timestamp);
00150     ts_delay += res;
00151     pkt->pts = timestamp.tv_sec * 1000000LL
00152                + (timestamp.tv_nsec * st->codec->sample_rate
00153                   - ts_delay * 1000000000LL + st->codec->sample_rate * 500LL)
00154                / (st->codec->sample_rate * 1000LL);
00155 
00156     pkt->size = res * s->frame_size;
00157 
00158     return 0;
00159 }
00160 
00161 static const AVOption options[] = {
00162     { "sample_rate", "", offsetof(AlsaData, sample_rate), FF_OPT_TYPE_INT, {.dbl = 48000}, 1, INT_MAX, AV_OPT_FLAG_DECODING_PARAM },
00163     { "channels",    "", offsetof(AlsaData, channels),    FF_OPT_TYPE_INT, {.dbl = 2},     1, INT_MAX, AV_OPT_FLAG_DECODING_PARAM },
00164     { NULL },
00165 };
00166 
00167 static const AVClass alsa_demuxer_class = {
00168     .class_name     = "ALSA demuxer",
00169     .item_name      = av_default_item_name,
00170     .option         = options,
00171     .version        = LIBAVUTIL_VERSION_INT,
00172 };
00173 
00174 AVInputFormat ff_alsa_demuxer = {
00175     "alsa",
00176     NULL_IF_CONFIG_SMALL("ALSA audio input"),
00177     sizeof(AlsaData),
00178     NULL,
00179     audio_read_header,
00180     audio_read_packet,
00181     ff_alsa_close,
00182     .flags = AVFMT_NOFILE,
00183     .priv_class = &alsa_demuxer_class,
00184 };

Generated on Wed Apr 11 2012 07:31:35 for FFmpeg by  doxygen 1.7.1