diff --git a/src/examples/video-play-fixate.c b/src/examples/video-play-fixate.c index eb9d139e3..ed250d914 100644 --- a/src/examples/video-play-fixate.c +++ b/src/examples/video-play-fixate.c @@ -18,6 +18,7 @@ #include #include #include +#include #include @@ -68,8 +69,12 @@ struct data { struct modifier_info mod_info[2]; 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) { struct pw_version pw_version; 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. * * 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; switch (id) { + case SPA_PARAM_Tag: + on_stream_tag_changed(data, param); + break; case SPA_PARAM_Format: on_stream_format_changed(data, param); break; @@ -421,8 +457,10 @@ int main(int argc, char *argv[]) const struct spa_pod *params[2]; uint8_t buffer[1024]; struct spa_pod_builder b = SPA_POD_BUILDER_INIT(buffer, sizeof(buffer)); + struct spa_pod_frame f; struct pw_properties *props; - int res, n_params; + int res, n_params = 0; + SDL_RendererInfo info; pw_init(&argc, &argv); @@ -472,11 +510,28 @@ int main(int argc, char *argv[]) return -1; } - /* 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); + SDL_GetRendererInfo(data.renderer, &info); + + /* Push bare minimum video format to inactive stream, and wait for + * sending actual format until capability discovery is done. */ + 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), * 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_ID_ANY, 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 */ params, n_params)) /* extra parameters, see above */ < 0) { fprintf(stderr, "can't connect: %s\n", spa_strerror(res)); diff --git a/src/examples/video-src-fixate.c b/src/examples/video-src-fixate.c index 0620c4ceb..53c5776c6 100644 --- a/src/examples/video-src-fixate.c +++ b/src/examples/video-src-fixate.c @@ -19,8 +19,10 @@ #include #include +#include #include #include +#include #include @@ -50,6 +52,8 @@ struct data { double crop; double accumulator; + + bool capabilities_known; }; 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); } +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. * * 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); + if (data->stride == 0) + return; + const struct spa_pod_prop *prop_modifier; // check if client supports modifier 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; switch (id) { + case SPA_PARAM_Tag: + on_stream_tag_changed(data, param); + break; case SPA_PARAM_Format: on_stream_format_changed(data, param); break; @@ -507,6 +554,7 @@ int main(int argc, char *argv[]) uint32_t n_params = 0; uint8_t buffer[1024]; struct spa_pod_builder b = SPA_POD_BUILDER_INIT(buffer, sizeof(buffer)); + struct spa_pod_frame f; srand(32); @@ -550,19 +598,25 @@ int main(int argc, char *argv[]) /* make a timer to schedule our frames */ 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 - * 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 < 2; i++) { - spa_debug_format(4, NULL, params[i]); - } + /* Push bare minimum video format to inactive stream, and wait for + * sending actual format until capability discovery is done. */ + 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(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), * 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_ID_ANY, PW_STREAM_FLAG_DRIVER | + PW_STREAM_FLAG_INACTIVE | PW_STREAM_FLAG_ALLOC_BUFFERS, params, n_params);