You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
* Add PTP hardware timing support to MTL and FFmpeg TX paths
- Wire MTL_FLAG_PTP_ENABLE/PI/UNICAST_ADDR into both the direct MTL TX
path (src/mtl/mtl_tx.c) and the FFmpeg mtl_st20p muxer path
(src/ffmpeg/ffmpeg_tx.c), with a sync-notify callback logging
master_utc_offset/delta.
- app_context.h: add ptp_enable/ptp_pi/ptp_unicast fields.
- config_reader.c/.h: hardcode PTP defaults (enable=true, pi=true,
unicast=false) instead of reading them from JSON.
Verified on hardware (Intel I225-V/igc) with both enable_mtl_tx=true
and enable_mtl_tx=false builds: PTP enables cleanly (tx pacing ptp,
ptp_init pi controller) with no grandmaster present on the test
network (sync cnt 0, as expected).
* PTP: graceful AVOption handling and review-comment fixes
- ffmpeg_tx.c: treat AVERROR_OPTION_NOT_FOUND from PTP AVOptions as a
benign case so the app works whether or not the MTL plugin carries the
PTP patch (single INFO log instead of repeated WARNs)
- config_reader.h: use bool for ptp_enable/ptp_pi/ptp_unicast toggles
- app_context.h / mtl_tx.c: clarify PTP comments (used by both the direct
MTL TX pipeline and the FFmpeg avdevice path)
- config: add tx_gbrp12le_pf_8session.json (8-session pf test config)
* Make PTP disabled by default, configurable via JSON "ptp" block
PTP-paced TX requires a PTP grandmaster on the network. MTL's built-in
PTP client is slave-only and cannot elect itself grandmaster, so with no
grandmaster present the TX pacing clock never locks and transmission
stalls. Previously ptp_enable/ptp_pi were hardcoded to true in the config
reader, forcing this failure mode on every deployment.
PTP now defaults to disabled (MTL falls back to TSC-based pacing) and is
opted into via an optional top-level "ptp" block:
"ptp": { "enable": true, "pi": true, "unicast": false }
- Add extract_json_bool() helper to config_reader, mirroring
extract_json_int() (returns 1/0 for true/false, -1 when absent).
- Parse the optional "ptp" object for enable/pi/unicast; each key falls
back to false when omitted.
- Log "PTP disabled (default TSC-based TX pacing)" on the default path.
- Document the block in the config_reader schema comment and README,
including the grandmaster requirement and expected log output.
- Point tx_1session_12bit and tx_fullhd_single_session at the local NIC
BDF 0000:01:00.1 and correct the latter's source dimensions/format.
Verified on an 8-session 1080p yuv422p12le config: PTP disabled selects
"pacing way: tsc" and runs clean (0 errors, ~29.8 fps per session,
~1361 Mb/s aggregate); setting "enable": true selects "pacing way: ptp".
* ffmpeg: enable libswscale slice threading for format conversion
The decode->transport colour conversion ran single-threaded and dominated the
per-frame budget whenever the source resolution or pixel format differed from
the transport one (26 ms/frame for 1080p gbrp12le -> 4K yuv444p12le against a
33.3 ms budget at 30 fps), capping 4K30 at ~21 fps.
sws_scale() can never thread: it redirects to the context's single-threaded
first slice sub-context. Build the SwsContext with sws_alloc_context() so the
'threads' option can be set before sws_init_context(), and convert through
sws_scale_frame(), which is the only entry point reaching the slice threads.
sws_scale_frame() reallocates any destination frame with a NULL buf[0], so
yuv_frame moves from av_image_alloc() to av_frame_get_buffer(); the cleanup
path now frees the manual buffer only when the frame is not reference-counted.
Thread count is auto-selected as min(nproc/2, 8) - the conversion plateaus
past 8 threads - and can be overridden via tx_video.sws_threads.
Measured 4K30, 1080p gbrp12le source -> yuv444p12le transport:
before 20.94 fps 6562.18 Mb/s avg 6592.62 peak
after 29.93 fps 9379.15 Mb/s avg 9401.41 peak
* scripts: add benchmark harness with --src30/--src60 source pinning
benchmark.sh sweeps (resolution, fps, pixel format) combinations, parses the
MTL statistics from each run and emits a CSV plus an XLSX report.
--src30/--src60 pin the source clip per frame rate so a whole sweep can be run
against one input format instead of per-format native sources.
* tests: cover swscale slice threading changes
convert_frame_format: threaded sws_scale_frame path normalises the 0 return
to a row count; a destination without an AVBuffer and a partial source slice
must both fall back to sws_scale so the caller's buffer stays the conversion
target; repeated threaded conversions must not swap the destination plane.
close_ffmpeg_decoder: a reference-counted yuv_frame must be released by
av_frame_free alone - the previous unconditional av_freep(&data[0]) double
frees it.
tx_video.sws_threads: parsing, 0 = auto default, validation bounds and the
copy into the app context.
resolve_sws_threads is renamed ffmpeg_resolve_sws_threads and declared in the
decoder header so the override, the clamp to 64 and the auto range are
directly testable.
* Remove local benchmark tooling scripts
* Remove JSON-configurable sws_threads option
Drops tx_video.sws_threads from the config struct, parser, validation
and context-apply path. libswscale slice threading still runs via
ffmpeg_resolve_sws_threads() auto-detection.
* Bump application version to 1.0.0
* Remove obsolete sws_threads unit tests
The tx_video.sws_threads config option was removed, so the tests
asserting on cfg.sws_threads / app.sws_threads no longer compile.
* Drop unreachable sws_threads override, fix frame handler doc
The tx_video.sws_threads config option was removed, so app->sws_threads
was never populated and ffmpeg_resolve_sws_threads() always took the
auto path. Remove the dead field, the configured parameter and the
open_ffmpeg_decoder() pass-through so slice threading is auto-only.
Also correct the ffmpeg_frame_handler.c header: convert_frame_format()
uses sws_scale_frame only for reference-counted destinations with a
complete source frame, and otherwise falls back to sws_scale.
* Fix cppcheck knownConditionTrueFalse in extract_json_bool
cppcheck flagged the '(size_t)(end - pos) >= 4/5' guards as always false
because it could not relate the pointer distance to the preceding
'pos < end' loop. Bail out explicitly when pos reaches end and hoist the
remaining-byte count into a local, which keeps the same bounds checks
without the false positive.
---------
Co-authored-by: sunilnom <you@example.com>
0 commit comments