Skip to content

Commit fc11c71

Browse files
committed
Refactor: Promote ST40 pipeline out of experimental tree
- relocate the st40 pipeline headers/sources into lib/src/st2110/pipeline and export the API from include/st40_pipeline_api.h - update app meson glue, pipeline samples, and shared sample utilities to point at the promoted API - refresh docs/run + doc/design along with app/sample/README.md to document the ST40 pipeline workflow in one place - wire the meson include lists and new rx length guard so ancillary rx stays robust after the move
1 parent f1b48c0 commit fc11c71

File tree

15 files changed

+85
-108
lines changed

15 files changed

+85
-108
lines changed

app/meson.build

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,6 @@ libpthread = cc.find_library('pthread', required : true)
2525
libjson_c = dependency('json-c', required : true)
2626
libpcap = dependency('pcap', required: true)
2727

28-
app_common_includes = include_directories('..', '../include')
29-
3028
libsdl2 = dependency('sdl2', required: false)
3129
if libsdl2.found()
3230
add_global_arguments('-DAPP_HAS_SDL2', language : 'c')
@@ -258,7 +256,6 @@ executable('TxSt30PipelineSample', pipeline_tx_st30_sample_sources,
258256
executable('TxSt40PipelineSample', pipeline_tx_st40_sample_sources,
259257
c_args : app_c_args,
260258
link_args: app_ld_args,
261-
include_directories: app_common_includes,
262259
# asan should be always the first dep
263260
dependencies: [asan_dep, mtl, libpthread, ws2_32_dep, mman_dep]
264261
)

app/sample/README.md

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,58 @@ The dir include the simple sample code for how to develop application quickly ba
4242
./build/app/RxSt22PipelineSample --p_port 0000:af:01.1 --p_sip 192.168.75.22 --p_rx_ip 239.168.75.22
4343
```
4444

45+
### 2.1. ST40 ancillary pipeline samples
46+
47+
`TxSt40PipelineSample` and `RxSt40PipelineSample` live in this directory (see `tx_st40_pipeline_sample.c` / `rx_st40_pipeline_sample.c`) and are built automatically by `./build.sh`. They leverage the same CLI foundation as the other pipeline samples, so familiar options such as `--p_port`, `--udp_port`, `--sessions_cnt`, `--multi_inc_addr`, `--ext_frame`, and destination MAC overrides behave identically.
48+
49+
#### Tx workflow
50+
51+
1. Prepare (or reuse) an ancillary payload. Any binary file works because frames are looped forever:
52+
```bash
53+
head -c 4096 /dev/urandom > /tmp/anc_payload.bin
54+
```
55+
2. Launch the TX sample. The example below keeps every frame below the 255-byte UDW limit returned by `st40p_tx_max_udw_buff_size()` so that each payload fits into a single RFC 8331 RTP packet.
56+
```bash
57+
./build/app/TxSt40PipelineSample \
58+
--p_port 0000:af:01.0 \
59+
--p_tx_ip 239.1.1.1 \
60+
--p_sip 192.168.96.2 \
61+
--udp_port 20000 \
62+
--payload_type 40 \
63+
--sessions_cnt 1 \
64+
--tx_url /tmp/anc_payload.bin \
65+
--ext_frame
66+
```
67+
68+
Helpful switches:
69+
70+
- `--ext_frame` keeps the sample in user-supplied buffer mode, mirroring how most applications integrate the pipeline API.
71+
- `--multi_inc_addr` increments the destination multicast address per session instead of the UDP port so you can spin up multiple ancillary streams on one NIC queue.
72+
73+
#### Rx workflow
74+
75+
Match the TX parameters on the receiver. Enabling `--rx_dump` writes a human-readable metadata block per frame to `--rx_url` (`foo.txt_0`, `_1`, … if multiple sessions are active):
76+
77+
```bash
78+
./build/app/RxSt40PipelineSample \
79+
--p_port 0000:af:01.0 \
80+
--p_rx_ip 239.1.1.1 \
81+
--p_sip 192.168.96.2 \
82+
--udp_port 20000 \
83+
--payload_type 40 \
84+
--sessions_cnt 1 \
85+
--rx_url /tmp/anc_dump.txt \
86+
--rx_dump
87+
```
88+
89+
The runtime log summarizes the number of metadata entries and UDW bytes received per frame, while the dump files capture DID/SDID/line information followed by the raw payload so you can diff TX/RX easily.
90+
91+
#### Troubleshooting and USDT hooks
92+
93+
- Use `--rx_dump`/`--tx_url` first to confirm that metadata completes the round trip.
94+
- When `st40_total_pkts` exceeds 1, the payload overflowed the 255-byte UDW buffer; trim the input file or drop the session count on slower links.
95+
- For end-to-end tracing, follow the ST40P probe examples in `doc/usdt.md` §2.5.6 (they cover `usdt::st40p:*` plus `usdt::sys:log_msg` combinations) instead of keeping scripts here.
96+
4597
## 3. Forward pipeline samples
4698

4799
[rx_st20p_tx_st22p_fwd.c](fwd/rx_st20p_tx_st22p_fwd.c): A demo application which receive a st20 stream and output as st22 compressed stream with logo rendering.

app/sample/rx_st40_pipeline_sample.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@
22
* Copyright(c) 2025 Intel Corporation
33
*/
44

5-
#include <mtl/experimental/st40_pipeline_api.h>
6-
75
#include "sample_util.h"
86

97
#define ST40P_SAMPLE_MAX_UDW_SIZE 2048

app/sample/sample_util.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include <inttypes.h>
1111
#include <mtl/experimental/st20_combined_api.h>
1212
#include <mtl/st30_pipeline_api.h>
13+
#include <mtl/st40_pipeline_api.h>
1314
#include <mtl/st_convert_api.h>
1415
#include <mtl/st_pipeline_api.h>
1516
#include <pthread.h>

app/sample/tx_st40_pipeline_sample.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@
22
* Copyright(c) 2025 Intel Corporation
33
*/
44

5-
#include <mtl/experimental/st40_pipeline_api.h>
6-
75
#include "sample_util.h"
86

97
#define ST40P_SAMPLE_MAX_UDW_SIZE 255

doc/design.md

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -335,6 +335,22 @@ Sample application code can be find in [tx_st20_pipeline_sample.c](../app/sample
335335
By default, the `st20p_tx_get_frame` and `st20p_rx_get_frame` functions operate in non-blocking mode, which means the function call will immediately return `NULL` if no frame is available.
336336
To switch to blocking mode, where the call will wait until a frame is ready for application use or one second timeout occurs, you must enable the `ST20P_TX_FLAG_BLOCK_GET` or `ST20P_RX_FLAG_BLOCK_GET` flag respectively during the session creation stage, and application can use `st20p_tx_wake_block`/`st20p_rx_wake_block` to wake up the waiting directly.
337337
338+
#### 6.3.1. Ancillary (ST40) pipeline
339+
340+
The same pipeline abstraction is now available for ancillary-only flows through `st40_pipeline_api.h`. It keeps the zero-copy RFC 8331 payload path but hides scheduler registration, frame queues, and pacing details behind the familiar get/put contract so applications only need to implement:
341+
342+
```c
343+
st40p_tx_get_frame
344+
st40p_tx_put_frame
345+
st40p_rx_get_frame
346+
st40p_rx_put_frame
347+
```
348+
349+
- **TX pipeline (`st40p_tx_*`)** wraps the lower-level `st40_tx_*` APIs while honoring redundancy, user timestamps, and user-managed frame buffers (for example when `ST40P_TX_FLAG_EXT_FRAME` is enabled). The helper also exposes the maximum user data word (UDW) size via `st40p_tx_max_udw_buff_size()` so that producers can pack metadata deterministically.
350+
- **RX pipeline (`st40p_rx_*`)** assembles ancillary packets into user buffers and can optionally dump metadata/UDW buffers directly to files for debugging through `st40p_rx_set_dump`. Each RX callback receives both the metadata blocks and the captured payload, mirroring the TX layout to simplify round-trip validation.
351+
352+
Reference implementations live in `app/sample/tx_st40_pipeline_sample.c` and `app/sample/rx_st40_pipeline_sample.c`. They reuse the shared `sample_util` CLI so you can swap between ST20/22/30/40 pipelines with identical arguments while testing pacing, redundancy, and USDT probes.
353+
338354
### 6.4. ST22 support
339355

340356
The support for ST 2110-22 JPEG XS can be categorized into two modes: ST 2110-22 raw codestream mode and ST 2110-22 pipeline mode. The pipeline mode leverages an MTL plugin to handle the decoding/encoding between the raw video buffer and the codestream.
@@ -498,21 +514,6 @@ For instance, with a 1080i50 format, you should use the following session parame
498514

499515
For transmission (TX), users can specify whether the current field is the first or second by using the `second_field` flag within the `struct st40_tx_frame_meta`. For reception (RX), RTP passthrough mode is the only supported, it's application's duty to check the if it's the first or second by inspecting the F bits in rfc8331 header.
500516

501-
### 6.18. ST40 pipeline mode
502-
503-
For applications that prefer the simplified pipeline abstraction (similar to `st20p`/`st30p`) MTL now exposes `st40_pipeline_api.h`. Pipeline mode keeps the zero-copy ancillary payload path but bundles common plumbing – scheduler registration, frame queues, tasklet threads, and pacing – behind a single handle so that an app only needs to implement the `get_next_frame`/`notify_frame_done` (TX) or `notify_frame_ready` (RX) callbacks.
504-
505-
- **TX pipeline (`st40p_tx_*`)** – wraps `st40_tx_create` under the hood while honoring flags such as redundant ports, user timestamps, and external frame ownership. The helper also surfaces the UDW/metadata buffers used by ancillary producers.
506-
- **RX pipeline (`st40p_rx_*`)** – converts incoming ancillary packets into frame callbacks and optionally dumps metadata/UDW buffers directly to user memory.
507-
508-
Reference code lives in `app/sample/tx_st40_pipeline_sample.c` and `app/sample/rx_st40_pipeline_sample.c`. These samples demonstrate how to:
509-
510-
1. Parse the shared sample CLI (`sample_util.c`) to configure multicast, payload-type, and redundant ports.
511-
2. Register pipeline callbacks that acquire frames, populate UDW/metas, and release them back to MTL.
512-
3. Enable optional debug paths such as on-disk metadata dumps or user pacing hooks.
513-
514-
Use the pipeline helpers whenever you need to stand up ancillary-only senders/receivers quickly without wiring the lower-level ST40 transport APIs manually.
515-
516517
## 7. Misc
517518

518519
### 7.1. Logging

doc/run.md

Lines changed: 0 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -364,80 +364,6 @@ packet egresses from the sender.
364364
--force_numa <id> : debug option, force the NIC port numa id instead of reading from PCIE topology
365365
```
366366
367-
### 5.4. ST40 pipeline samples
368-
369-
The repository ships standalone ancillary-only apps that exercise the experimental ST40 pipeline helpers. They live under `app/sample/` and are built automatically by `./build.sh`:
370-
371-
- `build/app/TxSt40PipelineSample`
372-
- `build/app/RxSt40PipelineSample`
373-
374-
Both apps reuse `sample_util.c`, so the CLI syntax mirrors the other sample binaries (`--p_port`, `--udp_port`, `--sessions_cnt`, `--multi_inc_addr`, etc.).
375-
376-
#### 5.4.1. Tx sample workflow
377-
378-
1. Build the binaries and (optionally) prepare a deterministic ANC payload. Any binary file works; the sample loops the buffer forever. For a quick test:
379-
```bash
380-
head -c 4096 /dev/urandom > /tmp/anc_payload.bin
381-
```
382-
2. Launch the TX sample (single-port multicast example shown). The sample pins the UDW payload to the maximum user buffer returned by `st40p_tx_max_udw_buff_size()`—currently 255 bytes—so every frame fits inside one RFC 8331 RTP packet. Larger input files are chunked per frame automatically.
383-
```bash
384-
./build/app/TxSt40PipelineSample \
385-
--p_port 0000:af:01.0 \
386-
--p_tx_ip 239.1.1.1 \
387-
--p_sip 192.168.96.2 \
388-
--udp_port 20000 \
389-
--payload_type 40 \
390-
--sessions_cnt 1 \
391-
--tx_url /tmp/anc_payload.bin \
392-
--ext_frame
393-
```
394-
395-
Key behaviors:
396-
397-
- `--ext_frame` keeps the sample in "user supplied frame" mode, matching how most applications integrate the pipeline API.
398-
- When `--multi_inc_addr` is present, each session increments the destination multicast address instead of the UDP port so you can fan out multiple streams on a single port.
399-
- Destination MAC overrides (`--p_tx_dst_mac`/`--r_tx_dst_mac`) work the same way as the other apps if you need explicit L2 addressing.
400-
401-
#### 5.4.2. Rx sample workflow
402-
403-
Run the RX sample with matching network parameters. Enabling `--rx_dump` writes one human-readable metadata report per frame to `--rx_url` (`foo.txt_0`, `_1`, … when multiple sessions are active):
404-
405-
```bash
406-
./build/app/RxSt40PipelineSample \
407-
--p_port 0000:af:01.0 \
408-
--p_rx_ip 239.1.1.1 \
409-
--p_sip 192.168.96.2 \
410-
--udp_port 20000 \
411-
--payload_type 40 \
412-
--sessions_cnt 1 \
413-
--rx_url /tmp/anc_dump.txt \
414-
--rx_dump
415-
```
416-
417-
The log stream shows per-frame metadata counts plus the number of user data words (UDW) that landed in the buffer. The dump file records DID/SDID/line info followed by the raw payload bytes so you can diff TX/RX easily.
418-
419-
#### 5.4.3. Troubleshooting and USDT hooks
420-
421-
- Use `--rx_dump`/`--tx_url` first to confirm that metadata makes the round trip.
422-
- When `st40_total_pkts` exceeds 1, it means the payload exceeded 255 bytes; trim the input file or lower `--sessions_cnt` on slow links.
423-
- Attach `bpftrace` to the USDT probes to see real-time pipeline events:
424-
```bash
425-
sudo BPFTRACE_STRLEN=200 bpftrace -e '
426-
usdt::st40p:rx_frame_available {
427-
printf("%s rx%u: frame %u meta=%u\n", strftime("%H:%M:%S", nsecs), arg0, arg1, arg2);
428-
}
429-
usdt::st40p:rx_frame_put {
430-
printf("%s rx%u: frame %u returned\n", strftime("%H:%M:%S", nsecs), arg0, arg1);
431-
}
432-
usdt::st40p:rx_frame_dump {
433-
printf("%s rx%u: dump meta=%u bytes=%u -> %s\n",
434-
strftime("%H:%M:%S", nsecs), arg0, arg2, arg3, str(arg1));
435-
}
436-
' -p $(pidof RxSt40PipelineSample)
437-
```
438-
- `usdt::sys:log_msg` mirrors the built-in status dump; attach to it when you want the sample to spit out scheduler stats without touching its log level.
439-
440-
These executables are the quickest way to validate port configuration, payload sizing, and USDT instrumentation before embedding the ST40 pipeline API into your production app.
441367
442368
## 6. Tests
443369

include/meson.build

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
mtl_header_files = files('mtl_api.h', 'st_api.h', 'st_convert_api.h', 'st_convert_internal.h',
55
'st_pipeline_api.h', 'st20_api.h', 'st30_api.h', 'st40_api.h', 'st41_api.h',
66
'mudp_api.h', 'mudp_sockfd_api.h', 'mudp_sockfd_internal.h', 'mtl_lcore_shm_api.h',
7-
'mtl_sch_api.h', 'st30_pipeline_api.h')
7+
'mtl_sch_api.h', 'st30_pipeline_api.h', 'st40_pipeline_api.h')
88

99
if is_windows
1010
mtl_header_files += files('mudp_win.h')
@@ -13,8 +13,7 @@ endif
1313
install_headers(mtl_header_files, subdir : meson.project_name())
1414

1515
# experimental features
16-
mtl_experimental_header_files = files('experimental/st20_combined_api.h',
17-
'experimental/st40_pipeline_api.h')
16+
mtl_experimental_header_files = files('experimental/st20_combined_api.h')
1817

1918
experimental_header_install_path = meson.project_name() + '/experimental'
2019

lib/src/st2110/experimental/meson.build

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,4 @@
33

44
sources += files(
55
'st20_redundant_combined_rx.c',
6-
'st40_pipeline_tx.c',
7-
'st40_pipeline_rx.c',
86
)

0 commit comments

Comments
 (0)