Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FEAT] Add timing module in lib_ccxr #1640

Merged
merged 11 commits into from
Sep 14, 2024
47 changes: 47 additions & 0 deletions src/lib_ccx/ccx_common_timing.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,18 @@ int gop_rollover = 0;

struct ccx_common_timing_settings_t ccx_common_timing_settings;

#ifndef DISABLE_RUST
void ccxr_add_current_pts(struct ccx_common_timing_ctx *ctx, LLONG pts);
void ccxr_set_current_pts(struct ccx_common_timing_ctx *ctx, LLONG pts);
int ccxr_set_fts(struct ccx_common_timing_ctx *ctx);
LLONG ccxr_get_fts(struct ccx_common_timing_ctx *ctx, int current_field);
LLONG ccxr_get_fts_max(struct ccx_common_timing_ctx *ctx);
char *ccxr_print_mstime_static(LLONG mstime, char *buf);
void ccxr_print_debug_timing(struct ccx_common_timing_ctx *ctx);
void ccxr_calculate_ms_gop_time(struct gop_time_code *g);
int ccxr_gop_accepted(struct gop_time_code *g);
#endif

void ccx_common_timing_init(LLONG *file_position, int no_sync)
{
ccx_common_timing_settings.disable_sync_check = 0;
Expand Down Expand Up @@ -73,11 +85,18 @@ struct ccx_common_timing_ctx *init_timing_ctx(struct ccx_common_timing_settings_

void add_current_pts(struct ccx_common_timing_ctx *ctx, LLONG pts)
{
#ifndef DISABLE_RUST
return ccxr_add_current_pts(ctx, pts);
#endif

set_current_pts(ctx, ctx->current_pts + pts);
}

void set_current_pts(struct ccx_common_timing_ctx *ctx, LLONG pts)
{
#ifndef DISABLE_RUST
return ccxr_set_current_pts(ctx, pts);
#endif
LLONG prev_pts = ctx->current_pts;
ctx->current_pts = pts;
if (ctx->pts_set == 0)
Expand All @@ -95,6 +114,9 @@ void set_current_pts(struct ccx_common_timing_ctx *ctx, LLONG pts)

int set_fts(struct ccx_common_timing_ctx *ctx)
{
#ifndef DISABLE_RUST
return ccxr_set_fts(ctx);
#endif
int pts_jump = 0;

// ES don't have PTS unless GOP timing is used
Expand Down Expand Up @@ -266,6 +288,10 @@ int set_fts(struct ccx_common_timing_ctx *ctx)

LLONG get_fts(struct ccx_common_timing_ctx *ctx, int current_field)
{
#ifndef DISABLE_RUST
return ccxr_get_fts(ctx, current_field);
#endif

LLONG fts;

switch (current_field)
Expand All @@ -290,6 +316,10 @@ LLONG get_fts(struct ccx_common_timing_ctx *ctx, int current_field)

LLONG get_fts_max(struct ccx_common_timing_ctx *ctx)
{
#ifndef DISABLE_RUST
return ccxr_get_fts_max(ctx);
#endif

// This returns the maximum FTS that belonged to a frame. Caption block
// counters are not applicable.
return ctx->fts_max + ctx->fts_global;
Expand Down Expand Up @@ -350,13 +380,22 @@ size_t print_mstime_buff(LLONG mstime, char *fmt, char *buf)
char *print_mstime_static(LLONG mstime)
{
static char buf[15]; // 14 should be long enough

#ifndef DISABLE_RUST
return ccxr_print_mstime_static(mstime, buf);
#endif

print_mstime_buff(mstime, "%02u:%02u:%02u:%03u", buf);
return buf;
}

/* Helper function for to display debug timing info. */
void print_debug_timing(struct ccx_common_timing_ctx *ctx)
{
#ifndef DISABLE_RUST
return ccxr_print_debug_timing(ctx);
#endif

// Avoid wrong "Calc. difference" and "Asynchronous by" numbers
// for uninitialized min_pts
LLONG tempmin_pts = (ctx->min_pts == 0x01FFFFFFFFLL ? ctx->sync_pts : ctx->min_pts);
Expand All @@ -383,6 +422,10 @@ void print_debug_timing(struct ccx_common_timing_ctx *ctx)

void calculate_ms_gop_time(struct gop_time_code *g)
{
#ifndef DISABLE_RUST
return ccxr_calculate_ms_gop_time(g);
#endif

int seconds = (g->time_code_hours * 3600) + (g->time_code_minutes * 60) + g->time_code_seconds;
g->ms = (LLONG)(1000 * (seconds + g->time_code_pictures / current_fps));
if (gop_rollover)
Expand All @@ -391,6 +434,10 @@ void calculate_ms_gop_time(struct gop_time_code *g)

int gop_accepted(struct gop_time_code *g)
{
#ifndef DISABLE_RUST
return ccxr_gop_accepted(g);
#endif

if (!((g->time_code_hours <= 23) && (g->time_code_minutes <= 59) && (g->time_code_seconds <= 59) && (g->time_code_pictures <= 59)))
return 0;

Expand Down
1 change: 1 addition & 0 deletions src/rust/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ fn main() {
"ccx_output_format",
"ccx_boundary_time",
"gop_time_code",
"ccx_common_timing_settings_t",
"ccx_s_options",
"ccx_s_teletext_config",
"ccx_output_date_format",
Expand Down
2 changes: 1 addition & 1 deletion src/rust/lib_ccxr/src/common/options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ impl Default for EncodersTranscriptFormat {
}
}

#[derive(Debug, Default, Copy, Clone)]
#[derive(Debug, Default, Copy, Clone, PartialEq)]
pub enum FrameType {
#[default]
ResetOrUnknown = 0,
Expand Down
61 changes: 61 additions & 0 deletions src/rust/lib_ccxr/src/time/c_functions.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
//! Provides Rust equivalent for functions in C. Uses Rust-native types as input and output.

use super::*;

/// Rust equivalent for `add_current_pts` function in C. Uses Rust-native types as input and output.
pub fn add_current_pts(ctx: &mut TimingContext, pts: MpegClockTick) {
ctx.add_current_pts(pts)
}

/// Rust equivalent for `set_current_pts` function in C. Uses Rust-native types as input and output.
pub fn set_current_pts(ctx: &mut TimingContext, pts: MpegClockTick) {
ctx.set_current_pts(pts)
}

/// Rust equivalent for `set_fts` function in C. Uses Rust-native types as input and output.
pub fn set_fts(ctx: &mut TimingContext) -> bool {
ctx.set_fts()
}

/// Rust equivalent for `get_fts` function in C. Uses Rust-native types as input and output.
pub fn get_fts(ctx: &mut TimingContext, current_field: CaptionField) -> Timestamp {
ctx.get_fts(current_field)
}

/// Rust equivalent for `get_fts_max` function in C. Uses Rust-native types as input and output.
pub fn get_fts_max(ctx: &mut TimingContext) -> Timestamp {
ctx.get_fts_max()
}

/// Rust equivalent for `print_mstime_static` function in C. Uses Rust-native types as input and output.
pub fn print_mstime_static(mstime: Timestamp, sep: char) -> String {
mstime.to_hms_millis_time(sep).unwrap()
}

/// Rust equivalent for `print_debug_timing` function in C. Uses Rust-native types as input and output.
pub fn print_debug_timing(ctx: &mut TimingContext) {
ctx.print_debug_timing()
}

/// Rust equivalent for `calculate_ms_gop_time` function in C. Uses Rust-native types as input and output.
pub fn calculate_ms_gop_time(g: GopTimeCode) -> Timestamp {
g.timestamp()
}

/// Rust equivalent for `gop_accepted` function in C. Uses Rust-native types as input and output.
pub fn gop_accepted(g: GopTimeCode) -> bool {
let mut timing_info = GLOBAL_TIMING_INFO.write().unwrap();

let gop_time = if let Some(gt) = timing_info.gop_time {
gt
} else {
return true;
};

if g.did_rollover(&gop_time) {
timing_info.gop_rollover = true;
true
} else {
gop_time.timestamp() <= g.timestamp()
}
}
24 changes: 23 additions & 1 deletion src/rust/lib_ccxr/src/time/mod.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
//! Provide types for storing time in different formats
//! Provide types for storing time in different formats and manage timing information while decoding.
//!
//! Time can be represented in one of following formats:
//! - [`Timestamp`] as number of milliseconds
//! - [`MpegClockTick`] as number of clock ticks (as defined in the MPEG standard)
//! - [`FrameCount`] as number of frames
//! - [`GopTimeCode`] as a GOP time code (as defined in the MPEG standard)
//!
//! [`GLOBAL_TIMING_INFO`] and [`TimingContext`] are used for managing time-related information
//! during the deocoding process.
//!
//! # Conversion Guide
//!
//! | From | To |
Expand All @@ -16,8 +19,27 @@
//! | any pts | [`MpegClockTick`] |
//! | any frame count | [`FrameCount`] |
//! | `gop_time_code` | [`GopTimeCode`] |
//! | `current_field` | [`CaptionField`] |
//! | `ccx_common_timing_ctx.pts_set` | [`PtsSet`] |
//! | `ccx_common_timing_settings_t` | [`TimingSettings`] |
//! | `ccx_common_timing_ctx` | [`TimingContext`] |
//! | `init_timing_ctx` | [`TimingContext::new`] |
//! | `add_current_pts` | [`TimingContext::add_current_pts`] |
//! | `set_current_pts` | [`TimingContext::set_current_pts`] |
//! | `set_fts` | [`TimingContext::set_fts`] |
//! | `get_fts` | [`TimingContext::get_fts`] |
//! | `get_fts_max` | [`TimingContext::get_fts_max`] |
//! | `print_mstime_buff` | [`Timestamp::write_hms_millis_time`] |
//! | `print_mstime_static` | [`Timestamp::to_hms_millis_time`] |
//! | `print_scc_time` | [`Timestamp::to_scc_time`] |
//! | `print_debug_timing` | [`TimingContext::print_debug_timing`] |
//! | `gop_accepted` | [`GopTimeCode::did_rollover`] + some additional logic |
//! | `calculate_ms_gop_time` | [`GopTimeCode::new`], [`GopTimeCode::timestamp`] |
//! | `cb_708`, `cb_field1`, `cb_field2`, `pts_big_change`, `current_fps`, `frames_since_ref_time`, `total_frames_count`, `gop_time`, `first_gop_time`, `fts_at_gop_start`, `gop_rollover`, `ccx_common_timing_settings` | [`GlobalTimingInfo`], [`GLOBAL_TIMING_INFO`] |

pub mod c_functions;
pub mod timing;
pub mod units;

pub use timing::*;
pub use units::*;
Loading
Loading