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

[FIX] Initialize data structures for the rust CEA-708 decoder and correct Dtvcc #1618

Open
wants to merge 19 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
2a1fce5
feat: Change `Dtvcc::new()` to create Dtvcc using `ccx_decoder_dtvcc_…
IshanGrover2004 Jun 4, 2024
05c6a2f
feat: Create `ccxr_dtvcc_init` & `ccxr_dtvcc_free`
IshanGrover2004 Jun 18, 2024
af23301
feat: Create `ccxr_dtvcc_set_encoder` to set encoder value
IshanGrover2004 Jun 18, 2024
92cc3c5
feat: Add `dtvcc_rust` member in `lib_cc_decoder` struct for storing …
IshanGrover2004 Jun 20, 2024
b9215f5
feat: Initialize extern `dtvcc init & free` functions in C header
IshanGrover2004 Jun 20, 2024
fce9fcf
feat: Create function to set dtvcc encoder to `dtvcc_rust` in C
IshanGrover2004 Jun 20, 2024
e8a2660
feat: Use of dtvcc init & free in C
IshanGrover2004 Jun 20, 2024
1ce5ad4
fix: rust build
IshanGrover2004 Jun 21, 2024
cf2a335
fix: Value of `dtvcc_rust.is_active` as per C
IshanGrover2004 Jun 21, 2024
6cb6f6e
refactor: Changed `ccxr_flush_decoder` to flush decoder of `dtvcc_rust`
IshanGrover2004 Jun 23, 2024
e8cf6ae
fix: Double free issue
IshanGrover2004 Jun 23, 2024
3f2d2f2
refactor: Convert some portion of code to rust
IshanGrover2004 Jun 23, 2024
e1ca3a6
refactor: Convert some portion of code to rust
IshanGrover2004 Jun 23, 2024
f8160d7
revert: formating issues
IshanGrover2004 Jun 24, 2024
4c50f43
chore: Clippy fixes
IshanGrover2004 Jun 24, 2024
7a7471c
feat: Use of rust function due to initialization of `dtvcc_rust` in m…
IshanGrover2004 Jun 24, 2024
609c4d0
fix: mp4 code arguments & clippy warning
IshanGrover2004 Jun 24, 2024
991de14
Fix memory leaks
PunitLodha Jun 27, 2024
294b9d9
fix: unit test error & build issues
IshanGrover2004 Aug 24, 2024
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
17 changes: 12 additions & 5 deletions src/lib_ccx/ccx_decoders_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ made to reuse, not duplicate, as many functions as possible */

#ifndef DISABLE_RUST
extern int ccxr_process_cc_data(struct lib_cc_decode *dec_ctx, unsigned char *cc_data, int cc_count);
extern void ccxr_flush_decoder(struct dtvcc_ctx *dtvcc, struct dtvcc_service_decoder *decoder);
#endif

uint64_t utc_refvalue = UINT64_MAX; /* _UI64_MAX/UINT64_MAX means don't use UNIX, 0 = use current system time as reference, +1 use a specific reference */
Expand Down Expand Up @@ -232,7 +231,11 @@ int do_cb(struct lib_cc_decode *ctx, unsigned char *cc_block, struct cc_subtitle
void dinit_cc_decode(struct lib_cc_decode **ctx)
{
struct lib_cc_decode *lctx = *ctx;
#ifndef DISABLE_RUST
ccxr_dtvcc_free(lctx->dtvcc_rust);
#else
dtvcc_free(&lctx->dtvcc);
#endif
dinit_avc(&lctx->avc_ctx);
ccx_decoder_608_dinit_library(&lctx->context_cc608_field_1);
ccx_decoder_608_dinit_library(&lctx->context_cc608_field_2);
Expand Down Expand Up @@ -261,8 +264,12 @@ struct lib_cc_decode *init_cc_decode(struct ccx_decoders_common_settings_t *sett
ctx->no_rollup = setting->no_rollup;
ctx->noscte20 = setting->noscte20;

#ifndef DISABLE_RUST
ctx->dtvcc_rust = ccxr_dtvcc_init(setting->settings_dtvcc);
#else
ctx->dtvcc = dtvcc_init(setting->settings_dtvcc);
ctx->dtvcc->is_active = setting->settings_dtvcc->enabled;
#endif

if (setting->codec == CCX_CODEC_ATSC_CC)
{
Expand Down Expand Up @@ -441,6 +448,9 @@ void flush_cc_decode(struct lib_cc_decode *ctx, struct cc_subtitle *sub)
}
}
}
#ifndef DISABLE_RUST
ccxr_flush_active_decoders(ctx);
#else
if (ctx->dtvcc->is_active)
{
for (int i = 0; i < CCX_DTVCC_MAX_SERVICES; i++)
Expand All @@ -451,14 +461,11 @@ void flush_cc_decode(struct lib_cc_decode *ctx, struct cc_subtitle *sub)
if (decoder->cc_count > 0)
{
ctx->current_field = 3;
#ifndef DISABLE_RUST
ccxr_flush_decoder(ctx->dtvcc, decoder);
#else
dtvcc_decoder_flush(ctx->dtvcc, decoder);
#endif
}
}
}
#endif
}
struct encoder_ctx *copy_encoder_context(struct encoder_ctx *ctx)
{
Expand Down
4 changes: 4 additions & 0 deletions src/lib_ccx/ccx_decoders_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,8 @@ struct cc_subtitle* copy_subtitle(struct cc_subtitle *sub);
void free_encoder_context(struct encoder_ctx *ctx);
void free_decoder_context(struct lib_cc_decode *ctx);
void free_subtitle(struct cc_subtitle* sub);
#ifndef DISABLE_RUST
void ccxr_flush_active_decoders(struct lib_cc_decode *ctx);
#endif // !DISABLE_RUST

#endif
3 changes: 3 additions & 0 deletions src/lib_ccx/ccx_decoders_structs.h
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,9 @@ struct lib_cc_decode
int stat_divicom;
int false_pict_header;

// For storing Dtvcc coming from rust
void *dtvcc_rust;

dtvcc_ctx *dtvcc;
int current_field;
// Analyse/use the picture information
Expand Down
8 changes: 7 additions & 1 deletion src/lib_ccx/ccx_dtvcc.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,10 @@ void dtvcc_process_data(struct dtvcc_ctx *dtvcc,
dtvcc_ctx *dtvcc_init(ccx_decoder_dtvcc_settings *opts);
void dtvcc_free(dtvcc_ctx **);

#endif //CCEXTRACTOR_CCX_DTVCC_H
#ifndef DISABLE_RUST
extern void *ccxr_dtvcc_init(struct ccx_decoder_dtvcc_settings *settings_dtvcc);
extern void ccxr_dtvcc_free(void *dtvcc_rust);
extern void ccxr_dtvcc_process_data(void *dtvcc_rust, const unsigned char cc_valid, const unsigned char cc_type, const unsigned char data1, const unsigned char data2);
#endif

#endif // CCEXTRACTOR_CCX_DTVCC_H
18 changes: 17 additions & 1 deletion src/lib_ccx/general_loop.c
Original file line number Diff line number Diff line change
Expand Up @@ -896,7 +896,12 @@ int process_non_multiprogram_general_loop(struct lib_ccx_ctx *ctx,
cinfo = get_cinfo(ctx->demux_ctx, pid);
*enc_ctx = update_encoder_list_cinfo(ctx, cinfo);
*dec_ctx = update_decoder_list_cinfo(ctx, cinfo);

#ifndef DISABLE_RUST
ccxr_dtvcc_set_encoder((*dec_ctx)->dtvcc_rust, *enc_ctx);
#else
(*dec_ctx)->dtvcc->encoder = (void *)(*enc_ctx);
#endif

if ((*dec_ctx)->timing->min_pts == 0x01FFFFFFFFLL) // if we didn't set the min_pts of the program
{
Expand Down Expand Up @@ -1093,7 +1098,12 @@ int general_loop(struct lib_ccx_ctx *ctx)

enc_ctx = update_encoder_list_cinfo(ctx, cinfo);
dec_ctx = update_decoder_list_cinfo(ctx, cinfo);

#ifndef DISABLE_RUST
ccxr_dtvcc_set_encoder(dec_ctx->dtvcc_rust, enc_ctx);
#else
dec_ctx->dtvcc->encoder = (void *)enc_ctx; // WARN: otherwise cea-708 will not work
#endif

if (dec_ctx->timing->min_pts == 0x01FFFFFFFFLL) // if we didn't set the min_pts of the program
{
Expand Down Expand Up @@ -1268,7 +1278,13 @@ int rcwt_loop(struct lib_ccx_ctx *ctx)
}

dec_ctx = update_decoder_list(ctx);
dec_ctx->dtvcc->encoder = (void *)enc_ctx; // WARN: otherwise cea-708 will not work

#ifndef DISABLE_RUST
ccxr_dtvcc_set_encoder(dec_ctx->dtvcc_rust, enc_ctx);
#else
dec_ctx->dtvcc->encoder = (void *)enc_ctx; // WARN: otherwise cea-708 will not work
#endif

if (parsebuf[6] == 0 && parsebuf[7] == 2)
{
dec_ctx->codec = CCX_CODEC_TELETEXT;
Expand Down
4 changes: 4 additions & 0 deletions src/lib_ccx/lib_ccx.h
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,10 @@ int general_loop(struct lib_ccx_ctx *ctx);
void process_hex(struct lib_ccx_ctx *ctx, char *filename);
int rcwt_loop(struct lib_ccx_ctx *ctx);

#ifndef DISABLE_RUST
void ccxr_dtvcc_set_encoder(void *dtvcc_rust, struct encoder_ctx* encoder);
#endif

extern int end_of_file;

int ccx_mxf_getmoredata(struct lib_ccx_ctx *ctx, struct demuxer_data **ppdata);
Expand Down
6 changes: 6 additions & 0 deletions src/lib_ccx/mp4.c
Original file line number Diff line number Diff line change
Expand Up @@ -417,8 +417,14 @@ static int process_clcp(struct lib_ccx_ctx *ctx, struct encoder_ctx *enc_ctx,
continue;
}
// WARN: otherwise cea-708 will not work

#ifndef DISABLE_RUST
ccxr_dtvcc_set_encoder(dec_ctx->dtvcc_rust, enc_ctx);
ccxr_dtvcc_process_data(dec_ctx->dtvcc_rust, temp[0], temp[1], temp[2], temp[3]);
#else
dec_ctx->dtvcc->encoder = (void *)enc_ctx;
dtvcc_process_data(dec_ctx->dtvcc, (unsigned char *)temp);
#endif
cb_708++;
}
if (ctx->write_format == CCX_OF_MCC)
Expand Down
137 changes: 110 additions & 27 deletions src/rust/src/decoder/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,20 @@ mod timing;
mod tv_screen;
mod window;

use crate::{bindings::*, utils::*};
use lib_ccxr::{
debug, fatal,
util::log::{DebugMessageFlag, ExitCause},
};

use crate::{bindings::*, utils::is_true};
use service_decoder::ccxr_flush_decoder;

const CCX_DTVCC_MAX_PACKET_LENGTH: u8 = 128;
const CCX_DTVCC_NO_LAST_SEQUENCE: i32 = -1;
const CCX_DTVCC_SCREENGRID_ROWS: u8 = 75;
const CCX_DTVCC_SCREENGRID_COLUMNS: u8 = 210;
const CCX_DTVCC_MAX_ROWS: u8 = 15;
const CCX_DTVCC_MAX_COLUMNS: u8 = 32 * 2;
pub const CCX_DTVCC_MAX_SERVICES: usize = 63;

/// Context required for processing 708 data
pub struct Dtvcc<'a> {
Expand All @@ -31,37 +32,92 @@ pub struct Dtvcc<'a> {
pub services_active: Vec<i32>,
pub report_enabled: bool,
pub report: &'a mut ccx_decoder_dtvcc_report,
pub decoders: Vec<&'a mut dtvcc_service_decoder>,
pub decoders: [Option<Box<dtvcc_service_decoder>>; CCX_DTVCC_MAX_SERVICES],
pub packet: Vec<u8>,
pub packet_length: u8,
pub is_header_parsed: bool,
pub last_sequence: i32,
pub encoder: &'a mut encoder_ctx,
pub encoder: *mut encoder_ctx,
pub no_rollup: bool,
pub timing: &'a mut ccx_common_timing_ctx,
}

impl<'a> Dtvcc<'a> {
/// Create a new dtvcc context
pub fn new(ctx: &'a mut dtvcc_ctx) -> Self {
let report = unsafe { &mut *ctx.report };
let encoder = unsafe { &mut *(ctx.encoder as *mut encoder_ctx) };
let timing = unsafe { &mut *ctx.timing };

Self {
is_active: is_true(ctx.is_active),
active_services_count: ctx.active_services_count as u8,
services_active: ctx.services_active.to_vec(),
report_enabled: is_true(ctx.report_enabled),
pub fn new(opts: &ccx_decoder_dtvcc_settings) -> Self {
// closely follows `dtvcc_init` at `src/lib_ccx/ccx_dtvcc.c:82`

let is_active = is_true(opts.enabled);
let active_services_count = opts.active_services_count as u8;
let services_active = opts.services_enabled.to_vec();
let report_enabled = is_true(opts.print_file_reports);

let report = unsafe { &mut *opts.report };
report.reset_count = 0;

// `dtvcc_clear_packet` does the following
let packet_length = 0;
let is_header_parsed = false;
let packet = [0; CCX_DTVCC_MAX_SERVICES].to_vec();

let last_sequence = CCX_DTVCC_NO_LAST_SEQUENCE;
let timing = unsafe { &mut *opts.timing };

let no_rollup = is_true(opts.no_rollup);

// unlike C, here the decoders are allocated on the stack as an array.
let decoders = {
const INIT: Option<Box<dtvcc_service_decoder>> = None;
let mut decoders = [INIT; CCX_DTVCC_MAX_SERVICES];

decoders
.iter_mut()
.zip(opts.services_enabled)
.enumerate()
.for_each(|(i, (d, se))| {
if is_false(se) {
return;
}

let mut decoder = Box::new(dtvcc_service_decoder {
// we cannot allocate this on the stack as `dtvcc_service_decoder` is a C
// struct cannot be changed trivially
tv: Box::into_raw(Box::new(dtvcc_tv_screen {
cc_count: 0,
service_number: i as i32 + 1,
..dtvcc_tv_screen::default()
})),
..dtvcc_service_decoder::default()
});

decoder.windows.iter_mut().for_each(|w| {
w.memory_reserved = 0;
});

decoder.handle_reset();

*d = Some(decoder);
});

decoders
};

let encoder = std::ptr::null_mut();

Dtvcc {
is_active,
active_services_count,
services_active,
report_enabled,
report,
decoders: ctx.decoders.iter_mut().collect(),
packet: ctx.current_packet.to_vec(),
packet_length: ctx.current_packet_length as u8,
is_header_parsed: is_true(ctx.is_current_packet_header_parsed),
last_sequence: ctx.last_sequence,
encoder,
no_rollup: is_true(ctx.no_rollup),
packet,
packet_length,
is_header_parsed,
last_sequence,
no_rollup,
timing,
encoder,
decoders,
}
}
/// Process cc data and add it to the dtvcc packet
Expand Down Expand Up @@ -175,10 +231,13 @@ impl<'a> Dtvcc<'a> {
}

if service_number > 0 && is_true(self.services_active[(service_number - 1) as usize]) {
let decoder = &mut self.decoders[(service_number - 1) as usize];
let decoder = &mut self.decoders[(service_number - 1) as usize]
.as_mut()
.unwrap();
let encoder = &mut unsafe { self.encoder.read() };
decoder.process_service_block(
&self.packet[pos as usize..(pos + block_length) as usize],
self.encoder,
encoder,
self.timing,
self.no_rollup,
);
Expand All @@ -202,6 +261,30 @@ impl<'a> Dtvcc<'a> {
}
}

#[no_mangle]
extern "C" fn ccxr_flush_active_decoders(ctx_ptr: *mut lib_cc_decode) {
let ctx = unsafe { &mut *ctx_ptr };
let dtvcc_rust = unsafe { &mut *(ctx.dtvcc_rust as *mut Dtvcc) };

if dtvcc_rust.is_active {
for i in 0..CCX_DTVCC_MAX_SERVICES {
let decoder_opt = &dtvcc_rust.decoders[i];
if decoder_opt.is_none() {
continue;
}
let decoder = decoder_opt.to_owned().unwrap();

if is_true(!dtvcc_rust.services_active[i]) {
continue;
}
if decoder.cc_count > 0 {
ctx.current_field = 3;
ccxr_flush_decoder(dtvcc_rust, decoder);
}
}
}
}

/// A single character symbol
///
/// sym stores the symbol
Expand Down Expand Up @@ -251,8 +334,8 @@ mod test {
false,
))
.ok();
let mut dtvcc_ctx = get_zero_allocated_obj::<dtvcc_ctx>();
let mut decoder = Dtvcc::new(&mut dtvcc_ctx);
let mut dtvcc_settings = get_zero_allocated_obj::<ccx_decoder_dtvcc_settings>();
let mut decoder = Dtvcc::new(&mut dtvcc_settings);

// Case 1: cc_type = 2
let mut dtvcc_report = ccx_decoder_dtvcc_report::default();
Expand Down Expand Up @@ -300,8 +383,8 @@ mod test {
false,
))
.ok();
let mut dtvcc_ctx = get_zero_allocated_obj::<dtvcc_ctx>();
let mut decoder = Dtvcc::new(&mut dtvcc_ctx);
let mut dtvcc_settings = get_zero_allocated_obj::<ccx_decoder_dtvcc_settings>();
let mut decoder = Dtvcc::new(&mut dtvcc_settings);

// Case 1: Without providing last_sequence
let mut dtvcc_report = ccx_decoder_dtvcc_report::default();
Expand Down
13 changes: 7 additions & 6 deletions src/rust/src/decoder/service_decoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,11 @@ use std::{
os::raw::c_uchar,
};

use super::commands::{self, C0CodeSet, C0Command, C1CodeSet, C1Command};
use super::window::{PenPreset, WindowPreset};
use super::{
commands::{self, C0CodeSet, C0Command, C1CodeSet, C1Command},
Dtvcc,
};
use super::{
CCX_DTVCC_MAX_COLUMNS, CCX_DTVCC_MAX_ROWS, CCX_DTVCC_SCREENGRID_COLUMNS,
CCX_DTVCC_SCREENGRID_ROWS,
Expand Down Expand Up @@ -1197,12 +1200,10 @@ impl dtvcc_service_decoder {
}

/// Flush service decoder
#[no_mangle]
extern "C" fn ccxr_flush_decoder(dtvcc: *mut dtvcc_ctx, decoder: *mut dtvcc_service_decoder) {
pub fn ccxr_flush_decoder(dtvcc_rust: &mut Dtvcc, mut decoder: Box<dtvcc_service_decoder>) {
debug!("dtvcc_decoder_flush: Flushing decoder");
let timing = unsafe { &mut *((*dtvcc).timing) };
let encoder = unsafe { &mut *((*dtvcc).encoder as *mut encoder_ctx) };
let decoder = unsafe { &mut *decoder };
let timing = &mut dtvcc_rust.timing;
let encoder = unsafe { &mut *(dtvcc_rust.encoder) };

let mut screen_content_changed = false;
for i in 0..CCX_DTVCC_MAX_WINDOWS {
Expand Down
Loading
Loading