1/* 2 * ALSA input and output 3 * Copyright (c) 2007 Luca Abeni ( lucabe72 email it ) 4 * Copyright (c) 2007 Benoit Fouet ( benoit fouet free fr ) 5 * 6 * This file is part of Libav. 7 * 8 * Libav is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU Lesser General Public 10 * License as published by the Free Software Foundation; either 11 * version 2.1 of the License, or (at your option) any later version. 12 * 13 * Libav is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 * Lesser General Public License for more details. 17 * 18 * You should have received a copy of the GNU Lesser General Public 19 * License along with Libav; if not, write to the Free Software 20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 21 */ 22 23/** 24 * @file 25 * ALSA input and output: output 26 * @author Luca Abeni ( lucabe72 email it ) 27 * @author Benoit Fouet ( benoit fouet free fr ) 28 * 29 * This avdevice encoder allows to play audio to an ALSA (Advanced Linux 30 * Sound Architecture) device. 31 * 32 * The filename parameter is the name of an ALSA PCM device capable of 33 * capture, for example "default" or "plughw:1"; see the ALSA documentation 34 * for naming conventions. The empty string is equivalent to "default". 35 * 36 * The playback period is set to the lower value available for the device, 37 * which gives a low latency suitable for real-time playback. 38 */ 39 40#include <alsa/asoundlib.h> 41#include "libavformat/avformat.h" 42 43#include "alsa-audio.h" 44 45static av_cold int audio_write_header(AVFormatContext *s1) 46{ 47 AlsaData *s = s1->priv_data; 48 AVStream *st; 49 unsigned int sample_rate; 50 enum CodecID codec_id; 51 int res; 52 53 st = s1->streams[0]; 54 sample_rate = st->codec->sample_rate; 55 codec_id = st->codec->codec_id; 56 res = ff_alsa_open(s1, SND_PCM_STREAM_PLAYBACK, &sample_rate, 57 st->codec->channels, &codec_id); 58 if (sample_rate != st->codec->sample_rate) { 59 av_log(s1, AV_LOG_ERROR, 60 "sample rate %d not available, nearest is %d\n", 61 st->codec->sample_rate, sample_rate); 62 goto fail; 63 } 64 65 return res; 66 67fail: 68 snd_pcm_close(s->h); 69 return AVERROR(EIO); 70} 71 72static int audio_write_packet(AVFormatContext *s1, AVPacket *pkt) 73{ 74 AlsaData *s = s1->priv_data; 75 int res; 76 int size = pkt->size; 77 uint8_t *buf = pkt->data; 78 79 size /= s->frame_size; 80 if (s->reorder_func) { 81 if (size > s->reorder_buf_size) 82 if (ff_alsa_extend_reorder_buf(s, size)) 83 return AVERROR(ENOMEM); 84 s->reorder_func(buf, s->reorder_buf, size); 85 buf = s->reorder_buf; 86 } 87 while ((res = snd_pcm_writei(s->h, buf, size)) < 0) { 88 if (res == -EAGAIN) { 89 90 return AVERROR(EAGAIN); 91 } 92 93 if (ff_alsa_xrun_recover(s1, res) < 0) { 94 av_log(s1, AV_LOG_ERROR, "ALSA write error: %s\n", 95 snd_strerror(res)); 96 97 return AVERROR(EIO); 98 } 99 } 100 101 return 0; 102} 103 104AVOutputFormat ff_alsa_muxer = { 105 .name = "alsa", 106 .long_name = NULL_IF_CONFIG_SMALL("ALSA audio output"), 107 .priv_data_size = sizeof(AlsaData), 108 .audio_codec = DEFAULT_CODEC_ID, 109 .video_codec = CODEC_ID_NONE, 110 .write_header = audio_write_header, 111 .write_packet = audio_write_packet, 112 .write_trailer = ff_alsa_close, 113 .flags = AVFMT_NOFILE, 114}; 115