Skip to content

Commit a8300a1

Browse files
committed
Convert MSFTS example to Publisher API
1 parent 57c45de commit a8300a1

18 files changed

Lines changed: 2649 additions & 31 deletions

CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -352,6 +352,8 @@ target_link_libraries(openmoq-publisher-auth-example PRIVATE openmoq_publisher_l
352352

353353
include(CTest)
354354

355+
add_subdirectory(examples/msfts-publisher)
356+
355357
if(OPENMOQ_BUILD_TESTS)
356358
add_executable(openmoq-publisher-packaging-tests
357359
tests/cmaf_segmenter_test.cpp

README.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,24 @@ OPENMOQ_PICOQUIC_TRACE=1 ./build/openmoq-publisher \
7979
--paced
8080
```
8181

82+
Publish a packet-aligned MPEG-2 TS or M2TS file with the MSFTS example:
83+
84+
```bash
85+
./build/examples/msfts-publisher/openmoq-publisher-msfts-example \
86+
--input sample.m2ts \
87+
--endpoint https://relay.example.com:443/moq \
88+
--namespace media.msfts \
89+
--track transport \
90+
--draft 17
91+
```
92+
93+
The example uses the public `Publisher::publish_live_objects(...)` API. It
94+
discovers PAT/PMT data, selects one program, filters unrelated PIDs, and emits
95+
the caller-supplied `"m2ts"` catalog required by the text draft in
96+
`examples/msfts-publisher/docs/`. Add `--program NUMBER` to select a specific
97+
program, `--packets-per-object COUNT` to change object sizing, or `--insecure`
98+
only for a relay whose certificate is intentionally untrusted.
99+
82100
Live ingest examples (choose one path):
83101

84102
1. SRT ingest path (`--live-source srt`)

docs/build.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,16 @@ The build also produces the reusable publisher API static library:
2929

3030
The CMake target remains `openmoq_publisher_lib`, so projects that include this repository with `add_subdirectory(...)` should link that target. Projects that consume the raw archive directly should add `include/` to their include path and link the same transport dependencies used by the build, especially picoquic, picotls, OpenSSL, and platform socket libraries when picoquic transport support is enabled.
3131

32+
The default build also compiles the MSFTS Publisher API example:
33+
34+
```bash
35+
cmake --build build --target openmoq-publisher-msfts-example
36+
./build/examples/msfts-publisher/openmoq-publisher-msfts-example --help
37+
```
38+
39+
Its CMake target links only `openmoq_publisher_lib`; it does not consume moq5
40+
or picoquic APIs directly.
41+
3242
## Build with Local Picoquic and Picotls
3343

3444
By default, CMake looks for:
@@ -98,6 +108,10 @@ reviewed, the backend is selectable:
98108
is independent of which backend is *selected*.
99109
- **`-DOPENMOQ_USE_LIBMOQ_PUBLISHER=ON`** — the production `Publisher` routes
100110
batch, live stdin, live SRT, and `LiveObjectSource` publishing through libmoq.
111+
- **Caller-supplied catalog exception** — a `LiveObjectSource` using
112+
`LiveCatalogMode::kSourceObject` is routed through `MoqtSession` in either
113+
configuration. This preserves catalog formats such as MSFTS `"m2ts"` that
114+
libmoq's current RAW/CMAF media sender cannot author.
101115
- **default (`OFF`)** — publishing stays on the legacy MoqtSession path.
102116

103117
Configure-time output reports both, e.g.:

docs/publisher-api.md

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,31 @@ the payload bytes to send. `object_id == 0` starts a group (and is treated as a
256256
sync point); `final_in_subgroup && subgroup_contains_group_largest` closes the
257257
group.
258258

259+
### Caller-supplied catalogs
260+
261+
Set `LiveCatalogMode::kSourceObject` when the source must provide a catalog
262+
whose format cannot be generated from `LiveTrack` media metadata:
263+
264+
```cpp
265+
openmoq::publisher::LiveObjectSource source;
266+
source.tracks = {
267+
openmoq::publisher::LiveTrack{.track_name = "catalog"},
268+
openmoq::publisher::LiveTrack{.track_name = "transport"},
269+
};
270+
source.next_object = next_catalog_then_media_object;
271+
source.catalog_mode =
272+
openmoq::publisher::LiveCatalogMode::kSourceObject;
273+
```
274+
275+
This mode requires exactly one track named `catalog`, at least one non-catalog
276+
track, and a non-empty catalog as the first returned object. The Publisher uses
277+
the `MoqtSession` object path for such a source even when the libmoq backend is
278+
selected, because libmoq currently authors catalogs only for its RAW and CMAF
279+
media packaging. The MSFTS example under `examples/msfts-publisher` uses this
280+
mode for `"m2ts"` packaging and supplies packet-size, program/PID, PSI interval,
281+
random-access, timestamp-mode, and Base64 PAT/PMT `initData` fields from its
282+
local text draft.
283+
259284
**Demand gating (lazy relays).** When the libmoq backend is selected, the publish
260285
path waits for at least one downstream media subscriber before producing media —
261286
a lazy relay forwards a SUBSCRIBE only when a player subscribes. Until then
@@ -270,9 +295,10 @@ interrupted, and the call returns success. For stdin specifically, cancellation
270295
observed once the current blocking read returns.
271296

272297
> **Legacy note:** bare `LiveTrack{.track_name = ...}` entries with no media
273-
> metadata (a generic "events"-style object track) are **legacy-only**. They are
274-
> rejected on the libmoq path with a clear error; to publish such tracks you must
275-
> inject a custom `TransportFactory`, which forces the older MoqtSession transport.
298+
> metadata (a generic "events"-style object track) are rejected on the normal
299+
> libmoq-generated-catalog path. Inject a custom `TransportFactory` for generic
300+
> legacy object tracks, or use `LiveCatalogMode::kSourceObject` only when the
301+
> source genuinely supplies the required catalog object.
276302
277303
The fragmented MP4 `publish_live(...)` API remains the default live publishing
278304
path for media ingest.

docs/testing.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@ This covers:
2121
- draft-16 LL-DASH await-subscribe behavior with catalog plus multiple FFmpeg-style representation paths
2222
- multitrack subscribe serving in publish-plan/media-time order rather than draining one track at a time
2323
- paced send scheduling against fragment media timestamps
24+
- caller-supplied catalog declaration, ordering, and backend-routing validation
25+
- MSFTS 188-byte TS and 192-byte M2TS detection, program filtering, rewritten
26+
PAT/PMT `initData`, catalog fields, whole-packet object payloads, and invalid
27+
partial-packet rejection
2428
- QUIC varint boundary coverage
2529

2630
Publish-plan numbering notes:
@@ -64,6 +68,23 @@ track/object translation, readiness and demand waits, bounded backpressure
6468
retries, cancellation, and live-object metadata validation. CMake also detects
6569
moq5 at `../libmoq`, `third_party/moq5`, and `thirdparty/moq5`.
6670

71+
## MSFTS Example Tests
72+
73+
Build and run the focused MSFTS Publisher API coverage with:
74+
75+
```bash
76+
cmake --build build --target \
77+
openmoq-publisher-msfts-example \
78+
openmoq-publisher-msfts-tests
79+
ctest --test-dir build -R openmoq-publisher-msfts-tests --output-on-failure
80+
./build/examples/msfts-publisher/openmoq-publisher-msfts-example --help
81+
```
82+
83+
The tests use synthetic transport streams for both supported source-packet
84+
sizes and do not require a relay. A live relay run is a separate
85+
interoperability check and should use a real subscriber before claiming media
86+
delivery.
87+
6788
## Picoquic Loopback Smoke Test
6889

6990
When you want to exercise the live QUIC path locally, enable the smoke test target:
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
add_executable(openmoq-publisher-msfts-example
2+
main.cpp
3+
msfts_options.cpp
4+
msfts_source.cpp
5+
)
6+
target_link_libraries(openmoq-publisher-msfts-example PRIVATE openmoq_publisher_lib)
7+
8+
if(OPENMOQ_BUILD_TESTS)
9+
add_executable(openmoq-publisher-msfts-tests
10+
tests/msfts_source_test.cpp
11+
msfts_options.cpp
12+
msfts_source.cpp
13+
)
14+
target_link_libraries(openmoq-publisher-msfts-tests PRIVATE openmoq_publisher_lib)
15+
add_test(NAME openmoq-publisher-msfts-tests COMMAND openmoq-publisher-msfts-tests)
16+
endif()

0 commit comments

Comments
 (0)