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
116 changes: 115 additions & 1 deletion src/lib_ccx/general_loop.c
Original file line number Diff line number Diff line change
Expand Up @@ -567,6 +567,104 @@ static size_t process_raw_for_mcc(struct encoder_ctx *enc_ctx, struct lib_cc_dec
}

// Raw file process
// Parse raw CDP (Caption Distribution Packet) data
// Returns number of bytes processed
static size_t process_raw_cdp(struct encoder_ctx *enc_ctx, struct lib_cc_decode *dec_ctx,
struct cc_subtitle *sub, unsigned char *buffer, size_t len)
{
size_t pos = 0;
int cdp_count = 0;

while (pos + 10 < len) // Minimum CDP size
{
// Check for CDP identifier
if (buffer[pos] != 0x96 || buffer[pos + 1] != 0x69)
{
pos++;
continue;
}

unsigned char cdp_length = buffer[pos + 2];
if (pos + cdp_length > len)
break; // Incomplete CDP packet

unsigned char framerate_byte = buffer[pos + 3];
int framerate_code = framerate_byte >> 4;

// Skip to find cc_data section (0x72)
size_t cdp_pos = pos + 4; // After identifier, length, framerate
int cc_count = 0;
unsigned char *cc_data = NULL;

// Skip header sequence counter (2 bytes)
cdp_pos += 2;

// Look for cc_data section (0x72) within CDP
while (cdp_pos < pos + cdp_length - 4)
{
if (buffer[cdp_pos] == 0x72) // cc_data section
{
cc_count = buffer[cdp_pos + 1] & 0x1F;
cc_data = buffer + cdp_pos + 2;
break;
}
else if (buffer[cdp_pos] == 0x71) // time code section
{
cdp_pos += 5; // Skip time code section
}
else if (buffer[cdp_pos] == 0x73) // service info section
{
break; // Past cc_data
}
else if (buffer[cdp_pos] == 0x74) // footer
{
break;
}
else
{
cdp_pos++;
}
}

if (cc_count > 0 && cc_data != NULL)
{
// Calculate PTS based on CDP frame count and frame rate
static const int fps_table[] = {0, 24, 24, 25, 30, 30, 50, 60, 60};
int fps = (framerate_code < 9) ? fps_table[framerate_code] : 30;
LLONG pts = (LLONG)cdp_count * 90000 / fps;

// Set timing if not already set
if (dec_ctx->timing->pts_set == 0)
{
dec_ctx->timing->min_pts = pts;
dec_ctx->timing->pts_set = 2;
dec_ctx->timing->sync_pts = pts;
}
set_current_pts(dec_ctx->timing, pts);
set_fts(dec_ctx->timing);

#ifndef DISABLE_RUST
// Enable DTVCC decoder for CEA-708 captions
if (dec_ctx->dtvcc_rust)
{
int is_active = ccxr_dtvcc_is_active(dec_ctx->dtvcc_rust);
if (!is_active)
{
ccxr_dtvcc_set_active(dec_ctx->dtvcc_rust, 1);
}
}
#endif
// Process cc_data triplets through process_cc_data for 708 support
process_cc_data(enc_ctx, dec_ctx, cc_data, cc_count, sub);
cdp_count++;
}

pos += cdp_length;
}

return pos;
}

int raw_loop(struct lib_ccx_ctx *ctx)
{
LLONG ret;
Expand All @@ -577,6 +675,7 @@ int raw_loop(struct lib_ccx_ctx *ctx)
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_cdp = 0; // Flag to track if this is raw CDP format
int is_mcc_output = 0; // Flag for MCC output format

dec_ctx = update_decoder_list(ctx);
Expand Down Expand Up @@ -622,7 +721,15 @@ int raw_loop(struct lib_ccx_ctx *ctx)
mprint("Detected SCC (Scenarist Closed Caption) format\n");
}

if (is_mcc_output && !is_dvdraw && !is_scc)
// Check if this is raw CDP format (starts with 0x9669)
if (!is_cdp && !is_scc && !is_dvdraw && data->len >= 2 &&
data->buffer[0] == 0x96 && data->buffer[1] == 0x69)
{
is_cdp = 1;
mprint("Detected raw CDP (Caption Distribution Packet) format\n");
}

if (is_mcc_output && !is_dvdraw && !is_scc && !is_cdp)
{
// For MCC output, encode raw data directly without decoding
// This preserves the original CEA-608 byte pairs in CDP format
Expand All @@ -640,6 +747,13 @@ int raw_loop(struct lib_ccx_ctx *ctx)
// 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 if (is_cdp)
{
// Process raw CDP packets (e.g., from SDI VANC capture)
ret = process_raw_cdp(enc_ctx, dec_ctx, dec_sub, data->buffer, data->len);
if (ret > 0)
caps = 1;
}
else
{
ret = process_raw(dec_ctx, dec_sub, data->buffer, data->len);
Expand Down
13 changes: 5 additions & 8 deletions src/rust/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,14 +103,11 @@ fn main() {
if std::path::Path::new(cellar_ffmpeg).exists() {
// Find the FFmpeg version directory
if let Ok(entries) = std::fs::read_dir(cellar_ffmpeg) {
for entry in entries {
if let Ok(entry) = entry {
let include_path = entry.path().join("include");
if include_path.exists() {
builder =
builder.clang_arg(format!("-I{}", include_path.display()));
break;
}
for entry in entries.flatten() {
let include_path = entry.path().join("include");
if include_path.exists() {
builder = builder.clang_arg(format!("-I{}", include_path.display()));
break;
}
}
}
Expand Down
Loading