FFmpeg
pulse_audio_enc.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2013 Lukasz Marek <lukasz.m.luki@gmail.com>
3  *
4  * This file is part of FFmpeg.
5  *
6  * FFmpeg is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * FFmpeg is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with FFmpeg; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19  */
20 
21 #include <math.h>
22 #include <pulse/pulseaudio.h>
23 #include <pulse/error.h>
24 #include "libavformat/avformat.h"
25 #include "libavformat/internal.h"
27 #include "libavutil/internal.h"
28 #include "libavutil/opt.h"
29 #include "libavutil/time.h"
30 #include "libavutil/log.h"
31 #include "libavutil/attributes.h"
32 #include "pulse_audio_common.h"
33 
34 typedef struct PulseData {
35  AVClass *class;
36  const char *server;
37  const char *name;
38  const char *stream_name;
39  const char *device;
40  int64_t timestamp;
41  int buffer_size; /**< Buffer size in bytes */
42  int buffer_duration; /**< Buffer size in ms, recalculated to buffer_size */
43  int prebuf;
44  int minreq;
46  pa_threaded_mainloop *mainloop;
47  pa_context *ctx;
48  pa_stream *stream;
50  int mute;
51  pa_volume_t base_volume;
52  pa_volume_t last_volume;
53 } PulseData;
54 
55 static void pulse_audio_sink_device_cb(pa_context *ctx, const pa_sink_info *dev,
56  int eol, void *userdata)
57 {
58  PulseData *s = userdata;
59 
60  if (s->ctx != ctx)
61  return;
62 
63  if (eol) {
64  pa_threaded_mainloop_signal(s->mainloop, 0);
65  } else {
66  if (dev->flags & PA_SINK_FLAT_VOLUME)
67  s->base_volume = dev->base_volume;
68  else
69  s->base_volume = PA_VOLUME_NORM;
70  av_log(s, AV_LOG_DEBUG, "base volume: %u\n", s->base_volume);
71  }
72 }
73 
74 /* Mainloop must be locked before calling this function as it uses pa_threaded_mainloop_wait. */
76 {
77  PulseData *s = h->priv_data;
78  pa_operation *op;
79  if (!(op = pa_context_get_sink_info_by_name(s->ctx, s->device,
81  av_log(s, AV_LOG_ERROR, "pa_context_get_sink_info_by_name failed.\n");
82  return AVERROR_EXTERNAL;
83  }
84  while (pa_operation_get_state(op) == PA_OPERATION_RUNNING)
85  pa_threaded_mainloop_wait(s->mainloop);
86  pa_operation_unref(op);
87  return 0;
88 }
89 
90 static void pulse_audio_sink_input_cb(pa_context *ctx, const pa_sink_input_info *i,
91  int eol, void *userdata)
92 {
93  AVFormatContext *h = userdata;
94  PulseData *s = h->priv_data;
95 
96  if (s->ctx != ctx)
97  return;
98 
99  if (!eol) {
100  double val;
101  pa_volume_t vol = pa_cvolume_avg(&i->volume);
102  if (s->mute < 0 || (s->mute && !i->mute) || (!s->mute && i->mute)) {
103  s->mute = i->mute;
105  }
106 
107  vol = pa_sw_volume_divide(vol, s->base_volume);
108  if (s->last_volume != vol) {
109  val = (double)vol / PA_VOLUME_NORM;
111  s->last_volume = vol;
112  }
113  }
114 }
115 
116 /* This function creates new loop so may be called from PA callbacks.
117  Mainloop must be locked before calling this function as it operates on streams. */
119 {
120  PulseData *s = h->priv_data;
121  pa_operation *op;
122  enum pa_operation_state op_state;
123  pa_mainloop *ml = NULL;
124  pa_context *ctx = NULL;
125  int ret = 0;
126 
127  if ((ret = ff_pulse_audio_connect_context(&ml, &ctx, s->server, "Update sink input information")) < 0)
128  return ret;
129 
130  if (!(op = pa_context_get_sink_input_info(ctx, pa_stream_get_index(s->stream),
133  goto fail;
134  }
135 
136  while ((op_state = pa_operation_get_state(op)) == PA_OPERATION_RUNNING)
137  pa_mainloop_iterate(ml, 1, NULL);
138  pa_operation_unref(op);
139  if (op_state != PA_OPERATION_DONE) {
141  goto fail;
142  }
143 
144  fail:
146  if (ret)
147  av_log(s, AV_LOG_ERROR, "pa_context_get_sink_input_info failed.\n");
148  return ret;
149 }
150 
151 static void pulse_event(pa_context *ctx, pa_subscription_event_type_t t,
152  uint32_t idx, void *userdata)
153 {
154  AVFormatContext *h = userdata;
155  PulseData *s = h->priv_data;
156 
157  if (s->ctx != ctx)
158  return;
159 
160  if ((t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_SINK_INPUT) {
161  if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_CHANGE)
162  // Calling from mainloop callback. No need to lock mainloop.
164  }
165 }
166 
167 static void pulse_stream_writable(pa_stream *stream, size_t nbytes, void *userdata)
168 {
169  AVFormatContext *h = userdata;
170  PulseData *s = h->priv_data;
171  int64_t val = nbytes;
172 
173  if (stream != s->stream)
174  return;
175 
177  pa_threaded_mainloop_signal(s->mainloop, 0);
178 }
179 
180 static void pulse_overflow(pa_stream *stream, void *userdata)
181 {
182  AVFormatContext *h = userdata;
184 }
185 
186 static void pulse_underflow(pa_stream *stream, void *userdata)
187 {
188  AVFormatContext *h = userdata;
190 }
191 
192 static void pulse_stream_state(pa_stream *stream, void *userdata)
193 {
194  PulseData *s = userdata;
195 
196  if (stream != s->stream)
197  return;
198 
199  switch (pa_stream_get_state(s->stream)) {
200  case PA_STREAM_READY:
201  case PA_STREAM_FAILED:
202  case PA_STREAM_TERMINATED:
203  pa_threaded_mainloop_signal(s->mainloop, 0);
204  default:
205  break;
206  }
207 }
208 
210 {
211  pa_stream_state_t state;
212 
213  while ((state = pa_stream_get_state(s->stream)) != PA_STREAM_READY) {
214  if (state == PA_STREAM_FAILED || state == PA_STREAM_TERMINATED)
215  return AVERROR_EXTERNAL;
216  pa_threaded_mainloop_wait(s->mainloop);
217  }
218  return 0;
219 }
220 
221 static void pulse_context_state(pa_context *ctx, void *userdata)
222 {
223  PulseData *s = userdata;
224 
225  if (s->ctx != ctx)
226  return;
227 
228  switch (pa_context_get_state(ctx)) {
229  case PA_CONTEXT_READY:
230  case PA_CONTEXT_FAILED:
231  case PA_CONTEXT_TERMINATED:
232  pa_threaded_mainloop_signal(s->mainloop, 0);
233  default:
234  break;
235  }
236 }
237 
239 {
240  pa_context_state_t state;
241 
242  while ((state = pa_context_get_state(s->ctx)) != PA_CONTEXT_READY) {
243  if (state == PA_CONTEXT_FAILED || state == PA_CONTEXT_TERMINATED)
244  return AVERROR_EXTERNAL;
245  pa_threaded_mainloop_wait(s->mainloop);
246  }
247  return 0;
248 }
249 
250 static void pulse_stream_result(pa_stream *stream, int success, void *userdata)
251 {
252  PulseData *s = userdata;
253 
254  if (stream != s->stream)
255  return;
256 
257  s->last_result = success ? 0 : AVERROR_EXTERNAL;
258  pa_threaded_mainloop_signal(s->mainloop, 0);
259 }
260 
261 static int pulse_finish_stream_operation(PulseData *s, pa_operation *op, const char *name)
262 {
263  if (!op) {
264  pa_threaded_mainloop_unlock(s->mainloop);
265  av_log(s, AV_LOG_ERROR, "%s failed.\n", name);
266  return AVERROR_EXTERNAL;
267  }
268  s->last_result = 2;
269  while (s->last_result == 2)
270  pa_threaded_mainloop_wait(s->mainloop);
271  pa_operation_unref(op);
272  pa_threaded_mainloop_unlock(s->mainloop);
273  if (s->last_result != 0)
274  av_log(s, AV_LOG_ERROR, "%s failed.\n", name);
275  return s->last_result;
276 }
277 
278 static int pulse_set_pause(PulseData *s, int pause)
279 {
280  pa_operation *op;
281  pa_threaded_mainloop_lock(s->mainloop);
282  op = pa_stream_cork(s->stream, pause, pulse_stream_result, s);
283  return pulse_finish_stream_operation(s, op, "pa_stream_cork");
284 }
285 
287 {
288  pa_operation *op;
289  pa_threaded_mainloop_lock(s->mainloop);
290  op = pa_stream_flush(s->stream, pulse_stream_result, s);
291  return pulse_finish_stream_operation(s, op, "pa_stream_flush");
292 }
293 
294 static void pulse_context_result(pa_context *ctx, int success, void *userdata)
295 {
296  PulseData *s = userdata;
297 
298  if (s->ctx != ctx)
299  return;
300 
301  s->last_result = success ? 0 : AVERROR_EXTERNAL;
302  pa_threaded_mainloop_signal(s->mainloop, 0);
303 }
304 
305 static int pulse_finish_context_operation(PulseData *s, pa_operation *op, const char *name)
306 {
307  if (!op) {
308  pa_threaded_mainloop_unlock(s->mainloop);
309  av_log(s, AV_LOG_ERROR, "%s failed.\n", name);
310  return AVERROR_EXTERNAL;
311  }
312  s->last_result = 2;
313  while (s->last_result == 2)
314  pa_threaded_mainloop_wait(s->mainloop);
315  pa_operation_unref(op);
316  pa_threaded_mainloop_unlock(s->mainloop);
317  if (s->last_result != 0)
318  av_log(s, AV_LOG_ERROR, "%s failed.\n", name);
319  return s->last_result;
320 }
321 
323 {
324  pa_operation *op;
325  pa_threaded_mainloop_lock(s->mainloop);
326  op = pa_context_set_sink_input_mute(s->ctx, pa_stream_get_index(s->stream),
327  s->mute, pulse_context_result, s);
328  return pulse_finish_context_operation(s, op, "pa_context_set_sink_input_mute");
329 }
330 
331 static int pulse_set_volume(PulseData *s, double volume)
332 {
333  pa_operation *op;
334  pa_cvolume cvol;
335  pa_volume_t vol;
336  const pa_sample_spec *ss = pa_stream_get_sample_spec(s->stream);
337 
338  vol = pa_sw_volume_multiply(lrint(volume * PA_VOLUME_NORM), s->base_volume);
339  pa_cvolume_set(&cvol, ss->channels, PA_VOLUME_NORM);
340  pa_sw_cvolume_multiply_scalar(&cvol, &cvol, vol);
341  pa_threaded_mainloop_lock(s->mainloop);
342  op = pa_context_set_sink_input_volume(s->ctx, pa_stream_get_index(s->stream),
343  &cvol, pulse_context_result, s);
344  return pulse_finish_context_operation(s, op, "pa_context_set_sink_input_volume");
345 }
346 
348 {
349  pa_operation *op;
350 
351  pa_threaded_mainloop_lock(s->mainloop);
352  op = pa_context_subscribe(s->ctx, PA_SUBSCRIPTION_MASK_SINK_INPUT, pulse_context_result, s);
353  return pulse_finish_context_operation(s, op, "pa_context_subscribe");
354 }
355 
356 static void pulse_map_channels_to_pulse(int64_t channel_layout, pa_channel_map *channel_map)
357 {
358  channel_map->channels = 0;
359  if (channel_layout & AV_CH_FRONT_LEFT)
360  channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_FRONT_LEFT;
361  if (channel_layout & AV_CH_FRONT_RIGHT)
362  channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_FRONT_RIGHT;
363  if (channel_layout & AV_CH_FRONT_CENTER)
364  channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_FRONT_CENTER;
365  if (channel_layout & AV_CH_LOW_FREQUENCY)
366  channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_LFE;
367  if (channel_layout & AV_CH_BACK_LEFT)
368  channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_REAR_LEFT;
369  if (channel_layout & AV_CH_BACK_RIGHT)
370  channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_REAR_RIGHT;
371  if (channel_layout & AV_CH_FRONT_LEFT_OF_CENTER)
372  channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER;
373  if (channel_layout & AV_CH_FRONT_RIGHT_OF_CENTER)
374  channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER;
375  if (channel_layout & AV_CH_BACK_CENTER)
376  channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_REAR_CENTER;
377  if (channel_layout & AV_CH_SIDE_LEFT)
378  channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_SIDE_LEFT;
379  if (channel_layout & AV_CH_SIDE_RIGHT)
380  channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_SIDE_RIGHT;
381  if (channel_layout & AV_CH_TOP_CENTER)
382  channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_TOP_CENTER;
383  if (channel_layout & AV_CH_TOP_FRONT_LEFT)
384  channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_TOP_FRONT_LEFT;
385  if (channel_layout & AV_CH_TOP_FRONT_CENTER)
386  channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_TOP_FRONT_CENTER;
387  if (channel_layout & AV_CH_TOP_FRONT_RIGHT)
388  channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_TOP_FRONT_RIGHT;
389  if (channel_layout & AV_CH_TOP_BACK_LEFT)
390  channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_TOP_REAR_LEFT;
391  if (channel_layout & AV_CH_TOP_BACK_CENTER)
392  channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_TOP_REAR_CENTER;
393  if (channel_layout & AV_CH_TOP_BACK_RIGHT)
394  channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_TOP_REAR_RIGHT;
395  if (channel_layout & AV_CH_STEREO_LEFT)
396  channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_FRONT_LEFT;
397  if (channel_layout & AV_CH_STEREO_RIGHT)
398  channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_FRONT_RIGHT;
399  if (channel_layout & AV_CH_WIDE_LEFT)
400  channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_AUX0;
401  if (channel_layout & AV_CH_WIDE_RIGHT)
402  channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_AUX1;
403  if (channel_layout & AV_CH_SURROUND_DIRECT_LEFT)
404  channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_AUX2;
405  if (channel_layout & AV_CH_SURROUND_DIRECT_RIGHT)
406  channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_AUX3;
407  if (channel_layout & AV_CH_LOW_FREQUENCY_2)
408  channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_LFE;
409 }
410 
412 {
413  PulseData *s = h->priv_data;
414 
415  if (s->mainloop) {
416  pa_threaded_mainloop_lock(s->mainloop);
417  if (s->stream) {
418  pa_stream_disconnect(s->stream);
419  pa_stream_set_state_callback(s->stream, NULL, NULL);
420  pa_stream_set_write_callback(s->stream, NULL, NULL);
421  pa_stream_set_overflow_callback(s->stream, NULL, NULL);
422  pa_stream_set_underflow_callback(s->stream, NULL, NULL);
423  pa_stream_unref(s->stream);
424  s->stream = NULL;
425  }
426  if (s->ctx) {
427  pa_context_disconnect(s->ctx);
428  pa_context_set_state_callback(s->ctx, NULL, NULL);
429  pa_context_set_subscribe_callback(s->ctx, NULL, NULL);
430  pa_context_unref(s->ctx);
431  s->ctx = NULL;
432  }
433  pa_threaded_mainloop_unlock(s->mainloop);
434  pa_threaded_mainloop_stop(s->mainloop);
435  pa_threaded_mainloop_free(s->mainloop);
436  s->mainloop = NULL;
437  }
438 
439  return 0;
440 }
441 
443 {
444  PulseData *s = h->priv_data;
445  AVStream *st = NULL;
446  int ret;
447  pa_sample_spec sample_spec;
448  pa_buffer_attr buffer_attributes = { -1, -1, -1, -1, -1 };
449  pa_channel_map channel_map;
450  pa_mainloop_api *mainloop_api;
451  const char *stream_name = s->stream_name;
452  static const pa_stream_flags_t stream_flags = PA_STREAM_INTERPOLATE_TIMING |
453  PA_STREAM_AUTO_TIMING_UPDATE |
454  PA_STREAM_NOT_MONOTONIC;
455 
456  if (h->nb_streams != 1 || h->streams[0]->codecpar->codec_type != AVMEDIA_TYPE_AUDIO) {
457  av_log(s, AV_LOG_ERROR, "Only a single audio stream is supported.\n");
458  return AVERROR(EINVAL);
459  }
460  st = h->streams[0];
461 
462  if (!stream_name) {
463  if (h->url[0])
464  stream_name = h->url;
465  else
466  stream_name = "Playback";
467  }
468  s->nonblocking = (h->flags & AVFMT_FLAG_NONBLOCK);
469 
470  if (s->buffer_duration) {
471  int64_t bytes = s->buffer_duration;
472  bytes *= st->codecpar->channels * st->codecpar->sample_rate *
474  bytes /= 1000;
475  buffer_attributes.tlength = FFMAX(s->buffer_size, av_clip64(bytes, 0, UINT32_MAX - 1));
477  "Buffer duration: %ums recalculated into %"PRId64" bytes buffer.\n",
478  s->buffer_duration, bytes);
479  av_log(s, AV_LOG_DEBUG, "Real buffer length is %u bytes\n", buffer_attributes.tlength);
480  } else if (s->buffer_size)
481  buffer_attributes.tlength = s->buffer_size;
482  if (s->prebuf)
483  buffer_attributes.prebuf = s->prebuf;
484  if (s->minreq)
485  buffer_attributes.minreq = s->minreq;
486 
487  sample_spec.format = ff_codec_id_to_pulse_format(st->codecpar->codec_id);
488  sample_spec.rate = st->codecpar->sample_rate;
489  sample_spec.channels = st->codecpar->channels;
490  if (!pa_sample_spec_valid(&sample_spec)) {
491  av_log(s, AV_LOG_ERROR, "Invalid sample spec.\n");
492  return AVERROR(EINVAL);
493  }
494 
495  if (sample_spec.channels == 1) {
496  channel_map.channels = 1;
497  channel_map.map[0] = PA_CHANNEL_POSITION_MONO;
498  } else if (st->codecpar->channel_layout) {
500  return AVERROR(EINVAL);
502  /* Unknown channel is present in channel_layout, let PulseAudio use its default. */
503  if (channel_map.channels != sample_spec.channels) {
504  av_log(s, AV_LOG_WARNING, "Unknown channel. Using defaul channel map.\n");
505  channel_map.channels = 0;
506  }
507  } else
508  channel_map.channels = 0;
509 
510  if (!channel_map.channels)
511  av_log(s, AV_LOG_WARNING, "Using PulseAudio's default channel map.\n");
512  else if (!pa_channel_map_valid(&channel_map)) {
513  av_log(s, AV_LOG_ERROR, "Invalid channel map.\n");
514  return AVERROR(EINVAL);
515  }
516 
517  /* start main loop */
518  s->mainloop = pa_threaded_mainloop_new();
519  if (!s->mainloop) {
520  av_log(s, AV_LOG_ERROR, "Cannot create threaded mainloop.\n");
521  return AVERROR(ENOMEM);
522  }
523  if ((ret = pa_threaded_mainloop_start(s->mainloop)) < 0) {
524  av_log(s, AV_LOG_ERROR, "Cannot start threaded mainloop: %s.\n", pa_strerror(ret));
525  pa_threaded_mainloop_free(s->mainloop);
526  s->mainloop = NULL;
527  return AVERROR_EXTERNAL;
528  }
529 
530  pa_threaded_mainloop_lock(s->mainloop);
531 
532  mainloop_api = pa_threaded_mainloop_get_api(s->mainloop);
533  if (!mainloop_api) {
534  av_log(s, AV_LOG_ERROR, "Cannot get mainloop API.\n");
536  goto fail;
537  }
538 
539  s->ctx = pa_context_new(mainloop_api, s->name);
540  if (!s->ctx) {
541  av_log(s, AV_LOG_ERROR, "Cannot create context.\n");
542  ret = AVERROR(ENOMEM);
543  goto fail;
544  }
545  pa_context_set_state_callback(s->ctx, pulse_context_state, s);
546  pa_context_set_subscribe_callback(s->ctx, pulse_event, h);
547 
548  if ((ret = pa_context_connect(s->ctx, s->server, 0, NULL)) < 0) {
549  av_log(s, AV_LOG_ERROR, "Cannot connect context: %s.\n", pa_strerror(ret));
551  goto fail;
552  }
553 
554  if ((ret = pulse_context_wait(s)) < 0) {
555  av_log(s, AV_LOG_ERROR, "Context failed.\n");
556  goto fail;
557  }
558 
559  s->stream = pa_stream_new(s->ctx, stream_name, &sample_spec,
560  channel_map.channels ? &channel_map : NULL);
561 
562  if ((ret = pulse_update_sink_info(h)) < 0) {
563  av_log(s, AV_LOG_ERROR, "Updating sink info failed.\n");
564  goto fail;
565  }
566 
567  if (!s->stream) {
568  av_log(s, AV_LOG_ERROR, "Cannot create stream.\n");
569  ret = AVERROR(ENOMEM);
570  goto fail;
571  }
572  pa_stream_set_state_callback(s->stream, pulse_stream_state, s);
573  pa_stream_set_write_callback(s->stream, pulse_stream_writable, h);
574  pa_stream_set_overflow_callback(s->stream, pulse_overflow, h);
575  pa_stream_set_underflow_callback(s->stream, pulse_underflow, h);
576 
577  if ((ret = pa_stream_connect_playback(s->stream, s->device, &buffer_attributes,
578  stream_flags, NULL, NULL)) < 0) {
579  av_log(s, AV_LOG_ERROR, "pa_stream_connect_playback failed: %s.\n", pa_strerror(ret));
581  goto fail;
582  }
583 
584  if ((ret = pulse_stream_wait(s)) < 0) {
585  av_log(s, AV_LOG_ERROR, "Stream failed.\n");
586  goto fail;
587  }
588 
589  /* read back buffer attributes for future use */
590  buffer_attributes = *pa_stream_get_buffer_attr(s->stream);
591  s->buffer_size = buffer_attributes.tlength;
592  s->prebuf = buffer_attributes.prebuf;
593  s->minreq = buffer_attributes.minreq;
594  av_log(s, AV_LOG_DEBUG, "Real buffer attributes: size: %d, prebuf: %d, minreq: %d\n",
595  s->buffer_size, s->prebuf, s->minreq);
596 
597  pa_threaded_mainloop_unlock(s->mainloop);
598 
599  if ((ret = pulse_subscribe_events(s)) < 0) {
600  av_log(s, AV_LOG_ERROR, "Event subscription failed.\n");
601  /* a bit ugly but the simplest to lock here*/
602  pa_threaded_mainloop_lock(s->mainloop);
603  goto fail;
604  }
605 
606  /* force control messages */
607  s->mute = -1;
608  s->last_volume = PA_VOLUME_INVALID;
609  pa_threaded_mainloop_lock(s->mainloop);
610  if ((ret = pulse_update_sink_input_info(h)) < 0) {
611  av_log(s, AV_LOG_ERROR, "Updating sink input info failed.\n");
612  goto fail;
613  }
614  pa_threaded_mainloop_unlock(s->mainloop);
615 
616  avpriv_set_pts_info(st, 64, 1, 1000000); /* 64 bits pts in us */
617 
618  return 0;
619  fail:
620  pa_threaded_mainloop_unlock(s->mainloop);
622  return ret;
623 }
624 
626 {
627  PulseData *s = h->priv_data;
628  int ret;
629  int64_t writable_size;
630 
631  if (!pkt)
632  return pulse_flash_stream(s);
633 
634  if (pkt->dts != AV_NOPTS_VALUE)
635  s->timestamp = pkt->dts;
636 
637  if (pkt->duration) {
638  s->timestamp += pkt->duration;
639  } else {
640  AVStream *st = h->streams[0];
641  AVRational r = { 1, st->codecpar->sample_rate };
643  s->timestamp += av_rescale_q(samples, r, st->time_base);
644  }
645 
646  pa_threaded_mainloop_lock(s->mainloop);
647  if (!PA_STREAM_IS_GOOD(pa_stream_get_state(s->stream))) {
648  av_log(s, AV_LOG_ERROR, "PulseAudio stream is in invalid state.\n");
649  goto fail;
650  }
651  while (pa_stream_writable_size(s->stream) < s->minreq) {
652  if (s->nonblocking) {
653  pa_threaded_mainloop_unlock(s->mainloop);
654  return AVERROR(EAGAIN);
655  } else
656  pa_threaded_mainloop_wait(s->mainloop);
657  }
658 
659  if ((ret = pa_stream_write(s->stream, pkt->data, pkt->size, NULL, 0, PA_SEEK_RELATIVE)) < 0) {
660  av_log(s, AV_LOG_ERROR, "pa_stream_write failed: %s\n", pa_strerror(ret));
661  goto fail;
662  }
663  if ((writable_size = pa_stream_writable_size(s->stream)) >= s->minreq)
664  avdevice_dev_to_app_control_message(h, AV_DEV_TO_APP_BUFFER_WRITABLE, &writable_size, sizeof(writable_size));
665 
666  pa_threaded_mainloop_unlock(s->mainloop);
667 
668  return 0;
669  fail:
670  pa_threaded_mainloop_unlock(s->mainloop);
671  return AVERROR_EXTERNAL;
672 }
673 
674 static int pulse_write_frame(AVFormatContext *h, int stream_index,
675  AVFrame **frame, unsigned flags)
676 {
677  AVPacket pkt;
678 
679  /* Planar formats are not supported yet. */
681  return av_sample_fmt_is_planar(h->streams[stream_index]->codecpar->format) ?
682  AVERROR(EINVAL) : 0;
683 
684  pkt.data = (*frame)->data[0];
685  pkt.size = (*frame)->nb_samples * av_get_bytes_per_sample((*frame)->format) * (*frame)->channels;
686  pkt.dts = (*frame)->pkt_dts;
687  pkt.duration = (*frame)->pkt_duration;
688  return pulse_write_packet(h, &pkt);
689 }
690 
691 
692 static void pulse_get_output_timestamp(AVFormatContext *h, int stream, int64_t *dts, int64_t *wall)
693 {
694  PulseData *s = h->priv_data;
695  pa_usec_t latency;
696  int neg;
697  pa_threaded_mainloop_lock(s->mainloop);
698  pa_stream_get_latency(s->stream, &latency, &neg);
699  pa_threaded_mainloop_unlock(s->mainloop);
700  if (wall)
701  *wall = av_gettime();
702  if (dts)
703  *dts = s->timestamp - (neg ? -latency : latency);
704 }
705 
707 {
708  PulseData *s = h->priv_data;
709  return ff_pulse_audio_get_devices(device_list, s->server, 1);
710 }
711 
713  void *data, size_t data_size)
714 {
715  PulseData *s = h->priv_data;
716  int ret;
717 
718  switch(type) {
719  case AV_APP_TO_DEV_PAUSE:
720  return pulse_set_pause(s, 1);
721  case AV_APP_TO_DEV_PLAY:
722  return pulse_set_pause(s, 0);
724  return pulse_set_pause(s, !pa_stream_is_corked(s->stream));
725  case AV_APP_TO_DEV_MUTE:
726  if (!s->mute) {
727  s->mute = 1;
728  return pulse_set_mute(s);
729  }
730  return 0;
732  if (s->mute) {
733  s->mute = 0;
734  return pulse_set_mute(s);
735  }
736  return 0;
738  s->mute = !s->mute;
739  return pulse_set_mute(s);
741  return pulse_set_volume(s, *(double *)data);
743  s->last_volume = PA_VOLUME_INVALID;
744  pa_threaded_mainloop_lock(s->mainloop);
746  pa_threaded_mainloop_unlock(s->mainloop);
747  return ret;
749  s->mute = -1;
750  pa_threaded_mainloop_lock(s->mainloop);
752  pa_threaded_mainloop_unlock(s->mainloop);
753  return ret;
754  default:
755  break;
756  }
757  return AVERROR(ENOSYS);
758 }
759 
760 #define OFFSET(a) offsetof(PulseData, a)
761 #define E AV_OPT_FLAG_ENCODING_PARAM
762 static const AVOption options[] = {
763  { "server", "set PulseAudio server", OFFSET(server), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E },
764  { "name", "set application name", OFFSET(name), AV_OPT_TYPE_STRING, {.str = LIBAVFORMAT_IDENT}, 0, 0, E },
765  { "stream_name", "set stream description", OFFSET(stream_name), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E },
766  { "device", "set device name", OFFSET(device), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E },
767  { "buffer_size", "set buffer size in bytes", OFFSET(buffer_size), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, E },
768  { "buffer_duration", "set buffer duration in millisecs", OFFSET(buffer_duration), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, E },
769  { "prebuf", "set pre-buffering size", OFFSET(prebuf), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, E },
770  { "minreq", "set minimum request size", OFFSET(minreq), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, E },
771  { NULL }
772 };
773 
774 static const AVClass pulse_muxer_class = {
775  .class_name = "PulseAudio outdev",
776  .item_name = av_default_item_name,
777  .option = options,
778  .version = LIBAVUTIL_VERSION_INT,
780 };
781 
783  .name = "pulse",
784  .long_name = NULL_IF_CONFIG_SMALL("Pulse audio output"),
785  .priv_data_size = sizeof(PulseData),
787  .video_codec = AV_CODEC_ID_NONE,
788  .write_header = pulse_write_header,
789  .write_packet = pulse_write_packet,
790  .write_uncoded_frame = pulse_write_frame,
791  .write_trailer = pulse_write_trailer,
792  .get_output_timestamp = pulse_get_output_timestamp,
793  .get_device_list = pulse_get_device_list,
794  .control_message = pulse_control_message,
795  .flags = AVFMT_NOFILE | AVFMT_ALLOW_FLUSH,
796  .priv_class = &pulse_muxer_class,
797 };
AV_CODEC_ID_PCM_S16LE
@ AV_CODEC_ID_PCM_S16LE
Definition: codec_id.h:313
pulse_finish_stream_operation
static int pulse_finish_stream_operation(PulseData *s, pa_operation *op, const char *name)
Definition: pulse_audio_enc.c:261
AV_LOG_WARNING
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:186
pulse_write_packet
static int pulse_write_packet(AVFormatContext *h, AVPacket *pkt)
Definition: pulse_audio_enc.c:625
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:46
AV_APP_TO_DEV_MUTE
@ AV_APP_TO_DEV_MUTE
Mute control messages.
Definition: avdevice.h:179
pulse_write_frame
static int pulse_write_frame(AVFormatContext *h, int stream_index, AVFrame **frame, unsigned flags)
Definition: pulse_audio_enc.c:674
AVOutputFormat::name
const char * name
Definition: avformat.h:496
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
pulse_context_wait
static int pulse_context_wait(PulseData *s)
Definition: pulse_audio_enc.c:238
PulseData::mainloop
pa_threaded_mainloop * mainloop
Definition: pulse_audio_dec.c:48
AV_APP_TO_DEV_SET_VOLUME
@ AV_APP_TO_DEV_SET_VOLUME
Volume control message.
Definition: avdevice.h:168
AV_CH_TOP_FRONT_CENTER
#define AV_CH_TOP_FRONT_CENTER
Definition: channel_layout.h:62
AV_DEV_TO_APP_BUFFER_OVERFLOW
@ AV_DEV_TO_APP_BUFFER_OVERFLOW
Buffer fullness status messages.
Definition: avdevice.h:260
PulseData::server
const char * server
Definition: pulse_audio_enc.c:36
AV_CH_LOW_FREQUENCY_2
#define AV_CH_LOW_FREQUENCY_2
Definition: channel_layout.h:73
pulse_write_header
static av_cold int pulse_write_header(AVFormatContext *h)
Definition: pulse_audio_enc.c:442
pulse_set_pause
static int pulse_set_pause(PulseData *s, int pause)
Definition: pulse_audio_enc.c:278
pulse_underflow
static void pulse_underflow(pa_stream *stream, void *userdata)
Definition: pulse_audio_enc.c:186
AV_CH_TOP_FRONT_RIGHT
#define AV_CH_TOP_FRONT_RIGHT
Definition: channel_layout.h:63
pulse_muxer_class
static const AVClass pulse_muxer_class
Definition: pulse_audio_enc.c:774
E
#define E
Definition: pulse_audio_enc.c:761
AVFrame
This structure describes decoded (raw) audio or video data.
Definition: frame.h:303
AVPacket::data
uint8_t * data
Definition: packet.h:373
AVOption
AVOption.
Definition: opt.h:247
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
data
const char data[16]
Definition: mxf.c:143
avdevice_dev_to_app_control_message
int avdevice_dev_to_app_control_message(struct AVFormatContext *s, enum AVDevToAppMessageType type, void *data, size_t data_size)
Send control message from device to application.
Definition: avdevice.c:60
AV_APP_TO_DEV_PAUSE
@ AV_APP_TO_DEV_PAUSE
Request pause/play.
Definition: avdevice.h:155
pulse_context_result
static void pulse_context_result(pa_context *ctx, int success, void *userdata)
Definition: pulse_audio_enc.c:294
AV_CH_TOP_FRONT_LEFT
#define AV_CH_TOP_FRONT_LEFT
Definition: channel_layout.h:61
AVPacket::duration
int64_t duration
Duration of this packet in AVStream->time_base units, 0 if unknown.
Definition: packet.h:391
FFMAX
#define FFMAX(a, b)
Definition: macros.h:47
pulse_overflow
static void pulse_overflow(pa_stream *stream, void *userdata)
Definition: pulse_audio_enc.c:180
AV_APP_TO_DEV_GET_MUTE
@ AV_APP_TO_DEV_GET_MUTE
Definition: avdevice.h:192
AV_CH_WIDE_LEFT
#define AV_CH_WIDE_LEFT
Definition: channel_layout.h:69
AV_DEV_TO_APP_MUTE_STATE_CHANGED
@ AV_DEV_TO_APP_MUTE_STATE_CHANGED
Mute state change message.
Definition: avdevice.h:284
pulse_stream_wait
static int pulse_stream_wait(PulseData *s)
Definition: pulse_audio_enc.c:209
AV_CH_SURROUND_DIRECT_RIGHT
#define AV_CH_SURROUND_DIRECT_RIGHT
Definition: channel_layout.h:72
AV_CH_WIDE_RIGHT
#define AV_CH_WIDE_RIGHT
Definition: channel_layout.h:70
AV_CH_TOP_BACK_LEFT
#define AV_CH_TOP_BACK_LEFT
Definition: channel_layout.h:64
PulseData::nonblocking
int nonblocking
Definition: pulse_audio_enc.c:49
PulseData
Definition: pulse_audio_dec.c:38
AV_CH_TOP_BACK_CENTER
#define AV_CH_TOP_BACK_CENTER
Definition: channel_layout.h:65
PulseData::last_volume
pa_volume_t last_volume
Definition: pulse_audio_enc.c:52
AVCodecParameters::channels
int channels
Audio only.
Definition: codec_par.h:166
PulseData::stream
pa_stream * stream
Definition: pulse_audio_dec.c:50
PulseData::timestamp
int64_t timestamp
Definition: pulse_audio_enc.c:40
AV_CODEC_ID_PCM_S16BE
@ AV_CODEC_ID_PCM_S16BE
Definition: codec_id.h:314
fail
#define fail()
Definition: checkasm.h:127
PulseData::base_volume
pa_volume_t base_volume
Definition: pulse_audio_enc.c:51
AV_CH_BACK_LEFT
#define AV_CH_BACK_LEFT
Definition: channel_layout.h:53
val
static double val(void *priv, double ch)
Definition: aeval.c:76
pulse_update_sink_input_info
static int pulse_update_sink_input_info(AVFormatContext *h)
Definition: pulse_audio_enc.c:118
type
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 type
Definition: writing_filters.txt:86
ss
#define ss(width, name, subs,...)
Definition: cbs_vp9.c:261
av_clip64
#define av_clip64
Definition: common.h:99
AV_APP_TO_DEV_UNMUTE
@ AV_APP_TO_DEV_UNMUTE
Definition: avdevice.h:180
lrint
#define lrint
Definition: tablegen.h:53
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
pulse_stream_state
static void pulse_stream_state(pa_stream *stream, void *userdata)
Definition: pulse_audio_enc.c:192
pulse_map_channels_to_pulse
static void pulse_map_channels_to_pulse(int64_t channel_layout, pa_channel_map *channel_map)
Definition: pulse_audio_enc.c:356
av_cold
#define av_cold
Definition: attributes.h:90
AV_APP_TO_DEV_TOGGLE_PAUSE
@ AV_APP_TO_DEV_TOGGLE_PAUSE
Definition: avdevice.h:157
AV_CH_LOW_FREQUENCY
#define AV_CH_LOW_FREQUENCY
Definition: channel_layout.h:52
s
#define s(width, name)
Definition: cbs_vp9.c:257
AV_NE
#define AV_NE(be, le)
Definition: macros.h:33
pulse_set_volume
static int pulse_set_volume(PulseData *s, double volume)
Definition: pulse_audio_enc.c:331
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
op
static int op(uint8_t **dst, const uint8_t *dst_end, GetByteContext *gb, int pixel, int count, int *x, int width, int linesize)
Perform decode operation.
Definition: anm.c:75
av_sample_fmt_is_planar
int av_sample_fmt_is_planar(enum AVSampleFormat sample_fmt)
Check if the sample format is planar.
Definition: samplefmt.c:112
AV_LOG_DEBUG
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition: log.h:201
ctx
AVFormatContext * ctx
Definition: movenc.c:48
av_rescale_q
int64_t av_rescale_q(int64_t a, AVRational bq, AVRational cq)
Rescale a 64-bit integer by 2 rational numbers.
Definition: mathematics.c:141
pulse_get_output_timestamp
static void pulse_get_output_timestamp(AVFormatContext *h, int stream, int64_t *dts, int64_t *wall)
Definition: pulse_audio_enc.c:692
pulse_update_sink_info
static int pulse_update_sink_info(AVFormatContext *h)
Definition: pulse_audio_enc.c:75
PulseData::stream_name
const char * stream_name
Definition: pulse_audio_enc.c:38
AV_CH_STEREO_RIGHT
#define AV_CH_STEREO_RIGHT
See AV_CH_STEREO_LEFT.
Definition: channel_layout.h:68
AVFormatContext
Format I/O context.
Definition: avformat.h:1097
internal.h
pulse_event
static void pulse_event(pa_context *ctx, pa_subscription_event_type_t t, uint32_t idx, void *userdata)
Definition: pulse_audio_enc.c:151
AVStream::codecpar
AVCodecParameters * codecpar
Codec parameters associated with this stream.
Definition: avformat.h:992
LIBAVUTIL_VERSION_INT
#define LIBAVUTIL_VERSION_INT
Definition: version.h:85
AVClass
Describe the class of an AVClass context structure.
Definition: log.h:66
AV_CH_TOP_CENTER
#define AV_CH_TOP_CENTER
Definition: channel_layout.h:60
AVStream::time_base
AVRational time_base
This is the fundamental unit of time (in seconds) in terms of which frame timestamps are represented.
Definition: avformat.h:868
NULL
#define NULL
Definition: coverity.c:32
AV_APP_TO_DEV_GET_VOLUME
@ AV_APP_TO_DEV_GET_VOLUME
Get volume/mute messages.
Definition: avdevice.h:191
PulseData::mute
int mute
Definition: pulse_audio_enc.c:50
PulseData::ctx
pa_context * ctx
Definition: pulse_audio_enc.c:47
AVRational
Rational number (pair of numerator and denominator).
Definition: rational.h:58
state
static struct @317 state
pulse_audio_sink_device_cb
static void pulse_audio_sink_device_cb(pa_context *ctx, const pa_sink_info *dev, int eol, void *userdata)
Definition: pulse_audio_enc.c:55
av_default_item_name
const char * av_default_item_name(void *ptr)
Return the context name.
Definition: log.c:235
pulse_flash_stream
static int pulse_flash_stream(PulseData *s)
Definition: pulse_audio_enc.c:286
time.h
AV_CH_FRONT_CENTER
#define AV_CH_FRONT_CENTER
Definition: channel_layout.h:51
pulse_stream_result
static void pulse_stream_result(pa_stream *stream, int success, void *userdata)
Definition: pulse_audio_enc.c:250
AV_CH_FRONT_LEFT_OF_CENTER
#define AV_CH_FRONT_LEFT_OF_CENTER
Definition: channel_layout.h:55
AVCodecParameters::sample_rate
int sample_rate
Audio only.
Definition: codec_par.h:170
av_get_channel_layout_nb_channels
int av_get_channel_layout_nb_channels(uint64_t channel_layout)
Return the number of channels in the channel layout.
Definition: channel_layout.c:226
pulse_audio_common.h
ff_pulse_muxer
const AVOutputFormat ff_pulse_muxer
Definition: pulse_audio_enc.c:782
pulse_control_message
static int pulse_control_message(AVFormatContext *h, int type, void *data, size_t data_size)
Definition: pulse_audio_enc.c:712
pulse_audio_sink_input_cb
static void pulse_audio_sink_input_cb(pa_context *ctx, const pa_sink_input_info *i, int eol, void *userdata)
Definition: pulse_audio_enc.c:90
AVPacket::size
int size
Definition: packet.h:374
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
AV_APP_TO_DEV_PLAY
@ AV_APP_TO_DEV_PLAY
Definition: avdevice.h:156
pulse_stream_writable
static void pulse_stream_writable(pa_stream *stream, size_t nbytes, void *userdata)
Definition: pulse_audio_enc.c:167
AV_NOPTS_VALUE
#define AV_NOPTS_VALUE
Undefined timestamp value.
Definition: avutil.h:248
ff_pulse_audio_disconnect_context
void ff_pulse_audio_disconnect_context(pa_mainloop **pa_ml, pa_context **pa_ctx)
Definition: pulse_audio_common.c:77
AVFMT_ALLOW_FLUSH
#define AVFMT_ALLOW_FLUSH
Format allows flushing.
Definition: avformat.h:476
AVFMT_NOFILE
#define AVFMT_NOFILE
Demuxer will use avio_open, no opened file should be provided by the caller.
Definition: avformat.h:463
AVPacket::dts
int64_t dts
Decompression timestamp in AVStream->time_base units; the time at which the packet is decompressed.
Definition: packet.h:372
pulse_context_state
static void pulse_context_state(pa_context *ctx, void *userdata)
Definition: pulse_audio_enc.c:221
AV_APP_TO_DEV_TOGGLE_MUTE
@ AV_APP_TO_DEV_TOGGLE_MUTE
Definition: avdevice.h:181
AVERROR_EXTERNAL
#define AVERROR_EXTERNAL
Generic error in an external library.
Definition: error.h:59
PulseData::prebuf
int prebuf
Definition: pulse_audio_enc.c:43
attributes.h
AV_CH_TOP_BACK_RIGHT
#define AV_CH_TOP_BACK_RIGHT
Definition: channel_layout.h:66
AV_CH_FRONT_RIGHT_OF_CENTER
#define AV_CH_FRONT_RIGHT_OF_CENTER
Definition: channel_layout.h:56
i
int i
Definition: input.c:406
ff_pulse_audio_connect_context
int ff_pulse_audio_connect_context(pa_mainloop **pa_ml, pa_context **pa_ctx, const char *server, const char *description)
Definition: pulse_audio_common.c:93
log.h
AV_CODEC_ID_NONE
@ AV_CODEC_ID_NONE
Definition: codec_id.h:48
AVOutputFormat
Definition: avformat.h:495
PulseData::buffer_size
int buffer_size
Buffer size in bytes.
Definition: pulse_audio_enc.c:41
av_get_bytes_per_sample
int av_get_bytes_per_sample(enum AVSampleFormat sample_fmt)
Return number of bytes per sample.
Definition: samplefmt.c:106
internal.h
AV_CLASS_CATEGORY_DEVICE_AUDIO_OUTPUT
@ AV_CLASS_CATEGORY_DEVICE_AUDIO_OUTPUT
Definition: log.h:42
AV_CH_BACK_CENTER
#define AV_CH_BACK_CENTER
Definition: channel_layout.h:57
AV_CH_FRONT_LEFT
#define AV_CH_FRONT_LEFT
Definition: channel_layout.h:49
AV_CH_SIDE_RIGHT
#define AV_CH_SIDE_RIGHT
Definition: channel_layout.h:59
AVFMT_FLAG_NONBLOCK
#define AVFMT_FLAG_NONBLOCK
Do not block when reading packets from input.
Definition: avformat.h:1218
ret
ret
Definition: filter_design.txt:187
AVStream
Stream structure.
Definition: avformat.h:845
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
frame
these buffered frames must be flushed immediately if a new input produces new the filter must not call request_frame to get more It must just process the frame or queue it The task of requesting more frames is left to the filter s request_frame method or the application If a filter has several the filter must be ready for frames arriving randomly on any input any filter with several inputs will most likely require some kind of queuing mechanism It is perfectly acceptable to have a limited queue and to drop frames when the inputs are too unbalanced request_frame For filters that do not use the this method is called when a frame is wanted on an output For a it should directly call filter_frame on the corresponding output For a if there are queued frames already one of these frames should be pushed If the filter should request a frame on one of its repeatedly until at least one frame has been pushed Return or at least make progress towards producing a frame
Definition: filter_design.txt:264
PulseData::name
const char * name
Definition: pulse_audio_enc.c:37
AVDeviceInfoList
List of devices.
Definition: avdevice.h:465
avformat.h
PulseData::buffer_duration
int buffer_duration
Buffer size in ms, recalculated to buffer_size.
Definition: pulse_audio_enc.c:42
channel_layout.h
OFFSET
#define OFFSET(a)
Definition: pulse_audio_enc.c:760
pulse_write_trailer
static av_cold int pulse_write_trailer(AVFormatContext *h)
Definition: pulse_audio_enc.c:411
AV_OPT_TYPE_INT
@ AV_OPT_TYPE_INT
Definition: opt.h:224
pulse_subscribe_events
static int pulse_subscribe_events(PulseData *s)
Definition: pulse_audio_enc.c:347
samples
Filter the word “frame” indicates either a video frame or a group of audio samples
Definition: filter_design.txt:8
pulse_set_mute
static int pulse_set_mute(PulseData *s)
Definition: pulse_audio_enc.c:322
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: utils.c:1146
AV_CH_SURROUND_DIRECT_LEFT
#define AV_CH_SURROUND_DIRECT_LEFT
Definition: channel_layout.h:71
AV_CH_FRONT_RIGHT
#define AV_CH_FRONT_RIGHT
Definition: channel_layout.h:50
av_gettime
int64_t av_gettime(void)
Get the current time in microseconds.
Definition: time.c:39
PulseData::minreq
int minreq
Definition: pulse_audio_enc.c:44
pulse_finish_context_operation
static int pulse_finish_context_operation(PulseData *s, pa_operation *op, const char *name)
Definition: pulse_audio_enc.c:305
AVCodecParameters::format
int format
Definition: codec_par.h:84
AV_DEV_TO_APP_VOLUME_LEVEL_CHANGED
@ AV_DEV_TO_APP_VOLUME_LEVEL_CHANGED
Volume level change message.
Definition: avdevice.h:293
AV_DEV_TO_APP_BUFFER_WRITABLE
@ AV_DEV_TO_APP_BUFFER_WRITABLE
Definition: avdevice.h:275
AVCodecParameters::codec_id
enum AVCodecID codec_id
Specific type of the encoded data (the codec used).
Definition: codec_par.h:60
AVPacket
This structure stores compressed data.
Definition: packet.h:350
AV_WRITE_UNCODED_FRAME_QUERY
@ AV_WRITE_UNCODED_FRAME_QUERY
Query whether the feature is possible on this stream.
Definition: internal.h:873
pulse_get_device_list
static int pulse_get_device_list(AVFormatContext *h, AVDeviceInfoList *device_list)
Definition: pulse_audio_enc.c:706
AVCodecParameters::channel_layout
uint64_t channel_layout
Audio only.
Definition: codec_par.h:162
PulseData::device
const char * device
Definition: pulse_audio_enc.c:39
flags
#define flags(name, subs,...)
Definition: cbs_av1.c:561
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:28
PulseData::last_result
int last_result
Definition: pulse_audio_enc.c:45
AV_CH_BACK_RIGHT
#define AV_CH_BACK_RIGHT
Definition: channel_layout.h:54
h
h
Definition: vp9dsp_template.c:2038
AV_CH_STEREO_LEFT
#define AV_CH_STEREO_LEFT
Stereo downmix.
Definition: channel_layout.h:67
AV_OPT_TYPE_STRING
@ AV_OPT_TYPE_STRING
Definition: opt.h:228
options
static const AVOption options[]
Definition: pulse_audio_enc.c:762
AV_DEV_TO_APP_BUFFER_UNDERFLOW
@ AV_DEV_TO_APP_BUFFER_UNDERFLOW
Definition: avdevice.h:261
AV_CH_SIDE_LEFT
#define AV_CH_SIDE_LEFT
Definition: channel_layout.h:58