mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2026-03-29 07:58:06 -04:00
examples: Make fixate examples start inactive
The actual formats are sent just before activating. This is done in preparation for supporting device ID negotiation.
This commit is contained in:
parent
58b958860e
commit
fc5b43a0b0
2 changed files with 130 additions and 19 deletions
|
|
@ -18,6 +18,7 @@
|
||||||
#include <spa/param/video/format-utils.h>
|
#include <spa/param/video/format-utils.h>
|
||||||
#include <spa/param/props.h>
|
#include <spa/param/props.h>
|
||||||
#include <spa/debug/format.h>
|
#include <spa/debug/format.h>
|
||||||
|
#include <spa/debug/pod.h>
|
||||||
|
|
||||||
#include <pipewire/pipewire.h>
|
#include <pipewire/pipewire.h>
|
||||||
|
|
||||||
|
|
@ -68,8 +69,12 @@ struct data {
|
||||||
struct modifier_info mod_info[2];
|
struct modifier_info mod_info[2];
|
||||||
|
|
||||||
int counter;
|
int counter;
|
||||||
|
|
||||||
|
bool capabilities_known;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static int build_formats(struct data *data, struct spa_pod_builder *b, const struct spa_pod **params);
|
||||||
|
|
||||||
static struct pw_version parse_pw_version(const char* version) {
|
static struct pw_version parse_pw_version(const char* version) {
|
||||||
struct pw_version pw_version;
|
struct pw_version pw_version;
|
||||||
sscanf(version, "%d.%d.%d", &pw_version.major, &pw_version.minor,
|
sscanf(version, "%d.%d.%d", &pw_version.major, &pw_version.minor,
|
||||||
|
|
@ -278,6 +283,34 @@ static void on_stream_state_changed(void *_data, enum pw_stream_state old,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_stream_tag_changed(struct data *data, const struct spa_pod *param)
|
||||||
|
{
|
||||||
|
struct pw_stream *stream = data->stream;
|
||||||
|
|
||||||
|
printf("tag param changed: \n");
|
||||||
|
spa_debug_pod(4, NULL, param);
|
||||||
|
|
||||||
|
if (!data->capabilities_known) {
|
||||||
|
const struct spa_pod *params[2];
|
||||||
|
uint32_t n_params = 0;
|
||||||
|
uint8_t buffer[1024];
|
||||||
|
struct spa_pod_builder b = SPA_POD_BUILDER_INIT(buffer, sizeof(buffer));
|
||||||
|
|
||||||
|
data->capabilities_known = true;
|
||||||
|
|
||||||
|
/* build the extra parameters to connect with. To connect, we can provide
|
||||||
|
* a list of supported formats. We use a builder that writes the param
|
||||||
|
* object to the stack. */
|
||||||
|
printf("supported formats:\n");
|
||||||
|
n_params = build_formats(data, &b, params);
|
||||||
|
pw_stream_update_params(data->stream, params, n_params);
|
||||||
|
|
||||||
|
printf("activating stream\n");
|
||||||
|
pw_stream_set_active(stream, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Be notified when the stream format param changes.
|
/* Be notified when the stream format param changes.
|
||||||
*
|
*
|
||||||
* We are now supposed to call pw_stream_finish_format() with success or
|
* We are now supposed to call pw_stream_finish_format() with success or
|
||||||
|
|
@ -357,6 +390,9 @@ on_stream_param_changed(void *_data, uint32_t id, const struct spa_pod *param)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
switch (id) {
|
switch (id) {
|
||||||
|
case SPA_PARAM_Tag:
|
||||||
|
on_stream_tag_changed(data, param);
|
||||||
|
break;
|
||||||
case SPA_PARAM_Format:
|
case SPA_PARAM_Format:
|
||||||
on_stream_format_changed(data, param);
|
on_stream_format_changed(data, param);
|
||||||
break;
|
break;
|
||||||
|
|
@ -421,8 +457,10 @@ int main(int argc, char *argv[])
|
||||||
const struct spa_pod *params[2];
|
const struct spa_pod *params[2];
|
||||||
uint8_t buffer[1024];
|
uint8_t buffer[1024];
|
||||||
struct spa_pod_builder b = SPA_POD_BUILDER_INIT(buffer, sizeof(buffer));
|
struct spa_pod_builder b = SPA_POD_BUILDER_INIT(buffer, sizeof(buffer));
|
||||||
|
struct spa_pod_frame f;
|
||||||
struct pw_properties *props;
|
struct pw_properties *props;
|
||||||
int res, n_params;
|
int res, n_params = 0;
|
||||||
|
SDL_RendererInfo info;
|
||||||
|
|
||||||
pw_init(&argc, &argv);
|
pw_init(&argc, &argv);
|
||||||
|
|
||||||
|
|
@ -472,11 +510,28 @@ int main(int argc, char *argv[])
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* build the extra parameters to connect with. To connect, we can provide
|
SDL_GetRendererInfo(data.renderer, &info);
|
||||||
* a list of supported formats. We use a builder that writes the param
|
|
||||||
* object to the stack. */
|
/* Push bare minimum video format to inactive stream, and wait for
|
||||||
printf("supported formats:\n");
|
* sending actual format until capability discovery is done. */
|
||||||
n_params = build_formats(&data, &b, params);
|
spa_pod_builder_push_object(&b, &f, SPA_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat);
|
||||||
|
spa_pod_builder_add(&b, SPA_FORMAT_mediaType,
|
||||||
|
SPA_POD_Id (SPA_MEDIA_TYPE_video),
|
||||||
|
0);
|
||||||
|
spa_pod_builder_add(&b, SPA_FORMAT_mediaSubtype,
|
||||||
|
SPA_POD_Id (SPA_MEDIA_SUBTYPE_raw),
|
||||||
|
0);
|
||||||
|
spa_pod_builder_add(&b, SPA_FORMAT_VIDEO_format,
|
||||||
|
SPA_POD_Id(SPA_VIDEO_FORMAT_RGBA),
|
||||||
|
0);
|
||||||
|
spa_pod_builder_add(&b, SPA_FORMAT_VIDEO_size,
|
||||||
|
SPA_POD_CHOICE_RANGE_Rectangle(
|
||||||
|
&SPA_RECTANGLE(WIDTH, HEIGHT),
|
||||||
|
&SPA_RECTANGLE(1,1),
|
||||||
|
&SPA_RECTANGLE(info.max_texture_width,
|
||||||
|
info.max_texture_height)),
|
||||||
|
0);
|
||||||
|
params[n_params++] = spa_pod_builder_pop(&b, &f);
|
||||||
|
|
||||||
/* now connect the stream, we need a direction (input/output),
|
/* now connect the stream, we need a direction (input/output),
|
||||||
* an optional target node to connect to, some flags and parameters
|
* an optional target node to connect to, some flags and parameters
|
||||||
|
|
@ -485,6 +540,7 @@ int main(int argc, char *argv[])
|
||||||
PW_DIRECTION_INPUT,
|
PW_DIRECTION_INPUT,
|
||||||
PW_ID_ANY,
|
PW_ID_ANY,
|
||||||
PW_STREAM_FLAG_AUTOCONNECT | /* try to automatically connect this stream */
|
PW_STREAM_FLAG_AUTOCONNECT | /* try to automatically connect this stream */
|
||||||
|
PW_STREAM_FLAG_INACTIVE | /* set active after capability discovery */
|
||||||
PW_STREAM_FLAG_MAP_BUFFERS, /* mmap the buffer data for us */
|
PW_STREAM_FLAG_MAP_BUFFERS, /* mmap the buffer data for us */
|
||||||
params, n_params)) /* extra parameters, see above */ < 0) {
|
params, n_params)) /* extra parameters, see above */ < 0) {
|
||||||
fprintf(stderr, "can't connect: %s\n", spa_strerror(res));
|
fprintf(stderr, "can't connect: %s\n", spa_strerror(res));
|
||||||
|
|
|
||||||
|
|
@ -19,8 +19,10 @@
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
|
|
||||||
|
#include <spa/param/tag-utils.h>
|
||||||
#include <spa/param/video/format-utils.h>
|
#include <spa/param/video/format-utils.h>
|
||||||
#include <spa/debug/format.h>
|
#include <spa/debug/format.h>
|
||||||
|
#include <spa/debug/pod.h>
|
||||||
|
|
||||||
#include <pipewire/pipewire.h>
|
#include <pipewire/pipewire.h>
|
||||||
|
|
||||||
|
|
@ -50,6 +52,8 @@ struct data {
|
||||||
|
|
||||||
double crop;
|
double crop;
|
||||||
double accumulator;
|
double accumulator;
|
||||||
|
|
||||||
|
bool capabilities_known;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void draw_elipse(uint32_t *dst, int width, int height, uint32_t color)
|
static void draw_elipse(uint32_t *dst, int width, int height, uint32_t color)
|
||||||
|
|
@ -363,6 +367,43 @@ static void on_stream_remove_buffer(void *_data, struct pw_buffer *buffer)
|
||||||
close(d[0].fd);
|
close(d[0].fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_stream_tag_changed(struct data *data, const struct spa_pod *param)
|
||||||
|
{
|
||||||
|
struct pw_stream *stream = data->stream;
|
||||||
|
|
||||||
|
printf("tag param changed: \n");
|
||||||
|
spa_debug_pod(4, NULL, param);
|
||||||
|
|
||||||
|
if (!data->capabilities_known) {
|
||||||
|
const struct spa_pod *params[2];
|
||||||
|
uint32_t n_params = 0;
|
||||||
|
uint8_t buffer[1024];
|
||||||
|
struct spa_pod_builder b = SPA_POD_BUILDER_INIT(buffer, sizeof(buffer));
|
||||||
|
|
||||||
|
data->capabilities_known = true;
|
||||||
|
|
||||||
|
/* build the extra parameter for the connection. Here we make an
|
||||||
|
* EnumFormat parameter which lists the possible formats we can provide.
|
||||||
|
* The server will select a format that matches and informs us about this
|
||||||
|
* in the stream param_changed event.
|
||||||
|
*/
|
||||||
|
params[n_params++] = build_format(&b, SPA_VIDEO_FORMAT_RGBA,
|
||||||
|
supported_modifiers, SPA_N_ELEMENTS(supported_modifiers));
|
||||||
|
params[n_params++] = build_format(&b, SPA_VIDEO_FORMAT_RGBA, NULL, 0);
|
||||||
|
|
||||||
|
printf("announcing starting EnumFormats\n");
|
||||||
|
for (unsigned int i=0; i < n_params; i++) {
|
||||||
|
spa_debug_format(4, NULL, params[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
pw_stream_update_params(data->stream, params, n_params);
|
||||||
|
|
||||||
|
printf("activating stream\n");
|
||||||
|
pw_stream_set_active(stream, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Be notified when the stream format param changes.
|
/* Be notified when the stream format param changes.
|
||||||
*
|
*
|
||||||
* We are now supposed to call pw_stream_update_params() with success or
|
* We are now supposed to call pw_stream_update_params() with success or
|
||||||
|
|
@ -390,6 +431,9 @@ on_stream_format_changed(struct data *data, const struct spa_pod *param)
|
||||||
|
|
||||||
data->stride = SPA_ROUND_UP_N(data->format.size.width * BPP, 4);
|
data->stride = SPA_ROUND_UP_N(data->format.size.width * BPP, 4);
|
||||||
|
|
||||||
|
if (data->stride == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
const struct spa_pod_prop *prop_modifier;
|
const struct spa_pod_prop *prop_modifier;
|
||||||
// check if client supports modifier
|
// check if client supports modifier
|
||||||
if ((prop_modifier = spa_pod_find_prop(param, NULL, SPA_FORMAT_VIDEO_modifier)) == NULL) {
|
if ((prop_modifier = spa_pod_find_prop(param, NULL, SPA_FORMAT_VIDEO_modifier)) == NULL) {
|
||||||
|
|
@ -479,6 +523,9 @@ on_stream_param_changed(void *_data, uint32_t id, const struct spa_pod *param)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
switch (id) {
|
switch (id) {
|
||||||
|
case SPA_PARAM_Tag:
|
||||||
|
on_stream_tag_changed(data, param);
|
||||||
|
break;
|
||||||
case SPA_PARAM_Format:
|
case SPA_PARAM_Format:
|
||||||
on_stream_format_changed(data, param);
|
on_stream_format_changed(data, param);
|
||||||
break;
|
break;
|
||||||
|
|
@ -507,6 +554,7 @@ int main(int argc, char *argv[])
|
||||||
uint32_t n_params = 0;
|
uint32_t n_params = 0;
|
||||||
uint8_t buffer[1024];
|
uint8_t buffer[1024];
|
||||||
struct spa_pod_builder b = SPA_POD_BUILDER_INIT(buffer, sizeof(buffer));
|
struct spa_pod_builder b = SPA_POD_BUILDER_INIT(buffer, sizeof(buffer));
|
||||||
|
struct spa_pod_frame f;
|
||||||
|
|
||||||
srand(32);
|
srand(32);
|
||||||
|
|
||||||
|
|
@ -550,19 +598,25 @@ int main(int argc, char *argv[])
|
||||||
/* make a timer to schedule our frames */
|
/* make a timer to schedule our frames */
|
||||||
data.timer = pw_loop_add_timer(pw_thread_loop_get_loop(data.loop), on_timeout, &data);
|
data.timer = pw_loop_add_timer(pw_thread_loop_get_loop(data.loop), on_timeout, &data);
|
||||||
|
|
||||||
/* build the extra parameter for the connection. Here we make an
|
/* Push bare minimum video format to inactive stream, and wait for
|
||||||
* EnumFormat parameter which lists the possible formats we can provide.
|
* sending actual format until capability discovery is done. */
|
||||||
* The server will select a format that matches and informs us about this
|
spa_pod_builder_push_object(&b, &f, SPA_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat);
|
||||||
* in the stream param_changed event.
|
spa_pod_builder_add(&b, SPA_FORMAT_mediaType,
|
||||||
*/
|
SPA_POD_Id(SPA_MEDIA_TYPE_video),
|
||||||
params[n_params++] = build_format(&b, SPA_VIDEO_FORMAT_RGBA,
|
0);
|
||||||
supported_modifiers, SPA_N_ELEMENTS(supported_modifiers));
|
spa_pod_builder_add(&b, SPA_FORMAT_mediaSubtype,
|
||||||
params[n_params++] = build_format(&b, SPA_VIDEO_FORMAT_RGBA, NULL, 0);
|
SPA_POD_Id(SPA_MEDIA_SUBTYPE_raw),
|
||||||
|
0);
|
||||||
printf("announcing starting EnumFormats\n");
|
spa_pod_builder_add(&b, SPA_FORMAT_VIDEO_format,
|
||||||
for (unsigned int i=0; i < 2; i++) {
|
SPA_POD_Id(SPA_VIDEO_FORMAT_RGBA),
|
||||||
spa_debug_format(4, NULL, params[i]);
|
0);
|
||||||
}
|
spa_pod_builder_add(&b, SPA_FORMAT_VIDEO_size,
|
||||||
|
SPA_POD_CHOICE_RANGE_Rectangle(
|
||||||
|
&SPA_RECTANGLE(320, 240),
|
||||||
|
&SPA_RECTANGLE(1,1),
|
||||||
|
&SPA_RECTANGLE(4096,4096)),
|
||||||
|
0);
|
||||||
|
params[n_params++] = spa_pod_builder_pop(&b, &f);
|
||||||
|
|
||||||
/* now connect the stream, we need a direction (input/output),
|
/* now connect the stream, we need a direction (input/output),
|
||||||
* an optional target node to connect to, some flags and parameters.
|
* an optional target node to connect to, some flags and parameters.
|
||||||
|
|
@ -575,6 +629,7 @@ int main(int argc, char *argv[])
|
||||||
PW_DIRECTION_OUTPUT,
|
PW_DIRECTION_OUTPUT,
|
||||||
PW_ID_ANY,
|
PW_ID_ANY,
|
||||||
PW_STREAM_FLAG_DRIVER |
|
PW_STREAM_FLAG_DRIVER |
|
||||||
|
PW_STREAM_FLAG_INACTIVE |
|
||||||
PW_STREAM_FLAG_ALLOC_BUFFERS,
|
PW_STREAM_FLAG_ALLOC_BUFFERS,
|
||||||
params, n_params);
|
params, n_params);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue