... |
... |
@@ -34,20 +34,27 @@ |
34
|
34
|
#include <errno.h>
|
35
|
35
|
#include <unistd.h>
|
36
|
36
|
|
|
37
|
+#include <pipewire/pipewire.h>
|
|
38
|
+
|
37
|
39
|
#include <spa/param/format-utils.h>
|
38
|
40
|
#include <spa/param/video/format-utils.h>
|
39
|
41
|
#include <spa/utils/defs.h>
|
40
|
42
|
|
41
|
|
-#include <pipewire/pipewire.h>
|
|
43
|
+#if PW_CHECK_VERSION(0, 2, 90)
|
|
44
|
+#include <spa/buffer/meta.h>
|
|
45
|
+#include <spa/utils/result.h>
|
|
46
|
+#endif
|
42
|
47
|
|
43
|
48
|
#define PROP_RANGE(min, max) 2, (min), (max)
|
44
|
49
|
|
|
50
|
+#if !PW_CHECK_VERSION(0, 2, 90)
|
45
|
51
|
struct type {
|
46
|
52
|
struct spa_type_media_type media_type;
|
47
|
53
|
struct spa_type_media_subtype media_subtype;
|
48
|
54
|
struct spa_type_format_video format_video;
|
49
|
55
|
struct spa_type_video_format video_format;
|
50
|
56
|
};
|
|
57
|
+#endif
|
51
|
58
|
|
52
|
59
|
struct weston_pipewire {
|
53
|
60
|
struct weston_compositor *compositor;
|
... |
... |
@@ -60,12 +67,19 @@ struct weston_pipewire { |
60
|
67
|
struct pw_loop *loop;
|
61
|
68
|
struct wl_event_source *loop_source;
|
62
|
69
|
|
|
70
|
+#if PW_CHECK_VERSION(0, 2, 90)
|
|
71
|
+ struct pw_context *context;
|
|
72
|
+#endif
|
63
|
73
|
struct pw_core *core;
|
64
|
74
|
struct pw_type *t;
|
|
75
|
+#if PW_CHECK_VERSION(0, 2, 90)
|
|
76
|
+ struct spa_hook core_listener;
|
|
77
|
+#else
|
65
|
78
|
struct type type;
|
66
|
79
|
|
67
|
80
|
struct pw_remote *remote;
|
68
|
81
|
struct spa_hook remote_listener;
|
|
82
|
+#endif
|
69
|
83
|
};
|
70
|
84
|
|
71
|
85
|
struct pipewire_output {
|
... |
... |
@@ -100,6 +114,7 @@ struct pipewire_frame_data { |
100
|
114
|
struct wl_event_source *fence_sync_event_source;
|
101
|
115
|
};
|
102
|
116
|
|
|
117
|
+#if !PW_CHECK_VERSION(0, 2, 90)
|
103
|
118
|
static inline void init_type(struct type *type, struct spa_type_map *map)
|
104
|
119
|
{
|
105
|
120
|
spa_type_media_type_map(map, &type->media_type);
|
... |
... |
@@ -107,6 +122,7 @@ static inline void init_type(struct type *type, struct spa_type_map *map) |
107
|
122
|
spa_type_format_video_map(map, &type->format_video);
|
108
|
123
|
spa_type_video_format_map(map, &type->video_format);
|
109
|
124
|
}
|
|
125
|
+#endif
|
110
|
126
|
|
111
|
127
|
static void
|
112
|
128
|
pipewire_debug_impl(struct weston_pipewire *pipewire,
|
... |
... |
@@ -141,6 +157,7 @@ pipewire_debug_impl(struct weston_pipewire *pipewire, |
141
|
157
|
free(logstr);
|
142
|
158
|
}
|
143
|
159
|
|
|
160
|
+#if !PW_CHECK_VERSION(0, 2, 90)
|
144
|
161
|
static void
|
145
|
162
|
pipewire_debug(struct weston_pipewire *pipewire, const char *fmt, ...)
|
146
|
163
|
{
|
... |
... |
@@ -150,6 +167,7 @@ pipewire_debug(struct weston_pipewire *pipewire, const char *fmt, ...) |
150
|
167
|
pipewire_debug_impl(pipewire, NULL, fmt, ap);
|
151
|
168
|
va_end(ap);
|
152
|
169
|
}
|
|
170
|
+#endif
|
153
|
171
|
|
154
|
172
|
static void
|
155
|
173
|
pipewire_output_debug(struct pipewire_output *output, const char *fmt, ...)
|
... |
... |
@@ -185,7 +203,9 @@ pipewire_output_handle_frame(struct pipewire_output *output, int fd, |
185
|
203
|
const struct weston_drm_virtual_output_api *api =
|
186
|
204
|
output->pipewire->virtual_output_api;
|
187
|
205
|
size_t size = output->output->height * stride;
|
|
206
|
+#if !PW_CHECK_VERSION(0, 2, 90)
|
188
|
207
|
struct pw_type *t = output->pipewire->t;
|
|
208
|
+#endif
|
189
|
209
|
struct pw_buffer *buffer;
|
190
|
210
|
struct spa_buffer *spa_buffer;
|
191
|
211
|
struct spa_meta_header *h;
|
... |
... |
@@ -203,7 +223,12 @@ pipewire_output_handle_frame(struct pipewire_output *output, int fd, |
203
|
223
|
|
204
|
224
|
spa_buffer = buffer->buffer;
|
205
|
225
|
|
|
226
|
+#if PW_CHECK_VERSION(0, 2, 90)
|
|
227
|
+ if ((h = spa_buffer_find_meta_data(spa_buffer, SPA_META_Header,
|
|
228
|
+ sizeof(struct spa_meta_header)))) {
|
|
229
|
+#else
|
206
|
230
|
if ((h = spa_buffer_find_meta(spa_buffer, t->meta.Header))) {
|
|
231
|
+#endif
|
207
|
232
|
h->pts = -1;
|
208
|
233
|
h->flags = 0;
|
209
|
234
|
h->seq = output->seq++;
|
... |
... |
@@ -375,18 +400,40 @@ pipewire_set_dpms(struct weston_output *base_output, enum dpms_enum level) |
375
|
400
|
static int
|
376
|
401
|
pipewire_output_connect(struct pipewire_output *output)
|
377
|
402
|
{
|
|
403
|
+#if !PW_CHECK_VERSION(0, 2, 90)
|
378
|
404
|
struct weston_pipewire *pipewire = output->pipewire;
|
379
|
405
|
struct type *type = &pipewire->type;
|
|
406
|
+#endif
|
380
|
407
|
uint8_t buffer[1024];
|
381
|
408
|
struct spa_pod_builder builder =
|
382
|
409
|
SPA_POD_BUILDER_INIT(buffer, sizeof(buffer));
|
383
|
410
|
const struct spa_pod *params[1];
|
|
411
|
+#if !PW_CHECK_VERSION(0, 2, 90)
|
384
|
412
|
struct pw_type *t = pipewire->t;
|
|
413
|
+#endif
|
385
|
414
|
int frame_rate = output->output->current_mode->refresh / 1000;
|
386
|
415
|
int width = output->output->width;
|
387
|
416
|
int height = output->output->height;
|
388
|
417
|
int ret;
|
389
|
418
|
|
|
419
|
+#if PW_CHECK_VERSION(0, 2, 90)
|
|
420
|
+ params[0] = spa_pod_builder_add_object(&builder,
|
|
421
|
+ SPA_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat,
|
|
422
|
+ SPA_FORMAT_mediaType, SPA_POD_Id(SPA_MEDIA_TYPE_video),
|
|
423
|
+ SPA_FORMAT_mediaSubtype, SPA_POD_Id(SPA_MEDIA_SUBTYPE_raw),
|
|
424
|
+ SPA_FORMAT_VIDEO_format, SPA_POD_Id(SPA_VIDEO_FORMAT_BGRx),
|
|
425
|
+ SPA_FORMAT_VIDEO_size, SPA_POD_Rectangle(&SPA_RECTANGLE(width, height)),
|
|
426
|
+ SPA_FORMAT_VIDEO_framerate, SPA_POD_Fraction(&SPA_FRACTION (0, 1)),
|
|
427
|
+ SPA_FORMAT_VIDEO_maxFramerate,
|
|
428
|
+ SPA_POD_CHOICE_RANGE_Fraction(&SPA_FRACTION(frame_rate, 1),
|
|
429
|
+ &SPA_FRACTION(1, 1),
|
|
430
|
+ &SPA_FRACTION(frame_rate, 1)));
|
|
431
|
+
|
|
432
|
+ ret = pw_stream_connect(output->stream, PW_DIRECTION_OUTPUT, SPA_ID_INVALID,
|
|
433
|
+ (PW_STREAM_FLAG_DRIVER |
|
|
434
|
+ PW_STREAM_FLAG_MAP_BUFFERS),
|
|
435
|
+ params, 1);
|
|
436
|
+#else
|
390
|
437
|
params[0] = spa_pod_builder_object(&builder,
|
391
|
438
|
t->param.idEnumFormat, t->spa_format,
|
392
|
439
|
"I", type->media_type.video,
|
... |
... |
@@ -406,6 +453,7 @@ pipewire_output_connect(struct pipewire_output *output) |
406
|
453
|
(PW_STREAM_FLAG_DRIVER |
|
407
|
454
|
PW_STREAM_FLAG_MAP_BUFFERS),
|
408
|
455
|
params, 1);
|
|
456
|
+#endif
|
409
|
457
|
if (ret != 0) {
|
410
|
458
|
weston_log("Failed to connect pipewire stream: %s",
|
411
|
459
|
spa_strerror(ret));
|
... |
... |
@@ -482,26 +530,42 @@ pipewire_output_stream_state_changed(void *data, enum pw_stream_state old, |
482
|
530
|
}
|
483
|
531
|
|
484
|
532
|
static void
|
|
533
|
+#if PW_CHECK_VERSION(0, 2, 90)
|
|
534
|
+pipewire_output_stream_param_changed(void *data, uint32_t id, const struct spa_pod *format)
|
|
535
|
+#else
|
485
|
536
|
pipewire_output_stream_format_changed(void *data, const struct spa_pod *format)
|
|
537
|
+#endif
|
486
|
538
|
{
|
487
|
539
|
struct pipewire_output *output = data;
|
|
540
|
+#if !PW_CHECK_VERSION(0, 2, 90)
|
488
|
541
|
struct weston_pipewire *pipewire = output->pipewire;
|
|
542
|
+#endif
|
489
|
543
|
uint8_t buffer[1024];
|
490
|
544
|
struct spa_pod_builder builder =
|
491
|
545
|
SPA_POD_BUILDER_INIT(buffer, sizeof(buffer));
|
492
|
546
|
const struct spa_pod *params[2];
|
|
547
|
+#if !PW_CHECK_VERSION(0, 2, 90)
|
493
|
548
|
struct pw_type *t = pipewire->t;
|
|
549
|
+#endif
|
494
|
550
|
int32_t width, height, stride, size;
|
495
|
551
|
const int bpp = 4;
|
496
|
552
|
|
497
|
553
|
if (!format) {
|
498
|
554
|
pipewire_output_debug(output, "format = None");
|
|
555
|
+#if PW_CHECK_VERSION(0, 2, 90)
|
|
556
|
+ pw_stream_update_params(output->stream, NULL, 0);
|
|
557
|
+#else
|
499
|
558
|
pw_stream_finish_format(output->stream, 0, NULL, 0);
|
|
559
|
+#endif
|
500
|
560
|
return;
|
501
|
561
|
}
|
502
|
562
|
|
|
563
|
+#if PW_CHECK_VERSION(0, 2, 90)
|
|
564
|
+ spa_format_video_raw_parse(format, &output->video_format);
|
|
565
|
+#else
|
503
|
566
|
spa_format_video_raw_parse(format, &output->video_format,
|
504
|
567
|
&pipewire->type.format_video);
|
|
568
|
+#endif
|
505
|
569
|
|
506
|
570
|
width = output->video_format.size.width;
|
507
|
571
|
height = output->video_format.size.height;
|
... |
... |
@@ -510,6 +574,21 @@ pipewire_output_stream_format_changed(void *data, const struct spa_pod *format) |
510
|
574
|
|
511
|
575
|
pipewire_output_debug(output, "format = %dx%d", width, height);
|
512
|
576
|
|
|
577
|
+#if PW_CHECK_VERSION(0, 2, 90)
|
|
578
|
+ params[0] = spa_pod_builder_add_object(&builder,
|
|
579
|
+ SPA_TYPE_OBJECT_ParamBuffers, SPA_PARAM_Buffers,
|
|
580
|
+ SPA_PARAM_BUFFERS_size, SPA_POD_Int(size),
|
|
581
|
+ SPA_PARAM_BUFFERS_stride, SPA_POD_Int(stride),
|
|
582
|
+ SPA_PARAM_BUFFERS_buffers, SPA_POD_CHOICE_RANGE_Int(4, 2, 8),
|
|
583
|
+ SPA_PARAM_BUFFERS_align, SPA_POD_Int(16));
|
|
584
|
+
|
|
585
|
+ params[1] = spa_pod_builder_add_object(&builder,
|
|
586
|
+ SPA_TYPE_OBJECT_ParamMeta, SPA_PARAM_Meta,
|
|
587
|
+ SPA_PARAM_META_type, SPA_POD_Id(SPA_META_Header),
|
|
588
|
+ SPA_PARAM_META_size, SPA_POD_Int(sizeof(struct spa_meta_header)));
|
|
589
|
+
|
|
590
|
+ pw_stream_update_params(output->stream, params, 2);
|
|
591
|
+#else
|
513
|
592
|
params[0] = spa_pod_builder_object(&builder,
|
514
|
593
|
t->param.idBuffers, t->param_buffers.Buffers,
|
515
|
594
|
":", t->param_buffers.size,
|
... |
... |
@@ -527,12 +606,17 @@ pipewire_output_stream_format_changed(void *data, const struct spa_pod *format) |
527
|
606
|
":", t->param_meta.size, "i", sizeof(struct spa_meta_header));
|
528
|
607
|
|
529
|
608
|
pw_stream_finish_format(output->stream, 0, params, 2);
|
|
609
|
+#endif
|
530
|
610
|
}
|
531
|
611
|
|
532
|
612
|
static const struct pw_stream_events stream_events = {
|
533
|
613
|
PW_VERSION_STREAM_EVENTS,
|
534
|
614
|
.state_changed = pipewire_output_stream_state_changed,
|
|
615
|
+#if PW_CHECK_VERSION(0, 2, 90)
|
|
616
|
+ .param_changed = pipewire_output_stream_param_changed,
|
|
617
|
+#else
|
535
|
618
|
.format_changed = pipewire_output_stream_format_changed,
|
|
619
|
+#endif
|
536
|
620
|
};
|
537
|
621
|
|
538
|
622
|
static struct weston_output *
|
... |
... |
@@ -560,7 +644,11 @@ pipewire_output_create(struct weston_compositor *c, char *name) |
560
|
644
|
if (!head)
|
561
|
645
|
goto err;
|
562
|
646
|
|
|
647
|
+#if PW_CHECK_VERSION(0, 2, 90)
|
|
648
|
+ output->stream = pw_stream_new(pipewire->core, name, NULL);
|
|
649
|
+#else
|
563
|
650
|
output->stream = pw_stream_new(pipewire->remote, name, NULL);
|
|
651
|
+#endif
|
564
|
652
|
if (!output->stream) {
|
565
|
653
|
weston_log("Cannot initialize pipewire stream\n");
|
566
|
654
|
goto err;
|
... |
... |
@@ -704,6 +792,14 @@ weston_pipewire_loop_handler(int fd, uint32_t mask, void *data) |
704
|
792
|
return 0;
|
705
|
793
|
}
|
706
|
794
|
|
|
795
|
+#if PW_CHECK_VERSION(0, 2, 90)
|
|
796
|
+static void
|
|
797
|
+weston_pipewire_error(void *data, uint32_t id, int seq, int res,
|
|
798
|
+ const char *error)
|
|
799
|
+{
|
|
800
|
+ weston_log("pipewire remote error: %s\n", error);
|
|
801
|
+}
|
|
802
|
+#else
|
707
|
803
|
static void
|
708
|
804
|
weston_pipewire_state_changed(void *data, enum pw_remote_state old,
|
709
|
805
|
enum pw_remote_state state, const char *error)
|
... |
... |
@@ -725,12 +821,20 @@ weston_pipewire_state_changed(void *data, enum pw_remote_state old, |
725
|
821
|
break;
|
726
|
822
|
}
|
727
|
823
|
}
|
|
824
|
+#endif
|
728
|
825
|
|
729
|
826
|
|
|
827
|
+#if PW_CHECK_VERSION(0, 2, 90)
|
|
828
|
+static const struct pw_core_events core_events = {
|
|
829
|
+ PW_VERSION_CORE_EVENTS,
|
|
830
|
+ .error = weston_pipewire_error,
|
|
831
|
+};
|
|
832
|
+#else
|
730
|
833
|
static const struct pw_remote_events remote_events = {
|
731
|
834
|
PW_VERSION_REMOTE_EVENTS,
|
732
|
835
|
.state_changed = weston_pipewire_state_changed,
|
733
|
836
|
};
|
|
837
|
+#endif
|
734
|
838
|
|
735
|
839
|
static int
|
736
|
840
|
weston_pipewire_init(struct weston_pipewire *pipewire)
|
... |
... |
@@ -745,10 +849,19 @@ weston_pipewire_init(struct weston_pipewire *pipewire) |
745
|
849
|
|
746
|
850
|
pw_loop_enter(pipewire->loop);
|
747
|
851
|
|
|
852
|
+#if PW_CHECK_VERSION(0, 2, 90)
|
|
853
|
+ pipewire->context = pw_context_new(pipewire->loop, NULL, 0);
|
|
854
|
+#else
|
748
|
855
|
pipewire->core = pw_core_new(pipewire->loop, NULL);
|
749
|
856
|
pipewire->t = pw_core_get_type(pipewire->core);
|
750
|
857
|
init_type(&pipewire->type, pipewire->t->map);
|
|
858
|
+#endif
|
751
|
859
|
|
|
860
|
+#if PW_CHECK_VERSION(0, 2, 90)
|
|
861
|
+ pw_core_add_listener(pipewire->core,
|
|
862
|
+ &pipewire->core_listener,
|
|
863
|
+ &core_events, pipewire);
|
|
864
|
+#else
|
752
|
865
|
pipewire->remote = pw_remote_new(pipewire->core, NULL, 0);
|
753
|
866
|
pw_remote_add_listener(pipewire->remote,
|
754
|
867
|
&pipewire->remote_listener,
|
... |
... |
@@ -777,6 +890,7 @@ weston_pipewire_init(struct weston_pipewire *pipewire) |
777
|
890
|
goto err;
|
778
|
891
|
}
|
779
|
892
|
}
|
|
893
|
+#endif
|
780
|
894
|
|
781
|
895
|
loop = wl_display_get_event_loop(pipewire->compositor->wl_display);
|
782
|
896
|
pipewire->loop_source =
|
... |
... |
@@ -786,12 +900,14 @@ weston_pipewire_init(struct weston_pipewire *pipewire) |
786
|
900
|
pipewire);
|
787
|
901
|
|
788
|
902
|
return 0;
|
|
903
|
+#if !PW_CHECK_VERSION(0, 2, 90)
|
789
|
904
|
err:
|
790
|
905
|
if (pipewire->remote)
|
791
|
906
|
pw_remote_destroy(pipewire->remote);
|
792
|
907
|
pw_loop_leave(pipewire->loop);
|
793
|
908
|
pw_loop_destroy(pipewire->loop);
|
794
|
909
|
return -1;
|
|
910
|
+#endif
|
795
|
911
|
}
|
796
|
912
|
|
797
|
913
|
static const struct weston_pipewire_api pipewire_api = {
|