00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
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
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);
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, ×tamp);
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 };