Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
6 changes: 6 additions & 0 deletions src/ccextractor.c
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,12 @@ int start_ccx()
if (!ret)
ret = tmp;
break;
case CCX_SM_SCC:
mprint("\rAnalyzing data in SCC (Scenarist Closed Caption) mode\n");
tmp = raw_loop(ctx);
if (!ret)
ret = tmp;
break;
case CCX_SM_RCWT:
mprint("\rAnalyzing data in CCExtractor's binary format\n");
tmp = rcwt_loop(ctx);
Expand Down
1 change: 1 addition & 0 deletions src/lib_ccx/ccx_common_constants.h
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,7 @@ enum ccx_stream_mode_enum
CCX_SM_GXF = 11,
CCX_SM_MKV = 12,
CCX_SM_MXF = 13,
CCX_SM_SCC = 14, // Scenarist Closed Caption input

CCX_SM_AUTODETECT = 16
};
Expand Down
2 changes: 2 additions & 0 deletions src/lib_ccx/ccx_common_option.c
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,8 @@ void init_options(struct ccx_s_options *options)
options->settings_dtvcc.services_enabled, 0,
CCX_DTVCC_MAX_SERVICES * sizeof(options->settings_dtvcc.services_enabled[0]));

options->scc_framerate = 0; // Default: 29.97fps

#ifdef WITH_LIBCURL
options->curlposturl = NULL;
#endif
Expand Down
1 change: 1 addition & 0 deletions src/lib_ccx/ccx_common_option.h
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,7 @@ struct ccx_s_options // Options from user parameters
int multiprogram;
int out_interval;
int segment_on_key_frames_only;
int scc_framerate; // SCC input framerate: 0=29.97 (default), 1=24, 2=25, 3=30
#ifdef WITH_LIBCURL
char *curlposturl;
#endif
Expand Down
17 changes: 15 additions & 2 deletions src/lib_ccx/general_loop.c
Original file line number Diff line number Diff line change
Expand Up @@ -575,6 +575,7 @@ int raw_loop(struct lib_ccx_ctx *ctx)
struct lib_cc_decode *dec_ctx = NULL;
int caps = 0;
int is_dvdraw = 0; // Flag to track if this is DVD raw format
int is_scc = 0; // Flag to track if this is SCC format
int is_mcc_output = 0; // Flag for MCC output format

dec_ctx = update_decoder_list(ctx);
Expand Down Expand Up @@ -607,13 +608,20 @@ int raw_loop(struct lib_ccx_ctx *ctx)
break;

// Check if this is DVD raw format using Rust detection
if (!is_dvdraw && ccxr_is_dvdraw_header(data->buffer, (unsigned int)data->len))
if (!is_dvdraw && !is_scc && ccxr_is_dvdraw_header(data->buffer, (unsigned int)data->len))
{
is_dvdraw = 1;
mprint("Detected McPoodle's DVD raw format\n");
}

if (is_mcc_output && !is_dvdraw)
// Check if this is SCC format using Rust detection
if (!is_scc && !is_dvdraw && ccxr_is_scc_file(data->buffer, (unsigned int)data->len))
{
is_scc = 1;
mprint("Detected SCC (Scenarist Closed Caption) format\n");
}

if (is_mcc_output && !is_dvdraw && !is_scc)
{
// For MCC output, encode raw data directly without decoding
// This preserves the original CEA-608 byte pairs in CDP format
Expand All @@ -626,6 +634,11 @@ int raw_loop(struct lib_ccx_ctx *ctx)
// Use Rust implementation - handles timing internally
ret = ccxr_process_dvdraw(dec_ctx, dec_sub, data->buffer, (unsigned int)data->len);
}
else if (is_scc)
{
// Use Rust SCC implementation - handles timing internally via SMPTE timecodes
ret = ccxr_process_scc(dec_ctx, dec_sub, data->buffer, (unsigned int)data->len, ccx_options.scc_framerate);
}
else
{
ret = process_raw(dec_ctx, dec_sub, data->buffer, data->len);
Expand Down
14 changes: 9 additions & 5 deletions src/lib_ccx/lib_ccx.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ struct file_report
};

