Skip to content

Commit 6621a7f

Browse files
committed
Add: gst/st40p: unify rx defaults and input formats
- add GST_MTL_DEFAULT_FRAMEBUFF_CNT to gst_mtl_common so every plugin can share the same fallback value; wire st20p/st30p/st40p RX to seed and consume it so ops structs pick up the common default when the element-specific property is 0 - relax the README ranges for st40p_rx frame buffers (0..G_MAXUINT) and note that rtp-ring-size is rejected unless it is a power of two, matching the new runtime check instead of auto-rounding values at startup - rework st40p_tx to expose an enum-based input-format property (raw UDW, RFC8331 packed, simplified RFC8331 produced by rx) while keeping parse-8331-meta as a deprecated alias for compatibility - implement the simplified RFC8331 parser so tx can ingest the 8-byte headers emitted by mtl_st40p_rx without repacking parity bits; switch the chain function to dispatch on the new enum and warn when DID/SDID are ignored - update ancillary validation helpers/tests to set input-format rather than the old boolean so CI and pytest continue to run in the intended mode
1 parent 496cf40 commit 6621a7f

File tree

8 files changed

+217
-56
lines changed

8 files changed

+217
-56
lines changed

ecosystem/gstreamer_plugin/README.md

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -409,11 +409,15 @@ The `mtl_st40p_tx` plugin supports all pad capabilities (the data is not checked
409409
| tx-sdid | uint | Secondary Data ID for the ancillary data. | 0 to 255 | 0 |
410410
| use-pts-for-pacing | gboolean | [User controlled timestamping offset](#233-pts-controlled-pacing) | TRUE/FALSE | FALSE |
411411
| pts-pacing-offset | uint | [User controlled timestamping offset](#233-pts-controlled-pacing) | 0 to G_MAXUINT | 0 |
412-
| parse-8331-meta | gboolean | Treat the input as rfc8331 payload data | TRUE/FALSE | FALSE |
412+
| input-format | enum | Encoding of incoming ANC buffers (`raw-udw`, `rfc8331-packed`, `rfc8331`) | enum | `raw-udw` |
413+
| parse-8331-meta | gboolean | **Deprecated.** Shortcut for `input-format=rfc8331-packed`. | TRUE/FALSE | FALSE |
413414
| max-combined-udw-size | uint | Maximum combined size of all user data words to send in one buffer | 0 to (20 * 255) | 20 * 255 |
414415
415-
> **Note:**
416-
> If `parse-8331-meta` is not enabled, only one ANC packet per frame is supported. It is recommended to limit the `max-combined-udw-size` if you are only using this option, since by default `max-combined-udw-size` is set to its maximum value.
416+
> **Note:**
417+
> - `raw-udw` streams carry a single ANC packet per frame without per-packet metadata; the element uses `tx-did`/`tx-sdid` for the outgoing headers, so keeping `max-combined-udw-size` small avoids oversized frames.
418+
> - `rfc8331-packed` expects the 10-bit RFC8331 payload (including headers) generated by external tools. This is the mode formerly controlled by `parse-8331-meta`.
419+
> - `rfc8331` accepts the simplified 8-bit representation produced by `mtl_st40p_rx output-format=rfc8331`, enabling metadata round-trips without re-packing parity bits.
420+
> - The `parse-8331-meta` flag remains available for backward compatibility but will be removed in a future release. Update existing pipelines to use `input-format=rfc8331-packed` (or `rfc8331`) to avoid breakage when the legacy boolean disappears.
417421
418422
#### 5.1.2. Example GStreamer Pipeline for Transmission
419423
@@ -442,7 +446,7 @@ The `mtl_st40p_rx` plugin supports all pad capabilities (the data is not checked
442446
443447
| Property Name | Type | Description | Range | Default Value |
444448
|---------------------|---------|-------------------------------------------------------------|-----------------------------|---------------|
445-
| rx-framebuff-cnt | uint | Number of frame buffers allocated in the pipeline | 2 to 16 | 3 |
449+
| rx-framebuff-cnt | uint | Number of frame buffers allocated in the pipeline | 0 to G_MAXUINT | 3 |
446450
| max-udw-size | uint | Maximum user-data word buffer size in bytes per frame | 1024 to 1,048,576 | 131,072 |
447451
| rtp-ring-size | uint | Size of the internal RTP ring (must be power of two) | 64 to 16,384 | 1,024 |
448452
| timeout | uint | Timeout in seconds for blocking frame retrieval | 0 to 300 | 60 |
@@ -454,6 +458,10 @@ header (C, line number, horizontal offset, S, stream number, DID, SDID, data cou
454458
its user data words so that downstream elements receive complete RFC8331 payloads. Selecting
455459
`raw-udw` delivers only the user-data words exactly as received on the wire.
456460
461+
> **Note:** `rtp-ring-size` values are validated at runtime. If the supplied number is not a power of
462+
> two the element fails to initialize, matching the behavior enforced inside
463+
> `gst_mtl_st40p_rx_start()`.
464+
457465
#### 5.2.2. Example GStreamer Pipeline for Reception
458466
459467
To run the `mtl_st40p_rx` plugin, use the following command:

ecosystem/gstreamer_plugin/gst_mtl_common.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#endif
3030

3131
#define DEFAULT_FRAMERATE 25
32+
#define GST_MTL_DEFAULT_FRAMEBUFF_CNT 3
3233

3334
enum {
3435
PROP_GENERAL_0,
@@ -65,6 +66,7 @@ typedef struct GeneralArgs {
6566
gchar dma_dev[MTL_PORT_MAX_LEN];
6667
gint log_level;
6768
gboolean enable_onboard_ptp;
69+
guint framebuff_cnt;
6870
} GeneralArgs;
6971

7072
typedef struct SessionPortArgs {

ecosystem/gstreamer_plugin/gst_mtl_st20p_rx.c

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,8 @@ static void gst_mtl_st20p_rx_class_init(Gst_Mtl_St20p_RxClass* klass) {
183183
gobject_class, PROP_ST20P_RX_FRAMEBUFF_NUM,
184184
g_param_spec_uint("rx-framebuff-num", "Number of framebuffers",
185185
"Number of framebuffers to be used for transmission.", 0,
186-
G_MAXUINT, 3, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
186+
G_MAXUINT, GST_MTL_DEFAULT_FRAMEBUFF_CNT,
187+
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
187188

188189
g_object_class_install_property(
189190
gobject_class, PROP_ST20P_RX_WIDTH,
@@ -251,7 +252,7 @@ static gboolean gst_mtl_st20p_rx_start(GstBaseSrc* basesrc) {
251252
if (src->framebuffer_num) {
252253
ops_rx.framebuff_cnt = src->framebuffer_num;
253254
} else {
254-
ops_rx.framebuff_cnt = 3;
255+
ops_rx.framebuff_cnt = src->generalArgs.framebuff_cnt;
255256
}
256257

257258
if (!gst_mtl_common_parse_pixel_format(src->pixel_format, &ops_rx.output_fmt)) {
@@ -310,6 +311,7 @@ static void gst_mtl_st20p_rx_init(Gst_Mtl_St20p_Rx* src) {
310311

311312
src->fps_n = DEFAULT_FRAMERATE;
312313
src->fps_d = 1;
314+
src->generalArgs.framebuff_cnt = GST_MTL_DEFAULT_FRAMEBUFF_CNT;
313315

314316
srcpad = gst_element_get_static_pad(element, "src");
315317
if (!srcpad) {
@@ -338,6 +340,11 @@ static void gst_mtl_st20p_rx_set_property(GObject* object, guint prop_id,
338340
break;
339341
case PROP_ST20P_RX_FRAMEBUFF_NUM:
340342
self->framebuffer_num = g_value_get_uint(value);
343+
if (self->framebuffer_num) {
344+
self->generalArgs.framebuff_cnt = self->framebuffer_num;
345+
} else {
346+
self->generalArgs.framebuff_cnt = GST_MTL_DEFAULT_FRAMEBUFF_CNT;
347+
}
341348
break;
342349
case PROP_ST20P_RX_WIDTH:
343350
self->width = g_value_get_uint(value);

ecosystem/gstreamer_plugin/gst_mtl_st30p_rx.c

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,8 @@ static void gst_mtl_st30p_rx_class_init(Gst_Mtl_St30p_RxClass* klass) {
157157
gobject_class, PROP_ST30P_RX_FRAMEBUFF_NUM,
158158
g_param_spec_uint("rx-framebuff-num", "Number of framebuffers",
159159
"Number of framebuffers to be used for transmission.", 0,
160-
G_MAXUINT, 3, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
160+
G_MAXUINT, GST_MTL_DEFAULT_FRAMEBUFF_CNT,
161+
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
161162

162163
g_object_class_install_property(
163164
gobject_class, PROP_ST30P_RX_CHANNEL,
@@ -237,7 +238,7 @@ static gboolean gst_mtl_st30p_rx_start(GstBaseSrc* basesrc) {
237238
if (src->framebuffer_num) {
238239
ops_rx->framebuff_cnt = src->framebuffer_num;
239240
} else {
240-
ops_rx->framebuff_cnt = 3;
241+
ops_rx->framebuff_cnt = src->generalArgs.framebuff_cnt;
241242
}
242243

243244
gst_mtl_common_copy_general_to_session_args(&(src->generalArgs), &(src->portArgs));
@@ -268,6 +269,8 @@ static void gst_mtl_st30p_rx_init(Gst_Mtl_St30p_Rx* src) {
268269
GstElement* element = GST_ELEMENT(src);
269270
GstPad* srcpad;
270271

272+
src->generalArgs.framebuff_cnt = GST_MTL_DEFAULT_FRAMEBUFF_CNT;
273+
271274
srcpad = gst_element_get_static_pad(element, "src");
272275
if (!srcpad) {
273276
GST_ERROR_OBJECT(src, "Failed to get src pad from child element");
@@ -288,6 +291,11 @@ static void gst_mtl_st30p_rx_set_property(GObject* object, guint prop_id,
288291
switch (prop_id) {
289292
case PROP_ST30P_RX_FRAMEBUFF_NUM:
290293
self->framebuffer_num = g_value_get_uint(value);
294+
if (self->framebuffer_num) {
295+
self->generalArgs.framebuff_cnt = self->framebuffer_num;
296+
} else {
297+
self->generalArgs.framebuff_cnt = GST_MTL_DEFAULT_FRAMEBUFF_CNT;
298+
}
291299
break;
292300
case PROP_ST30P_RX_CHANNEL:
293301
self->channel = g_value_get_uint(value);

ecosystem/gstreamer_plugin/gst_mtl_st40p_rx.c

Lines changed: 21 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -67,12 +67,7 @@
6767
#include <config.h>
6868
#endif
6969

70-
#include <arpa/inet.h> /* For htonl */
71-
#include <errno.h>
7270
#include <gst/gstinfo.h>
73-
#include <stdint.h>
74-
#include <stdio.h>
75-
#include <stdlib.h>
7671
#include <string.h>
7772

7873
#include "gst_mtl_st40p_rx.h"
@@ -99,14 +94,6 @@ static GType gst_mtl_st40p_rx_output_format_get_type(void) {
9994
GST_DEBUG_CATEGORY_STATIC(gst_mtl_st40p_rx_debug);
10095
#define GST_CAT_DEFAULT gst_mtl_st40p_rx_debug
10196

102-
/* Force verbose logging for all mtl* categories at plugin load time */
103-
static void gst_mtl_st40p_set_debug_thresholds(void) {
104-
gst_debug_category_set_threshold(gst_mtl_st40p_rx_debug, GST_LEVEL_LOG);
105-
gst_debug_set_threshold_for_name("mtl_st40p_tx", GST_LEVEL_LOG);
106-
gst_debug_set_threshold_for_name("mtl_common", GST_LEVEL_LOG);
107-
gst_debug_set_threshold_for_name("mtl", GST_LEVEL_LOG);
108-
}
109-
11097
#ifndef GST_LICENSE
11198
#define GST_LICENSE "LGPL"
11299
#endif
@@ -131,9 +118,8 @@ static void gst_mtl_st40p_set_debug_thresholds(void) {
131118
#define PACKAGE_VERSION "1.0"
132119
#endif
133120

134-
#define DEFAULT_RX_FRAMEBUFF_CNT 3
135-
#define DEFAULT_MAX_UDW_SIZE (128 * 1024) // 128KB default
136-
#define DEFAULT_RTP_RING_SIZE 1024 // power-of-two default
121+
#define DEFAULT_MAX_UDW_SIZE (128 * 1024) /* 128KB default */
122+
#define DEFAULT_RTP_RING_SIZE 1024 /* power-of-two default */
137123

138124
enum {
139125
PROP_ST40P_RX_FRAMEBUFF_CNT = PROP_GENERAL_MAX,
@@ -288,6 +274,10 @@ static gboolean gst_mtl_st40p_rx_serialize_frame(Gst_Mtl_St40p_Rx* src,
288274
}
289275
}
290276

277+
static gboolean gst_mtl_st40p_is_power_of_two(uint32_t value) {
278+
return value && ((value & (value - 1)) == 0);
279+
}
280+
291281
static void gst_mtl_st40p_rx_class_init(Gst_Mtl_St40p_RxClass* klass) {
292282
GObjectClass* gobject_class;
293283
GstElementClass* gstelement_class;
@@ -305,13 +295,12 @@ static void gst_mtl_st40p_rx_class_init(Gst_Mtl_St40p_RxClass* klass) {
305295
gstbasesrc_class->create = GST_DEBUG_FUNCPTR(gst_mtl_st40p_rx_create);
306296

307297
gst_mtl_common_init_general_arguments(gobject_class);
308-
gst_mtl_st40p_set_debug_thresholds();
309298

310299
g_object_class_install_property(
311300
gobject_class, PROP_ST40P_RX_FRAMEBUFF_CNT,
312301
g_param_spec_uint("rx-framebuff-cnt", "RX Frame Buffer Count",
313-
"Number of frame buffers for RX pipeline", 2, 16,
314-
DEFAULT_RX_FRAMEBUFF_CNT,
302+
"Number of frame buffers for RX pipeline", 0, G_MAXUINT,
303+
GST_MTL_DEFAULT_FRAMEBUFF_CNT,
315304
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
316305

317306
g_object_class_install_property(
@@ -357,7 +346,8 @@ static void gst_mtl_st40p_rx_class_init(Gst_Mtl_St40p_RxClass* klass) {
357346
}
358347

359348
static void gst_mtl_st40p_rx_init(Gst_Mtl_St40p_Rx* src) {
360-
src->rx_framebuff_cnt = DEFAULT_RX_FRAMEBUFF_CNT;
349+
src->generalArgs.framebuff_cnt = GST_MTL_DEFAULT_FRAMEBUFF_CNT;
350+
src->rx_framebuff_cnt = GST_MTL_DEFAULT_FRAMEBUFF_CNT;
361351
src->max_udw_size = DEFAULT_MAX_UDW_SIZE;
362352
src->rtp_ring_size = DEFAULT_RTP_RING_SIZE;
363353
src->timeout_s = 60;
@@ -385,6 +375,11 @@ static void gst_mtl_st40p_rx_set_property(GObject* object, guint prop_id,
385375
switch (prop_id) {
386376
case PROP_ST40P_RX_FRAMEBUFF_CNT:
387377
src->rx_framebuff_cnt = g_value_get_uint(value);
378+
if (src->rx_framebuff_cnt) {
379+
src->generalArgs.framebuff_cnt = src->rx_framebuff_cnt;
380+
} else {
381+
src->generalArgs.framebuff_cnt = GST_MTL_DEFAULT_FRAMEBUFF_CNT;
382+
}
388383
break;
389384
case PROP_ST40P_RX_MAX_UDW_SIZE:
390385
src->max_udw_size = g_value_get_uint(value);
@@ -457,27 +452,19 @@ static gboolean gst_mtl_st40p_rx_start(GstBaseSrc* basesrc) {
457452
}
458453

459454
ops_rx.name = "st40p_rx";
460-
ops_rx.framebuff_cnt = src->rx_framebuff_cnt;
455+
ops_rx.framebuff_cnt =
456+
src->rx_framebuff_cnt ? src->rx_framebuff_cnt : src->generalArgs.framebuff_cnt;
461457
ops_rx.max_udw_buff_size = src->max_udw_size;
462458
ops_rx.flags = 0; /* Use non-blocking mode - blocking causes preroll timeout */
463459

464460
GST_DEBUG_OBJECT(src, "RX START: framebuff_cnt=%d, max_udw_buff_size=%d",
465461
ops_rx.framebuff_cnt, ops_rx.max_udw_buff_size);
466462

467-
/* set rtp ring size ensuring power-of-two */
468463
uint32_t ring_sz = src->rtp_ring_size ? src->rtp_ring_size : DEFAULT_RTP_RING_SIZE;
469-
if ((ring_sz & (ring_sz - 1)) != 0) {
470-
uint32_t v = ring_sz;
471-
v--;
472-
v |= v >> 1;
473-
v |= v >> 2;
474-
v |= v >> 4;
475-
v |= v >> 8;
476-
v |= v >> 16;
477-
v++;
478-
GST_WARNING_OBJECT(src, "RX START: rtp-ring-size %u not power of two, using %u",
479-
ring_sz, v);
480-
ring_sz = v;
464+
/* ST40 pipeline requires ring size to be 2^n; fail fast on invalid input. */
465+
if (!gst_mtl_st40p_is_power_of_two(ring_sz)) {
466+
GST_ERROR_OBJECT(src, "RX START: rtp-ring-size %u must be a power of two", ring_sz);
467+
return FALSE;
481468
}
482469
ops_rx.rtp_ring_size = ring_sz;
483470

0 commit comments

Comments
 (0)