Skip to content

Commit ebfa31c

Browse files
cfsmp3claude
andcommitted
fix(raw): Fix premature EOF and timing overflow in raw_loop (CCExtractor#1565)
Fix raw caption file processing that would stop at exactly 9:43:00 (2MB). Root causes and fixes: 1. Premature EOF: After processing first chunk (BUFSIZE ~2MB), data->len was never reset. On next iteration, general_get_more_data() calculated want = BUFSIZE - len = 0 and returned EOF immediately. Fix: Reset data->len = 0 after each chunk and change loop condition. 2. 32-bit integer overflow: The calculation cb_field1 * 1001 / 30 * 90 overflowed for large cb_field1 values (>1M). For example, 34,989,487 * 90 = 3,149,053,830 exceeds 32-bit signed max. Fix: Cast cb_field1 to LLONG before multiplication. 3. Timing initialization: Raw mode needs min_pts=0, sync_pts=0, and pts_set=MinPtsSet for correct fts_now calculation. Tested with sample files from issue CCExtractor#1565: - DTV3.raw: Now processes to 17:59:56 (was stopping at 9:43) - DTV4.raw: Now processes to 14:00:00 (was stopping at 9:43) - DTV5.raw: Now processes to 13:19:59 (was stopping at 9:43) Closes CCExtractor#1565 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent c3f637a commit ebfa31c

File tree

1 file changed

+21
-5
lines changed

1 file changed

+21
-5
lines changed

src/lib_ccx/general_loop.c

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -534,8 +534,14 @@ int raw_loop(struct lib_ccx_ctx *ctx)
534534
dec_ctx = update_decoder_list(ctx);
535535
dec_sub = &dec_ctx->dec_sub;
536536

537-
set_current_pts(dec_ctx->timing, 90);
538-
set_fts(dec_ctx->timing); // Now set the FTS related variables
537+
// For raw mode, timing is derived from the caption block counter (cb_field1).
538+
// We set min_pts=0 and pts_set=MinPtsSet so set_fts() will calculate fts_now.
539+
// Initialize timing for raw mode - no video PTS, just caption block counting.
540+
dec_ctx->timing->min_pts = 0;
541+
dec_ctx->timing->sync_pts = 0;
542+
dec_ctx->timing->pts_set = 2; // MinPtsSet
543+
set_current_pts(dec_ctx->timing, 0);
544+
set_fts(dec_ctx->timing);
539545

540546
do
541547
{
@@ -561,8 +567,13 @@ int raw_loop(struct lib_ccx_ctx *ctx)
561567
else
562568
{
563569
ret = process_raw(dec_ctx, dec_sub, data->buffer, data->len);
564-
// For regular raw format, advance timing based on field 1 blocks
565-
add_current_pts(dec_ctx->timing, cb_field1 * 1001 / 30 * (MPEG_CLOCK_FREQ / 1000));
570+
// For raw mode, cb_field1 is incremented by do_cb() for each CC pair.
571+
// After processing each chunk, add the accumulated time to current_pts
572+
// and call set_fts() to update fts_now. set_fts() resets cb_field1 to 0,
573+
// so each chunk's timing is added incrementally.
574+
// Note: Cast cb_field1 to LLONG to prevent 32-bit integer overflow
575+
// when calculating ticks for large raw files (issue #1565).
576+
add_current_pts(dec_ctx->timing, (LLONG)cb_field1 * 1001 / 30 * (MPEG_CLOCK_FREQ / 1000));
566577
set_fts(dec_ctx->timing);
567578
}
568579

@@ -573,7 +584,12 @@ int raw_loop(struct lib_ccx_ctx *ctx)
573584
dec_sub->got_output = 0;
574585
}
575586

576-
} while (data->len);
587+
// Reset buffer length after processing so we can read more data
588+
// Without this, data->len stays at BUFSIZE and general_get_more_data
589+
// returns CCX_EOF prematurely (it calculates want = BUFSIZE - len = 0)
590+
data->len = 0;
591+
592+
} while (1); // Loop exits via break on CCX_EOF or terminate_asap
577593
free(data);
578594
return caps;
579595
}

0 commit comments

Comments
 (0)