Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions include/app_context.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,13 @@ struct dvledtx_context {
bool force_dhcp;
int test_time_s;

/* PTP hardware timing (built-in MTL PTP client, FFmpeg mtl_st20p muxer path).
* See MTL_FLAG_PTP_* in mtl_api.h. Only used when ENABLE_MTL_TX is NOT set
* (the FFmpeg avdevice TX path); passed through as AVOptions in ffmpeg_tx.c. */
bool ptp_enable; /* enable built-in PTP client + PTP-paced TX */
bool ptp_pi; /* use PI controller for built-in PTP (PF only) */
bool ptp_unicast; /* use unicast address for PTP_DELAY_REQ message */

/* Per-session network + crop config — dynamically allocated, st20p_sessions elements */
struct tx_session_net* session_net;

Expand Down
6 changes: 6 additions & 0 deletions include/util/config_reader.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,12 @@ struct dvledtx_config {
/* optional log file path (empty = console only) */
char log_file[256];

/* PTP hardware timing (built-in MTL PTP client) — hardcoded in config_reader.c,
* not configurable via JSON. */
int ptp_enable;
int ptp_pi;
int ptp_unicast;

/* tx_sessions array — dynamically allocated */
int session_count;
int session_cap; /* allocated capacity */
Expand Down
12 changes: 12 additions & 0 deletions src/ffmpeg/ffmpeg_tx.c
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,18 @@ int open_ffmpeg_tx(struct st20p_tx_ctx* ctx) {
ret = av_opt_set_int(ctx->out_fmt_ctx->priv_data, "payload_type", (int64_t)payload_type, 0);
if (ret < 0) LOG_WARN("ST20P TX(%d): av_opt_set_int payload_type failed (ret=%d)", ctx->idx, ret);

/* PTP hardware timing (built-in MTL PTP client). Only takes effect on the
* session that actually calls mtl_init() (mtl_dev_get()'s singleton shared
* handle) — harmless to set on every session. */
if (ctx->app->ptp_enable) {
ret = av_opt_set_int(ctx->out_fmt_ctx->priv_data, "ptp_enable", 1, 0);
if (ret < 0) LOG_WARN("ST20P TX(%d): av_opt_set_int ptp_enable failed (ret=%d)", ctx->idx, ret);
ret = av_opt_set_int(ctx->out_fmt_ctx->priv_data, "ptp_pi", ctx->app->ptp_pi ? 1 : 0, 0);
if (ret < 0) LOG_WARN("ST20P TX(%d): av_opt_set_int ptp_pi failed (ret=%d)", ctx->idx, ret);
ret = av_opt_set_int(ctx->out_fmt_ctx->priv_data, "ptp_unicast", ctx->app->ptp_unicast ? 1 : 0, 0);
if (ret < 0) LOG_WARN("ST20P TX(%d): av_opt_set_int ptp_unicast failed (ret=%d)", ctx->idx, ret);
}

/* Multi-NIC: The FFmpeg mtl_st20p plugin's mtl_dev_get() uses a singleton
* shared MTL handle — the FIRST avformat_write_header() call creates the
* MTL instance via mtl_init(), which initialises DPDK EAL. EAL cannot be
Expand Down
19 changes: 19 additions & 0 deletions src/mtl/mtl_tx.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
#include "app_context.h"
#include "core/session_manager.h"
#include "util/logger.h"
#include <inttypes.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
Expand Down Expand Up @@ -198,13 +199,31 @@ void mtl_copy_crop_to_frame(struct st_frame* dst, const AVFrame* src,
*
* mtl_tx_uninit() — release the MTL library instance.
*/
/* PTP hardware timing (built-in MTL PTP client, direct MTL TX path).
* See MTL_FLAG_PTP_* in mtl_api.h. Mirrors the AVOption-driven callback
* wired for the FFmpeg muxer path in the external ffmpeg_plugin repo. */
static void mtl_tx_ptp_sync_notify_cb(void* priv, struct mtl_ptp_sync_notify_meta* meta) {
(void)priv;
LOG_INFO("PTP sync: master_utc_offset=%d delta=%" PRId64 "ns",
meta->master_utc_offset, meta->delta);
}

int mtl_tx_init(session_manager_t* manager, struct dvledtx_context* app) {
struct mtl_init_params mtl_params;
memset(&mtl_params, 0, sizeof(mtl_params));

mtl_params.flags = MTL_FLAG_BIND_NUMA | MTL_FLAG_DEV_AUTO_START_STOP;
mtl_params.num_ports = app->nic_count;

if (app->ptp_enable) {
mtl_params.flags |= MTL_FLAG_PTP_ENABLE;
mtl_params.pacing = ST21_TX_PACING_WAY_PTP;
if (app->ptp_pi) mtl_params.flags |= MTL_FLAG_PTP_PI;
if (app->ptp_unicast) mtl_params.flags |= MTL_FLAG_PTP_UNICAST_ADDR;
mtl_params.ptp_sync_notify = mtl_tx_ptp_sync_notify_cb;
LOG_INFO("MTL init: PTP enabled (pi=%d unicast=%d)", app->ptp_pi, app->ptp_unicast);
}

/* Count sessions assigned to each NIC for queue allocation */
int* sessions_per_nic = calloc((size_t)app->nic_count, sizeof(int));
if (sessions_per_nic == NULL) {
Expand Down
13 changes: 13 additions & 0 deletions src/util/config_reader.c
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,11 @@ int parse_tx_config(const char* config_file, struct dvledtx_config* config) {
/* --- optional top-level log_file --- */
extract_json_string(json, buf_end, "log_file", config->log_file, sizeof(config->log_file));

/* PTP hardware timing (built-in MTL PTP client) — hardcoded, not configurable via JSON. */
config->ptp_enable = true;
config->ptp_pi = true;
config->ptp_unicast = false;

/* --- tx_sessions array --- */
const char* sessions_arr = find_array(json, buf_end, "tx_sessions");
if (sessions_arr == NULL) {
Expand Down Expand Up @@ -798,6 +803,14 @@ int load_and_apply_config(struct dvledtx_context* app, const char* config_file)
app->log_file[sizeof(app->log_file) - 1] = '\0';
}

/* PTP hardware timing (built-in MTL PTP client) */
app->ptp_enable = config.ptp_enable;
app->ptp_pi = config.ptp_pi;
app->ptp_unicast = config.ptp_unicast;
if (app->ptp_enable)
LOG_INFO("PTP enabled: pi_controller=%d unicast_delay_req=%d",
app->ptp_pi, app->ptp_unicast);

LOG_INFO("Config loaded: %s (%d NIC(s), %d session(s))",
config_file, config.nic_count, config.session_count);
for (int ni = 0; ni < config.nic_count; ni++)
Expand Down
Loading