mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-02-02 04:22:27 +00:00
pulse: Expose the correct max rate that we support
PulseAudio defines PA_RATE_MAX as the maximum sampling rate that it supports. We were previously exposing a maximum rate of INT_MAX, which is incorrect, but worked because nothing was really using a rate greater than 384000 kHz. While playing DSD data, we hit a case where there might be very high sample rates (>1MHz), and pulsesink fails during stream creation with such streams because it erroneously advertises that it supports such rates. Since PA_RATE_MAX is #define'd to (8*48000U), we can't just use it in the caps string. Instead, we fix up the rate to what we actually support whenever we use our macro caps.
This commit is contained in:
parent
753b7c17f3
commit
a24ef929a4
4 changed files with 60 additions and 14 deletions
|
@ -1815,11 +1815,6 @@ static gboolean gst_pulsesink_query (GstBaseSink * sink, GstQuery * query);
|
||||||
static GstStateChangeReturn gst_pulsesink_change_state (GstElement * element,
|
static GstStateChangeReturn gst_pulsesink_change_state (GstElement * element,
|
||||||
GstStateChange transition);
|
GstStateChange transition);
|
||||||
|
|
||||||
static GstStaticPadTemplate pad_template = GST_STATIC_PAD_TEMPLATE ("sink",
|
|
||||||
GST_PAD_SINK,
|
|
||||||
GST_PAD_ALWAYS,
|
|
||||||
GST_STATIC_CAPS (PULSE_SINK_TEMPLATE_CAPS));
|
|
||||||
|
|
||||||
#define gst_pulsesink_parent_class parent_class
|
#define gst_pulsesink_parent_class parent_class
|
||||||
G_DEFINE_TYPE_WITH_CODE (GstPulseSink, gst_pulsesink, GST_TYPE_AUDIO_BASE_SINK,
|
G_DEFINE_TYPE_WITH_CODE (GstPulseSink, gst_pulsesink, GST_TYPE_AUDIO_BASE_SINK,
|
||||||
gst_pulsesink_init_contexts ();
|
gst_pulsesink_init_contexts ();
|
||||||
|
@ -1891,6 +1886,7 @@ gst_pulsesink_class_init (GstPulseSinkClass * klass)
|
||||||
GstBaseSinkClass *bc;
|
GstBaseSinkClass *bc;
|
||||||
GstAudioBaseSinkClass *gstaudiosink_class = GST_AUDIO_BASE_SINK_CLASS (klass);
|
GstAudioBaseSinkClass *gstaudiosink_class = GST_AUDIO_BASE_SINK_CLASS (klass);
|
||||||
GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
|
GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
|
||||||
|
GstCaps *caps;
|
||||||
gchar *clientname;
|
gchar *clientname;
|
||||||
|
|
||||||
gobject_class->finalize = gst_pulsesink_finalize;
|
gobject_class->finalize = gst_pulsesink_finalize;
|
||||||
|
@ -1983,7 +1979,12 @@ gst_pulsesink_class_init (GstPulseSinkClass * klass)
|
||||||
gst_element_class_set_static_metadata (gstelement_class,
|
gst_element_class_set_static_metadata (gstelement_class,
|
||||||
"PulseAudio Audio Sink",
|
"PulseAudio Audio Sink",
|
||||||
"Sink/Audio", "Plays audio to a PulseAudio server", "Lennart Poettering");
|
"Sink/Audio", "Plays audio to a PulseAudio server", "Lennart Poettering");
|
||||||
gst_element_class_add_static_pad_template (gstelement_class, &pad_template);
|
|
||||||
|
caps =
|
||||||
|
gst_pulse_fix_pcm_caps (gst_caps_from_string (PULSE_SINK_TEMPLATE_CAPS));
|
||||||
|
gst_element_class_add_pad_template (gstelement_class,
|
||||||
|
gst_pad_template_new ("sink", GST_PAD_SINK, GST_PAD_ALWAYS, caps));
|
||||||
|
gst_caps_unref (caps);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
|
@ -112,12 +112,6 @@ static GstStateChangeReturn gst_pulsesrc_change_state (GstElement *
|
||||||
|
|
||||||
static GstClockTime gst_pulsesrc_get_time (GstClock * clock, GstPulseSrc * src);
|
static GstClockTime gst_pulsesrc_get_time (GstClock * clock, GstPulseSrc * src);
|
||||||
|
|
||||||
static GstStaticPadTemplate pad_template = GST_STATIC_PAD_TEMPLATE ("src",
|
|
||||||
GST_PAD_SRC,
|
|
||||||
GST_PAD_ALWAYS,
|
|
||||||
GST_STATIC_CAPS (_PULSE_CAPS_PCM)
|
|
||||||
);
|
|
||||||
|
|
||||||
#define gst_pulsesrc_parent_class parent_class
|
#define gst_pulsesrc_parent_class parent_class
|
||||||
G_DEFINE_TYPE_WITH_CODE (GstPulseSrc, gst_pulsesrc, GST_TYPE_AUDIO_SRC,
|
G_DEFINE_TYPE_WITH_CODE (GstPulseSrc, gst_pulsesrc, GST_TYPE_AUDIO_SRC,
|
||||||
G_IMPLEMENT_INTERFACE (GST_TYPE_STREAM_VOLUME, NULL));
|
G_IMPLEMENT_INTERFACE (GST_TYPE_STREAM_VOLUME, NULL));
|
||||||
|
@ -129,6 +123,7 @@ gst_pulsesrc_class_init (GstPulseSrcClass * klass)
|
||||||
GstAudioSrcClass *gstaudiosrc_class = GST_AUDIO_SRC_CLASS (klass);
|
GstAudioSrcClass *gstaudiosrc_class = GST_AUDIO_SRC_CLASS (klass);
|
||||||
GstBaseSrcClass *gstbasesrc_class = GST_BASE_SRC_CLASS (klass);
|
GstBaseSrcClass *gstbasesrc_class = GST_BASE_SRC_CLASS (klass);
|
||||||
GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
|
GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
|
||||||
|
GstCaps *caps;
|
||||||
gchar *clientname;
|
gchar *clientname;
|
||||||
|
|
||||||
gobject_class->finalize = gst_pulsesrc_finalize;
|
gobject_class->finalize = gst_pulsesrc_finalize;
|
||||||
|
@ -222,7 +217,11 @@ gst_pulsesrc_class_init (GstPulseSrcClass * klass)
|
||||||
"PulseAudio Audio Source",
|
"PulseAudio Audio Source",
|
||||||
"Source/Audio",
|
"Source/Audio",
|
||||||
"Captures audio from a PulseAudio server", "Lennart Poettering");
|
"Captures audio from a PulseAudio server", "Lennart Poettering");
|
||||||
gst_element_class_add_static_pad_template (gstelement_class, &pad_template);
|
|
||||||
|
caps = gst_pulse_fix_pcm_caps (gst_caps_from_string (_PULSE_CAPS_PCM));
|
||||||
|
gst_element_class_add_pad_template (gstelement_class,
|
||||||
|
gst_pad_template_new ("src", GST_PAD_SRC, GST_PAD_ALWAYS, caps));
|
||||||
|
gst_caps_unref (caps);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GstPulseSrc:volume:
|
* GstPulseSrc:volume:
|
||||||
|
|
|
@ -450,7 +450,7 @@ gst_pulse_format_info_to_caps (pa_format_info * format)
|
||||||
if (pa_format_info_get_prop_string (format,
|
if (pa_format_info_get_prop_string (format,
|
||||||
PA_PROP_FORMAT_SAMPLE_FORMAT, &tmp)) {
|
PA_PROP_FORMAT_SAMPLE_FORMAT, &tmp)) {
|
||||||
/* No specific sample format means any sample format */
|
/* No specific sample format means any sample format */
|
||||||
ret = gst_caps_from_string (_PULSE_CAPS_PCM);
|
ret = gst_pulse_fix_pcm_caps (gst_caps_from_string (_PULSE_CAPS_PCM));
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
} else if (ss.format == PA_SAMPLE_ALAW) {
|
} else if (ss.format == PA_SAMPLE_ALAW) {
|
||||||
|
@ -507,3 +507,46 @@ gst_pulse_format_info_to_caps (pa_format_info * format)
|
||||||
out:
|
out:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GstCaps *
|
||||||
|
gst_pulse_fix_pcm_caps (GstCaps * incaps)
|
||||||
|
{
|
||||||
|
GstCaps *outcaps;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
outcaps = gst_caps_make_writable (incaps);
|
||||||
|
|
||||||
|
for (i = 0; i < gst_caps_get_size (outcaps); i++) {
|
||||||
|
GstStructure *st = gst_caps_get_structure (outcaps, i);
|
||||||
|
const gchar *format = gst_structure_get_name (st);
|
||||||
|
const GValue *value;
|
||||||
|
GValue new_value = G_VALUE_INIT;
|
||||||
|
gint min, max, step;
|
||||||
|
|
||||||
|
if (!(g_str_equal (format, "audio/x-raw") ||
|
||||||
|
g_str_equal (format, "audio/x-alaw") ||
|
||||||
|
g_str_equal (format, "audio/x-mulaw")))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
value = gst_structure_get_value (st, "rate");
|
||||||
|
|
||||||
|
if (!GST_VALUE_HOLDS_INT_RANGE (value))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
min = gst_value_get_int_range_min (value);
|
||||||
|
max = gst_value_get_int_range_max (value);
|
||||||
|
step = gst_value_get_int_range_step (value);
|
||||||
|
|
||||||
|
if (min > PA_RATE_MAX)
|
||||||
|
min = PA_RATE_MAX;
|
||||||
|
if (max > PA_RATE_MAX)
|
||||||
|
max = PA_RATE_MAX;
|
||||||
|
|
||||||
|
g_value_init (&new_value, GST_TYPE_INT_RANGE);
|
||||||
|
gst_value_set_int_range_step (&new_value, min, max, step);
|
||||||
|
|
||||||
|
gst_structure_take_value (st, "rate", &new_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return outcaps;
|
||||||
|
}
|
||||||
|
|
|
@ -40,6 +40,8 @@
|
||||||
"S24BE, S24LE, S24_32BE, S24_32LE, U8 }"
|
"S24BE, S24LE, S24_32BE, S24_32LE, U8 }"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* NOTE! that we do NOT actually support rate=MAX. This must be fixed up using
|
||||||
|
* gst_pulse_fix_pcm_caps() before being used. */
|
||||||
#define _PULSE_CAPS_LINEAR \
|
#define _PULSE_CAPS_LINEAR \
|
||||||
"audio/x-raw, " \
|
"audio/x-raw, " \
|
||||||
"format = (string) " _PULSE_FORMATS ", " \
|
"format = (string) " _PULSE_FORMATS ", " \
|
||||||
|
@ -90,5 +92,6 @@ pa_proplist *gst_pulse_make_proplist (const GstStructure *properties);
|
||||||
GstStructure *gst_pulse_make_structure (pa_proplist *properties);
|
GstStructure *gst_pulse_make_structure (pa_proplist *properties);
|
||||||
|
|
||||||
GstCaps * gst_pulse_format_info_to_caps (pa_format_info * format);
|
GstCaps * gst_pulse_format_info_to_caps (pa_format_info * format);
|
||||||
|
GstCaps * gst_pulse_fix_pcm_caps (GstCaps * incaps);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in a new issue