Skip to content

Commit

Permalink
[FEAT] Add timing module in lib_ccxr (#1640)
Browse files Browse the repository at this point in the history
* feat: Add new module for timings functionality

* feat: Add timing functionality in `timing.rs` module

* feat: List all module & function conversion

* chore: Clippy fixes

* feat: Equivalent `ccx_common_timing.h` functions in rust module

* feat: Add static constants & include struct in `build.rs`

* feat: Add extern C functions

* feat: Include & use rust extern functions in C

* fix: Windows build

* fix: Windows build

---------

Co-authored-by: Prateek Sunal <[email protected]>
  • Loading branch information
IshanGrover2004 and prateekmedia committed Sep 14, 2024
1 parent 349020e commit cbd8e27
Show file tree
Hide file tree
Showing 12 changed files with 1,150 additions and 12 deletions.
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

0 comments on commit cbd8e27

Please sign in to comment.