annotate ffmpeg/libavdevice/pulse.c @ 13:844d341cf643 tip

Back up before ISMIR
author Yading Song <yading.song@eecs.qmul.ac.uk>
date Thu, 31 Oct 2013 13:17:06 +0000
parents 6840f77b83aa
children
rev   line source
yading@10 1 /*
yading@10 2 * Pulseaudio input
yading@10 3 * Copyright (c) 2011 Luca Barbato <lu_zero@gentoo.org>
yading@10 4 *
yading@10 5 * This file is part of Libav.
yading@10 6 *
yading@10 7 * Libav is free software; you can redistribute it and/or
yading@10 8 * modify it under the terms of the GNU Lesser General Public
yading@10 9 * License as published by the Free Software Foundation; either
yading@10 10 * version 2.1 of the License, or (at your option) any later version.
yading@10 11 *
yading@10 12 * Libav is distributed in the hope that it will be useful,
yading@10 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
yading@10 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
yading@10 15 * Lesser General Public License for more details.
yading@10 16 *
yading@10 17 * You should have received a copy of the GNU Lesser General Public
yading@10 18 * License along with Libav; if not, write to the Free Software
yading@10 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
yading@10 20 */
yading@10 21
yading@10 22 /**
yading@10 23 * @file
yading@10 24 * PulseAudio input using the simple API.
yading@10 25 * @author Luca Barbato <lu_zero@gentoo.org>
yading@10 26 */
yading@10 27
yading@10 28 #include <pulse/simple.h>
yading@10 29 #include <pulse/rtclock.h>
yading@10 30 #include <pulse/error.h>
yading@10 31
yading@10 32 #include "libavformat/avformat.h"
yading@10 33 #include "libavformat/internal.h"
yading@10 34 #include "libavutil/opt.h"
yading@10 35
yading@10 36 #define DEFAULT_CODEC_ID AV_NE(AV_CODEC_ID_PCM_S16BE, AV_CODEC_ID_PCM_S16LE)
yading@10 37
yading@10 38 typedef struct PulseData {
yading@10 39 AVClass *class;
yading@10 40 char *server;
yading@10 41 char *name;
yading@10 42 char *stream_name;
yading@10 43 int sample_rate;
yading@10 44 int channels;
yading@10 45 int frame_size;
yading@10 46 int fragment_size;
yading@10 47 pa_simple *s;
yading@10 48 int64_t pts;
yading@10 49 int64_t frame_duration;
yading@10 50 } PulseData;
yading@10 51
yading@10 52 static pa_sample_format_t codec_id_to_pulse_format(int codec_id) {
yading@10 53 switch (codec_id) {
yading@10 54 case AV_CODEC_ID_PCM_U8: return PA_SAMPLE_U8;
yading@10 55 case AV_CODEC_ID_PCM_ALAW: return PA_SAMPLE_ALAW;
yading@10 56 case AV_CODEC_ID_PCM_MULAW: return PA_SAMPLE_ULAW;
yading@10 57 case AV_CODEC_ID_PCM_S16LE: return PA_SAMPLE_S16LE;
yading@10 58 case AV_CODEC_ID_PCM_S16BE: return PA_SAMPLE_S16BE;
yading@10 59 case AV_CODEC_ID_PCM_F32LE: return PA_SAMPLE_FLOAT32LE;
yading@10 60 case AV_CODEC_ID_PCM_F32BE: return PA_SAMPLE_FLOAT32BE;
yading@10 61 case AV_CODEC_ID_PCM_S32LE: return PA_SAMPLE_S32LE;
yading@10 62 case AV_CODEC_ID_PCM_S32BE: return PA_SAMPLE_S32BE;
yading@10 63 case AV_CODEC_ID_PCM_S24LE: return PA_SAMPLE_S24LE;
yading@10 64 case AV_CODEC_ID_PCM_S24BE: return PA_SAMPLE_S24BE;
yading@10 65 default: return PA_SAMPLE_INVALID;
yading@10 66 }
yading@10 67 }
yading@10 68
yading@10 69 static av_cold int pulse_read_header(AVFormatContext *s)
yading@10 70 {
yading@10 71 PulseData *pd = s->priv_data;
yading@10 72 AVStream *st;
yading@10 73 char *device = NULL;
yading@10 74 int ret;
yading@10 75 enum AVCodecID codec_id =
yading@10 76 s->audio_codec_id == AV_CODEC_ID_NONE ? DEFAULT_CODEC_ID : s->audio_codec_id;
yading@10 77 const pa_sample_spec ss = { codec_id_to_pulse_format(codec_id),
yading@10 78 pd->sample_rate,
yading@10 79 pd->channels };
yading@10 80
yading@10 81 pa_buffer_attr attr = { -1 };
yading@10 82
yading@10 83 st = avformat_new_stream(s, NULL);
yading@10 84
yading@10 85 if (!st) {
yading@10 86 av_log(s, AV_LOG_ERROR, "Cannot add stream\n");
yading@10 87 return AVERROR(ENOMEM);
yading@10 88 }
yading@10 89
yading@10 90 attr.fragsize = pd->fragment_size;
yading@10 91
yading@10 92 if (strcmp(s->filename, "default"))
yading@10 93 device = s->filename;
yading@10 94
yading@10 95 pd->s = pa_simple_new(pd->server, pd->name,
yading@10 96 PA_STREAM_RECORD,
yading@10 97 device, pd->stream_name, &ss,
yading@10 98 NULL, &attr, &ret);
yading@10 99
yading@10 100 if (!pd->s) {
yading@10 101 av_log(s, AV_LOG_ERROR, "pa_simple_new failed: %s\n",
yading@10 102 pa_strerror(ret));
yading@10 103 return AVERROR(EIO);
yading@10 104 }
yading@10 105 /* take real parameters */
yading@10 106 st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
yading@10 107 st->codec->codec_id = codec_id;
yading@10 108 st->codec->sample_rate = pd->sample_rate;
yading@10 109 st->codec->channels = pd->channels;
yading@10 110 avpriv_set_pts_info(st, 64, 1, 1000000); /* 64 bits pts in us */
yading@10 111
yading@10 112 pd->pts = AV_NOPTS_VALUE;
yading@10 113 pd->frame_duration = (pd->frame_size * 1000000LL * 8) /
yading@10 114 (pd->sample_rate * pd->channels * av_get_bits_per_sample(codec_id));
yading@10 115
yading@10 116 return 0;
yading@10 117 }
yading@10 118
yading@10 119 static int pulse_read_packet(AVFormatContext *s, AVPacket *pkt)
yading@10 120 {
yading@10 121 PulseData *pd = s->priv_data;
yading@10 122 int res;
yading@10 123 pa_usec_t latency;
yading@10 124
yading@10 125 if (av_new_packet(pkt, pd->frame_size) < 0) {
yading@10 126 return AVERROR(ENOMEM);
yading@10 127 }
yading@10 128
yading@10 129 if ((pa_simple_read(pd->s, pkt->data, pkt->size, &res)) < 0) {
yading@10 130 av_log(s, AV_LOG_ERROR, "pa_simple_read failed: %s\n",
yading@10 131 pa_strerror(res));
yading@10 132 av_free_packet(pkt);
yading@10 133 return AVERROR(EIO);
yading@10 134 }
yading@10 135
yading@10 136 if ((latency = pa_simple_get_latency(pd->s, &res)) == (pa_usec_t) -1) {
yading@10 137 av_log(s, AV_LOG_ERROR, "pa_simple_get_latency() failed: %s\n",
yading@10 138 pa_strerror(res));
yading@10 139 return AVERROR(EIO);
yading@10 140 }
yading@10 141
yading@10 142 if (pd->pts == AV_NOPTS_VALUE) {
yading@10 143 pd->pts = -latency;
yading@10 144 }
yading@10 145
yading@10 146 pkt->pts = pd->pts;
yading@10 147
yading@10 148 pd->pts += pd->frame_duration;
yading@10 149
yading@10 150 return 0;
yading@10 151 }
yading@10 152
yading@10 153 static av_cold int pulse_close(AVFormatContext *s)
yading@10 154 {
yading@10 155 PulseData *pd = s->priv_data;
yading@10 156 pa_simple_free(pd->s);
yading@10 157 return 0;
yading@10 158 }
yading@10 159
yading@10 160 #define OFFSET(a) offsetof(PulseData, a)
yading@10 161 #define D AV_OPT_FLAG_DECODING_PARAM
yading@10 162
yading@10 163 static const AVOption options[] = {
yading@10 164 { "server", "pulse server name", OFFSET(server), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, D },
yading@10 165 { "name", "application name", OFFSET(name), AV_OPT_TYPE_STRING, {.str = LIBAVFORMAT_IDENT}, 0, 0, D },
yading@10 166 { "stream_name", "stream description", OFFSET(stream_name), AV_OPT_TYPE_STRING, {.str = "record"}, 0, 0, D },
yading@10 167 { "sample_rate", "sample rate in Hz", OFFSET(sample_rate), AV_OPT_TYPE_INT, {.i64 = 48000}, 1, INT_MAX, D },
yading@10 168 { "channels", "number of audio channels", OFFSET(channels), AV_OPT_TYPE_INT, {.i64 = 2}, 1, INT_MAX, D },
yading@10 169 { "frame_size", "number of bytes per frame", OFFSET(frame_size), AV_OPT_TYPE_INT, {.i64 = 1024}, 1, INT_MAX, D },
yading@10 170 { "fragment_size", "buffering size, affects latency and cpu usage", OFFSET(fragment_size), AV_OPT_TYPE_INT, {.i64 = -1}, -1, INT_MAX, D },
yading@10 171 { NULL },
yading@10 172 };
yading@10 173
yading@10 174 static const AVClass pulse_demuxer_class = {
yading@10 175 .class_name = "Pulse demuxer",
yading@10 176 .item_name = av_default_item_name,
yading@10 177 .option = options,
yading@10 178 .version = LIBAVUTIL_VERSION_INT,
yading@10 179 };
yading@10 180
yading@10 181 AVInputFormat ff_pulse_demuxer = {
yading@10 182 .name = "pulse",
yading@10 183 .long_name = NULL_IF_CONFIG_SMALL("Pulse audio input"),
yading@10 184 .priv_data_size = sizeof(PulseData),
yading@10 185 .read_header = pulse_read_header,
yading@10 186 .read_packet = pulse_read_packet,
yading@10 187 .read_close = pulse_close,
yading@10 188 .flags = AVFMT_NOFILE,
yading@10 189 .priv_class = &pulse_demuxer_class,
yading@10 190 };