// Stuff for telxcc.c
#define MAX_TLT_PAGES_EXTRACT 8 // Maximum number of teletext pages to extract simultaneously
#define MAX_TLT_PAGES_EXTRACT 8 // Maximum number of teletext pages to extract simultaneously

struct ccx_s_teletext_config
{
Expand All @@ -55,11 +55,11 @@ struct ccx_s_teletext_config
uint8_t nonempty : 1; // produce at least one (dummy) frame
// uint8_t se_mode : 1; // search engine compatible mode => Uses CCExtractor's write_format
// uint64_t utc_refvalue; // UTC referential value => Moved to ccx_decoders_common, so can be used for other decoders (608/xds) too
uint16_t user_page; // Page selected by user (legacy, first page)
uint16_t user_page; // Page selected by user (legacy, first page)
// Multi-page teletext extraction (issue #665)
uint16_t user_pages[MAX_TLT_PAGES_EXTRACT]; // Pages selected by user for extraction
int num_user_pages; // Number of pages to extract (0 = auto-detect single page)
int extract_all_pages; // If 1, extract all detected subtitle pages
uint16_t user_pages[MAX_TLT_PAGES_EXTRACT]; // Pages selected by user for extraction
int num_user_pages; // Number of pages to extract (0 = auto-detect single page)
int extract_all_pages; // If 1, extract all detected subtitle pages
int dolevdist; // 0=Don't attempt to correct errors
int levdistmincnt, levdistmaxpct; // Means 2 fails or less is "the same", 10% or less is also "the same"
struct ccx_boundary_time extraction_start, extraction_end; // Segment we actually process
Expand Down Expand Up @@ -183,6 +183,10 @@ size_t process_raw(struct lib_cc_decode *ctx, struct cc_subtitle *sub, unsigned
unsigned int ccxr_process_dvdraw(struct lib_cc_decode *ctx, struct cc_subtitle *sub, const unsigned char *buffer, unsigned int len);
int ccxr_is_dvdraw_header(const unsigned char *buffer, unsigned int len);

// Rust FFI: SCC (Scenarist Closed Caption) format processing (see src/rust/src/demuxer/scc.rs)
unsigned int ccxr_process_scc(struct lib_cc_decode *ctx, struct cc_subtitle *sub, const unsigned char *buffer, unsigned int len, int framerate);
int ccxr_is_scc_file(const unsigned char *buffer, unsigned int len);

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);
Expand Down
24 changes: 24 additions & 0 deletions src/lib_ccx/stream_functions.c
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,30 @@ void detect_stream_type(struct ccx_demuxer *ctx)
ctx->startbytes[7] == 0xf8)
ctx->stream_mode = CCX_SM_MCPOODLESRAW;
}
// Check for SCC (Scenarist Closed Caption) text format
// SCC files start with "Scenarist_SCC V1.0" (18 bytes), optionally with UTF-8 BOM (3 bytes)
if (ctx->stream_mode == CCX_SM_ELEMENTARY_OR_NOT_FOUND)
{
unsigned char *check_buf = ctx->startbytes;
int check_pos = 0;

// Skip UTF-8 BOM if present
if (ctx->startbytes_avail >= 3 &&
ctx->startbytes[0] == 0xEF &&
ctx->startbytes[1] == 0xBB &&
ctx->startbytes[2] == 0xBF)
{
check_buf += 3;
check_pos = 3;
}

if (ctx->startbytes_avail >= check_pos + 18 &&
memcmp(check_buf, "Scenarist_SCC V1.0", 18) == 0)
{
ctx->stream_mode = CCX_SM_SCC;
mprint("Detected SCC (Scenarist Closed Caption) format\n");
}
}
#ifdef WTV_DEBUG
if (ctx->stream_mode == CCX_SM_ELEMENTARY_OR_NOT_FOUND && ctx->startbytes_avail >= 6)
{
Expand Down
1 change: 1 addition & 0 deletions src/rust/lib_ccxr/src/common/constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,7 @@ pub enum StreamMode {
Gxf = 11,
Mkv = 12,
Mxf = 13,
Scc = 14, // Scenarist Closed Caption input
Autodetect = 16,
}
#[derive(Debug, Eq, Clone, Copy)]
Expand Down
3 changes: 3 additions & 0 deletions src/rust/lib_ccxr/src/common/options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -517,6 +517,8 @@ pub struct Options {
pub multiprogram: bool,
pub out_interval: i32,
pub segment_on_key_frames_only: bool,
/// SCC input framerate: 0=29.97 (default), 1=24, 2=25, 3=30
pub scc_framerate: i32,
pub debug_mask: DebugMessageMask,

#[cfg(feature = "with_libcurl")]
Expand Down Expand Up @@ -618,6 +620,7 @@ impl Default for Options {
multiprogram: Default::default(),
out_interval: -1,
segment_on_key_frames_only: Default::default(),
scc_framerate: 0, // 0 = 29.97fps (default)
debug_mask: DebugMessageMask::new(
DebugMessageFlag::GENERIC_NOTICE,
DebugMessageFlag::VERBOSE,
Expand Down
5 changes: 5 additions & 0 deletions src/rust/src/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,11 @@ pub struct Args {
/// DVD Recorder)
#[arg(long="90090", verbatim_doc_comment, help_heading=OPTIONS_AFFECTING_INPUT_FILES)]
pub mpeg90090: bool,
/// Set the frame rate for SCC (Scenarist Closed Caption) input files.
/// Valid values: 29.97 (default), 24, 25, 30
/// Example: --scc-framerate 25
#[arg(long="scc-framerate", verbatim_doc_comment, value_name="fps", help_heading=OPTIONS_AFFECTING_INPUT_FILES)]
pub scc_framerate: Option<String>,
/// By default, ccextractor will process input files in
/// sequence as if they were all one large file (i.e.
/// split by a generic, non video-aware tool. If you
Expand Down
3 changes: 3 additions & 0 deletions src/rust/src/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,7 @@ pub unsafe fn copy_from_rust(ccx_s_options: *mut ccx_s_options, options: Options
(*ccx_s_options).multiprogram = options.multiprogram as _;
(*ccx_s_options).out_interval = options.out_interval;
(*ccx_s_options).segment_on_key_frames_only = options.segment_on_key_frames_only as _;
(*ccx_s_options).scc_framerate = options.scc_framerate;
#[cfg(feature = "with_libcurl")]
{
if options.curlposturl.is_some() {
Expand Down Expand Up @@ -531,6 +532,7 @@ pub unsafe fn copy_to_rust(ccx_s_options: *const ccx_s_options) -> Options {
options.multiprogram = (*ccx_s_options).multiprogram != 0;
options.out_interval = (*ccx_s_options).out_interval;
options.segment_on_key_frames_only = (*ccx_s_options).segment_on_key_frames_only != 0;
options.scc_framerate = (*ccx_s_options).scc_framerate;

// Handle optional features with conditional compilation
#[cfg(feature = "with_libcurl")]
Expand Down Expand Up @@ -873,6 +875,7 @@ impl CType<u32> for StreamMode {
StreamMode::Gxf => ccx_stream_mode_enum_CCX_SM_GXF as _,
StreamMode::Mkv => ccx_stream_mode_enum_CCX_SM_MKV as _,
StreamMode::Mxf => ccx_stream_mode_enum_CCX_SM_MXF as _,
StreamMode::Scc => ccx_stream_mode_enum_CCX_SM_SCC as _,
StreamMode::Autodetect => ccx_stream_mode_enum_CCX_SM_AUTODETECT as _,
_ => ccx_stream_mode_enum_CCX_SM_ELEMENTARY_OR_NOT_FOUND as _,
}
Expand Down
1 change: 1 addition & 0 deletions src/rust/src/ctorust.rs
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,7 @@ impl FromCType<ccx_stream_mode_enum> for StreamMode {
11 => StreamMode::Gxf,
12 => StreamMode::Mkv,
13 => StreamMode::Mxf,
14 => StreamMode::Scc,
16 => StreamMode::Autodetect,
_ => StreamMode::ElementaryOrNotFound,
})
Expand Down
1 change: 1 addition & 0 deletions src/rust/src/demuxer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,5 @@ pub mod common_types;
pub mod demux;
pub mod demuxer_data;
pub mod dvdraw;
pub mod scc;
pub mod stream_functions;
Loading
Loading