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/demux.h"
33 #include "libavformat/internal.h"
34 #include "libavformat/version.h"
35 #include "pulse_audio_common.h"
36 #include "timefilter.h"
37 
38 #define DEFAULT_CODEC_ID AV_NE(AV_CODEC_ID_PCM_S16BE, AV_CODEC_ID_PCM_S16LE)
39 
40 typedef struct PulseData {
41  AVClass *class;
42  char *server;
43  char *name;
44  char *stream_name;
46  int channels;
49 
50  pa_threaded_mainloop *mainloop;
51  pa_context *context;
52  pa_stream *stream;
53  size_t pa_frame_size;
54 
57  int wallclock;
58 } PulseData;
59 
60 
61 #define CHECK_SUCCESS_GOTO(rerror, expression, label) \
62  do { \
63  if (!(expression)) { \
64  rerror = AVERROR_EXTERNAL; \
65  goto label; \
66  } \
67  } while (0)
68 
69 #define CHECK_DEAD_GOTO(p, rerror, label) \
70  do { \
71  if (!(p)->context || !PA_CONTEXT_IS_GOOD(pa_context_get_state((p)->context)) || \
72  !(p)->stream || !PA_STREAM_IS_GOOD(pa_stream_get_state((p)->stream))) { \
73  rerror = AVERROR_EXTERNAL; \
74  goto label; \
75  } \
76  } while (0)
77 
78 static void context_state_cb(pa_context *c, void *userdata) {
79  PulseData *p = userdata;
80 
81  switch (pa_context_get_state(c)) {
82  case PA_CONTEXT_READY:
83  case PA_CONTEXT_TERMINATED:
84  case PA_CONTEXT_FAILED:
85  pa_threaded_mainloop_signal(p->mainloop, 0);
86  break;
87  }
88 }
89 
90 static void stream_state_cb(pa_stream *s, void * userdata) {
91  PulseData *p = userdata;
92 
93  switch (pa_stream_get_state(s)) {
94  case PA_STREAM_READY:
95  case PA_STREAM_FAILED:
96  case PA_STREAM_TERMINATED:
97  pa_threaded_mainloop_signal(p->mainloop, 0);
98  break;
99  }
100 }
101 
102 static void stream_request_cb(pa_stream *s, size_t length, void *userdata) {
103  PulseData *p = userdata;
104 
105  pa_threaded_mainloop_signal(p->mainloop, 0);
106 }
107 
108 static void stream_latency_update_cb(pa_stream *s, void *userdata) {
109  PulseData *p = userdata;
110 
111  pa_threaded_mainloop_signal(p->mainloop, 0);
112 }
113 
115 {
116  PulseData *pd = s->priv_data;
117 
118  if (pd->mainloop)
119  pa_threaded_mainloop_stop(pd->mainloop);
120 
121  if (pd->stream)
122  pa_stream_unref(pd->stream);
123  pd->stream = NULL;
124 
125  if (pd->context) {
126  pa_context_disconnect(pd->context);
127  pa_context_unref(pd->context);
128  }
129  pd->context = NULL;
130 
131  if (pd->mainloop)
132  pa_threaded_mainloop_free(pd->mainloop);
133  pd->mainloop = NULL;
134 
136  pd->timefilter = NULL;
137 
138  return 0;
139 }
140 
142 {
143  PulseData *pd = s->priv_data;
144  AVStream *st;
145  char *device = NULL;
146  int ret;
147  enum AVCodecID codec_id =
148  s->audio_codec_id == AV_CODEC_ID_NONE ? DEFAULT_CODEC_ID : s->audio_codec_id;
149  const pa_sample_spec ss = { ff_codec_id_to_pulse_format(codec_id),
150  pd->sample_rate,
151  pd->channels };
152 
153  pa_buffer_attr attr = { -1 };
154  pa_channel_map cmap;
155  const pa_buffer_attr *queried_attr;
156 
157  pa_channel_map_init_extend(&cmap, pd->channels, PA_CHANNEL_MAP_WAVEEX);
158 
159  st = avformat_new_stream(s, NULL);
160 
161  if (!st) {
162  av_log(s, AV_LOG_ERROR, "Cannot add stream\n");
163  return AVERROR(ENOMEM);
164  }
165 
166  if (pd->fragment_size == -1) {
167  // 50 ms fragments/latency by default seem good enough
168  attr.fragsize = pa_frame_size(&ss) * (pd->sample_rate / 20);
169  } else {
170  attr.fragsize = pd->fragment_size;
171  }
172 
173  if (s->url[0] != '\0' && strcmp(s->url, "default"))
174  device = s->url;
175 
176  if (!(pd->mainloop = pa_threaded_mainloop_new())) {
177  pulse_close(s);
178  return AVERROR_EXTERNAL;
179  }
180 
181  if (!(pd->context = pa_context_new(pa_threaded_mainloop_get_api(pd->mainloop), pd->name))) {
182  pulse_close(s);
183  return AVERROR_EXTERNAL;
184  }
185 
186  pa_context_set_state_callback(pd->context, context_state_cb, pd);
187 
188  if (pa_context_connect(pd->context, pd->server, 0, NULL) < 0) {
189  pulse_close(s);
190  return AVERROR(pa_context_errno(pd->context));
191  }
192 
193  pa_threaded_mainloop_lock(pd->mainloop);
194 
195  if (pa_threaded_mainloop_start(pd->mainloop) < 0) {
196  ret = -1;
197  goto unlock_and_fail;
198  }
199 
200  for (;;) {
201  pa_context_state_t state;
202 
203  state = pa_context_get_state(pd->context);
204 
205  if (state == PA_CONTEXT_READY)
206  break;
207 
208  if (!PA_CONTEXT_IS_GOOD(state)) {
209  ret = AVERROR(pa_context_errno(pd->context));
210  goto unlock_and_fail;
211  }
212 
213  /* Wait until the context is ready */
214  pa_threaded_mainloop_wait(pd->mainloop);
215  }
216 
217  if (!(pd->stream = pa_stream_new(pd->context, pd->stream_name, &ss, &cmap))) {
218  ret = AVERROR(pa_context_errno(pd->context));
219  goto unlock_and_fail;
220  }
221 
222  pa_stream_set_state_callback(pd->stream, stream_state_cb, pd);
223  pa_stream_set_read_callback(pd->stream, stream_request_cb, pd);
224  pa_stream_set_write_callback(pd->stream, stream_request_cb, pd);
225  pa_stream_set_latency_update_callback(pd->stream, stream_latency_update_cb, pd);
226 
227  ret = pa_stream_connect_record(pd->stream, device, &attr,
228  PA_STREAM_INTERPOLATE_TIMING
229  |PA_STREAM_ADJUST_LATENCY
230  |PA_STREAM_AUTO_TIMING_UPDATE);
231 
232  if (ret < 0) {
233  ret = AVERROR(pa_context_errno(pd->context));
234  goto unlock_and_fail;
235  }
236 
237  for (;;) {
238  pa_stream_state_t state;
239 
240  state = pa_stream_get_state(pd->stream);
241 
242  if (state == PA_STREAM_READY)
243  break;
244 
245  if (!PA_STREAM_IS_GOOD(state)) {
246  ret = AVERROR(pa_context_errno(pd->context));
247  goto unlock_and_fail;
248  }
249 
250  /* Wait until the stream is ready */
251  pa_threaded_mainloop_wait(pd->mainloop);
252  }
253 
254  /* Query actual fragment size */
255  queried_attr = pa_stream_get_buffer_attr(pd->stream);
256  if (!queried_attr || queried_attr->fragsize > INT_MAX/100) {
258  goto unlock_and_fail;
259  }
260  pd->fragment_size = queried_attr->fragsize;
261  pd->pa_frame_size = pa_frame_size(&ss);
262 
263  pa_threaded_mainloop_unlock(pd->mainloop);
264 
265  /* take real parameters */
267  st->codecpar->codec_id = codec_id;
268  st->codecpar->sample_rate = pd->sample_rate;
270  avpriv_set_pts_info(st, 64, 1, 1000000); /* 64 bits pts in us */
271 
272  pd->timefilter = ff_timefilter_new(1000000.0 / pd->sample_rate,
273  pd->fragment_size / pd->pa_frame_size, 1.5E-6);
274 
275  if (!pd->timefilter) {
276  pulse_close(s);
277  return AVERROR(ENOMEM);
278  }
279 
280  return 0;
281 
282 unlock_and_fail:
283  pa_threaded_mainloop_unlock(pd->mainloop);
284 
285  pulse_close(s);
286  return ret;
287 }
288 
290 {
291  PulseData *pd = s->priv_data;
292  int ret;
293  size_t read_length;
294  const void *read_data = NULL;
295  int64_t dts;
296  pa_usec_t latency;
297  int negative;
298  ptrdiff_t pos = 0;
299 
300  pa_threaded_mainloop_lock(pd->mainloop);
301 
302  CHECK_DEAD_GOTO(pd, ret, unlock_and_fail);
303 
304  while (pos < pd->fragment_size) {
305  int r;
306 
307  r = pa_stream_peek(pd->stream, &read_data, &read_length);
308  CHECK_SUCCESS_GOTO(ret, r == 0, unlock_and_fail);
309 
310  if (read_length <= 0) {
311  pa_threaded_mainloop_wait(pd->mainloop);
312  CHECK_DEAD_GOTO(pd, ret, unlock_and_fail);
313  } else if (!read_data) {
314  /* There's a hole in the stream, skip it. We could generate
315  * silence, but that wouldn't work for compressed streams. */
316  r = pa_stream_drop(pd->stream);
317  CHECK_SUCCESS_GOTO(ret, r == 0, unlock_and_fail);
318  } else {
319  if (!pos) {
320  if (av_new_packet(pkt, pd->fragment_size) < 0) {
321  ret = AVERROR(ENOMEM);
322  goto unlock_and_fail;
323  }
324 
325  dts = av_gettime();
326  pa_operation_unref(pa_stream_update_timing_info(pd->stream, NULL, NULL));
327 
328  if (pa_stream_get_latency(pd->stream, &latency, &negative) >= 0) {
329  if (negative) {
330  dts += latency;
331  } else
332  dts -= latency;
333  } else {
334  av_log(s, AV_LOG_WARNING, "pa_stream_get_latency() failed\n");
335  }
336  }
337  if (pkt->size - pos < read_length) {
338  if (pos)
339  break;
340  pa_stream_drop(pd->stream);
341  /* Oversized fragment??? */
343  goto unlock_and_fail;
344  }
345  memcpy(pkt->data + pos, read_data, read_length);
346  pos += read_length;
347  pa_stream_drop(pd->stream);
348  }
349  }
350 
351  pa_threaded_mainloop_unlock(pd->mainloop);
352 
354 
355  if (pd->wallclock)
357  pd->last_period = pkt->size / pd->pa_frame_size;
358 
359  return 0;
360 
361 unlock_and_fail:
363  pa_threaded_mainloop_unlock(pd->mainloop);
364  return ret;
365 }
366 
368 {
369  PulseData *s = h->priv_data;
370  return ff_pulse_audio_get_devices(device_list, s->server, 0);
371 }
372 
373 #define OFFSET(a) offsetof(PulseData, a)
374 #define D AV_OPT_FLAG_DECODING_PARAM
375 #define DEPR AV_OPT_FLAG_DEPRECATED
376 
377 static const AVOption options[] = {
378  { "server", "set PulseAudio server", OFFSET(server), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, D },
379  { "name", "set application name", OFFSET(name), AV_OPT_TYPE_STRING, {.str = LIBAVFORMAT_IDENT}, 0, 0, D },
380  { "stream_name", "set stream description", OFFSET(stream_name), AV_OPT_TYPE_STRING, {.str = "record"}, 0, 0, D },
381  { "sample_rate", "set sample rate in Hz", OFFSET(sample_rate), AV_OPT_TYPE_INT, {.i64 = 48000}, 1, INT_MAX, D },
382  { "channels", "set number of audio channels", OFFSET(channels), AV_OPT_TYPE_INT, {.i64 = 2}, 1, INT_MAX, D },
383  { "frame_size", "set number of bytes per frame", OFFSET(frame_size), AV_OPT_TYPE_INT, {.i64 = 1024}, 1, INT_MAX, D | DEPR },
384  { "fragment_size", "set buffering size, affects latency and cpu usage", OFFSET(fragment_size), AV_OPT_TYPE_INT, {.i64 = -1}, -1, INT_MAX, D },
385  { "wallclock", "set the initial pts using the current time", OFFSET(wallclock), AV_OPT_TYPE_INT, {.i64 = 1}, -1, 1, D },
386  { NULL },
387 };
388 
389 static const AVClass pulse_demuxer_class = {
390  .class_name = "Pulse indev",
391  .item_name = av_default_item_name,
392  .option = options,
393  .version = LIBAVUTIL_VERSION_INT,
395 };
396 
398  .p.name = "pulse",
399  .p.long_name = NULL_IF_CONFIG_SMALL("Pulse audio input"),
400  .p.flags = AVFMT_NOFILE,
401  .p.priv_class = &pulse_demuxer_class,
402  .priv_data_size = sizeof(PulseData),
406  .get_device_list = pulse_get_device_list,
407 };
DEPR
#define DEPR
Definition: pulse_audio_dec.c:375
PulseData::context
pa_context * context
Definition: pulse_audio_dec.c:51
options
static const AVOption options[]
Definition: pulse_audio_dec.c:377
av_packet_unref
void av_packet_unref(AVPacket *pkt)
Wipe the packet.
Definition: packet.c:429
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:215
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:1772
r
const char * r
Definition: vf_curves.c:127
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
AVCodecParameters::codec_type
enum AVMediaType codec_type
General type of the encoded data.
Definition: codec_par.h:51
PulseData::mainloop
pa_threaded_mainloop * mainloop
Definition: pulse_audio_dec.c:50
avformat_new_stream
AVStream * avformat_new_stream(AVFormatContext *s, const struct AVCodec *c)
Add a new stream to a media file.
pulse_get_device_list
static int pulse_get_device_list(AVFormatContext *h, AVDeviceInfoList *device_list)
Definition: pulse_audio_dec.c:367
int64_t
long long int64_t
Definition: coverity.c:34
PulseData::frame_size
int frame_size
Definition: pulse_audio_dec.c:47
stream_latency_update_cb
static void stream_latency_update_cb(pa_stream *s, void *userdata)
Definition: pulse_audio_dec.c:108
AVPacket::data
uint8_t * data
Definition: packet.h:539
AVOption
AVOption.
Definition: opt.h:429
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
server
FFmpeg hosted at Telepoint in bulgaria ns2 avcodec org Replica Name server(provided by an ffmpeg developer, hosted at Hetzner in germany) ns3.avcodec.org Replica Name server(provided by an ffmpeg developer
PulseData::channels
int channels
Definition: pulse_audio_dec.c:46
AVChannelLayout::nb_channels
int nb_channels
Number of channels in this layout.
Definition: channel_layout.h:327
PulseData
Definition: pulse_audio_dec.c:40
PulseData::stream
pa_stream * stream
Definition: pulse_audio_dec.c:52
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:867
PulseData::name
char * name
Definition: pulse_audio_dec.c:43
av_shrink_packet
void av_shrink_packet(AVPacket *pkt, int size)
Reduce packet size, correctly zeroing padding.
Definition: packet.c:113
read_close
static av_cold int read_close(AVFormatContext *ctx)
Definition: libcdio.c:143
ss
#define ss(width, name, subs,...)
Definition: cbs_vp9.c:202
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:102
AV_CLASS_CATEGORY_DEVICE_AUDIO_INPUT
@ AV_CLASS_CATEGORY_DEVICE_AUDIO_INPUT
Definition: log.h:43
pkt
AVPacket * pkt
Definition: movenc.c:60
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:209
av_cold
#define av_cold
Definition: attributes.h:90
read_packet
static int read_packet(void *opaque, uint8_t *buf, int buf_size)
Definition: avio_read_callback.c:42
s
#define s(width, name)
Definition: cbs_vp9.c:198
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: packet.c:98
AVInputFormat::name
const char * name
A comma separated list of short names for the format.
Definition: avformat.h:553
frame_size
int frame_size
Definition: mxfenc.c:2429
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:57
PulseData::sample_rate
int sample_rate
Definition: pulse_audio_dec.c:45
channels
channels
Definition: aptx.h:31
codec_id
enum AVCodecID codec_id
Definition: vaapi_decode.c:410
PulseData::stream_name
char * stream_name
Definition: pulse_audio_dec.c:44
if
if(ret)
Definition: filter_design.txt:179
AVFormatContext
Format I/O context.
Definition: avformat.h:1300
internal.h
AVStream::codecpar
AVCodecParameters * codecpar
Codec parameters associated with this stream.
Definition: avformat.h:771
pulse_close
static av_cold int pulse_close(AVFormatContext *s)
Definition: pulse_audio_dec.c:114
LIBAVUTIL_VERSION_INT
#define LIBAVUTIL_VERSION_INT
Definition: version.h:85
read_header
static int read_header(FFV1Context *f)
Definition: ffv1dec.c:540
AVClass
Describe the class of an AVClass context structure.
Definition: log.h:75
NULL
#define NULL
Definition: coverity.c:32
timefilter.h
state
static struct @466 state
av_default_item_name
const char * av_default_item_name(void *ptr)
Return the context name.
Definition: log.c:237
options
Definition: swscale.c:42
time.h
AVCodecParameters::ch_layout
AVChannelLayout ch_layout
Audio only.
Definition: codec_par.h:180
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:184
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:55
AVPacket::size
int size
Definition: packet.h:540
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:94
PulseData::server
char * server
Definition: pulse_audio_dec.c:42
AVFMT_NOFILE
#define AVFMT_NOFILE
Demuxer will use avio_open, no opened file should be provided by the caller.
Definition: avformat.h:468
ff_pulse_demuxer
const FFInputFormat ff_pulse_demuxer
Definition: pulse_audio_dec.c:397
FFInputFormat::p
AVInputFormat p
The public AVInputFormat.
Definition: demux.h:46
CHECK_SUCCESS_GOTO
#define CHECK_SUCCESS_GOTO(rerror, expression, label)
Definition: pulse_audio_dec.c:61
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:69
pulse_read_packet
static int pulse_read_packet(AVFormatContext *s, AVPacket *pkt)
Definition: pulse_audio_dec.c:289
pulse_read_header
static av_cold int pulse_read_header(AVFormatContext *s)
Definition: pulse_audio_dec.c:141
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:532
internal.h
ff_timefilter_update
double ff_timefilter_update(TimeFilter *self, double system_time, double period)
Update the filter.
Definition: timefilter.c:76
demux.h
version.h
ret
ret
Definition: filter_design.txt:187
AVStream
Stream structure.
Definition: avformat.h:748
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:80
AVDeviceInfoList
List of devices.
Definition: avdevice.h:343
pos
unsigned int pos
Definition: spdifenc.c:414
avformat.h
D
#define D
Definition: pulse_audio_dec.c:374
PulseData::fragment_size
int fragment_size
Definition: pulse_audio_dec.c:48
AV_OPT_TYPE_INT
@ AV_OPT_TYPE_INT
Underlying C type is int.
Definition: opt.h:259
PulseData::last_period
int last_period
Definition: pulse_audio_dec.c:56
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:53
context_state_cb
static void context_state_cb(pa_context *c, void *userdata)
Definition: pulse_audio_dec.c:78
AVCodecParameters::codec_id
enum AVCodecID codec_id
Specific type of the encoded data (the codec used).
Definition: codec_par.h:55
AVPacket
This structure stores compressed data.
Definition: packet.h:516
DEFAULT_CODEC_ID
#define DEFAULT_CODEC_ID
Definition: pulse_audio_dec.c:38
stream_state_cb
static void stream_state_cb(pa_stream *s, void *userdata)
Definition: pulse_audio_dec.c:90
FFInputFormat
Definition: demux.h:42
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:27
h
h
Definition: vp9dsp_template.c:2070
pulse_demuxer_class
static const AVClass pulse_demuxer_class
Definition: pulse_audio_dec.c:389
AV_OPT_TYPE_STRING
@ AV_OPT_TYPE_STRING
Underlying C type is a uint8_t* that is either NULL or points to a C string allocated with the av_mal...
Definition: opt.h:276
OFFSET
#define OFFSET(a)
Definition: pulse_audio_dec.c:373