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"
26 #include "libavformat/mux.h"
27 #include "libavformat/version.h"
29 #include "libavutil/internal.h"
30 #include "libavutil/opt.h"
31 #include "libavutil/time.h"
32 #include "libavutil/log.h"
33 #include "libavutil/attributes.h"
34 #include "pulse_audio_common.h"
35 
36 typedef struct PulseData {
37  AVClass *class;
38  const char *server;
39  const char *name;
40  const char *stream_name;
41  const char *device;
42  int64_t timestamp;
43  int buffer_size; /**< Buffer size in bytes */
44  int buffer_duration; /**< Buffer size in ms, recalculated to buffer_size */
45  int prebuf;
46  int minreq;
48  pa_threaded_mainloop *mainloop;
49  pa_context *ctx;
50  pa_stream *stream;
52  int mute;
53  pa_volume_t base_volume;
54  pa_volume_t last_volume;
55 } PulseData;
56 
57 static void pulse_audio_sink_device_cb(pa_context *ctx, const pa_sink_info *dev,
58  int eol, void *userdata)
59 {
60  PulseData *s = userdata;
61 
62  if (s->ctx != ctx)
63  return;
64 
65  if (eol) {
66  pa_threaded_mainloop_signal(s->mainloop, 0);
67  } else {
68  if (dev->flags & PA_SINK_FLAT_VOLUME)
69  s->base_volume = dev->base_volume;
70  else
71  s->base_volume = PA_VOLUME_NORM;
72  av_log(s, AV_LOG_DEBUG, "base volume: %u\n", s->base_volume);
73  }
74 }
75 
76 /* Mainloop must be locked before calling this function as it uses pa_threaded_mainloop_wait. */
78 {
79  PulseData *s = h->priv_data;
80  pa_operation *op;
81  if (!(op = pa_context_get_sink_info_by_name(s->ctx, s->device,
83  av_log(s, AV_LOG_ERROR, "pa_context_get_sink_info_by_name failed.\n");
84  return AVERROR_EXTERNAL;
85  }
86  while (pa_operation_get_state(op) == PA_OPERATION_RUNNING)
87  pa_threaded_mainloop_wait(s->mainloop);
88  pa_operation_unref(op);
89  return 0;
90 }
91 
92 static void pulse_audio_sink_input_cb(pa_context *ctx, const pa_sink_input_info *i,
93  int eol, void *userdata)
94 {
95  AVFormatContext *h = userdata;
96  PulseData *s = h->priv_data;
97 
98  if (s->ctx != ctx)
99  return;
100 
101  if (!eol) {
102  double val;
103  pa_volume_t vol = pa_cvolume_avg(&i->volume);
104  if (s->mute < 0 || (s->mute && !i->mute) || (!s->mute && i->mute)) {
105  s->mute = i->mute;
107  }
108 
109  vol = pa_sw_volume_divide(vol, s->base_volume);
110  if (s->last_volume != vol) {
111  val = (double)vol / PA_VOLUME_NORM;
113  s->last_volume = vol;
114  }
115  }
116 }
117 
118 /* This function creates new loop so may be called from PA callbacks.
119  Mainloop must be locked before calling this function as it operates on streams. */
121 {
122  PulseData *s = h->priv_data;
123  pa_operation *op;
124  enum pa_operation_state op_state;
125  pa_mainloop *ml = NULL;
126  pa_context *ctx = NULL;
127  int ret = 0;
128 
129  if ((ret = ff_pulse_audio_connect_context(&ml, &ctx, s->server, "Update sink input information")) < 0)
130  return ret;
131 
132  if (!(op = pa_context_get_sink_input_info(ctx, pa_stream_get_index(s->stream),
135  goto fail;
136  }
137 
138  while ((op_state = pa_operation_get_state(op)) == PA_OPERATION_RUNNING)
139  pa_mainloop_iterate(ml, 1, NULL);
140  pa_operation_unref(op);
141  if (op_state != PA_OPERATION_DONE) {
143  goto fail;
144  }
145 
146  fail:
148  if (ret)
149  av_log(s, AV_LOG_ERROR, "pa_context_get_sink_input_info failed.\n");
150  return ret;
151 }
152 
153 static void pulse_event(pa_context *ctx, pa_subscription_event_type_t t,
154  uint32_t idx, void *userdata)
155 {
156  AVFormatContext *h = userdata;
157  PulseData *s = h->priv_data;
158 
159  if (s->ctx != ctx)
160  return;
161 
162  if ((t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_SINK_INPUT) {
163  if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_CHANGE)
164  // Calling from mainloop callback. No need to lock mainloop.
166  }
167 }
168 
169 static void pulse_stream_writable(pa_stream *stream, size_t nbytes, void *userdata)
170 {
171  AVFormatContext *h = userdata;
172  PulseData *s = h->priv_data;
173  int64_t val = nbytes;
174 
175  if (stream != s->stream)
176  return;
177 
179  pa_threaded_mainloop_signal(s->mainloop, 0);
180 }
181 
182 static void pulse_overflow(pa_stream *stream, void *userdata)
183 {
184  AVFormatContext *h = userdata;
186 }
187 
188 static void pulse_underflow(pa_stream *stream, void *userdata)
189 {
190  AVFormatContext *h = userdata;
192 }
193 
194 static void pulse_stream_state(pa_stream *stream, void *userdata)
195 {
196  PulseData *s = userdata;
197 
198  if (stream != s->stream)
199  return;
200 
201  switch (pa_stream_get_state(s->stream)) {
202  case PA_STREAM_READY:
203  case PA_STREAM_FAILED:
204  case PA_STREAM_TERMINATED:
205  pa_threaded_mainloop_signal(s->mainloop, 0);
206  default:
207  break;
208  }
209 }
210 
212 {
213  pa_stream_state_t state;
214 
215  while ((state = pa_stream_get_state(s->stream)) != PA_STREAM_READY) {
216  if (state == PA_STREAM_FAILED || state == PA_STREAM_TERMINATED)
217  return AVERROR_EXTERNAL;
218  pa_threaded_mainloop_wait(s->mainloop);
219  }
220  return 0;
221 }
222 
223 static void pulse_context_state(pa_context *ctx, void *userdata)
224 {
225  PulseData *s = userdata;
226 
227  if (s->ctx != ctx)
228  return;
229 
230  switch (pa_context_get_state(ctx)) {
231  case PA_CONTEXT_READY:
232  case PA_CONTEXT_FAILED:
233  case PA_CONTEXT_TERMINATED:
234  pa_threaded_mainloop_signal(s->mainloop, 0);
235  default:
236  break;
237  }
238 }
239 
241 {
242  pa_context_state_t state;
243 
244  while ((state = pa_context_get_state(s->ctx)) != PA_CONTEXT_READY) {
245  if (state == PA_CONTEXT_FAILED || state == PA_CONTEXT_TERMINATED)
246  return AVERROR_EXTERNAL;
247  pa_threaded_mainloop_wait(s->mainloop);
248  }
249  return 0;
250 }
251 
252 static void pulse_stream_result(pa_stream *stream, int success, void *userdata)
253 {
254  PulseData *s = userdata;
255 
256  if (stream != s->stream)
257  return;
258 
259  s->last_result = success ? 0 : AVERROR_EXTERNAL;
260  pa_threaded_mainloop_signal(s->mainloop, 0);
261 }
262 
263 static int pulse_finish_stream_operation(PulseData *s, pa_operation *op, const char *name)
264 {
265  if (!op) {
266  pa_threaded_mainloop_unlock(s->mainloop);
267  av_log(s, AV_LOG_ERROR, "%s failed.\n", name);
268  return AVERROR_EXTERNAL;
269  }
270  s->last_result = 2;
271  while (s->last_result == 2)
272  pa_threaded_mainloop_wait(s->mainloop);
273  pa_operation_unref(op);
274  pa_threaded_mainloop_unlock(s->mainloop);
275  if (s->last_result != 0)
276  av_log(s, AV_LOG_ERROR, "%s failed.\n", name);
277  return s->last_result;
278 }
279 
280 static int pulse_set_pause(PulseData *s, int pause)
281 {
282  pa_operation *op;
283  pa_threaded_mainloop_lock(s->mainloop);
284  op = pa_stream_cork(s->stream, pause, pulse_stream_result, s);
285  return pulse_finish_stream_operation(s, op, "pa_stream_cork");
286 }
287 
289 {
290  pa_operation *op;
291  pa_threaded_mainloop_lock(s->mainloop);
292  op = pa_stream_flush(s->stream, pulse_stream_result, s);
293  return pulse_finish_stream_operation(s, op, "pa_stream_flush");
294 }
295 
296 static void pulse_context_result(pa_context *ctx, int success, void *userdata)
297 {
298  PulseData *s = userdata;
299 
300  if (s->ctx != ctx)
301  return;
302 
303  s->last_result = success ? 0 : AVERROR_EXTERNAL;
304  pa_threaded_mainloop_signal(s->mainloop, 0);
305 }
306 
307 static int pulse_finish_context_operation(PulseData *s, pa_operation *op, const char *name)
308 {
309  if (!op) {
310  pa_threaded_mainloop_unlock(s->mainloop);
311  av_log(s, AV_LOG_ERROR, "%s failed.\n", name);
312  return AVERROR_EXTERNAL;
313  }
314  s->last_result = 2;
315  while (s->last_result == 2)
316  pa_threaded_mainloop_wait(s->mainloop);
317  pa_operation_unref(op);
318  pa_threaded_mainloop_unlock(s->mainloop);
319  if (s->last_result != 0)
320  av_log(s, AV_LOG_ERROR, "%s failed.\n", name);
321  return s->last_result;
322 }
323 
325 {
326  pa_operation *op;
327  pa_threaded_mainloop_lock(s->mainloop);
328  op = pa_context_set_sink_input_mute(s->ctx, pa_stream_get_index(s->stream),
329  s->mute, pulse_context_result, s);
330  return pulse_finish_context_operation(s, op, "pa_context_set_sink_input_mute");
331 }
332 
333 static int pulse_set_volume(PulseData *s, double volume)
334 {
335  pa_operation *op;
336  pa_cvolume cvol;
337  pa_volume_t vol;
338  const pa_sample_spec *ss = pa_stream_get_sample_spec(s->stream);
339 
340  vol = pa_sw_volume_multiply(lrint(volume * PA_VOLUME_NORM), s->base_volume);
341  pa_cvolume_set(&cvol, ss->channels, PA_VOLUME_NORM);
342  pa_sw_cvolume_multiply_scalar(&cvol, &cvol, vol);
343  pa_threaded_mainloop_lock(s->mainloop);
344  op = pa_context_set_sink_input_volume(s->ctx, pa_stream_get_index(s->stream),
345  &cvol, pulse_context_result, s);
346  return pulse_finish_context_operation(s, op, "pa_context_set_sink_input_volume");
347 }
348 
350 {
351  pa_operation *op;
352 
353  pa_threaded_mainloop_lock(s->mainloop);
354  op = pa_context_subscribe(s->ctx, PA_SUBSCRIPTION_MASK_SINK_INPUT, pulse_context_result, s);
355  return pulse_finish_context_operation(s, op, "pa_context_subscribe");
356 }
357 
358 static void pulse_map_channels_to_pulse(const AVChannelLayout *channel_layout, pa_channel_map *channel_map)
359 {
360  channel_map->channels = 0;
362  channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_FRONT_LEFT;
364  channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_FRONT_RIGHT;
366  channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_FRONT_CENTER;
368  channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_LFE;
370  channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_REAR_LEFT;
372  channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_REAR_RIGHT;
374  channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER;
376  channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER;
378  channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_REAR_CENTER;
380  channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_SIDE_LEFT;
382  channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_SIDE_RIGHT;
384  channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_TOP_CENTER;
386  channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_TOP_FRONT_LEFT;
388  channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_TOP_FRONT_CENTER;
390  channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_TOP_FRONT_RIGHT;
392  channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_TOP_REAR_LEFT;
394  channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_TOP_REAR_CENTER;
396  channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_TOP_REAR_RIGHT;
398  channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_FRONT_LEFT;
400  channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_FRONT_RIGHT;
402  channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_AUX0;
404  channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_AUX1;
406  channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_AUX2;
408  channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_AUX3;
410  channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_LFE;
411 }
412 
414 {
415  PulseData *s = h->priv_data;
416 
417  if (s->mainloop) {
418  pa_threaded_mainloop_lock(s->mainloop);
419  if (s->stream) {
420  pa_stream_disconnect(s->stream);
421  pa_stream_set_state_callback(s->stream, NULL, NULL);
422  pa_stream_set_write_callback(s->stream, NULL, NULL);
423  pa_stream_set_overflow_callback(s->stream, NULL, NULL);
424  pa_stream_set_underflow_callback(s->stream, NULL, NULL);
425  pa_stream_unref(s->stream);
426  s->stream = NULL;
427  }
428  if (s->ctx) {
429  pa_context_disconnect(s->ctx);
430  pa_context_set_state_callback(s->ctx, NULL, NULL);
431  pa_context_set_subscribe_callback(s->ctx, NULL, NULL);
432  pa_context_unref(s->ctx);
433  s->ctx = NULL;
434  }
435  pa_threaded_mainloop_unlock(s->mainloop);
436  pa_threaded_mainloop_stop(s->mainloop);
437  pa_threaded_mainloop_free(s->mainloop);
438  s->mainloop = NULL;
439  }
440 
441  return 0;
442 }
443 
445 {
446  PulseData *s = h->priv_data;
447  AVStream *st = NULL;
448  int ret;
449  pa_sample_spec sample_spec;
450  pa_buffer_attr buffer_attributes = { -1, -1, -1, -1, -1 };
451  pa_channel_map channel_map;
452  pa_mainloop_api *mainloop_api;
453  const char *stream_name = s->stream_name;
454  static const pa_stream_flags_t stream_flags = PA_STREAM_INTERPOLATE_TIMING |
455  PA_STREAM_AUTO_TIMING_UPDATE |
456  PA_STREAM_NOT_MONOTONIC;
457 
458  if (h->nb_streams != 1 || h->streams[0]->codecpar->codec_type != AVMEDIA_TYPE_AUDIO) {
459  av_log(s, AV_LOG_ERROR, "Only a single audio stream is supported.\n");
460  return AVERROR(EINVAL);
461  }
462  st = h->streams[0];
463 
464  if (!stream_name) {
465  if (h->url[0])
466  stream_name = h->url;
467  else
468  stream_name = "Playback";
469  }
470  s->nonblocking = (h->flags & AVFMT_FLAG_NONBLOCK);
471 
472  if (s->buffer_duration) {
473  int64_t bytes = s->buffer_duration;
474  bytes *= st->codecpar->ch_layout.nb_channels * st->codecpar->sample_rate *
476  bytes /= 1000;
477  buffer_attributes.tlength = FFMAX(s->buffer_size, av_clip64(bytes, 0, UINT32_MAX - 1));
479  "Buffer duration: %ums recalculated into %"PRId64" bytes buffer.\n",
480  s->buffer_duration, bytes);
481  av_log(s, AV_LOG_DEBUG, "Real buffer length is %u bytes\n", buffer_attributes.tlength);
482  } else if (s->buffer_size)
483  buffer_attributes.tlength = s->buffer_size;
484  if (s->prebuf)
485  buffer_attributes.prebuf = s->prebuf;
486  if (s->minreq)
487  buffer_attributes.minreq = s->minreq;
488 
489  sample_spec.format = ff_codec_id_to_pulse_format(st->codecpar->codec_id);
490  sample_spec.rate = st->codecpar->sample_rate;
491  sample_spec.channels = st->codecpar->ch_layout.nb_channels;
492  if (!pa_sample_spec_valid(&sample_spec)) {
493  av_log(s, AV_LOG_ERROR, "Invalid sample spec.\n");
494  return AVERROR(EINVAL);
495  }
496 
497  if (sample_spec.channels == 1) {
498  channel_map.channels = 1;
499  channel_map.map[0] = PA_CHANNEL_POSITION_MONO;
500  } else if (st->codecpar->ch_layout.order != AV_CHANNEL_ORDER_UNSPEC) {
502  return AVERROR(EINVAL);
504  /* Unknown channel is present in channel_layout, let PulseAudio use its default. */
505  if (channel_map.channels != sample_spec.channels) {
506  av_log(s, AV_LOG_WARNING, "Unknown channel. Using defaul channel map.\n");
507  channel_map.channels = 0;
508  }
509  } else
510  channel_map.channels = 0;
511 
512  if (!channel_map.channels)
513  av_log(s, AV_LOG_WARNING, "Using PulseAudio's default channel map.\n");
514  else if (!pa_channel_map_valid(&channel_map)) {
515  av_log(s, AV_LOG_ERROR, "Invalid channel map.\n");
516  return AVERROR(EINVAL);
517  }
518 
519  /* start main loop */
520  s->mainloop = pa_threaded_mainloop_new();
521  if (!s->mainloop) {
522  av_log(s, AV_LOG_ERROR, "Cannot create threaded mainloop.\n");
523  return AVERROR(ENOMEM);
524  }
525  if ((ret = pa_threaded_mainloop_start(s->mainloop)) < 0) {
526  av_log(s, AV_LOG_ERROR, "Cannot start threaded mainloop: %s.\n", pa_strerror(ret));
527  pa_threaded_mainloop_free(s->mainloop);
528  s->mainloop = NULL;
529  return AVERROR_EXTERNAL;
530  }
531 
532  pa_threaded_mainloop_lock(s->mainloop);
533 
534  mainloop_api = pa_threaded_mainloop_get_api(s->mainloop);
535  if (!mainloop_api) {
536  av_log(s, AV_LOG_ERROR, "Cannot get mainloop API.\n");
538  goto fail;
539  }
540 
541  s->ctx = pa_context_new(mainloop_api, s->name);
542  if (!s->ctx) {
543  av_log(s, AV_LOG_ERROR, "Cannot create context.\n");
544  ret = AVERROR(ENOMEM);
545  goto fail;
546  }
547  pa_context_set_state_callback(s->ctx, pulse_context_state, s);
548  pa_context_set_subscribe_callback(s->ctx, pulse_event, h);
549 
550  if ((ret = pa_context_connect(s->ctx, s->server, 0, NULL)) < 0) {
551  av_log(s, AV_LOG_ERROR, "Cannot connect context: %s.\n", pa_strerror(ret));
553  goto fail;
554  }
555 
556  if ((ret = pulse_context_wait(s)) < 0) {
557  av_log(s, AV_LOG_ERROR, "Context failed.\n");
558  goto fail;
559  }
560 
561  s->stream = pa_stream_new(s->ctx, stream_name, &sample_spec,
562  channel_map.channels ? &channel_map : NULL);
563 
564  if ((ret = pulse_update_sink_info(h)) < 0) {
565  av_log(s, AV_LOG_ERROR, "Updating sink info failed.\n");
566  goto fail;
567  }
568 
569  if (!s->stream) {
570  av_log(s, AV_LOG_ERROR, "Cannot create stream.\n");
571  ret = AVERROR(ENOMEM);
572  goto fail;
573  }
574  pa_stream_set_state_callback(s->stream, pulse_stream_state, s);
575  pa_stream_set_write_callback(s->stream, pulse_stream_writable, h);
576  pa_stream_set_overflow_callback(s->stream, pulse_overflow, h);
577  pa_stream_set_underflow_callback(s->stream, pulse_underflow, h);
578 
579  if ((ret = pa_stream_connect_playback(s->stream, s->device, &buffer_attributes,
580  stream_flags, NULL, NULL)) < 0) {
581  av_log(s, AV_LOG_ERROR, "pa_stream_connect_playback failed: %s.\n", pa_strerror(ret));
583  goto fail;
584  }
585 
586  if ((ret = pulse_stream_wait(s)) < 0) {
587  av_log(s, AV_LOG_ERROR, "Stream failed.\n");
588  goto fail;
589  }
590 
591  /* read back buffer attributes for future use */
592  buffer_attributes = *pa_stream_get_buffer_attr(s->stream);
593  s->buffer_size = buffer_attributes.tlength;
594  s->prebuf = buffer_attributes.prebuf;
595  s->minreq = buffer_attributes.minreq;
596  av_log(s, AV_LOG_DEBUG, "Real buffer attributes: size: %d, prebuf: %d, minreq: %d\n",
597  s->buffer_size, s->prebuf, s->minreq);
598 
599  pa_threaded_mainloop_unlock(s->mainloop);
600 
601  if ((ret = pulse_subscribe_events(s)) < 0) {
602  av_log(s, AV_LOG_ERROR, "Event subscription failed.\n");
603  /* a bit ugly but the simplest to lock here*/
604  pa_threaded_mainloop_lock(s->mainloop);
605  goto fail;
606  }
607 
608  /* force control messages */
609  s->mute = -1;
610  s->last_volume = PA_VOLUME_INVALID;
611  pa_threaded_mainloop_lock(s->mainloop);
612  if ((ret = pulse_update_sink_input_info(h)) < 0) {
613  av_log(s, AV_LOG_ERROR, "Updating sink input info failed.\n");
614  goto fail;
615  }
616  pa_threaded_mainloop_unlock(s->mainloop);
617 
618  avpriv_set_pts_info(st, 64, 1, 1000000); /* 64 bits pts in us */
619 
620  return 0;
621  fail:
622  pa_threaded_mainloop_unlock(s->mainloop);
624  return ret;
625 }
626 
628 {
629  PulseData *s = h->priv_data;
630  int ret;
631  int64_t writable_size;
632 
633  if (!pkt)
634  return pulse_flash_stream(s);
635 
636  if (pkt->dts != AV_NOPTS_VALUE)
637  s->timestamp = pkt->dts;
638 
639  if (pkt->duration) {
640  s->timestamp += pkt->duration;
641  } else {
642  AVStream *st = h->streams[0];
643  AVRational r = { 1, st->codecpar->sample_rate };
645  s->timestamp += av_rescale_q(samples, r, st->time_base);
646  }
647 
648  pa_threaded_mainloop_lock(s->mainloop);
649  if (!PA_STREAM_IS_GOOD(pa_stream_get_state(s->stream))) {
650  av_log(s, AV_LOG_ERROR, "PulseAudio stream is in invalid state.\n");
651  goto fail;
652  }
653  while (pa_stream_writable_size(s->stream) < s->minreq) {
654  if (s->nonblocking) {
655  pa_threaded_mainloop_unlock(s->mainloop);
656  return AVERROR(EAGAIN);
657  } else
658  pa_threaded_mainloop_wait(s->mainloop);
659  }
660 
661  if ((ret = pa_stream_write(s->stream, pkt->data, pkt->size, NULL, 0, PA_SEEK_RELATIVE)) < 0) {
662  av_log(s, AV_LOG_ERROR, "pa_stream_write failed: %s\n", pa_strerror(ret));
663  goto fail;
664  }
665  if ((writable_size = pa_stream_writable_size(s->stream)) >= s->minreq)
666  avdevice_dev_to_app_control_message(h, AV_DEV_TO_APP_BUFFER_WRITABLE, &writable_size, sizeof(writable_size));
667 
668  pa_threaded_mainloop_unlock(s->mainloop);
669 
670  return 0;
671  fail:
672  pa_threaded_mainloop_unlock(s->mainloop);
673  return AVERROR_EXTERNAL;
674 }
675 
676 static int pulse_write_frame(AVFormatContext *h, int stream_index,
677  AVFrame **frame, unsigned flags)
678 {
679  AVPacket pkt;
680 
681  /* Planar formats are not supported yet. */
683  return av_sample_fmt_is_planar(h->streams[stream_index]->codecpar->format) ?
684  AVERROR(EINVAL) : 0;
685 
686  pkt.data = (*frame)->data[0];
687  pkt.size = (*frame)->nb_samples * av_get_bytes_per_sample((*frame)->format) * (*frame)->ch_layout.nb_channels;
688  pkt.dts = (*frame)->pkt_dts;
689 #if FF_API_PKT_DURATION
691  if ((*frame)->pkt_duration)
692  pkt.duration = (*frame)->pkt_duration;
693  else
695 #endif
696  pkt.duration = (*frame)->duration;
697  return pulse_write_packet(h, &pkt);
698 }
699 
700 
701 static void pulse_get_output_timestamp(AVFormatContext *h, int stream, int64_t *dts, int64_t *wall)
702 {
703  PulseData *s = h->priv_data;
704  pa_usec_t latency;
705  int neg;
706  pa_threaded_mainloop_lock(s->mainloop);
707  pa_stream_get_latency(s->stream, &latency, &neg);
708  pa_threaded_mainloop_unlock(s->mainloop);
709  if (wall)
710  *wall = av_gettime();
711  if (dts)
712  *dts = s->timestamp - (neg ? -latency : latency);
713 }
714 
716 {
717  PulseData *s = h->priv_data;
718  return ff_pulse_audio_get_devices(device_list, s->server, 1);
719 }
720 
722  void *data, size_t data_size)
723 {
724  PulseData *s = h->priv_data;
725  int ret;
726 
727  switch(type) {
728  case AV_APP_TO_DEV_PAUSE:
729  return pulse_set_pause(s, 1);
730  case AV_APP_TO_DEV_PLAY:
731  return pulse_set_pause(s, 0);
733  return pulse_set_pause(s, !pa_stream_is_corked(s->stream));
734  case AV_APP_TO_DEV_MUTE:
735  if (!s->mute) {
736  s->mute = 1;
737  return pulse_set_mute(s);
738  }
739  return 0;
741  if (s->mute) {
742  s->mute = 0;
743  return pulse_set_mute(s);
744  }
745  return 0;
747  s->mute = !s->mute;
748  return pulse_set_mute(s);
750  return pulse_set_volume(s, *(double *)data);
752  s->last_volume = PA_VOLUME_INVALID;
753  pa_threaded_mainloop_lock(s->mainloop);
755  pa_threaded_mainloop_unlock(s->mainloop);
756  return ret;
758  s->mute = -1;
759  pa_threaded_mainloop_lock(s->mainloop);
761  pa_threaded_mainloop_unlock(s->mainloop);
762  return ret;
763  default:
764  break;
765  }
766  return AVERROR(ENOSYS);
767 }
768 
769 #define OFFSET(a) offsetof(PulseData, a)
770 #define E AV_OPT_FLAG_ENCODING_PARAM
771 static const AVOption options[] = {
772  { "server", "set PulseAudio server", OFFSET(server), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E },
773  { "name", "set application name", OFFSET(name), AV_OPT_TYPE_STRING, {.str = LIBAVFORMAT_IDENT}, 0, 0, E },
774  { "stream_name", "set stream description", OFFSET(stream_name), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E },
775  { "device", "set device name", OFFSET(device), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E },
776  { "buffer_size", "set buffer size in bytes", OFFSET(buffer_size), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, E },
777  { "buffer_duration", "set buffer duration in millisecs", OFFSET(buffer_duration), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, E },
778  { "prebuf", "set pre-buffering size", OFFSET(prebuf), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, E },
779  { "minreq", "set minimum request size", OFFSET(minreq), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, E },
780  { NULL }
781 };
782 
783 static const AVClass pulse_muxer_class = {
784  .class_name = "PulseAudio outdev",
785  .item_name = av_default_item_name,
786  .option = options,
787  .version = LIBAVUTIL_VERSION_INT,
789 };
790 
792  .p.name = "pulse",
793  .p.long_name = NULL_IF_CONFIG_SMALL("Pulse audio output"),
794  .priv_data_size = sizeof(PulseData),
796  .p.video_codec = AV_CODEC_ID_NONE,
797  .write_header = pulse_write_header,
798  .write_packet = pulse_write_packet,
799  .write_uncoded_frame = pulse_write_frame,
800  .write_trailer = pulse_write_trailer,
801  .get_output_timestamp = pulse_get_output_timestamp,
802  .get_device_list = pulse_get_device_list,
803  .control_message = pulse_control_message,
804  .p.flags = AVFMT_NOFILE | AVFMT_ALLOW_FLUSH,
805  .p.priv_class = &pulse_muxer_class,
806 };
AV_CODEC_ID_PCM_S16LE
@ AV_CODEC_ID_PCM_S16LE
Definition: codec_id.h:326
FF_ENABLE_DEPRECATION_WARNINGS
#define FF_ENABLE_DEPRECATION_WARNINGS
Definition: internal.h:82
pulse_finish_stream_operation
static int pulse_finish_stream_operation(PulseData *s, pa_operation *op, const char *name)
Definition: pulse_audio_enc.c:263
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:627
pulse_map_channels_to_pulse
static void pulse_map_channels_to_pulse(const AVChannelLayout *channel_layout, pa_channel_map *channel_map)
Definition: pulse_audio_enc.c:358
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
AV_APP_TO_DEV_MUTE
@ AV_APP_TO_DEV_MUTE
Mute control messages.
Definition: avdevice.h:185
pulse_write_frame
static int pulse_write_frame(AVFormatContext *h, int stream_index, AVFrame **frame, unsigned flags)
Definition: pulse_audio_enc.c:676
AVOutputFormat::name
const char * name
Definition: avformat.h:508
r
const char * r
Definition: vf_curves.c:126
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:240
PulseData::mainloop
pa_threaded_mainloop * mainloop
Definition: pulse_audio_dec.c:49
AV_APP_TO_DEV_SET_VOLUME
@ AV_APP_TO_DEV_SET_VOLUME
Volume control message.
Definition: avdevice.h:174
AV_DEV_TO_APP_BUFFER_OVERFLOW
@ AV_DEV_TO_APP_BUFFER_OVERFLOW
Buffer fullness status messages.
Definition: avdevice.h:266
PulseData::server
const char * server
Definition: pulse_audio_enc.c:38
pulse_write_header
static av_cold int pulse_write_header(AVFormatContext *h)
Definition: pulse_audio_enc.c:444
pulse_set_pause
static int pulse_set_pause(PulseData *s, int pause)
Definition: pulse_audio_enc.c:280
AV_CHAN_WIDE_LEFT
@ AV_CHAN_WIDE_LEFT
Definition: channel_layout.h:72
pulse_underflow
static void pulse_underflow(pa_stream *stream, void *userdata)
Definition: pulse_audio_enc.c:188
pulse_muxer_class
static const AVClass pulse_muxer_class
Definition: pulse_audio_enc.c:783
E
#define E
Definition: pulse_audio_enc.c:770
AVFrame
This structure describes decoded (raw) audio or video data.
Definition: frame.h:330
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
data
const char data[16]
Definition: mxf.c:146
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:32
AV_APP_TO_DEV_PAUSE
@ AV_APP_TO_DEV_PAUSE
Request pause/play.
Definition: avdevice.h:161
pulse_context_result
static void pulse_context_result(pa_context *ctx, int success, void *userdata)
Definition: pulse_audio_enc.c:296
AVPacket::duration
int64_t duration
Duration of this packet in AVStream->time_base units, 0 if unknown.
Definition: packet.h:392
AVChannelLayout::order
enum AVChannelOrder order
Channel order used in this layout.
Definition: channel_layout.h:306
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:182
AV_APP_TO_DEV_GET_MUTE
@ AV_APP_TO_DEV_GET_MUTE
Definition: avdevice.h:198
AVChannelLayout::nb_channels
int nb_channels
Number of channels in this layout.
Definition: channel_layout.h:311
AV_DEV_TO_APP_MUTE_STATE_CHANGED
@ AV_DEV_TO_APP_MUTE_STATE_CHANGED
Mute state change message.
Definition: avdevice.h:290
pulse_stream_wait
static int pulse_stream_wait(PulseData *s)
Definition: pulse_audio_enc.c:211
FFOutputFormat::p
AVOutputFormat p
The public AVOutputFormat.
Definition: mux.h:34
PulseData::nonblocking
int nonblocking
Definition: pulse_audio_enc.c:51
PulseData
Definition: pulse_audio_dec.c:39
AV_CHAN_SURROUND_DIRECT_LEFT
@ AV_CHAN_SURROUND_DIRECT_LEFT
Definition: channel_layout.h:74
PulseData::last_volume
pa_volume_t last_volume
Definition: pulse_audio_enc.c:54
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:771
PulseData::timestamp
int64_t timestamp
Definition: pulse_audio_enc.c:42
AV_CODEC_ID_PCM_S16BE
@ AV_CODEC_ID_PCM_S16BE
Definition: codec_id.h:327
AV_CHAN_TOP_BACK_RIGHT
@ AV_CHAN_TOP_BACK_RIGHT
Definition: channel_layout.h:67
fail
#define fail()
Definition: checkasm.h:134
PulseData::base_volume
pa_volume_t base_volume
Definition: pulse_audio_enc.c:53
val
static double val(void *priv, double ch)
Definition: aeval.c:77
pulse_update_sink_input_info
static int pulse_update_sink_input_info(AVFormatContext *h)
Definition: pulse_audio_enc.c:120
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:260
av_clip64
#define av_clip64
Definition: common.h:98
AV_CHAN_STEREO_RIGHT
@ AV_CHAN_STEREO_RIGHT
See above.
Definition: channel_layout.h:71
AV_APP_TO_DEV_UNMUTE
@ AV_APP_TO_DEV_UNMUTE
Definition: avdevice.h:186
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:194
av_cold
#define av_cold
Definition: attributes.h:90
AV_APP_TO_DEV_TOGGLE_PAUSE
@ AV_APP_TO_DEV_TOGGLE_PAUSE
Definition: avdevice.h:163
s
#define s(width, name)
Definition: cbs_vp9.c:256
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:333
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:76
AV_CHANNEL_ORDER_UNSPEC
@ AV_CHANNEL_ORDER_UNSPEC
Only the channel count is specified, without any further information about the channel order.
Definition: channel_layout.h:112
AV_CHAN_SIDE_RIGHT
@ AV_CHAN_SIDE_RIGHT
Definition: channel_layout.h:60
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:114
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:142
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:701
channel_map
static const uint8_t channel_map[8][8]
Definition: atrac3plusdec.c:51
pulse_update_sink_info
static int pulse_update_sink_info(AVFormatContext *h)
Definition: pulse_audio_enc.c:77
PulseData::stream_name
const char * stream_name
Definition: pulse_audio_enc.c:40
AVFormatContext
Format I/O context.
Definition: avformat.h:1104
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:153
AVStream::codecpar
AVCodecParameters * codecpar
Codec parameters associated with this stream.
Definition: avformat.h:861
LIBAVUTIL_VERSION_INT
#define LIBAVUTIL_VERSION_INT
Definition: version.h:85
AVClass
Describe the class of an AVClass context structure.
Definition: log.h:66
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:877
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:197
PulseData::mute
int mute
Definition: pulse_audio_enc.c:52
ff_pulse_muxer
const FFOutputFormat ff_pulse_muxer
Definition: pulse_audio_enc.c:791
PulseData::ctx
pa_context * ctx
Definition: pulse_audio_enc.c:49
AVRational
Rational number (pair of numerator and denominator).
Definition: rational.h:58
AV_CHAN_TOP_BACK_CENTER
@ AV_CHAN_TOP_BACK_CENTER
Definition: channel_layout.h:66
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:57
av_default_item_name
const char * av_default_item_name(void *ptr)
Return the context name.
Definition: log.c:237
FFOutputFormat
Definition: mux.h:30
pulse_flash_stream
static int pulse_flash_stream(PulseData *s)
Definition: pulse_audio_enc.c:288
double
double
Definition: af_crystalizer.c:132
time.h
AV_CHAN_TOP_CENTER
@ AV_CHAN_TOP_CENTER
Definition: channel_layout.h:61
AVCodecParameters::ch_layout
AVChannelLayout ch_layout
Audio only.
Definition: codec_par.h:213
pulse_stream_result
static void pulse_stream_result(pa_stream *stream, int success, void *userdata)
Definition: pulse_audio_enc.c:252
AVCodecParameters::sample_rate
int sample_rate
Audio only.
Definition: codec_par.h:178
AV_CHAN_FRONT_RIGHT_OF_CENTER
@ AV_CHAN_FRONT_RIGHT_OF_CENTER
Definition: channel_layout.h:57
AV_CHAN_FRONT_RIGHT
@ AV_CHAN_FRONT_RIGHT
Definition: channel_layout.h:51
AV_CHAN_FRONT_CENTER
@ AV_CHAN_FRONT_CENTER
Definition: channel_layout.h:52
pulse_audio_common.h
pulse_control_message
static int pulse_control_message(AVFormatContext *h, int type, void *data, size_t data_size)
Definition: pulse_audio_enc.c:721
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:92
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
AVChannelLayout
An AVChannelLayout holds information about the channel layout of audio data.
Definition: channel_layout.h:301
AV_APP_TO_DEV_PLAY
@ AV_APP_TO_DEV_PLAY
Definition: avdevice.h:162
pulse_stream_writable
static void pulse_stream_writable(pa_stream *stream, size_t nbytes, void *userdata)
Definition: pulse_audio_enc.c:169
AV_CHAN_LOW_FREQUENCY
@ AV_CHAN_LOW_FREQUENCY
Definition: channel_layout.h:53
AV_CHAN_BACK_RIGHT
@ AV_CHAN_BACK_RIGHT
Definition: channel_layout.h:55
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:488
AV_CHAN_SIDE_LEFT
@ AV_CHAN_SIDE_LEFT
Definition: channel_layout.h:59
AVFMT_NOFILE
#define AVFMT_NOFILE
Demuxer will use avio_open, no opened file should be provided by the caller.
Definition: avformat.h:468
AVPacket::dts
int64_t dts
Decompression timestamp in AVStream->time_base units; the time at which the packet is decompressed.
Definition: packet.h:373
pulse_context_state
static void pulse_context_state(pa_context *ctx, void *userdata)
Definition: pulse_audio_enc.c:223
AV_APP_TO_DEV_TOGGLE_MUTE
@ AV_APP_TO_DEV_TOGGLE_MUTE
Definition: avdevice.h:187
AVERROR_EXTERNAL
#define AVERROR_EXTERNAL
Generic error in an external library.
Definition: error.h:59
AV_CHAN_TOP_FRONT_RIGHT
@ AV_CHAN_TOP_FRONT_RIGHT
Definition: channel_layout.h:64
PulseData::prebuf
int prebuf
Definition: pulse_audio_enc.c:45
attributes.h
AV_CHAN_FRONT_LEFT_OF_CENTER
@ AV_CHAN_FRONT_LEFT_OF_CENTER
Definition: channel_layout.h:56
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_CHAN_SURROUND_DIRECT_RIGHT
@ AV_CHAN_SURROUND_DIRECT_RIGHT
Definition: channel_layout.h:75
AV_CODEC_ID_NONE
@ AV_CODEC_ID_NONE
Definition: codec_id.h:50
PulseData::buffer_size
int buffer_size
Buffer size in bytes.
Definition: pulse_audio_enc.c:43
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:269
av_get_bytes_per_sample
int av_get_bytes_per_sample(enum AVSampleFormat sample_fmt)
Return number of bytes per sample.
Definition: samplefmt.c:108
internal.h
AV_CLASS_CATEGORY_DEVICE_AUDIO_OUTPUT
@ AV_CLASS_CATEGORY_DEVICE_AUDIO_OUTPUT
Definition: log.h:42
AV_CHAN_STEREO_LEFT
@ AV_CHAN_STEREO_LEFT
Stereo downmix.
Definition: channel_layout.h:69
AVFMT_FLAG_NONBLOCK
#define AVFMT_FLAG_NONBLOCK
Do not block when reading packets from input.
Definition: avformat.h:1225
version.h
ret
ret
Definition: filter_design.txt:187
AVStream
Stream structure.
Definition: avformat.h:838
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:39
AVDeviceInfoList
List of devices.
Definition: avdevice.h:343
av_channel_layout_check
int av_channel_layout_check(const AVChannelLayout *channel_layout)
Check whether a channel layout is valid, i.e.
Definition: channel_layout.c:906
avformat.h
PulseData::buffer_duration
int buffer_duration
Buffer size in ms, recalculated to buffer_size.
Definition: pulse_audio_enc.c:44
AV_CHAN_BACK_CENTER
@ AV_CHAN_BACK_CENTER
Definition: channel_layout.h:58
channel_layout.h
OFFSET
#define OFFSET(a)
Definition: pulse_audio_enc.c:769
AV_CHAN_LOW_FREQUENCY_2
@ AV_CHAN_LOW_FREQUENCY_2
Definition: channel_layout.h:76
AV_CHAN_TOP_BACK_LEFT
@ AV_CHAN_TOP_BACK_LEFT
Definition: channel_layout.h:65
av_channel_layout_index_from_channel
int av_channel_layout_index_from_channel(const AVChannelLayout *channel_layout, enum AVChannel channel)
Get the index of a given channel in a channel layout.
Definition: channel_layout.c:836
pulse_write_trailer
static av_cold int pulse_write_trailer(AVFormatContext *h)
Definition: pulse_audio_enc.c:413
AV_OPT_TYPE_INT
@ AV_OPT_TYPE_INT
Definition: opt.h:225
pulse_subscribe_events
static int pulse_subscribe_events(PulseData *s)
Definition: pulse_audio_enc.c:349
AV_WRITE_UNCODED_FRAME_QUERY
@ AV_WRITE_UNCODED_FRAME_QUERY
Query whether the feature is possible on this stream.
Definition: mux.h:208
AV_CHAN_BACK_LEFT
@ AV_CHAN_BACK_LEFT
Definition: channel_layout.h:54
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:324
av_gettime
int64_t av_gettime(void)
Get the current time in microseconds.
Definition: time.c:39
FF_DISABLE_DEPRECATION_WARNINGS
#define FF_DISABLE_DEPRECATION_WARNINGS
Definition: internal.h:81
PulseData::minreq
int minreq
Definition: pulse_audio_enc.c:46
AV_CHAN_TOP_FRONT_CENTER
@ AV_CHAN_TOP_FRONT_CENTER
Definition: channel_layout.h:63
pulse_finish_context_operation
static int pulse_finish_context_operation(PulseData *s, pa_operation *op, const char *name)
Definition: pulse_audio_enc.c:307
AV_CHAN_WIDE_RIGHT
@ AV_CHAN_WIDE_RIGHT
Definition: channel_layout.h:73
AVCodecParameters::format
int format
Definition: codec_par.h:86
AV_DEV_TO_APP_VOLUME_LEVEL_CHANGED
@ AV_DEV_TO_APP_VOLUME_LEVEL_CHANGED
Volume level change message.
Definition: avdevice.h:299
AV_DEV_TO_APP_BUFFER_WRITABLE
@ AV_DEV_TO_APP_BUFFER_WRITABLE
Definition: avdevice.h:281
AVCodecParameters::codec_id
enum AVCodecID codec_id
Specific type of the encoded data (the codec used).
Definition: codec_par.h:62
AVPacket
This structure stores compressed data.
Definition: packet.h:351
pulse_get_device_list
static int pulse_get_device_list(AVFormatContext *h, AVDeviceInfoList *device_list)
Definition: pulse_audio_enc.c:715
AV_CHAN_TOP_FRONT_LEFT
@ AV_CHAN_TOP_FRONT_LEFT
Definition: channel_layout.h:62
PulseData::device
const char * device
Definition: pulse_audio_enc.c:41
flags
#define flags(name, subs,...)
Definition: cbs_av1.c:561
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:27
PulseData::last_result
int last_result
Definition: pulse_audio_enc.c:47
h
h
Definition: vp9dsp_template.c:2038
AV_CHAN_FRONT_LEFT
@ AV_CHAN_FRONT_LEFT
Definition: channel_layout.h:50
AV_OPT_TYPE_STRING
@ AV_OPT_TYPE_STRING
Definition: opt.h:229
state
static struct @345 state
options
static const AVOption options[]
Definition: pulse_audio_enc.c:771
AV_DEV_TO_APP_BUFFER_UNDERFLOW
@ AV_DEV_TO_APP_BUFFER_UNDERFLOW
Definition: avdevice.h:267
mux.h