FFmpeg
pulse_audio_dec.c
Go to the documentation of this file.
1 /*
2  * Pulseaudio input
3  * Copyright (c) 2011 Luca Barbato <lu_zero@gentoo.org>
4  * Copyright 2004-2006 Lennart Poettering
5  * Copyright (c) 2014 Michael Niedermayer <michaelni@gmx.at>
6  *
7  * This file is part of FFmpeg.
8  *
9  * FFmpeg is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 2.1 of the License, or (at your option) any later version.
13  *
14  * FFmpeg is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with FFmpeg; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22  */
23 
24 #include <pulse/rtclock.h>
25 #include <pulse/error.h>
26 
27 #include "libavutil/internal.h"
28 #include "libavutil/opt.h"
29 #include "libavutil/time.h"
30 
31 #include "libavformat/avformat.h"
32 #include "libavformat/internal.h"
33 #include "libavformat/version.h"
34 #include "pulse_audio_common.h"
35 #include "timefilter.h"
36 
37 #define DEFAULT_CODEC_ID AV_NE(AV_CODEC_ID_PCM_S16BE, AV_CODEC_ID_PCM_S16LE)
38 
39 typedef struct PulseData {
40  AVClass *class;
41  char *server;
42  char *name;
43  char *stream_name;
45  int channels;
48 
49  pa_threaded_mainloop *mainloop;
50  pa_context *context;
51  pa_stream *stream;
52  size_t pa_frame_size;
53 
56  int wallclock;
57 } PulseData;
58 
59 
60 #define CHECK_SUCCESS_GOTO(rerror, expression, label) \
61  do { \
62  if (!(expression)) { \
63  rerror = AVERROR_EXTERNAL; \
64  goto label; \
65  } \
66  } while (0)
67 
68 #define CHECK_DEAD_GOTO(p, rerror, label) \
69  do { \
70  if (!(p)->context || !PA_CONTEXT_IS_GOOD(pa_context_get_state((p)->context)) || \
71  !(p)->stream || !PA_STREAM_IS_GOOD(pa_stream_get_state((p)->stream))) { \
72  rerror = AVERROR_EXTERNAL; \
73  goto label; \
74  } \
75  } while (0)
76 
77 static void context_state_cb(pa_context *c, void *userdata) {
78  PulseData *p = userdata;
79 
80  switch (pa_context_get_state(c)) {
81  case PA_CONTEXT_READY:
82  case PA_CONTEXT_TERMINATED:
83  case PA_CONTEXT_FAILED:
84  pa_threaded_mainloop_signal(p->mainloop, 0);
85  break;
86  }
87 }
88 
89 static void stream_state_cb(pa_stream *s, void * userdata) {
90  PulseData *p = userdata;
91 
92  switch (pa_stream_get_state(s)) {
93  case PA_STREAM_READY:
94  case PA_STREAM_FAILED:
95  case PA_STREAM_TERMINATED:
96  pa_threaded_mainloop_signal(p->mainloop, 0);
97  break;
98  }
99 }
100 
101 static void stream_request_cb(pa_stream *s, size_t length, void *userdata) {
102  PulseData *p = userdata;
103 
104  pa_threaded_mainloop_signal(p->mainloop, 0);
105 }
106 
107 static void stream_latency_update_cb(pa_stream *s, void *userdata) {
108  PulseData *p = userdata;
109 
110  pa_threaded_mainloop_signal(p->mainloop, 0);
111 }
112 
114 {
115  PulseData *pd = s->priv_data;
116 
117  if (pd->mainloop)
118  pa_threaded_mainloop_stop(pd->mainloop);
119 
120  if (pd->stream)
121  pa_stream_unref(pd->stream);
122  pd->stream = NULL;
123 
124  if (pd->context) {
125  pa_context_disconnect(pd->context);
126  pa_context_unref(pd->context);
127  }
128  pd->context = NULL;
129 
130  if (pd->mainloop)
131  pa_threaded_mainloop_free(pd->mainloop);
132  pd->mainloop = NULL;
133 
135  pd->timefilter = NULL;
136 
137  return 0;
138 }
139 
141 {
142  PulseData *pd = s->priv_data;
143  AVStream *st;
144  char *device = NULL;
145  int ret;
146  enum AVCodecID codec_id =
147  s->audio_codec_id == AV_CODEC_ID_NONE ? DEFAULT_CODEC_ID : s->audio_codec_id;
148  const pa_sample_spec ss = { ff_codec_id_to_pulse_format(codec_id),
149  pd->sample_rate,
150  pd->channels };
151 
152  pa_buffer_attr attr = { -1 };
153  pa_channel_map cmap;
154  const pa_buffer_attr *queried_attr;
155 
156  pa_channel_map_init_extend(&cmap, pd->channels, PA_CHANNEL_MAP_WAVEEX);
157 
158  st = avformat_new_stream(s, NULL);
159 
160  if (!st) {
161  av_log(s, AV_LOG_ERROR, "Cannot add stream\n");
162  return AVERROR(ENOMEM);
163  }
164 
165  attr.fragsize = pd->fragment_size;
166 
167  if (s->url[0] != '\0' && strcmp(s->url, "default"))
168  device = s->url;
169 
170  if (!(pd->mainloop = pa_threaded_mainloop_new())) {
171  pulse_close(s);
172  return AVERROR_EXTERNAL;
173  }
174 
175  if (!(pd->context = pa_context_new(pa_threaded_mainloop_get_api(pd->mainloop), pd->name))) {
176  pulse_close(s);
177  return AVERROR_EXTERNAL;
178  }
179 
180  pa_context_set_state_callback(pd->context, context_state_cb, pd);
181 
182  if (pa_context_connect(pd->context, pd->server, 0, NULL) < 0) {
183  pulse_close(s);
184  return AVERROR(pa_context_errno(pd->context));
185  }
186 
187  pa_threaded_mainloop_lock(pd->mainloop);
188 
189  if (pa_threaded_mainloop_start(pd->mainloop) < 0) {
190  ret = -1;
191  goto unlock_and_fail;
192  }
193 
194  for (;;) {
195  pa_context_state_t state;
196 
197  state = pa_context_get_state(pd->context);
198 
199  if (state == PA_CONTEXT_READY)
200  break;
201 
202  if (!PA_CONTEXT_IS_GOOD(state)) {
203  ret = AVERROR(pa_context_errno(pd->context));
204  goto unlock_and_fail;
205  }
206 
207  /* Wait until the context is ready */
208  pa_threaded_mainloop_wait(pd->mainloop);
209  }
210 
211  if (!(pd->stream = pa_stream_new(pd->context, pd->stream_name, &ss, &cmap))) {
212  ret = AVERROR(pa_context_errno(pd->context));
213  goto unlock_and_fail;
214  }
215 
216  pa_stream_set_state_callback(pd->stream, stream_state_cb, pd);
217  pa_stream_set_read_callback(pd->stream, stream_request_cb, pd);
218  pa_stream_set_write_callback(pd->stream, stream_request_cb, pd);
219  pa_stream_set_latency_update_callback(pd->stream, stream_latency_update_cb, pd);
220 
221  ret = pa_stream_connect_record(pd->stream, device, &attr,
222  PA_STREAM_INTERPOLATE_TIMING
223  | (pd->fragment_size == -1 ? PA_STREAM_ADJUST_LATENCY : 0)
224  |PA_STREAM_AUTO_TIMING_UPDATE);
225 
226  if (ret < 0) {
227  ret = AVERROR(pa_context_errno(pd->context));
228  goto unlock_and_fail;
229  }
230 
231  for (;;) {
232  pa_stream_state_t state;
233 
234  state = pa_stream_get_state(pd->stream);
235 
236  if (state == PA_STREAM_READY)
237  break;
238 
239  if (!PA_STREAM_IS_GOOD(state)) {
240  ret = AVERROR(pa_context_errno(pd->context));
241  goto unlock_and_fail;
242  }
243 
244  /* Wait until the stream is ready */
245  pa_threaded_mainloop_wait(pd->mainloop);
246  }
247 
248  /* Query actual fragment size */
249  queried_attr = pa_stream_get_buffer_attr(pd->stream);
250  if (!queried_attr || queried_attr->fragsize > INT_MAX/100) {
252  goto unlock_and_fail;
253  }
254  pd->fragment_size = queried_attr->fragsize;
255  pd->pa_frame_size = pa_frame_size(&ss);
256 
257  pa_threaded_mainloop_unlock(pd->mainloop);
258 
259  /* take real parameters */
261  st->codecpar->codec_id = codec_id;
262  st->codecpar->sample_rate = pd->sample_rate;
264  avpriv_set_pts_info(st, 64, 1, 1000000); /* 64 bits pts in us */
265 
266  pd->timefilter = ff_timefilter_new(1000000.0 / pd->sample_rate,
267  pd->fragment_size / pd->pa_frame_size, 1.5E-6);
268 
269  if (!pd->timefilter) {
270  pulse_close(s);
271  return AVERROR(ENOMEM);
272  }
273 
274  return 0;
275 
276 unlock_and_fail:
277  pa_threaded_mainloop_unlock(pd->mainloop);
278 
279  pulse_close(s);
280  return ret;
281 }
282 
284 {
285  PulseData *pd = s->priv_data;
286  int ret;
287  size_t read_length;
288  const void *read_data = NULL;
289  int64_t dts;
290  pa_usec_t latency;
291  int negative;
292  ptrdiff_t pos = 0;
293 
294  pa_threaded_mainloop_lock(pd->mainloop);
295 
296  CHECK_DEAD_GOTO(pd, ret, unlock_and_fail);
297 
298  while (pos < pd->fragment_size) {
299  int r;
300 
301  r = pa_stream_peek(pd->stream, &read_data, &read_length);
302  CHECK_SUCCESS_GOTO(ret, r == 0, unlock_and_fail);
303 
304  if (read_length <= 0) {
305  pa_threaded_mainloop_wait(pd->mainloop);
306  CHECK_DEAD_GOTO(pd, ret, unlock_and_fail);
307  } else if (!read_data) {
308  /* There's a hole in the stream, skip it. We could generate
309  * silence, but that wouldn't work for compressed streams. */
310  r = pa_stream_drop(pd->stream);
311  CHECK_SUCCESS_GOTO(ret, r == 0, unlock_and_fail);
312  } else {
313  if (!pos) {
314  if (av_new_packet(pkt, pd->fragment_size) < 0) {
315  ret = AVERROR(ENOMEM);
316  goto unlock_and_fail;
317  }
318 
319  dts = av_gettime();
320  pa_operation_unref(pa_stream_update_timing_info(pd->stream, NULL, NULL));
321 
322  if (pa_stream_get_latency(pd->stream, &latency, &negative) >= 0) {
323  if (negative) {
324  dts += latency;
325  } else
326  dts -= latency;
327  } else {
328  av_log(s, AV_LOG_WARNING, "pa_stream_get_latency() failed\n");
329  }
330  }
331  if (pkt->size - pos < read_length) {
332  if (pos)
333  break;
334  pa_stream_drop(pd->stream);
335  /* Oversized fragment??? */
337  goto unlock_and_fail;
338  }
339  memcpy(pkt->data + pos, read_data, read_length);
340  pos += read_length;
341  pa_stream_drop(pd->stream);
342  }
343  }
344 
345  pa_threaded_mainloop_unlock(pd->mainloop);
346 
348 
349  if (pd->wallclock)
351  pd->last_period = pkt->size / pd->pa_frame_size;
352 
353  return 0;
354 
355 unlock_and_fail:
357  pa_threaded_mainloop_unlock(pd->mainloop);
358  return ret;
359 }
360 
362 {
363  PulseData *s = h->priv_data;
364  return ff_pulse_audio_get_devices(device_list, s->server, 0);
365 }
366 
367 #define OFFSET(a) offsetof(PulseData, a)
368 #define D AV_OPT_FLAG_DECODING_PARAM
369 
370 static const AVOption options[] = {
371  { "server", "set PulseAudio server", OFFSET(server), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, D },
372  { "name", "set application name", OFFSET(name), AV_OPT_TYPE_STRING, {.str = LIBAVFORMAT_IDENT}, 0, 0, D },
373  { "stream_name", "set stream description", OFFSET(stream_name), AV_OPT_TYPE_STRING, {.str = "record"}, 0, 0, D },
374  { "sample_rate", "set sample rate in Hz", OFFSET(sample_rate), AV_OPT_TYPE_INT, {.i64 = 48000}, 1, INT_MAX, D },
375  { "channels", "set number of audio channels", OFFSET(channels), AV_OPT_TYPE_INT, {.i64 = 2}, 1, INT_MAX, D },
376  { "frame_size", "set number of bytes per frame", OFFSET(frame_size), AV_OPT_TYPE_INT, {.i64 = 1024}, 1, INT_MAX, D },
377  { "fragment_size", "set buffering size, affects latency and cpu usage", OFFSET(fragment_size), AV_OPT_TYPE_INT, {.i64 = -1}, -1, INT_MAX, D },
378  { "wallclock", "set the initial pts using the current time", OFFSET(wallclock), AV_OPT_TYPE_INT, {.i64 = 1}, -1, 1, D },
379  { NULL },
380 };
381 
382 static const AVClass pulse_demuxer_class = {
383  .class_name = "Pulse indev",
384  .item_name = av_default_item_name,
385  .option = options,
386  .version = LIBAVUTIL_VERSION_INT,
388 };
389 
391  .name = "pulse",
392  .long_name = NULL_IF_CONFIG_SMALL("Pulse audio input"),
393  .priv_data_size = sizeof(PulseData),
397  .get_device_list = pulse_get_device_list,
398  .flags = AVFMT_NOFILE,
399  .priv_class = &pulse_demuxer_class,
400 };
PulseData::context
pa_context * context
Definition: pulse_audio_dec.c:50
options
static const AVOption options[]
Definition: pulse_audio_dec.c:370
av_packet_unref
void av_packet_unref(AVPacket *pkt)
Wipe the packet.
Definition: avpacket.c:422
TimeFilter
Opaque type representing a time filter state.
Definition: timefilter.c:34
AV_LOG_WARNING
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:186
name
it s the only field you need to keep assuming you have a context There is some magic you don t need to care about around this just let it vf default minimum maximum flags name is the option name
Definition: writing_filters.txt:88
LIBAVFORMAT_IDENT
#define LIBAVFORMAT_IDENT
Definition: version.h:45
read_data
static int read_data(void *opaque, uint8_t *buf, int buf_size)
Definition: dashdec.c:1764
r
const char * r
Definition: vf_curves.c:116
AVERROR
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later. That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another. Frame references ownership and permissions
opt.h
avformat_new_stream
AVStream * avformat_new_stream(AVFormatContext *s, const AVCodec *c)
Add a new stream to a media file.
Definition: options.c:237
AVCodecParameters::codec_type
enum AVMediaType codec_type
General type of the encoded data.
Definition: codec_par.h:57
PulseData::mainloop
pa_threaded_mainloop * mainloop
Definition: pulse_audio_dec.c:49
pulse_get_device_list
static int pulse_get_device_list(AVFormatContext *h, AVDeviceInfoList *device_list)
Definition: pulse_audio_dec.c:361
PulseData::frame_size
int frame_size
Definition: pulse_audio_dec.c:46
stream_latency_update_cb
static void stream_latency_update_cb(pa_stream *s, void *userdata)
Definition: pulse_audio_dec.c:107
AVPacket::data
uint8_t * data
Definition: packet.h:374
AVOption
AVOption.
Definition: opt.h:251
ff_codec_id_to_pulse_format
pa_sample_format_t av_cold ff_codec_id_to_pulse_format(enum AVCodecID codec_id)
Definition: pulse_audio_common.c:29
PulseData::channels
int channels
Definition: pulse_audio_dec.c:45
AVChannelLayout::nb_channels
int nb_channels
Number of channels in this layout.
Definition: channel_layout.h:300
sample_rate
sample_rate
Definition: ffmpeg_filter.c:153
PulseData
Definition: pulse_audio_dec.c:39
PulseData::stream
pa_stream * stream
Definition: pulse_audio_dec.c:51
avpriv_set_pts_info
void avpriv_set_pts_info(AVStream *st, int pts_wrap_bits, unsigned int pts_num, unsigned int pts_den)
Set the time base and wrapping info for a given stream.
Definition: avformat.c:697
PulseData::name
char * name
Definition: pulse_audio_dec.c:42
av_shrink_packet
void av_shrink_packet(AVPacket *pkt, int size)
Reduce packet size, correctly zeroing padding.
Definition: avpacket.c:112
read_close
static av_cold int read_close(AVFormatContext *ctx)
Definition: libcdio.c:143
ss
#define ss(width, name, subs,...)
Definition: cbs_vp9.c:260
ff_timefilter_new
TimeFilter * ff_timefilter_new(double time_base, double period, double bandwidth)
Create a new Delay Locked Loop time filter.
Definition: timefilter.c:50
stream_request_cb
static void stream_request_cb(pa_stream *s, size_t length, void *userdata)
Definition: pulse_audio_dec.c:101
AV_CLASS_CATEGORY_DEVICE_AUDIO_INPUT
@ AV_CLASS_CATEGORY_DEVICE_AUDIO_INPUT
Definition: log.h:43
pkt
AVPacket * pkt
Definition: movenc.c:59
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:180
AVInputFormat
Definition: avformat.h:656
av_cold
#define av_cold
Definition: attributes.h:90
s
#define s(width, name)
Definition: cbs_vp9.c:256
av_new_packet
int av_new_packet(AVPacket *pkt, int size)
Allocate the payload of a packet and initialize its fields with default values.
Definition: avpacket.c:97
ff_pulse_demuxer
const AVInputFormat ff_pulse_demuxer
Definition: pulse_audio_dec.c:390
AVInputFormat::name
const char * name
A comma separated list of short names for the format.
Definition: avformat.h:661
frame_size
int frame_size
Definition: mxfenc.c:2201
ff_pulse_audio_get_devices
int ff_pulse_audio_get_devices(AVDeviceInfoList *devices, const char *server, int output)
Definition: pulse_audio_common.c:197
AVMEDIA_TYPE_AUDIO
@ AVMEDIA_TYPE_AUDIO
Definition: avutil.h:202
PulseData::wallclock
int wallclock
Definition: pulse_audio_dec.c:56
PulseData::sample_rate
int sample_rate
Definition: pulse_audio_dec.c:44
channels
channels
Definition: aptx.h:32
codec_id
enum AVCodecID codec_id
Definition: vaapi_decode.c:371
PulseData::stream_name
char * stream_name
Definition: pulse_audio_dec.c:43
AVFormatContext
Format I/O context.
Definition: avformat.h:1213
internal.h
AVStream::codecpar
AVCodecParameters * codecpar
Codec parameters associated with this stream.
Definition: avformat.h:1108
pulse_close
static av_cold int pulse_close(AVFormatContext *s)
Definition: pulse_audio_dec.c:113
LIBAVUTIL_VERSION_INT
#define LIBAVUTIL_VERSION_INT
Definition: version.h:85
read_header
static int read_header(FFV1Context *f)
Definition: ffv1dec.c:529
AVClass
Describe the class of an AVClass context structure.
Definition: log.h:66
NULL
#define NULL
Definition: coverity.c:32
timefilter.h
av_default_item_name
const char * av_default_item_name(void *ptr)
Return the context name.
Definition: log.c:237
time.h
AVCodecParameters::ch_layout
AVChannelLayout ch_layout
Audio only.
Definition: codec_par.h:212
c
Undefined Behavior In the C some operations are like signed integer dereferencing freed accessing outside allocated Undefined Behavior must not occur in a C it is not safe even if the output of undefined operations is unused The unsafety may seem nit picking but Optimizing compilers have in fact optimized code on the assumption that no undefined Behavior occurs Optimizing code based on wrong assumptions can and has in some cases lead to effects beyond the output of computations The signed integer overflow problem in speed critical code Code which is highly optimized and works with signed integers sometimes has the problem that often the output of the computation does not c
Definition: undefined.txt:32
AVCodecParameters::sample_rate
int sample_rate
Audio only.
Definition: codec_par.h:177
AVCodecID
AVCodecID
Identify the syntax and semantics of the bitstream.
Definition: codec_id.h:47
pulse_audio_common.h
PulseData::timefilter
TimeFilter * timefilter
Definition: pulse_audio_dec.c:54
AVPacket::size
int size
Definition: packet.h:375
NULL_IF_CONFIG_SMALL
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification.
Definition: internal.h:117
PulseData::server
char * server
Definition: pulse_audio_dec.c:41
AVFMT_NOFILE
#define AVFMT_NOFILE
Demuxer will use avio_open, no opened file should be provided by the caller.
Definition: avformat.h:470
CHECK_SUCCESS_GOTO
#define CHECK_SUCCESS_GOTO(rerror, expression, label)
Definition: pulse_audio_dec.c:60
AVERROR_EXTERNAL
#define AVERROR_EXTERNAL
Generic error in an external library.
Definition: error.h:59
CHECK_DEAD_GOTO
#define CHECK_DEAD_GOTO(p, rerror, label)
Definition: pulse_audio_dec.c:68
pulse_read_packet
static int pulse_read_packet(AVFormatContext *s, AVPacket *pkt)
Definition: pulse_audio_dec.c:283
pulse_read_header
static av_cold int pulse_read_header(AVFormatContext *s)
Definition: pulse_audio_dec.c:140
ff_timefilter_destroy
void ff_timefilter_destroy(TimeFilter *self)
Free all resources associated with the filter.
Definition: timefilter.c:66
AV_CODEC_ID_NONE
@ AV_CODEC_ID_NONE
Definition: codec_id.h:48
AVPacket::pts
int64_t pts
Presentation timestamp in AVStream->time_base units; the time at which the decompressed packet will b...
Definition: packet.h:367
internal.h
ff_timefilter_update
double ff_timefilter_update(TimeFilter *self, double system_time, double period)
Update the filter.
Definition: timefilter.c:76
version.h
ret
ret
Definition: filter_design.txt:187
read_packet
static int read_packet(void *opaque, uint8_t *buf, int buf_size)
Definition: avio_reading.c:42
AVStream
Stream structure.
Definition: avformat.h:948
AVClass::class_name
const char * class_name
The name of the class; usually it is the same name as the context structure type to which the AVClass...
Definition: log.h:71
AVDeviceInfoList
List of devices.
Definition: avdevice.h:473
pos
unsigned int pos
Definition: spdifenc.c:412
avformat.h
D
#define D
Definition: pulse_audio_dec.c:368
PulseData::fragment_size
int fragment_size
Definition: pulse_audio_dec.c:47
AV_OPT_TYPE_INT
@ AV_OPT_TYPE_INT
Definition: opt.h:225
PulseData::last_period
int last_period
Definition: pulse_audio_dec.c:55
state
static struct @326 state
av_gettime
int64_t av_gettime(void)
Get the current time in microseconds.
Definition: time.c:39
PulseData::pa_frame_size
size_t pa_frame_size
Definition: pulse_audio_dec.c:52
context_state_cb
static void context_state_cb(pa_context *c, void *userdata)
Definition: pulse_audio_dec.c:77
AVCodecParameters::codec_id
enum AVCodecID codec_id
Specific type of the encoded data (the codec used).
Definition: codec_par.h:61
AVPacket
This structure stores compressed data.
Definition: packet.h:351
DEFAULT_CODEC_ID
#define DEFAULT_CODEC_ID
Definition: pulse_audio_dec.c:37
stream_state_cb
static void stream_state_cb(pa_stream *s, void *userdata)
Definition: pulse_audio_dec.c:89
flags
#define flags(name, subs,...)
Definition: cbs_av1.c:561
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:27
h
h
Definition: vp9dsp_template.c:2038
pulse_demuxer_class
static const AVClass pulse_demuxer_class
Definition: pulse_audio_dec.c:382
AV_OPT_TYPE_STRING
@ AV_OPT_TYPE_STRING
Definition: opt.h:229
OFFSET
#define OFFSET(a)
Definition: pulse_audio_dec.c:367