00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00040 #include <alsa/asoundlib.h>
00041
00042 #include "avdevice.h"
00043 #include "alsa-audio.h"
00044
00045 static av_cold int audio_write_header(AVFormatContext *s1)
00046 {
00047 AlsaData *s = s1->priv_data;
00048 AVStream *st;
00049 unsigned int sample_rate;
00050 enum CodecID codec_id;
00051 int res;
00052
00053 st = s1->streams[0];
00054 sample_rate = st->codec->sample_rate;
00055 codec_id = st->codec->codec_id;
00056 res = ff_alsa_open(s1, SND_PCM_STREAM_PLAYBACK, &sample_rate,
00057 st->codec->channels, &codec_id);
00058 if (sample_rate != st->codec->sample_rate) {
00059 av_log(s1, AV_LOG_ERROR,
00060 "sample rate %d not available, nearest is %d\n",
00061 st->codec->sample_rate, sample_rate);
00062 goto fail;
00063 }
00064
00065 return res;
00066
00067 fail:
00068 snd_pcm_close(s->h);
00069 return AVERROR(EIO);
00070 }
00071
00072 static int audio_write_packet(AVFormatContext *s1, AVPacket *pkt)
00073 {
00074 AlsaData *s = s1->priv_data;
00075 int res;
00076 int size = pkt->size;
00077 uint8_t *buf = pkt->data;
00078
00079 size /= s->frame_size;
00080 if (s->reorder_func) {
00081 if (size > s->reorder_buf_size)
00082 if (ff_alsa_extend_reorder_buf(s, size))
00083 return AVERROR(ENOMEM);
00084 s->reorder_func(buf, s->reorder_buf, size);
00085 buf = s->reorder_buf;
00086 }
00087 while ((res = snd_pcm_writei(s->h, buf, size)) < 0) {
00088 if (res == -EAGAIN) {
00089
00090 return AVERROR(EAGAIN);
00091 }
00092
00093 if (ff_alsa_xrun_recover(s1, res) < 0) {
00094 av_log(s1, AV_LOG_ERROR, "ALSA write error: %s\n",
00095 snd_strerror(res));
00096
00097 return AVERROR(EIO);
00098 }
00099 }
00100
00101 return 0;
00102 }
00103
00104 AVOutputFormat ff_alsa_muxer = {
00105 "alsa",
00106 NULL_IF_CONFIG_SMALL("ALSA audio output"),
00107 "",
00108 "",
00109 sizeof(AlsaData),
00110 DEFAULT_CODEC_ID,
00111 CODEC_ID_NONE,
00112 audio_write_header,
00113 audio_write_packet,
00114 ff_alsa_close,
00115 .flags = AVFMT_NOFILE,
00116 };