Skip to content

Commit 1349ef2

Browse files
cfsmp3claude
andcommitted
fix(rust): Use persistent DtvccRust context in ccxr_process_cc_data
The ccxr_process_cc_data function was still accessing dec_ctx.dtvcc (which is NULL when Rust is enabled), causing a null pointer panic. Changed to use dec_ctx.dtvcc_rust (the persistent DtvccRust context) instead, which fixes the crash when processing CEA-708 data. Added do_cb_dtvcc_rust() function that works with DtvccRust instead of the old Dtvcc struct. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent aa98fe0 commit 1349ef2

File tree

1 file changed

+63
-4
lines changed

1 file changed

+63
-4
lines changed

src/rust/src/lib.rs

Lines changed: 63 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -367,6 +367,7 @@ pub extern "C" fn ccxr_dtvcc_is_active(dtvcc_ptr: *mut std::ffi::c_void) -> i32
367367
/// # Safety
368368
/// dec_ctx should not be a null pointer
369369
/// data should point to cc_data of length cc_count
370+
/// dec_ctx.dtvcc_rust must point to a valid DtvccRust instance
370371
#[no_mangle]
371372
extern "C" fn ccxr_process_cc_data(
372373
dec_ctx: *mut lib_cc_decode,
@@ -378,13 +379,20 @@ extern "C" fn ccxr_process_cc_data(
378379
.map(|x| unsafe { *data.add(x as usize) })
379380
.collect();
380381
let dec_ctx = unsafe { &mut *dec_ctx };
381-
let dtvcc_ctx = unsafe { &mut *dec_ctx.dtvcc };
382-
let mut dtvcc = Dtvcc::new(dtvcc_ctx);
382+
383+
// Use the persistent DtvccRust context from dtvcc_rust
384+
let dtvcc_rust = dec_ctx.dtvcc_rust as *mut DtvccRust;
385+
if dtvcc_rust.is_null() {
386+
warn!("ccxr_process_cc_data: dtvcc_rust is null");
387+
return ret;
388+
}
389+
let dtvcc = unsafe { &mut *dtvcc_rust };
390+
383391
for cc_block in cc_data.chunks_exact_mut(3) {
384392
if !validate_cc_pair(cc_block) {
385393
continue;
386394
}
387-
let success = do_cb_dtvcc(dec_ctx, &mut dtvcc, cc_block);
395+
let success = do_cb_dtvcc_rust(dec_ctx, dtvcc, cc_block);
388396
if success {
389397
ret = 0;
390398
}
@@ -427,7 +435,7 @@ pub fn verify_parity(data: u8) -> bool {
427435
false
428436
}
429437

430-
/// Process CC data according to its type
438+
/// Process CC data according to its type (using Dtvcc)
431439
pub fn do_cb_dtvcc(ctx: &mut lib_cc_decode, dtvcc: &mut Dtvcc, cc_block: &[u8]) -> bool {
432440
let cc_valid = (cc_block[0] & 4) >> 2;
433441
let cc_type = cc_block[0] & 3;
@@ -478,6 +486,57 @@ pub fn do_cb_dtvcc(ctx: &mut lib_cc_decode, dtvcc: &mut Dtvcc, cc_block: &[u8])
478486
true
479487
}
480488

489+
/// Process CC data according to its type (using DtvccRust - persistent context)
490+
pub fn do_cb_dtvcc_rust(ctx: &mut lib_cc_decode, dtvcc: &mut DtvccRust, cc_block: &[u8]) -> bool {
491+
let cc_valid = (cc_block[0] & 4) >> 2;
492+
let cc_type = cc_block[0] & 3;
493+
let mut timeok = true;
494+
495+
if ctx.write_format != ccx_output_format::CCX_OF_DVDRAW
496+
&& ctx.write_format != ccx_output_format::CCX_OF_RAW
497+
&& (cc_block[0] == 0xFA || cc_block[0] == 0xFC || cc_block[0] == 0xFD)
498+
&& (cc_block[1] & 0x7F) == 0
499+
&& (cc_block[2] & 0x7F) == 0
500+
{
501+
return true;
502+
}
503+
504+
if cc_valid == 1 || cc_type == 3 {
505+
ctx.cc_stats[cc_type as usize] += 1;
506+
match cc_type {
507+
// Type 0 and 1 are for CEA-608 data. Handled by C code, do nothing
508+
0 | 1 => {}
509+
// Type 2 and 3 are for CEA-708 data.
510+
2 | 3 => {
511+
let current_time = if ctx.timing.is_null() {
512+
0
513+
} else {
514+
unsafe { (*ctx.timing).get_fts(ctx.current_field as u8) }
515+
};
516+
ctx.current_field = 3;
517+
518+
// Check whether current time is within start and end bounds
519+
if is_true(ctx.extraction_start.set)
520+
&& current_time < ctx.extraction_start.time_in_ms
521+
{
522+
timeok = false;
523+
}
524+
if is_true(ctx.extraction_end.set) && current_time > ctx.extraction_end.time_in_ms {
525+
timeok = false;
526+
ctx.processed_enough = 1;
527+
}
528+
529+
if timeok && ctx.write_format != ccx_output_format::CCX_OF_RAW {
530+
dtvcc.process_cc_data(cc_valid, cc_type, cc_block[1], cc_block[2]);
531+
}
532+
unsafe { cb_708 += 1 }
533+
}
534+
_ => warn!("Invalid cc_type"),
535+
}
536+
}
537+
true
538+
}
539+
481540
#[cfg(windows)]
482541
#[no_mangle]
483542
extern "C" fn ccxr_close_handle(handle: RawHandle) {

0 commit comments

Comments
 (0)