22 #include <pulse/pulseaudio.h> 23 #include <pulse/error.h> 55 int eol,
void *userdata)
63 pa_threaded_mainloop_signal(s->
mainloop, 0);
65 if (dev->flags & PA_SINK_FLAT_VOLUME)
78 if (!(op = pa_context_get_sink_info_by_name(s->
ctx, s->
device,
83 while (pa_operation_get_state(op) == PA_OPERATION_RUNNING)
84 pa_threaded_mainloop_wait(s->
mainloop);
85 pa_operation_unref(op);
90 int eol,
void *userdata)
100 pa_volume_t vol = pa_cvolume_avg(&i->volume);
101 if (s->
mute < 0 || (s->
mute && !i->mute) || (!s->
mute && i->mute)) {
108 val = (double)vol / PA_VOLUME_NORM;
121 enum pa_operation_state op_state;
122 pa_mainloop *ml =
NULL;
129 if (!(op = pa_context_get_sink_input_info(ctx, pa_stream_get_index(s->
stream),
135 while ((op_state = pa_operation_get_state(op)) == PA_OPERATION_RUNNING)
136 pa_mainloop_iterate(ml, 1,
NULL);
137 pa_operation_unref(op);
138 if (op_state != PA_OPERATION_DONE) {
151 uint32_t idx,
void *userdata)
159 if ((t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_SINK_INPUT) {
160 if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_CHANGE)
170 int64_t
val = nbytes;
176 pa_threaded_mainloop_signal(s->
mainloop, 0);
198 switch (pa_stream_get_state(s->
stream)) {
199 case PA_STREAM_READY:
200 case PA_STREAM_FAILED:
201 case PA_STREAM_TERMINATED:
202 pa_threaded_mainloop_signal(s->
mainloop, 0);
210 pa_stream_state_t
state;
212 while ((state = pa_stream_get_state(s->
stream)) != PA_STREAM_READY) {
213 if (state == PA_STREAM_FAILED || state == PA_STREAM_TERMINATED)
215 pa_threaded_mainloop_wait(s->
mainloop);
227 switch (pa_context_get_state(ctx)) {
228 case PA_CONTEXT_READY:
229 case PA_CONTEXT_FAILED:
230 case PA_CONTEXT_TERMINATED:
231 pa_threaded_mainloop_signal(s->
mainloop, 0);
239 pa_context_state_t
state;
241 while ((state = pa_context_get_state(s->
ctx)) != PA_CONTEXT_READY) {
242 if (state == PA_CONTEXT_FAILED || state == PA_CONTEXT_TERMINATED)
244 pa_threaded_mainloop_wait(s->
mainloop);
257 pa_threaded_mainloop_signal(s->
mainloop, 0);
263 pa_threaded_mainloop_unlock(s->
mainloop);
269 pa_threaded_mainloop_wait(s->
mainloop);
270 pa_operation_unref(op);
271 pa_threaded_mainloop_unlock(s->
mainloop);
280 pa_threaded_mainloop_lock(s->
mainloop);
288 pa_threaded_mainloop_lock(s->
mainloop);
301 pa_threaded_mainloop_signal(s->
mainloop, 0);
307 pa_threaded_mainloop_unlock(s->
mainloop);
313 pa_threaded_mainloop_wait(s->
mainloop);
314 pa_operation_unref(op);
315 pa_threaded_mainloop_unlock(s->
mainloop);
324 pa_threaded_mainloop_lock(s->
mainloop);
325 op = pa_context_set_sink_input_mute(s->
ctx, pa_stream_get_index(s->
stream),
335 const pa_sample_spec *
ss = pa_stream_get_sample_spec(s->
stream);
337 vol = pa_sw_volume_multiply(
lrint(volume * PA_VOLUME_NORM), s->
base_volume);
338 pa_cvolume_set(&cvol, ss->channels, PA_VOLUME_NORM);
339 pa_sw_cvolume_multiply_scalar(&cvol, &cvol, vol);
340 pa_threaded_mainloop_lock(s->
mainloop);
341 op = pa_context_set_sink_input_volume(s->
ctx, pa_stream_get_index(s->
stream),
350 pa_threaded_mainloop_lock(s->
mainloop);
357 channel_map->channels = 0;
359 channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_FRONT_LEFT;
361 channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_FRONT_RIGHT;
363 channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_FRONT_CENTER;
365 channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_LFE;
367 channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_REAR_LEFT;
369 channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_REAR_RIGHT;
371 channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER;
373 channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER;
375 channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_REAR_CENTER;
377 channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_SIDE_LEFT;
379 channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_SIDE_RIGHT;
381 channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_TOP_CENTER;
383 channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_TOP_FRONT_LEFT;
385 channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_TOP_FRONT_CENTER;
387 channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_TOP_FRONT_RIGHT;
389 channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_TOP_REAR_LEFT;
391 channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_TOP_REAR_CENTER;
393 channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_TOP_REAR_RIGHT;
395 channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_FRONT_LEFT;
397 channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_FRONT_RIGHT;
399 channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_AUX0;
401 channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_AUX1;
403 channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_AUX2;
405 channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_AUX3;
407 channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_LFE;
415 pa_threaded_mainloop_lock(s->
mainloop);
417 pa_stream_disconnect(s->
stream);
422 pa_stream_unref(s->
stream);
426 pa_context_disconnect(s->
ctx);
428 pa_context_set_subscribe_callback(s->
ctx,
NULL,
NULL);
429 pa_context_unref(s->
ctx);
432 pa_threaded_mainloop_unlock(s->
mainloop);
433 pa_threaded_mainloop_stop(s->
mainloop);
434 pa_threaded_mainloop_free(s->
mainloop);
446 pa_sample_spec sample_spec;
447 pa_buffer_attr buffer_attributes = { -1, -1, -1, -1, -1 };
448 pa_channel_map channel_map;
449 pa_mainloop_api *mainloop_api;
451 static const pa_stream_flags_t stream_flags = PA_STREAM_INTERPOLATE_TIMING |
452 PA_STREAM_AUTO_TIMING_UPDATE |
453 PA_STREAM_NOT_MONOTONIC;
463 stream_name = h->
url;
465 stream_name =
"Playback";
474 buffer_attributes.tlength =
FFMAX(s->
buffer_size, av_clip64(bytes, 0, UINT32_MAX - 1));
476 "Buffer duration: %ums recalculated into %"PRId64
" bytes buffer.\n",
478 av_log(s,
AV_LOG_DEBUG,
"Real buffer length is %u bytes\n", buffer_attributes.tlength);
482 buffer_attributes.prebuf = s->
prebuf;
484 buffer_attributes.minreq = s->
minreq;
489 if (!pa_sample_spec_valid(&sample_spec)) {
494 if (sample_spec.channels == 1) {
495 channel_map.channels = 1;
496 channel_map.map[0] = PA_CHANNEL_POSITION_MONO;
502 if (channel_map.channels != sample_spec.channels) {
504 channel_map.channels = 0;
507 channel_map.channels = 0;
509 if (!channel_map.channels)
511 else if (!pa_channel_map_valid(&channel_map)) {
517 s->
mainloop = pa_threaded_mainloop_new();
522 if ((ret = pa_threaded_mainloop_start(s->
mainloop)) < 0) {
524 pa_threaded_mainloop_free(s->
mainloop);
529 pa_threaded_mainloop_lock(s->
mainloop);
531 mainloop_api = pa_threaded_mainloop_get_api(s->
mainloop);
538 s->
ctx = pa_context_new(mainloop_api, s->
name);
547 if ((ret = pa_context_connect(s->
ctx, s->
server, 0,
NULL)) < 0) {
558 s->
stream = pa_stream_new(s->
ctx, stream_name, &sample_spec,
559 channel_map.channels ? &channel_map :
NULL);
576 if ((ret = pa_stream_connect_playback(s->
stream, s->
device, &buffer_attributes,
577 stream_flags, NULL, NULL)) < 0) {
578 av_log(s,
AV_LOG_ERROR,
"pa_stream_connect_playback failed: %s.\n", pa_strerror(ret));
589 buffer_attributes = *pa_stream_get_buffer_attr(s->
stream);
591 s->
prebuf = buffer_attributes.prebuf;
592 s->
minreq = buffer_attributes.minreq;
596 pa_threaded_mainloop_unlock(s->
mainloop);
601 pa_threaded_mainloop_lock(s->
mainloop);
608 pa_threaded_mainloop_lock(s->
mainloop);
613 pa_threaded_mainloop_unlock(s->
mainloop);
619 pa_threaded_mainloop_unlock(s->
mainloop);
628 int64_t writable_size;
645 pa_threaded_mainloop_lock(s->
mainloop);
646 if (!PA_STREAM_IS_GOOD(pa_stream_get_state(s->
stream))) {
650 while (pa_stream_writable_size(s->
stream) < s->
minreq) {
652 pa_threaded_mainloop_unlock(s->
mainloop);
655 pa_threaded_mainloop_wait(s->
mainloop);
658 if ((ret = pa_stream_write(s->
stream, pkt->
data, pkt->
size,
NULL, 0, PA_SEEK_RELATIVE)) < 0) {
662 if ((writable_size = pa_stream_writable_size(s->
stream)) >= s->
minreq)
665 pa_threaded_mainloop_unlock(s->
mainloop);
669 pa_threaded_mainloop_unlock(s->
mainloop);
683 pkt.
data = (*frame)->data[0];
685 pkt.
dts = (*frame)->pkt_dts;
686 pkt.
duration = (*frame)->pkt_duration;
696 pa_threaded_mainloop_lock(s->
mainloop);
697 pa_stream_get_latency(s->
stream, &latency, &neg);
698 pa_threaded_mainloop_unlock(s->
mainloop);
702 *dts = s->
timestamp - (neg ? -latency : latency);
712 void *
data,
size_t data_size)
743 pa_threaded_mainloop_lock(s->
mainloop);
745 pa_threaded_mainloop_unlock(s->
mainloop);
749 pa_threaded_mainloop_lock(s->
mainloop);
751 pa_threaded_mainloop_unlock(s->
mainloop);
759 #define OFFSET(a) offsetof(PulseData, a) 760 #define E AV_OPT_FLAG_ENCODING_PARAM
static void pulse_map_channels_to_pulse(int64_t channel_layout, pa_channel_map *channel_map)
This structure describes decoded (raw) audio or video data.
static int pulse_flash_stream(PulseData *s)
#define AV_CH_TOP_FRONT_RIGHT
ptrdiff_t const GLvoid * data
static void pulse_context_result(pa_context *ctx, int success, void *userdata)
static int pulse_context_wait(PulseData *s)
#define AV_LOG_WARNING
Something somehow does not look correct.
#define LIBAVUTIL_VERSION_INT
#define AV_CH_TOP_FRONT_LEFT
enum AVCodecID codec_id
Specific type of the encoded data (the codec used).
#define AV_CH_TOP_FRONT_CENTER
static int pulse_finish_stream_operation(PulseData *s, pa_operation *op, const char *name)
const char * av_default_item_name(void *ptr)
Return the context name.
Volume level change message.
#define AV_CH_LOW_FREQUENCY_2
static void pulse_overflow(pa_stream *stream, void *userdata)
#define AV_CH_SURROUND_DIRECT_RIGHT
Buffer fullness status messages.
Macro definitions for various function/variable attributes.
int av_get_channel_layout_nb_channels(uint64_t channel_layout)
Return the number of channels in the channel layout.
const char * class_name
The name of the class; usually it is the same name as the context structure type to which the AVClass...
static void pulse_stream_state(pa_stream *stream, void *userdata)
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.
#define AV_CH_TOP_BACK_LEFT
int64_t duration
Duration of this packet in AVStream->time_base units, 0 if unknown.
#define AV_CH_TOP_BACK_CENTER
static int pulse_write_packet(AVFormatContext *h, AVPacket *pkt)
static int pulse_control_message(AVFormatContext *h, int type, void *data, size_t data_size)
#define AV_CH_LOW_FREQUENCY
AVStream ** streams
A list of all streams in the file.
static const AVClass pulse_muxer_class
static av_cold int pulse_write_trailer(AVFormatContext *h)
static void pulse_audio_sink_input_cb(pa_context *ctx, const pa_sink_input_info *i, int eol, void *userdata)
static int pulse_stream_wait(PulseData *s)
Get volume/mute messages.
int flags
Flags modifying the (de)muxer behaviour.
int ff_pulse_audio_connect_context(pa_mainloop **pa_ml, pa_context **pa_ctx, const char *server, const char *description)
static int pulse_write_frame(AVFormatContext *h, int stream_index, AVFrame **frame, unsigned flags)
uint64_t channel_layout
Audio only.
int av_sample_fmt_is_planar(enum AVSampleFormat sample_fmt)
Check if the sample format is planar.
int64_t av_rescale_q(int64_t a, AVRational bq, AVRational cq)
Rescale a 64-bit integer by 2 rational numbers.
static void pulse_underflow(pa_stream *stream, void *userdata)
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
static int pulse_set_volume(PulseData *s, double volume)
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
char * url
input or output URL.
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
static void pulse_event(pa_context *ctx, pa_subscription_event_type_t t, uint32_t idx, void *userdata)
enum AVMediaType codec_type
General type of the encoded data.
common internal API header
unsigned int nb_streams
Number of elements in AVFormatContext.streams.
#define AV_CH_STEREO_RIGHT
See AV_CH_STEREO_LEFT.
#define ss(width, name, subs,...)
static const AVOption options[]
AVOutputFormat ff_pulse_muxer
static int pulse_set_pause(PulseData *s, int pause)
void ff_pulse_audio_disconnect_context(pa_mainloop **pa_ml, pa_context **pa_ctx)
static int pulse_update_sink_input_info(AVFormatContext *h)
static int pulse_subscribe_events(PulseData *s)
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
pa_sample_format_t av_cold ff_codec_id_to_pulse_format(enum AVCodecID codec_id)
#define AV_CH_FRONT_LEFT_OF_CENTER
#define AV_CH_FRONT_CENTER
#define AV_CH_FRONT_RIGHT_OF_CENTER
int64_t av_gettime(void)
Get the current time in microseconds.
int buffer_duration
Buffer size in ms, recalculated to buffer_size.
#define AV_CH_TOP_BACK_RIGHT
Describe the class of an AVClass context structure.
Rational number (pair of numerator and denominator).
int ff_pulse_audio_get_devices(AVDeviceInfoList *devices, const char *server, int output)
static int pulse_get_device_list(AVFormatContext *h, AVDeviceInfoList *device_list)
Mute state change message.
#define flags(name, subs,...)
static int pulse_finish_context_operation(PulseData *s, pa_operation *op, const char *name)
static void pulse_audio_sink_device_cb(pa_context *ctx, const pa_sink_info *dev, int eol, void *userdata)
#define AV_CH_BACK_CENTER
int av_get_bytes_per_sample(enum AVSampleFormat sample_fmt)
Return number of bytes per sample.
int sample_rate
Audio only.
static av_cold int pulse_write_header(AVFormatContext *h)
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.
static int pulse_set_mute(PulseData *s)
static void pulse_stream_writable(pa_stream *stream, size_t nbytes, void *userdata)
static int pulse_update_sink_info(AVFormatContext *h)
static void pulse_context_state(pa_context *ctx, void *userdata)
void * priv_data
Format private data.
#define AV_CH_SURROUND_DIRECT_LEFT
int64_t dts
Decompression timestamp in AVStream->time_base units; the time at which the packet is decompressed...
#define AV_CH_FRONT_RIGHT
pa_threaded_mainloop * mainloop
Filter the word “frame” indicates either a video frame or a group of audio samples
AVCodecParameters * codecpar
Codec parameters associated with this stream.
int buffer_size
Buffer size in bytes.
static void pulse_get_output_timestamp(AVFormatContext *h, int stream, int64_t *dts, int64_t *wall)
AVRational time_base
This is the fundamental unit of time (in seconds) in terms of which frame timestamps are represented...
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
#define AVERROR_EXTERNAL
Generic error in an external library.
static double val(void *priv, double ch)
This structure stores compressed data.
static void pulse_stream_result(pa_stream *stream, int success, void *userdata)
#define AV_NOPTS_VALUE
Undefined timestamp value.
#define AV_CH_STEREO_LEFT
Stereo downmix.