mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-12-17 08:56:49 -05:00
pulse-server: find the rate in the format_info
Also look for the highest rate in the format_info to suggest as the graph sample rate. See #1523
This commit is contained in:
parent
f8aa4dcfcc
commit
f96fa1bf36
3 changed files with 74 additions and 50 deletions
|
|
@ -430,7 +430,7 @@ int format_parse_param(const struct spa_pod *param, struct sample_spec *ss, stru
|
||||||
}
|
}
|
||||||
|
|
||||||
const struct spa_pod *format_build_param(struct spa_pod_builder *b, uint32_t id,
|
const struct spa_pod *format_build_param(struct spa_pod_builder *b, uint32_t id,
|
||||||
struct sample_spec *spec, struct channel_map *map)
|
const struct sample_spec *spec, const struct channel_map *map)
|
||||||
{
|
{
|
||||||
struct spa_audio_info_raw info;
|
struct spa_audio_info_raw info;
|
||||||
|
|
||||||
|
|
@ -444,8 +444,8 @@ const struct spa_pod *format_build_param(struct spa_pod_builder *b, uint32_t id,
|
||||||
return spa_format_audio_raw_build(b, id, &info);
|
return spa_format_audio_raw_build(b, id, &info);
|
||||||
}
|
}
|
||||||
|
|
||||||
int format_info_from_spec(struct format_info *info, struct sample_spec *ss,
|
int format_info_from_spec(struct format_info *info, const struct sample_spec *ss,
|
||||||
struct channel_map *map)
|
const struct channel_map *map)
|
||||||
{
|
{
|
||||||
spa_zero(*info);
|
spa_zero(*info);
|
||||||
info->encoding = ENCODING_PCM;
|
info->encoding = ENCODING_PCM;
|
||||||
|
|
@ -473,84 +473,97 @@ int format_info_from_spec(struct format_info *info, struct sample_spec *ss,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
const struct spa_pod *format_info_build_param(struct spa_pod_builder *b, uint32_t id,
|
int format_info_to_spec(const struct format_info *info, struct sample_spec *ss,
|
||||||
struct format_info *info)
|
struct channel_map *map)
|
||||||
{
|
{
|
||||||
const char *str, *val;
|
const char *str, *val;
|
||||||
struct sample_spec ss;
|
|
||||||
struct channel_map map, *pmap = NULL;
|
|
||||||
struct spa_json it[2];
|
struct spa_json it[2];
|
||||||
float f;
|
float f;
|
||||||
int len;
|
int len;
|
||||||
|
|
||||||
spa_zero(ss);
|
spa_zero(*ss);
|
||||||
spa_zero(map);
|
spa_zero(*map);
|
||||||
|
|
||||||
if (info->encoding != ENCODING_PCM)
|
if (info->encoding != ENCODING_PCM)
|
||||||
return NULL;
|
return -ENOTSUP;
|
||||||
|
if (info->props == NULL)
|
||||||
|
return -ENOENT;
|
||||||
|
|
||||||
if ((str = pw_properties_get(info->props, "format.sample_format")) == NULL)
|
if ((str = pw_properties_get(info->props, "format.sample_format")) == NULL)
|
||||||
return NULL;
|
return -ENOENT;
|
||||||
|
|
||||||
spa_json_init(&it[0], str, strlen(str));
|
spa_json_init(&it[0], str, strlen(str));
|
||||||
if ((len = spa_json_next(&it[0], &val)) <= 0)
|
if ((len = spa_json_next(&it[0], &val)) <= 0)
|
||||||
return NULL;
|
return -EINVAL;
|
||||||
if (spa_json_is_string(val, len)) {
|
if (spa_json_is_string(val, len)) {
|
||||||
ss.format = format_paname2id(val+1, len-2);
|
ss->format = format_paname2id(val+1, len-2);
|
||||||
if (ss.format == SPA_AUDIO_FORMAT_UNKNOWN)
|
if (ss->format == SPA_AUDIO_FORMAT_UNKNOWN)
|
||||||
return NULL;
|
return -ENOTSUP;
|
||||||
} else if (spa_json_is_array(val, len)) {
|
} else if (spa_json_is_array(val, len)) {
|
||||||
return NULL;
|
return -ENOTSUP;
|
||||||
} else
|
} else
|
||||||
return NULL;
|
return -ENOTSUP;
|
||||||
|
|
||||||
if ((str = pw_properties_get(info->props, "format.rate")) == NULL)
|
if ((str = pw_properties_get(info->props, "format.rate")) == NULL)
|
||||||
return NULL;
|
return -ENOENT;
|
||||||
|
|
||||||
spa_json_init(&it[0], str, strlen(str));
|
spa_json_init(&it[0], str, strlen(str));
|
||||||
if ((len = spa_json_next(&it[0], &val)) <= 0)
|
if ((len = spa_json_next(&it[0], &val)) <= 0)
|
||||||
return NULL;
|
return -EINVAL;
|
||||||
if (spa_json_is_float(val, len)) {
|
if (spa_json_is_float(val, len)) {
|
||||||
if (spa_json_parse_float(val, len, &f) <= 0)
|
if (spa_json_parse_float(val, len, &f) <= 0)
|
||||||
return NULL;
|
return -EINVAL;
|
||||||
ss.rate = f;
|
ss->rate = f;
|
||||||
} else if (spa_json_is_array(val, len)) {
|
} else if (spa_json_is_array(val, len)) {
|
||||||
return NULL;
|
return -ENOTSUP;
|
||||||
} else if (spa_json_is_object(val, len)) {
|
} else if (spa_json_is_object(val, len)) {
|
||||||
return NULL;
|
return -ENOTSUP;
|
||||||
} else
|
} else
|
||||||
return NULL;
|
return -ENOTSUP;
|
||||||
|
|
||||||
if ((str = pw_properties_get(info->props, "format.channels")) == NULL)
|
if ((str = pw_properties_get(info->props, "format.channels")) == NULL)
|
||||||
return NULL;
|
return -ENOENT;
|
||||||
|
|
||||||
spa_json_init(&it[0], str, strlen(str));
|
spa_json_init(&it[0], str, strlen(str));
|
||||||
if ((len = spa_json_next(&it[0], &val)) <= 0)
|
if ((len = spa_json_next(&it[0], &val)) <= 0)
|
||||||
return NULL;
|
return -EINVAL;
|
||||||
if (spa_json_is_float(val, len)) {
|
if (spa_json_is_float(val, len)) {
|
||||||
if (spa_json_parse_float(val, len, &f) <= 0)
|
if (spa_json_parse_float(val, len, &f) <= 0)
|
||||||
return NULL;
|
return -EINVAL;
|
||||||
ss.channels = f;
|
ss->channels = f;
|
||||||
} else if (spa_json_is_array(val, len)) {
|
} else if (spa_json_is_array(val, len)) {
|
||||||
return NULL;
|
return -ENOTSUP;
|
||||||
} else if (spa_json_is_object(val, len)) {
|
} else if (spa_json_is_object(val, len)) {
|
||||||
return NULL;
|
return -ENOTSUP;
|
||||||
} else
|
} else
|
||||||
return NULL;
|
return -ENOTSUP;
|
||||||
|
|
||||||
if ((str = pw_properties_get(info->props, "format.channel_map")) != NULL) {
|
if ((str = pw_properties_get(info->props, "format.channel_map")) != NULL) {
|
||||||
spa_json_init(&it[0], str, strlen(str));
|
spa_json_init(&it[0], str, strlen(str));
|
||||||
if ((len = spa_json_next(&it[0], &val)) <= 0)
|
if ((len = spa_json_next(&it[0], &val)) <= 0)
|
||||||
return NULL;
|
return -EINVAL;
|
||||||
if (!spa_json_is_string(val, len))
|
if (!spa_json_is_string(val, len))
|
||||||
return NULL;
|
return -EINVAL;
|
||||||
while ((*str == '\"' || *str == ',') &&
|
while ((*str == '\"' || *str == ',') &&
|
||||||
(len = strcspn(++str, "\",")) > 0) {
|
(len = strcspn(++str, "\",")) > 0) {
|
||||||
map.map[map.channels++] = channel_paname2id(str, len);
|
map->map[map->channels++] = channel_paname2id(str, len);
|
||||||
str += len;
|
str += len;
|
||||||
}
|
}
|
||||||
if (map.channels == ss.channels)
|
|
||||||
pmap = ↦
|
|
||||||
}
|
}
|
||||||
return format_build_param(b, id, &ss, pmap);
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const struct spa_pod *format_info_build_param(struct spa_pod_builder *b, uint32_t id,
|
||||||
|
const struct format_info *info, uint32_t *rate)
|
||||||
|
{
|
||||||
|
struct sample_spec ss;
|
||||||
|
struct channel_map map;
|
||||||
|
int res;
|
||||||
|
|
||||||
|
if ((res = format_info_to_spec(info, &ss, &map)) < 0) {
|
||||||
|
errno = -res;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
*rate = ss.rate;
|
||||||
|
return format_build_param(b, id, &ss, &map);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -208,13 +208,14 @@ int format_parse_param(const struct spa_pod *param, struct sample_spec *ss,
|
||||||
struct channel_map *map);
|
struct channel_map *map);
|
||||||
|
|
||||||
const struct spa_pod *format_build_param(struct spa_pod_builder *b, uint32_t id,
|
const struct spa_pod *format_build_param(struct spa_pod_builder *b, uint32_t id,
|
||||||
struct sample_spec *spec, struct channel_map *map);
|
const struct sample_spec *spec, const struct channel_map *map);
|
||||||
|
|
||||||
int format_info_from_spec(struct format_info *info, struct sample_spec *ss,
|
|
||||||
struct channel_map *map);
|
|
||||||
|
|
||||||
const struct spa_pod *format_info_build_param(struct spa_pod_builder *b, uint32_t id,
|
const struct spa_pod *format_info_build_param(struct spa_pod_builder *b, uint32_t id,
|
||||||
struct format_info *info);
|
const struct format_info *info, uint32_t *rate);
|
||||||
|
|
||||||
|
int format_info_from_spec(struct format_info *info, const struct sample_spec *ss,
|
||||||
|
const struct channel_map *map);
|
||||||
|
int format_info_to_spec(const struct format_info *info, struct sample_spec *ss,
|
||||||
|
struct channel_map *map);
|
||||||
|
|
||||||
static inline void format_info_clear(struct format_info *info)
|
static inline void format_info_clear(struct format_info *info)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -1291,7 +1291,7 @@ static int do_create_playback_stream(struct client *client, uint32_t command, ui
|
||||||
int res;
|
int res;
|
||||||
struct sample_spec ss;
|
struct sample_spec ss;
|
||||||
struct channel_map map;
|
struct channel_map map;
|
||||||
uint32_t sink_index, syncid;
|
uint32_t sink_index, syncid, rate = 0;
|
||||||
const char *sink_name;
|
const char *sink_name;
|
||||||
struct buffer_attr attr = { 0 };
|
struct buffer_attr attr = { 0 };
|
||||||
bool corked = false,
|
bool corked = false,
|
||||||
|
|
@ -1411,6 +1411,7 @@ static int do_create_playback_stream(struct client *client, uint32_t command, ui
|
||||||
uint8_t i;
|
uint8_t i;
|
||||||
for (i = 0; i < n_formats; i++) {
|
for (i = 0; i < n_formats; i++) {
|
||||||
struct format_info format;
|
struct format_info format;
|
||||||
|
uint32_t r;
|
||||||
|
|
||||||
if (message_get(m,
|
if (message_get(m,
|
||||||
TAG_FORMAT_INFO, &format,
|
TAG_FORMAT_INFO, &format,
|
||||||
|
|
@ -1419,9 +1420,11 @@ static int do_create_playback_stream(struct client *client, uint32_t command, ui
|
||||||
|
|
||||||
if (n_params < MAX_FORMATS &&
|
if (n_params < MAX_FORMATS &&
|
||||||
(params[n_params] = format_info_build_param(&b,
|
(params[n_params] = format_info_build_param(&b,
|
||||||
SPA_PARAM_EnumFormat, &format)) != NULL) {
|
SPA_PARAM_EnumFormat, &format, &r)) != NULL) {
|
||||||
n_params++;
|
n_params++;
|
||||||
n_valid_formats++;
|
n_valid_formats++;
|
||||||
|
if (r > rate)
|
||||||
|
rate = r;
|
||||||
} else {
|
} else {
|
||||||
log_format_info(impl, SPA_LOG_LEVEL_WARN, &format);
|
log_format_info(impl, SPA_LOG_LEVEL_WARN, &format);
|
||||||
}
|
}
|
||||||
|
|
@ -1440,7 +1443,7 @@ static int do_create_playback_stream(struct client *client, uint32_t command, ui
|
||||||
impl, format_id2name(ss.format), ss.rate,
|
impl, format_id2name(ss.format), ss.rate,
|
||||||
ss.channels);
|
ss.channels);
|
||||||
}
|
}
|
||||||
pw_properties_setf(props, PW_KEY_NODE_RATE, "1/%u", ss.rate);
|
rate = ss.rate;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m->offset != m->length)
|
if (m->offset != m->length)
|
||||||
|
|
@ -1475,6 +1478,8 @@ static int do_create_playback_stream(struct client *client, uint32_t command, ui
|
||||||
stream->is_underrun = true;
|
stream->is_underrun = true;
|
||||||
stream->underrun_for = -1;
|
stream->underrun_for = -1;
|
||||||
|
|
||||||
|
if (rate != 0)
|
||||||
|
pw_properties_setf(props, PW_KEY_NODE_RATE, "1/%u", rate);
|
||||||
if (no_remix)
|
if (no_remix)
|
||||||
pw_properties_set(props, PW_KEY_STREAM_DONT_REMIX, "true");
|
pw_properties_set(props, PW_KEY_STREAM_DONT_REMIX, "true");
|
||||||
flags = 0;
|
flags = 0;
|
||||||
|
|
@ -1562,7 +1567,7 @@ static int do_create_record_stream(struct client *client, uint32_t command, uint
|
||||||
struct pw_properties *props = NULL;
|
struct pw_properties *props = NULL;
|
||||||
uint8_t n_formats = 0;
|
uint8_t n_formats = 0;
|
||||||
struct stream *stream = NULL;
|
struct stream *stream = NULL;
|
||||||
uint32_t n_params = 0, n_valid_formats = 0, flags, id;
|
uint32_t n_params = 0, n_valid_formats = 0, flags, id, rate = 0;
|
||||||
const struct spa_pod *params[MAX_FORMATS];
|
const struct spa_pod *params[MAX_FORMATS];
|
||||||
uint8_t buffer[4096];
|
uint8_t buffer[4096];
|
||||||
struct spa_pod_builder b = SPA_POD_BUILDER_INIT(buffer, sizeof(buffer));
|
struct spa_pod_builder b = SPA_POD_BUILDER_INIT(buffer, sizeof(buffer));
|
||||||
|
|
@ -1640,6 +1645,7 @@ static int do_create_record_stream(struct client *client, uint32_t command, uint
|
||||||
uint8_t i;
|
uint8_t i;
|
||||||
for (i = 0; i < n_formats; i++) {
|
for (i = 0; i < n_formats; i++) {
|
||||||
struct format_info format;
|
struct format_info format;
|
||||||
|
uint32_t r;
|
||||||
|
|
||||||
if (message_get(m,
|
if (message_get(m,
|
||||||
TAG_FORMAT_INFO, &format,
|
TAG_FORMAT_INFO, &format,
|
||||||
|
|
@ -1648,9 +1654,11 @@ static int do_create_record_stream(struct client *client, uint32_t command, uint
|
||||||
|
|
||||||
if (n_params < MAX_FORMATS &&
|
if (n_params < MAX_FORMATS &&
|
||||||
(params[n_params] = format_info_build_param(&b,
|
(params[n_params] = format_info_build_param(&b,
|
||||||
SPA_PARAM_EnumFormat, &format)) != NULL) {
|
SPA_PARAM_EnumFormat, &format, &r)) != NULL) {
|
||||||
n_params++;
|
n_params++;
|
||||||
n_valid_formats++;
|
n_valid_formats++;
|
||||||
|
if (r > rate)
|
||||||
|
rate = r;
|
||||||
} else {
|
} else {
|
||||||
log_format_info(impl, SPA_LOG_LEVEL_WARN, &format);
|
log_format_info(impl, SPA_LOG_LEVEL_WARN, &format);
|
||||||
}
|
}
|
||||||
|
|
@ -1680,7 +1688,7 @@ static int do_create_record_stream(struct client *client, uint32_t command, uint
|
||||||
impl, format_id2name(ss.format), ss.rate,
|
impl, format_id2name(ss.format), ss.rate,
|
||||||
ss.channels);
|
ss.channels);
|
||||||
}
|
}
|
||||||
pw_properties_setf(props, PW_KEY_NODE_RATE, "1/%u", ss.rate);
|
rate = ss.rate;
|
||||||
}
|
}
|
||||||
if (m->offset != m->length)
|
if (m->offset != m->length)
|
||||||
goto error_protocol;
|
goto error_protocol;
|
||||||
|
|
@ -1715,6 +1723,8 @@ static int do_create_record_stream(struct client *client, uint32_t command, uint
|
||||||
if (client->quirks & QUIRK_REMOVE_CAPTURE_DONT_MOVE)
|
if (client->quirks & QUIRK_REMOVE_CAPTURE_DONT_MOVE)
|
||||||
no_move = false;
|
no_move = false;
|
||||||
|
|
||||||
|
if (rate != 0)
|
||||||
|
pw_properties_setf(props, PW_KEY_NODE_RATE, "1/%u", rate);
|
||||||
if (peak_detect)
|
if (peak_detect)
|
||||||
pw_properties_set(props, PW_KEY_STREAM_MONITOR, "true");
|
pw_properties_set(props, PW_KEY_STREAM_MONITOR, "true");
|
||||||
if (no_remix)
|
if (no_remix)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue