Skip to content

Commit d0d46fc

Browse files
cfsmp3claude
andcommitted
fix(mcc): Add MCC output support for raw caption files
Previously, when using -out=mcc with raw input files (-in=raw), CCExtractor would print "Output format not supported" and produce no output. This was because the raw file processing path decoded CEA-608 data to text, but MCC format requires raw cc_data bytes. The fix adds a new code path that bypasses the 608 decoder when MCC output is requested: - Added process_raw_for_mcc() helper function that: - Converts 2-byte raw pairs to 3-byte cc_data format - Wraps each CC pair in CDP format via mcc_encode_cc_data() - Maintains proper timing at 29.97fps - Modified raw_loop() to detect MCC output and use the new path Test results with McPoodle raw files: - Before: "Output format not supported" (exit code 10) - After: Valid MCC file with proper timing and CDP-wrapped data Fixes #1542 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <[email protected]>
1 parent 5f0c672 commit d0d46fc

File tree

1 file changed

+65
-3
lines changed

1 file changed

+65
-3
lines changed

src/lib_ccx/general_loop.c

Lines changed: 65 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
#include "dvb_subtitle_decoder.h"
1010
#include "ccx_encoders_common.h"
11+
#include "ccx_encoders_mcc.h"
1112
#include "activity.h"
1213
#include "utility.h"
1314
#include "ccx_demuxer.h"
@@ -520,6 +521,50 @@ void process_hex(struct lib_ccx_ctx *ctx, char *filename)
520521
fclose(fr);
521522
}
522523
#endif
524+
525+
/* Process raw caption data (2-byte pairs) and encode directly to MCC format.
526+
* This bypasses the 608 decoder and writes raw cc_data to MCC.
527+
* Used when -out=mcc is specified with raw input files (issue #1542). */
528+
static size_t process_raw_for_mcc(struct encoder_ctx *enc_ctx, struct lib_cc_decode *dec_ctx,
529+
unsigned char *buffer, size_t len)
530+
{
531+
unsigned char cc_data[3];
532+
size_t i;
533+
size_t pairs_processed = 0;
534+
535+
// Set frame rate to 29.97fps (code 4) for raw 608 captions
536+
// This is needed for proper MCC timing
537+
if (dec_ctx->current_frame_rate == 0)
538+
dec_ctx->current_frame_rate = 4; // CCX_FR_29_97
539+
540+
cc_data[0] = 0x04; // Field 1, cc_valid=1, cc_type=0 (NTSC field 1)
541+
542+
for (i = 0; i < len; i += 2)
543+
{
544+
// Skip broadcast header (0xff 0xff)
545+
if (!dec_ctx->saw_caption_block && buffer[i] == 0xff && buffer[i + 1] == 0xff)
546+
continue;
547+
548+
dec_ctx->saw_caption_block = 1;
549+
cc_data[1] = buffer[i];
550+
cc_data[2] = buffer[i + 1];
551+
552+
// Update timing for this CC pair (each pair is one frame at 29.97fps)
553+
// Timing: 1001/30 ms per pair = ~33.37ms
554+
set_fts(enc_ctx->timing);
555+
556+
// Encode this CC pair to MCC format
557+
mcc_encode_cc_data(enc_ctx, dec_ctx, cc_data, 1);
558+
559+
// Advance timing for next pair
560+
add_current_pts(enc_ctx->timing, 1001 * (MPEG_CLOCK_FREQ / 1000) / 30);
561+
562+
pairs_processed++;
563+
}
564+
565+
return pairs_processed;
566+
}
567+
523568
// Raw file process
524569
int raw_loop(struct lib_ccx_ctx *ctx)
525570
{
@@ -529,11 +574,20 @@ int raw_loop(struct lib_ccx_ctx *ctx)
529574
struct encoder_ctx *enc_ctx = update_encoder_list(ctx);
530575
struct lib_cc_decode *dec_ctx = NULL;
531576
int caps = 0;
532-
int is_dvdraw = 0; // Flag to track if this is DVD raw format
577+
int is_dvdraw = 0; // Flag to track if this is DVD raw format
578+
int is_mcc_output = 0; // Flag for MCC output format
533579

534580
dec_ctx = update_decoder_list(ctx);
535581
dec_sub = &dec_ctx->dec_sub;
536582

583+
// Check if MCC output is requested (issue #1542)
584+
if (enc_ctx && dec_ctx->write_format == CCX_OF_MCC)
585+
{
586+
is_mcc_output = 1;
587+
// Share timing context between decoder and encoder for MCC
588+
enc_ctx->timing = dec_ctx->timing;
589+
}
590+
537591
// For raw mode, timing is derived from the caption block counter (cb_field1).
538592
// We set min_pts=0 and pts_set=MinPtsSet so set_fts() will calculate fts_now.
539593
// Initialize timing for raw mode - no video PTS, just caption block counting.
@@ -559,7 +613,15 @@ int raw_loop(struct lib_ccx_ctx *ctx)
559613
mprint("Detected McPoodle's DVD raw format\n");
560614
}
561615

562-
if (is_dvdraw)
616+
if (is_mcc_output && !is_dvdraw)
617+
{
618+
// For MCC output, encode raw data directly without decoding
619+
// This preserves the original CEA-608 byte pairs in CDP format
620+
size_t pairs = process_raw_for_mcc(enc_ctx, dec_ctx, data->buffer, data->len);
621+
if (pairs > 0)
622+
caps = 1;
623+
}
624+
else if (is_dvdraw)
563625
{
564626
// Use Rust implementation - handles timing internally
565627
ret = ccxr_process_dvdraw(dec_ctx, dec_sub, data->buffer, (unsigned int)data->len);
@@ -577,7 +639,7 @@ int raw_loop(struct lib_ccx_ctx *ctx)
577639
set_fts(dec_ctx->timing);
578640
}
579641

580-
if (dec_sub->got_output)
642+
if (!is_mcc_output && dec_sub->got_output)
581643
{
582644
caps = 1;
583645
encode_sub(enc_ctx, dec_sub);

0 commit comments

Comments
 (0)