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 FFmpeg. 7 * 8 * FFmpeg 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 * FFmpeg 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 FFmpeg; 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 libavdevice/alsa-audio-enc.c 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 "libavformat/avformat.h" 41#include <alsa/asoundlib.h> 42 43#include "alsa-audio.h" 44 45av_cold static int audio_write_header(AVFormatContext *s1) 46{ 47 AlsaData *s = s1->priv_data; 48 AVStream *st; 49 unsigned int sample_rate; 50 int 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 while((res = snd_pcm_writei(s->h, buf, size / s->frame_size)) < 0) { 80 if (res == -EAGAIN) { 81 82 return AVERROR(EAGAIN); 83 } 84 85 if (ff_alsa_xrun_recover(s1, res) < 0) { 86 av_log(s1, AV_LOG_ERROR, "ALSA write error: %s\n", 87 snd_strerror(res)); 88 89 return AVERROR(EIO); 90 } 91 } 92 93 return 0; 94} 95 96AVOutputFormat alsa_muxer = { 97 "alsa", 98 NULL_IF_CONFIG_SMALL("ALSA audio output"), 99 "", 100 "", 101 sizeof(AlsaData), 102 DEFAULT_CODEC_ID, 103 CODEC_ID_NONE, 104 audio_write_header, 105 audio_write_packet, 106 ff_alsa_close, 107 .flags = AVFMT_NOFILE, 108}; 109