diff --git a/src/lib_ccx/stream_functions.c b/src/lib_ccx/stream_functions.c index 14d2372e8..96287133f 100644 --- a/src/lib_ccx/stream_functions.c +++ b/src/lib_ccx/stream_functions.c @@ -12,8 +12,14 @@ #include "ccx_gxf.h" #include "ccx_demuxer_mxf.h" +extern void ccxr_detect_stream_type(struct ccx_demuxer *ctx); + void detect_stream_type(struct ccx_demuxer *ctx) { +#ifndef DISABLE_RUST + ccxr_detect_stream_type(ctx); // Use the Rust implementation +#else + // Original C code ctx->stream_mode = CCX_SM_ELEMENTARY_OR_NOT_FOUND; // Not found ctx->startbytes_avail = (int)buffered_read_opt(ctx, ctx->startbytes, STARTBYTESLENGTH); @@ -216,6 +222,7 @@ void detect_stream_type(struct ccx_demuxer *ctx) } // Don't use STARTBYTESLENGTH. It might be longer than the file length! return_to_buffer(ctx, ctx->startbytes, ctx->startbytes_avail); +#endif } int detect_myth(struct ccx_demuxer *ctx) diff --git a/src/rust/lib_ccxr/src/util/stream_detector.rs b/src/rust/lib_ccxr/src/util/stream_detector.rs new file mode 100644 index 000000000..5fe0c1fc0 --- /dev/null +++ b/src/rust/lib_ccxr/src/util/stream_detector.rs @@ -0,0 +1,262 @@ +use std::io::{self, Read}; + +const STARTBYTESLENGTH: usize = 1024; +const CCX_SM_ELEMENTARY_OR_NOT_FOUND: i32 = 0; +const CCX_SM_ASF: i32 = 1; +const CCX_SM_MKV: i32 = 2; +const CCX_SM_GXF: i32 = 3; +const CCX_SM_WTV: i32 = 4; +const CCX_SM_HEX_DUMP: i32 = 5; +const CCX_SM_RCWT: i32 = 6; +const CCX_SM_MP4: i32 = 7; +const CCX_SM_MXF: i32 = 8; +const CCX_SM_TRANSPORT: i32 = 9; +const CCX_SM_PROGRAM: i32 = 10; + +struct CcxDemuxer { + stream_mode: i32, + startbytes: Vec, + startbytes_avail: usize, + startbytes_pos: usize, + m2ts: i32, + strangeheader: i32, + private_data: Option<()>, +} + +impl CcxDemuxer { + fn new() -> Self { + Self { + stream_mode: CCX_SM_ELEMENTARY_OR_NOT_FOUND, + startbytes: vec![0; STARTBYTESLENGTH], + startbytes_avail: 0, + startbytes_pos: 0, + m2ts: 0, + strangeheader: 0, + private_data: None, + } + } +} + +fn buffered_read_opt(ctx: &mut CcxDemuxer, buffer: &mut [u8], length: usize) -> io::Result { + // Implement the buffered read logic here + Ok(0) +} + +fn fatal(exit_code: i32, message: &str) { + eprintln!("{}", message); + std::process::exit(exit_code); +} + +fn ccx_gxf_probe(startbytes: &[u8], startbytes_avail: usize) -> bool { + // Implement the GXF probe logic here + false +} + +fn ccx_gxf_init(ctx: &mut CcxDemuxer) -> Option<()> { + // Implement the GXF init logic here + None +} + +fn ccx_probe_mxf(ctx: &mut CcxDemuxer) -> bool { + // Implement the MXF probe logic here + false +} + +fn ccx_mxf_init(ctx: &mut CcxDemuxer) -> Option<()> { + // Implement the MXF init logic here + None +} + +fn is_valid_mp4_box( + buffer: &[u8], + position: usize, + next_box_location: &mut usize, + box_score: &mut i32, +) -> bool { + // Implement the MP4 box validation logic here + false +} + +fn return_to_buffer(ctx: &mut CcxDemuxer, buffer: &[u8], length: usize) { + // Implement the return to buffer logic here +} + +pub fn detect_stream_type(ctx: &mut CcxDemuxer) { + ctx.stream_mode = CCX_SM_ELEMENTARY_OR_NOT_FOUND; + ctx.startbytes_avail = match buffered_read_opt(ctx, &mut ctx.startbytes, STARTBYTESLENGTH) { + Ok(n) => n, + Err(_) => { + fatal(1, "Error reading input file!\n"); + return; + } + }; + + if ctx.startbytes_avail >= 4 { + if ctx.startbytes[0] == 0x30 + && ctx.startbytes[1] == 0x26 + && ctx.startbytes[2] == 0xb2 + && ctx.startbytes[3] == 0x75 + { + ctx.stream_mode = CCX_SM_ASF; + } + } + + if ctx.stream_mode == CCX_SM_ELEMENTARY_OR_NOT_FOUND && ctx.startbytes_avail >= 4 { + if (ctx.startbytes[0] == 0x1a + && ctx.startbytes[1] == 0x45 + && ctx.startbytes[2] == 0xdf + && ctx.startbytes[3] == 0xa3) + || (ctx.startbytes[0] == 0x18 + && ctx.startbytes[1] == 0x53 + && ctx.startbytes[2] == 0x80 + && ctx.startbytes[3] == 0x67) + { + ctx.stream_mode = CCX_SM_MKV; + } + } + + if ctx.stream_mode == CCX_SM_ELEMENTARY_OR_NOT_FOUND { + if ccx_gxf_probe(&ctx.startbytes, ctx.startbytes_avail) { + ctx.stream_mode = CCX_SM_GXF; + ctx.private_data = ccx_gxf_init(ctx); + } + } + + if ctx.stream_mode == CCX_SM_ELEMENTARY_OR_NOT_FOUND && ctx.startbytes_avail >= 4 { + if ctx.startbytes[0] == 0xb7 + && ctx.startbytes[1] == 0xd8 + && ctx.startbytes[2] == 0x00 + && ctx.startbytes[3] == 0x20 + { + ctx.stream_mode = CCX_SM_WTV; + } + } + + if ctx.stream_mode == CCX_SM_ELEMENTARY_OR_NOT_FOUND && ctx.startbytes_avail >= 11 { + if ctx.startbytes[0] == 0xCC + && ctx.startbytes[1] == 0xCC + && ctx.startbytes[2] == 0xED + && ctx.startbytes[8] == 0 + && ctx.startbytes[9] == 0 + && ctx.startbytes[10] == 0 + { + ctx.stream_mode = CCX_SM_RCWT; + } + } + + if (ctx.stream_mode == CCX_SM_ELEMENTARY_OR_NOT_FOUND || true/* ccx_options.print_file_reports */) + && ctx.startbytes_avail >= 4 + { + let mut idx = 0; + let mut next_box_location = 0; + let mut box_score = 0; + + while idx < ctx.startbytes_avail - 8 { + if is_valid_mp4_box(&ctx.startbytes, idx, &mut next_box_location, &mut box_score) + && next_box_location > idx + { + idx = next_box_location; + if box_score > 7 { + break; + } + continue; + } else { + box_score = 0; + idx += 1; + } + } + + if box_score > 1 { + ctx.stream_mode = CCX_SM_MP4; + } + } + + if ctx.stream_mode == CCX_SM_ELEMENTARY_OR_NOT_FOUND { + if ccx_probe_mxf(ctx) { + ctx.stream_mode = CCX_SM_MXF; + ctx.private_data = ccx_mxf_init(ctx); + } + } + + if ctx.stream_mode == CCX_SM_ELEMENTARY_OR_NOT_FOUND { + if ctx.startbytes_avail > 188 * 8 { + for i in 0..188 { + if ctx.startbytes[i] == 0x47 + && ctx.startbytes[i + 188] == 0x47 + && ctx.startbytes[i + 188 * 2] == 0x47 + && ctx.startbytes[i + 188 * 3] == 0x47 + && ctx.startbytes[i + 188 * 4] == 0x47 + && ctx.startbytes[i + 188 * 5] == 0x47 + && ctx.startbytes[i + 188 * 6] == 0x47 + && ctx.startbytes[i + 188 * 7] == 0x47 + { + ctx.startbytes_pos = i; + ctx.stream_mode = CCX_SM_TRANSPORT; + ctx.m2ts = 0; + break; + } + } + + if ctx.stream_mode == CCX_SM_TRANSPORT { + println!("detect_stream_type: detected as TS"); + return_to_buffer(ctx, &ctx.startbytes, ctx.startbytes_avail); + return; + } + + for i in 0..192 { + if ctx.startbytes[i + 4] == 0x47 + && ctx.startbytes[i + 4 + 192] == 0x47 + && ctx.startbytes[i + 192 * 2 + 4] == 0x47 + && ctx.startbytes[i + 192 * 3 + 4] == 0x47 + && ctx.startbytes[i + 192 * 4 + 4] == 0x47 + && ctx.startbytes[i + 192 * 5 + 4] == 0x47 + && ctx.startbytes[i + 192 * 6 + 4] == 0x47 + && ctx.startbytes[i + 192 * 7 + 4] == 0x47 + { + ctx.startbytes_pos = i; + ctx.stream_mode = CCX_SM_TRANSPORT; + ctx.m2ts = 1; + break; + } + } + + if ctx.stream_mode == CCX_SM_TRANSPORT { + println!("detect_stream_type: detected as M2TS"); + return_to_buffer(ctx, &ctx.startbytes, ctx.startbytes_avail); + return; + } + + for i in 0..(ctx.startbytes_avail.min(50000) - 3) { + if ctx.startbytes[i] == 0x00 + && ctx.startbytes[i + 1] == 0x00 + && ctx.startbytes[i + 2] == 0x01 + && ctx.startbytes[i + 3] == 0xBA + { + ctx.startbytes_pos = i; + ctx.stream_mode = CCX_SM_PROGRAM; + break; + } + } + + if ctx.stream_mode == CCX_SM_PROGRAM { + println!("detect_stream_type: detected as PS"); + } + + if ctx.startbytes[0] == b'T' + && ctx.startbytes[1] == b'i' + && ctx.startbytes[2] == b'V' + && ctx.startbytes[3] == b'o' + { + println!("detect_stream_type: detected as Tivo PS"); + ctx.startbytes_pos = 187; + ctx.stream_mode = CCX_SM_PROGRAM; + ctx.strangeheader = 1; + } + } else { + ctx.startbytes_pos = 0; + ctx.stream_mode = CCX_SM_ELEMENTARY_OR_NOT_FOUND; + } + } + + return_to_buffer(ctx, &ctx.startbytes, ctx.startbytes_avail); +} diff --git a/src/rust/src/libccxr_exports/mod.rs b/src/rust/src/libccxr_exports/mod.rs index c2f64a258..68e02380c 100644 --- a/src/rust/src/libccxr_exports/mod.rs +++ b/src/rust/src/libccxr_exports/mod.rs @@ -93,3 +93,10 @@ pub unsafe extern "C" fn ccxr_levenshtein_dist_char( ans.try_into() .expect("Failed to convert the levenshtein distance to C int") } + +#[no_mangle] +pub extern "C" fn ccxr_detect_stream_type(ctx: *mut CcxDemuxer) { + unsafe { + detect_stream_type(&mut *ctx); + } +} diff --git a/src/thirdparty/freetype/gzip/ftzconf.h b/src/thirdparty/freetype/gzip/ftzconf.h index 3abf0ba03..616798b87 100644 --- a/src/thirdparty/freetype/gzip/ftzconf.h +++ b/src/thirdparty/freetype/gzip/ftzconf.h @@ -215,9 +215,14 @@ # define FAR #endif -#if !defined(MACOS) && !defined(TARGET_OS_MAC) +#if !defined(__APPLE__) && !defined(__MACH__) typedef unsigned char Byte; /* 8 bits */ #endif + +#if defined(__APPLE__) && defined(__MACH__) +typedef char Byte; /* 8 bits(1 byte) */ +#endif + typedef unsigned int uInt; /* 16 bits or more */ typedef unsigned long uLong; /* 32 bits or more */ diff --git a/src/thirdparty/freetype/gzip/zutil.h b/src/thirdparty/freetype/gzip/zutil.h index c9688cd9c..dc18e98e9 100644 --- a/src/thirdparty/freetype/gzip/zutil.h +++ b/src/thirdparty/freetype/gzip/zutil.h @@ -105,7 +105,7 @@ typedef unsigned long ulg; # define OS_CODE 0x05 #endif -#if defined(MACOS) || defined(TARGET_OS_MAC) +#if defined(__APPLE__) || defined(__MACH__) # define OS_CODE 0x07 # if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os # include /* for fdopen */