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  if (pd->fragment_size == -1) {
166  // 50 ms fragments/latency by default seem good enough
167  attr.fragsize = pa_frame_size(&ss) * (pd->sample_rate / 20);
168  } else {
169  attr.fragsize = pd->fragment_size;
170  }
171 
172  if (s->url[0] != '\0' && strcmp(s->url, "default"))
173  device = s->url;
174 
175  if (!(pd->mainloop = pa_threaded_mainloop_new())) {
176  pulse_close(s);
177  return AVERROR_EXTERNAL;
178  }
179 
180  if (!(pd->context = pa_context_new(pa_threaded_mainloop_get_api(pd->mainloop), pd->name))) {
181  pulse_close(s);
182  return AVERROR_EXTERNAL;
183  }
184 
185  pa_context_set_state_callback(pd->context, context_state_cb, pd);
186 
187  if (pa_context_connect(pd->context, pd->server, 0, NULL) < 0) {
188  pulse_close(s);
189  return AVERROR(pa_context_errno(pd->context));
190  }
191 
192  pa_threaded_mainloop_lock(pd->mainloop);
193 
194  if (pa_threaded_mainloop_start(pd->mainloop) < 0) {
195  ret = -1;
196  goto unlock_and_fail;
197  }
198 
199  for (;;) {
200  pa_context_state_t state;
201 
202  state = pa_context_get_state(pd->context);
203 
204  if (state == PA_CONTEXT_READY)
205  break;
206 
207  if (!PA_CONTEXT_IS_GOOD(state)) {
208  ret = AVERROR(pa_context_errno(pd->context));
209  goto unlock_and_fail;
210  }
211 
212  /* Wait until the context is ready */
213  pa_threaded_mainloop_wait(pd->mainloop);
214  }
215 
216  if (!(pd->stream = pa_stream_new(pd->context, pd->stream_name, &ss, &cmap))) {
217  ret = AVERROR(pa_context_errno(pd->context));
218  goto unlock_and_fail;
219  }
220 
221  pa_stream_set_state_callback(pd->stream, stream_state_cb, pd);
222  pa_stream_set_read_callback(pd->stream, stream_request_cb, pd);
223  pa_stream_set_write_callback(pd->stream, stream_request_cb, pd);
224  pa_stream_set_latency_update_callback(pd->stream, stream_latency_update_cb, pd);
225 
226  ret = pa_stream_connect_record(pd->stream, device, &attr,
227  PA_STREAM_INTERPOLATE_TIMING
228  |PA_STREAM_ADJUST_LATENCY
229  |PA_STREAM_AUTO_TIMING_UPDATE);
230 
231  if (ret < 0) {
232  ret = AVERROR(pa_context_errno(pd->context));
233  goto unlock_and_fail;
234  }
235 
236  for (;;) {
237  pa_stream_state_t state;
238 
239  state = pa_stream_get_state(pd->stream);
240 
241  if (state == PA_STREAM_READY)
242  break;
243 
244  if (!PA_STREAM_IS_GOOD(state)) {
245  ret = AVERROR(pa_context_errno(pd->context));
246  goto unlock_and_fail;
247  }
248 
249  /* Wait until the stream is ready */
250  pa_threaded_mainloop_wait(pd->mainloop);
251  }
252 
253  /* Query actual fragment size */
254  queried_attr = pa_stream_get_buffer_attr(pd->stream);
255  if (!queried_attr || queried_attr->fragsize > INT_MAX/100) {
257  goto unlock_and_fail;
258  }
259  pd->fragment_size = queried_attr->fragsize;
260  pd->pa_frame_size = pa_frame_size(&ss);
261 
262  pa_threaded_mainloop_unlock(pd->mainloop);
263 
264  /* take real parameters */
266  st->codecpar->codec_id = codec_id;
267  st->codecpar->sample_rate = pd->sample_rate;
269  avpriv_set_pts_info(st, 64, 1, 1000000); /* 64 bits pts in us */
270 
271  pd->timefilter = ff_timefilter_new(1000000.0 / pd->sample_rate,
272  pd->fragment_size / pd->pa_frame_size, 1.5E-6);
273 
274  if (!pd->timefilter) {
275  pulse_close(s);
276  return AVERROR(ENOMEM);
277  }
278 
279  return 0;
280 
281 unlock_and_fail:
282  pa_threaded_mainloop_unlock(pd->mainloop);
283 
284  pulse_close(s);
285  return ret;
286 }
287 
289 {
290  PulseData *pd = s->priv_data;
291  int ret;
292  size_t read_length;
293  const void *read_data = NULL;
294  int64_t dts;
295  pa_usec_t latency;
296  int negative;
297  ptrdiff_t pos = 0;
298 
299  pa_threaded_mainloop_lock(pd->mainloop);
300 
301  CHECK_DEAD_GOTO(pd, ret, unlock_and_fail);
302 
303  while (pos < pd->fragment_size) {
304  int r;
305 
306  r = pa_stream_peek(pd->stream, &read_data, &read_length);
307  CHECK_SUCCESS_GOTO(ret, r == 0, unlock_and_fail);
308 
309  if (read_length <= 0) {
310  pa_threaded_mainloop_wait(pd->mainloop);
311  CHECK_DEAD_GOTO(pd, ret, unlock_and_fail);
312  } else if (!read_data) {
313  /* There's a hole in the stream, skip it. We could generate
314  * silence, but that wouldn't work for compressed streams. */
315  r = pa_stream_drop(pd->stream);
316  CHECK_SUCCESS_GOTO(ret, r == 0, unlock_and_fail);
317  } else {
318  if (!pos) {
319  if (av_new_packet(pkt, pd->fragment_size) < 0) {
320  ret = AVERROR(ENOMEM);
321  goto unlock_and_fail;
322  }
323 
324  dts = av_gettime();
325  pa_operation_unref(pa_stream_update_timing_info(pd->stream, NULL, NULL));
326 
327  if (pa_stream_get_latency(pd->stream, &latency, &negative) >= 0) {
328  if (negative) {
329  dts += latency;
330  } else
331  dts -= latency;
332  } else {
333  av_log(s, AV_LOG_WARNING, "pa_stream_get_latency() failed\n");
334  }
335  }
336  if (pkt->size - pos < read_length) {
337  if (pos)
338  break;
339  pa_stream_drop(pd->stream);
340  /* Oversized fragment??? */
342  goto unlock_and_fail;
343  }
344  memcpy(pkt->data + pos, read_data, read_length);
345  pos += read_length;
346  pa_stream_drop(pd->stream);
347  }
348  }
349 
350  pa_threaded_mainloop_unlock(pd->mainloop);
351 
353 
354  if (pd->wallclock)
356  pd->last_period = pkt->size / pd->pa_frame_size;
357 
358  return 0;
359 
360 unlock_and_fail:
362  pa_threaded_mainloop_unlock(pd->mainloop);
363  return ret;
364 }
365 
367 {
368  PulseData *s = h->priv_data;
369  return ff_pulse_audio_get_devices(device_list, s->server, 0);
370 }
371 
372 #define OFFSET(a) offsetof(PulseData, a)
373 #define D AV_OPT_FLAG_DECODING_PARAM
374 #define DEPR AV_OPT_FLAG_DEPRECATED
375 
376 static const AVOption options[] = {
377  { "server", "set PulseAudio server", OFFSET(server), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, D },
378  { "name", "set application name", OFFSET(name), AV_OPT_TYPE_STRING, {.str = LIBAVFORMAT_IDENT}, 0, 0, D },
379  { "stream_name", "set stream description", OFFSET(stream_name), AV_OPT_TYPE_STRING, {.str = "record"}, 0, 0, D },
380  { "sample_rate", "set sample rate in Hz", OFFSET(sample_rate), AV_OPT_TYPE_INT, {.i64 = 48000}, 1, INT_MAX, D },
381  { "channels", "set number of audio channels", OFFSET(channels), AV_OPT_TYPE_INT, {.i64 = 2}, 1, INT_MAX, D },
382  { "frame_size", "set number of bytes per frame", OFFSET(frame_size), AV_OPT_TYPE_INT, {.i64 = 1024}, 1, INT_MAX, D | DEPR },
383  { "fragment_size", "set buffering size, affects latency and cpu usage", OFFSET(fragment_size), AV_OPT_TYPE_INT, {.i64 = -1}, -1, INT_MAX, D },
384  { "wallclock", "set the initial pts using the current time", OFFSET(wallclock), AV_OPT_TYPE_INT, {.i64 = 1}, -1, 1, D },
385  { NULL },
386 };
387 
388 static const AVClass pulse_demuxer_class = {
389  .class_name = "Pulse indev",
390  .item_name = av_default_item_name,
391  .option = options,
392  .version = LIBAVUTIL_VERSION_INT,
394 };
395 
397  .name = "pulse",
398  .long_name = NULL_IF_CONFIG_SMALL("Pulse audio input"),
399  .priv_data_size = sizeof(PulseData),
403  .get_device_list = pulse_get_device_list,
404  .flags = AVFMT_NOFILE,
405  .priv_class = &pulse_demuxer_class,
406 };
DEPR
#define DEPR
Definition: pulse_audio_dec.c:374
PulseData::context
pa_context * context
Definition: pulse_audio_dec.c:50
options
static const AVOption options[]
Definition: pulse_audio_dec.c:376
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:1769
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:366
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:303
sample_rate
sample_rate
Definition: ffmpeg_filter.c:156
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:763
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:396
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:2202
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:31
codec_id
enum AVCodecID codec_id
Definition: vaapi_decode.c:388
PulseData::stream_name
char * stream_name
Definition: pulse_audio_dec.c:43
if
if(ret)
Definition: filter_design.txt:179
AVFormatContext
Format I/O context.
Definition: avformat.h:1216
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:530
AVClass
Describe the class of an AVClass context structure.
Definition: log.h:66
NULL
#define NULL
Definition: coverity.c:32
timefilter.h
state
static struct @336 state
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:49
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:115
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:288
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:50
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:373
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
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:388
AV_OPT_TYPE_STRING
@ AV_OPT_TYPE_STRING
Definition: opt.h:229
OFFSET
#define OFFSET(a)
Definition: pulse_audio_dec.c:372