Skip to content

Commit

Permalink
upipe_ts_demux: add configurable max PCRs interval
Browse files Browse the repository at this point in the history
  • Loading branch information
quarium committed Sep 4, 2024
1 parent f14f539 commit eecdcbe
Show file tree
Hide file tree
Showing 2 changed files with 141 additions and 5 deletions.
31 changes: 31 additions & 0 deletions include/upipe-ts/upipe_ts_demux.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,10 @@ enum upipe_ts_demux_command {
UPIPE_TS_DEMUX_SET_EIT_ENABLED,
/** enables or disables EITs table ID decoding (int) */
UPIPE_TS_DEMUX_SET_EITS_ENABLED,
/** sets the maximum allow interval between PCRs (uint64_t) */
UPIPE_TS_DEMUX_SET_MAX_PCR_INTERVAL,
/** gets the configured maximum interval between PCRs (uint64_t *) */
UPIPE_TS_DEMUX_GET_MAX_PCR_INTERVAL,
};

/** @This returns the currently detected conformance mode. It cannot return
Expand Down Expand Up @@ -128,6 +132,33 @@ static inline int upipe_ts_demux_set_eits_enabled(struct upipe *upipe,
UPIPE_TS_DEMUX_SIGNATURE, enabled ? 1 : 0);
}

/** @This sets the maximum allowed interval between PCRs.
*
* @param upipe description structure of the pipe
* @param max maximum allowed interval between PCRs in 27MHz ticks
* @return an error code
*/
static inline int upipe_ts_demux_set_max_pcr_interval(struct upipe *upipe,
uint64_t max)
{
return upipe_control(upipe, UPIPE_TS_DEMUX_SET_MAX_PCR_INTERVAL,
UPIPE_TS_DEMUX_SIGNATURE, max);
}

/** @This gets the configured maximum allowed interval between PCRs.
*
* @param upipe description structure of the pipe
* @param max filled with the maximum allowed internal between PCRs in 27MHz
* ticks
* @return an error code
*/
static inline int upipe_ts_demux_get_max_pcr_interval(struct upipe *upipe,
uint64_t *max)
{
return upipe_control(upipe, UPIPE_TS_DEMUX_GET_MAX_PCR_INTERVAL,
UPIPE_TS_DEMUX_SIGNATURE, max);
}

/** @This returns the management structure for all ts_demux pipes.
*
* @return pointer to manager
Expand Down
115 changes: 110 additions & 5 deletions lib/upipe-ts/upipe_ts_demux.c
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,8 @@ struct upipe_ts_demux {
bool eit_enabled;
/** enable EITs table ID decoder */
bool eits_enabled;
/** maximum allowed interval between PCRs */
uint64_t max_pcr_interval;

/** probe to get new flow events from inner pipes created by psi_pid
* objects */
Expand Down Expand Up @@ -407,6 +409,8 @@ struct upipe_ts_demux_program {

/** offset between MPEG timestamps and Upipe timestamps */
int64_t timestamp_offset;
/** maximum allowed interval between PCRs */
uint64_t max_pcr_interval;
/** last MPEG clock reference */
uint64_t last_pcr;
/** highest Upipe timestamp given to a frame */
Expand Down Expand Up @@ -751,7 +755,7 @@ static int upipe_ts_demux_output_clock_ts(struct upipe *upipe,
/* handle 2^33 wrap-arounds */
uint64_t delta = (TS_CLOCK_MAX + dts_orig -
(program->last_pcr % TS_CLOCK_MAX)) % TS_CLOCK_MAX;
if (delta <= output->max_delay + MAX_PCR_INTERVAL) {
if (delta <= output->max_delay + program->max_pcr_interval) {
uint64_t dts = program->timestamp_offset +
program->last_pcr + delta;
uref_clock_set_dts_prog(uref, dts);
Expand Down Expand Up @@ -1908,7 +1912,7 @@ static void upipe_ts_demux_program_handle_pcr(struct upipe *upipe,
uint64_t delta =
(TS_CLOCK_MAX + pcr_orig -
(upipe_ts_demux_program->last_pcr % TS_CLOCK_MAX)) % TS_CLOCK_MAX;
if (delta <= MAX_PCR_INTERVAL)
if (delta <= upipe_ts_demux_program->max_pcr_interval)
upipe_ts_demux_program->last_pcr += delta;
else {
upipe_warn_va(upipe, "PCR discontinuity %"PRIu64, delta);
Expand Down Expand Up @@ -2064,8 +2068,11 @@ static struct upipe *upipe_ts_demux_program_alloc(struct upipe_mgr *mgr,
args, &flow_def);
if (unlikely(upipe == NULL))
return NULL;

struct upipe_ts_demux *demux = upipe_ts_demux_from_program_mgr(upipe->mgr);
struct upipe_ts_demux_program *upipe_ts_demux_program =
upipe_ts_demux_program_from_upipe(upipe);

upipe_ts_demux_program_init_urefcount(upipe);
urefcount_init(upipe_ts_demux_program_to_urefcount_real(upipe_ts_demux_program), upipe_ts_demux_program_free);
upipe_ts_demux_program_init_output(upipe);
Expand Down Expand Up @@ -2094,6 +2101,7 @@ static struct upipe *upipe_ts_demux_program_alloc(struct upipe_mgr *mgr,
}
upipe_ts_demux_program->timestamp_offset = 0;
upipe_ts_demux_program->timestamp_highest = TS_CLOCK_MAX;
upipe_ts_demux_program->max_pcr_interval = demux->max_pcr_interval;
upipe_ts_demux_program->last_pcr = TS_CLOCK_MAX;
uprobe_init(&upipe_ts_demux_program->pmtd_probe,
upipe_ts_demux_program_pmtd_probe, NULL);
Expand All @@ -2119,7 +2127,6 @@ static struct upipe *upipe_ts_demux_program_alloc(struct upipe_mgr *mgr,
upipe_ts_demux_program_init_sub(upipe);
upipe_throw_ready(upipe);

struct upipe_ts_demux *demux = upipe_ts_demux_from_program_mgr(upipe->mgr);
const uint8_t *filter, *mask;
size_t size;
const char *def;
Expand Down Expand Up @@ -2199,6 +2206,38 @@ static struct upipe *upipe_ts_demux_program_alloc(struct upipe_mgr *mgr,
return upipe;
}

/** @internal @This sets the maximum allow interval between PCRs.
*
* @param upipe description structure of the pipe
* @param max maximum allowed interval between PCRs in 27MHz ticks
* @return an error code
*/
static int upipe_ts_demux_program_set_max_pcr_interval(struct upipe *upipe,
uint64_t max)
{
struct upipe_ts_demux_program *program =
upipe_ts_demux_program_from_upipe(upipe);
program->max_pcr_interval = max;
return UBASE_ERR_NONE;
}

/** @internal @This gets the configured maximum interval between PCRs.
*
* @param upipe description structure of the pipe
* @param max filled with the maximum allowed internal between PCRs in 27MHz
* ticks.
* @return an error code
*/
static int upipe_ts_demux_program_get_max_pcr_interval(struct upipe *upipe,
uint64_t *max)
{
struct upipe_ts_demux_program *program =
upipe_ts_demux_program_from_upipe(upipe);
if (max)
*max = program->max_pcr_interval;
return UBASE_ERR_NONE;
}

/** @internal @This processes control commands on a ts_demux_program pipe.
*
* @param upipe description structure of the pipe
Expand Down Expand Up @@ -2241,10 +2280,27 @@ static int upipe_ts_demux_program_control(struct upipe *upipe,
*p = upipe_ts_demux_program->pmtd;
return (*p != NULL) ? UBASE_ERR_NONE : UBASE_ERR_UNHANDLED;
}

default:
return UBASE_ERR_NONE;
break;
}

if (ubase_get_signature(args) == UPIPE_TS_DEMUX_SIGNATURE) {
switch (command) {
case UPIPE_TS_DEMUX_SET_MAX_PCR_INTERVAL: {
UBASE_SIGNATURE_CHECK(args, UPIPE_TS_DEMUX_SIGNATURE);
uint64_t max = va_arg(args, uint64_t);
return upipe_ts_demux_program_set_max_pcr_interval(upipe, max);
}

case UPIPE_TS_DEMUX_GET_MAX_PCR_INTERVAL: {
UBASE_SIGNATURE_CHECK(args, UPIPE_TS_DEMUX_SIGNATURE);
uint64_t *max = va_arg(args, uint64_t *);
return upipe_ts_demux_program_get_max_pcr_interval(upipe, max);
}
}
}

return UBASE_ERR_NONE;
}

/** @This frees a upipe.
Expand Down Expand Up @@ -3334,6 +3390,7 @@ static struct upipe *upipe_ts_demux_alloc(struct upipe_mgr *mgr,
upipe_ts_demux->auto_conformance = true;
upipe_ts_demux->eit_enabled = true;
upipe_ts_demux->eits_enabled = true;
upipe_ts_demux->max_pcr_interval = MAX_PCR_INTERVAL;
upipe_ts_demux->nit_pid = 0;
upipe_ts_demux->flow_def_input = NULL;

Expand Down Expand Up @@ -3629,6 +3686,44 @@ static int _upipe_ts_demux_set_eits_enabled(struct upipe *upipe,
return UBASE_ERR_NONE;
}

/** @internal @This sets the maximum allow interval between PCRs.
*
* @param upipe description structure of the pipe
* @param max maximum allowed interval between PCRs in 27MHz ticks
* @return an error code
*/
static int _upipe_ts_demux_set_max_pcr_interval(struct upipe *upipe,
uint64_t max)
{
struct upipe_ts_demux *demux = upipe_ts_demux_from_upipe(upipe);
demux->max_pcr_interval = max;

struct uchain *uchain;
ulist_foreach(&demux->programs, uchain) {
struct upipe_ts_demux_program *program =
upipe_ts_demux_program_from_uchain(uchain);
struct upipe *sub = upipe_ts_demux_program_to_upipe(program);
upipe_ts_demux_program_set_max_pcr_interval(sub, max);
}
return UBASE_ERR_NONE;
}

/** @internal @This gets the configured maximum interval between PCRs.
*
* @param upipe description structure of the pipe
* @param max filled with the maximum allowed internal between PCRs in 27MHz
* ticks.
* @return an error code
*/
static int _upipe_ts_demux_get_max_pcr_interval(struct upipe *upipe,
uint64_t *max)
{
struct upipe_ts_demux *demux = upipe_ts_demux_from_upipe(upipe);
if (max)
*max = demux->max_pcr_interval;
return UBASE_ERR_NONE;
}

/** @internal @This processes control commands on a ts_demux pipe.
*
* @param upipe description structure of the pipe
Expand Down Expand Up @@ -3701,6 +3796,16 @@ static int upipe_ts_demux_control(struct upipe *upipe,
int enabled = va_arg(args, int);
return _upipe_ts_demux_set_eits_enabled(upipe, !!enabled);
}
case UPIPE_TS_DEMUX_SET_MAX_PCR_INTERVAL: {
UBASE_SIGNATURE_CHECK(args, UPIPE_TS_DEMUX_SIGNATURE);
uint64_t max = va_arg(args, uint64_t);
return _upipe_ts_demux_set_max_pcr_interval(upipe, max);
}
case UPIPE_TS_DEMUX_GET_MAX_PCR_INTERVAL: {
UBASE_SIGNATURE_CHECK(args, UPIPE_TS_DEMUX_SIGNATURE);
uint64_t *max = va_arg(args, uint64_t *);
return _upipe_ts_demux_get_max_pcr_interval(upipe, max);
}

default:
break;
Expand Down

0 comments on commit eecdcbe

Please sign in to comment.