ext/alsa/gstalsa.*: Add HW probing for period_count/size and buffer_size MIX/MAX

Original commit message from CVS:
* ext/alsa/gstalsa.c: (gst_alsa_class_init), (gst_alsa_get_caps):
* ext/alsa/gstalsa.h:
Add HW probing for period_count/size and buffer_size MIX/MAX
Adjust default/user defined value if out of bounds
Should fix bug #162024
This commit is contained in:
Stéphane Loeuillet 2005-01-10 04:09:43 +00:00
parent 620c1765bb
commit 6686d9e7ee
3 changed files with 109 additions and 7 deletions

View file

@ -1,3 +1,11 @@
2005-01-10 Stephane LOEUILLET <stephane.loeuillet@tiscali.fr>
* ext/alsa/gstalsa.c: (gst_alsa_class_init), (gst_alsa_get_caps):
* ext/alsa/gstalsa.h:
Add HW probing for period_count/size and buffer_size MIX/MAX
Adjust default/user defined value if out of bounds
Should fix bug #162024
2005-01-09 Ronald S. Bultje <rbultje@ronald.bitfreak.net>
* gst/qtdemux/qtdemux.c: (gst_qtdemux_handle_sink_event):

View file

@ -177,19 +177,22 @@ gst_alsa_class_init (gpointer g_class, gpointer class_data)
g_object_class_install_property (object_class, ARG_PERIODCOUNT,
g_param_spec_int ("period-count", "Period count",
"Number of hardware buffers to use",
2, 64, 2, G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
GST_ALSA_MIN_PERIOD_CNT, GST_ALSA_MAX_PERIOD_CNT,
GST_ALSA_MIN_PERIOD_CNT, G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
g_object_class_install_property (object_class, ARG_PERIODSIZE,
g_param_spec_int ("period-size", "Period size",
"Number of frames (samples on each channel) in one hardware period",
2, 8192, 8192, G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
GST_ALSA_MIN_PERIOD_SZ, GST_ALSA_MAX_PERIOD_SZ,
GST_ALSA_MAX_PERIOD_SZ, G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
g_object_class_install_property (object_class, ARG_BUFFERSIZE,
g_param_spec_int ("buffer-size", "Buffer size",
"Number of frames the hardware buffer can hold",
4, 65536, 16384, G_PARAM_READWRITE));
GST_ALSA_MIN_BUFFER_SZ, GST_ALSA_MAX_BUFFER_SZ,
GST_ALSA_MIN_PERIOD_CNT * GST_ALSA_MAX_PERIOD_SZ, G_PARAM_READWRITE));
g_object_class_install_property (object_class, ARG_AUTORECOVER,
g_param_spec_boolean ("autorecover", "Automatic xrun recovery",
"When TRUE tries to reduce processor load on xruns",
TRUE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
"When TRUE tries to reduce processor load on xruns", TRUE,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
g_object_class_install_property (object_class, ARG_MMAP,
g_param_spec_boolean ("mmap", "Use mmap'ed access",
"Wether to use mmap (faster) or standard read/write (more compatible)",
@ -813,6 +816,10 @@ gst_alsa_get_caps (GstPad * pad)
snd_pcm_format_mask_t *mask;
int i;
unsigned int min_rate, max_rate;
unsigned int min_period_cnt, max_period_cnt;
snd_pcm_uframes_t min_period_sz, max_period_sz;
snd_pcm_uframes_t min_buffer_sz, max_buffer_sz;
gint buffer_size;
gint min_channels, max_channels;
GstCaps *ret = NULL;
@ -844,10 +851,83 @@ gst_alsa_get_caps (GstPad * pad)
ERROR_CHECK (snd_pcm_hw_params_get_rate_min (hw_params, &min_rate, &i),
"Couldn't get minimum rate for device %s: %s", this->device);
min_rate = min_rate < GST_ALSA_MIN_RATE ? GST_ALSA_MIN_RATE : min_rate + i;
min_rate =
min_rate <
GST_ALSA_MIN_RATE ? GST_ALSA_MIN_RATE : (min_rate + GST_ALSA_DIR_MIN (i));
ERROR_CHECK (snd_pcm_hw_params_get_rate_max (hw_params, &max_rate, &i),
"Couldn't get maximum rate for device %s: %s", this->device);
max_rate = max_rate > GST_ALSA_MAX_RATE ? GST_ALSA_MAX_RATE : max_rate + i;
max_rate =
max_rate >
GST_ALSA_MAX_RATE ? GST_ALSA_MAX_RATE : (max_rate + GST_ALSA_DIR_MAX (i));
/* Probe period_count and adjust default/user provided value against probed MIN/MAX */
ERROR_CHECK (snd_pcm_hw_params_get_periods_min (hw_params, &min_period_cnt,
&i), "Couldn't get minimum period_count for device %s: %s",
this->device);
min_period_cnt =
min_period_cnt <
GST_ALSA_MIN_PERIOD_CNT ? GST_ALSA_MIN_PERIOD_CNT : (min_period_cnt +
GST_ALSA_DIR_MIN (i));
if (this->period_count < min_period_cnt) {
this->period_count = min_period_cnt;
};
ERROR_CHECK (snd_pcm_hw_params_get_periods_max (hw_params, &max_period_cnt,
&i), "Couldn't get maximum period_count for device %s: %s",
this->device);
max_period_cnt =
max_period_cnt >
GST_ALSA_MAX_PERIOD_CNT ? GST_ALSA_MAX_PERIOD_CNT : (max_period_cnt +
GST_ALSA_DIR_MAX (i));
if (this->period_count > max_period_cnt) {
this->period_count = max_period_cnt;
};
/* Probe period_size and adjust default/user provided value against probed MIN/MAX */
ERROR_CHECK (snd_pcm_hw_params_get_period_size_min (hw_params, &min_period_sz,
&i), "Couldn't get minimum period_size for device %s: %s",
this->device);
min_period_sz =
min_period_sz <
GST_ALSA_MIN_PERIOD_SZ ? GST_ALSA_MIN_PERIOD_SZ : (min_period_sz +
GST_ALSA_DIR_MIN (i));
if (this->period_size < min_period_sz) {
this->period_size = min_period_sz;
};
ERROR_CHECK (snd_pcm_hw_params_get_period_size_max (hw_params, &max_period_sz,
&i), "Couldn't get maximum period_size for device %s: %s",
this->device);
max_period_sz =
max_period_sz >
GST_ALSA_MAX_PERIOD_SZ ? GST_ALSA_MAX_PERIOD_SZ : (max_period_sz +
GST_ALSA_DIR_MAX (i));
if (this->period_size > max_period_sz) {
this->period_size = max_period_sz;
};
/* Probe buffer_size MIN/MAX */
buffer_size = this->period_count * this->period_size;
ERROR_CHECK (snd_pcm_hw_params_get_buffer_size_min (hw_params,
&min_buffer_sz), "Couldn't get minimum buffer_size for device %s: %s",
this->device);
min_buffer_sz =
min_buffer_sz <
GST_ALSA_MIN_BUFFER_SZ ? GST_ALSA_MIN_BUFFER_SZ : min_buffer_sz;
if (buffer_size < min_buffer_sz) {
buffer_size = min_buffer_sz;
this->period_size = GST_ALSA_MIN_BUFFER_SZ / this->period_count;
};
ERROR_CHECK (snd_pcm_hw_params_get_buffer_size_max (hw_params,
&max_buffer_sz), "Couldn't get maximum buffer_size for device %s: %s",
this->device);
max_buffer_sz =
max_buffer_sz >
GST_ALSA_MAX_BUFFER_SZ ? GST_ALSA_MAX_BUFFER_SZ : max_buffer_sz;
if (buffer_size > max_buffer_sz) {
buffer_size = max_buffer_sz;
this->period_size = GST_ALSA_MAX_BUFFER_SZ / this->period_count;
};
snd_pcm_format_mask_alloca (&mask);
snd_pcm_hw_params_get_format_mask (hw_params, mask);

View file

@ -78,9 +78,23 @@ GST_DEBUG_CATEGORY_EXTERN (alsa_debug);
#define GST_ALSA_MIN_RATE 8000
#define GST_ALSA_MAX_RATE 192000
#define GST_ALSA_MIN_PERIOD_CNT 2
#define GST_ALSA_MAX_PERIOD_CNT 64
#define GST_ALSA_MIN_PERIOD_SZ 2
#define GST_ALSA_MAX_PERIOD_SZ 8192
#define GST_ALSA_MIN_BUFFER_SZ GST_ALSA_MIN_PERIOD_CNT*GST_ALSA_MIN_PERIOD_SZ
#define GST_ALSA_MAX_BUFFER_SZ 65536
#define GST_ALSA_MAX_TRACKS 64 /* we don't support more than 64 tracks */
#define GST_ALSA_MAX_CHANNELS 32 /* tracks can have up to 32 channels */
/* a few alsa functions return an int value and a 'direction', -1, 0 or +1
0 = exact value
-1 = real value is up to 1 before given value
+1 = real value is up to 1 after given value
*/
#define GST_ALSA_DIR_MIN(i) ((i == 1) ? 1 : 0)
#define GST_ALSA_DIR_MAX(i) ((i ==-1) ?-1 : 0)
/* Mono is 1 channel ; the 5.1 standard is 6 channels. The value for
GST_ALSA_MAX_CHANNELS comes from alsa/mixer.h. */