mirror of
https://github.com/CCExtractor/ccextractor.git
synced 2026-07-08 18:06:30 +00:00
fix(608): handle pop-on to roll-up transition ending at EOF (#2268)
When a stream switches from pop-on to roll-up mode and ends before check_roll_up() reports changes=1 (fewer lines than the roll-up window requires), the CR handler never runs the backfill at line 836 and current_visible_start_ms is still zero when flush_608_context fires EraseDisplayedMemory. Result: the first emitted caption is timestamped at 00:00:00,000. Capture the FTS of the first character after the transition in a new field ts_first_char_rollup_transition. Unlike ts_start_of_current_line, this field is not overwritten by intermediate changes=0 CRs, so the first-char time survives to the end-of-stream flush path. write_cc_buffer uses it to backfill current_visible_start_ms when rollup_from_popon is still set at emit time, and clears it together with the flag. The normal popon->roll-up flow (where a scrolling CR eventually fires) and every other caption path are unchanged. Verified on c4dd893cb9d6...ts: first subtitle now starts at 00:00:13,913 (was 00:00:00,000). Regression tested against six master samples the mentor flagged (0069dffd.mpg 03,603; 5cbb21ad.dvr-ms 00,534; 132d7df7.mov 12,812; 6395b281.asf 02,436; 8849331d.mp4 03,771; b22260d0.ts 04,838) - all match the reference timings unchanged. Co-authored-by: GAURAV KARMAKAR <gaurav.k@graeon.ai>
This commit is contained in:
@@ -150,6 +150,7 @@ ccx_decoder_608_context *ccx_decoder_608_init_library(struct ccx_decoder_608_set
|
||||
data->my_channel = channel;
|
||||
data->have_cursor_position = 0;
|
||||
data->rollup_from_popon = 0;
|
||||
data->ts_first_char_rollup_transition = -1;
|
||||
data->output_format = output_format;
|
||||
data->cc_to_stdout = cc_to_stdout;
|
||||
data->textprinted = 0;
|
||||
@@ -246,6 +247,12 @@ void write_char(const unsigned char c, ccx_decoder_608_context *context)
|
||||
context->cursor_column++;
|
||||
if (context->ts_start_of_current_line == -1)
|
||||
context->ts_start_of_current_line = get_fts(context->timing, context->my_field);
|
||||
// First char after a pop-on -> roll-up transition: remember its FTS so
|
||||
// write_cc_buffer can use it if EOF fires before a scrolling CR.
|
||||
// Unlike ts_start_of_current_line, this field is NOT touched by
|
||||
// intermediate CR commands (changes=0 CRs overwrite ts_start_of_current_line).
|
||||
if (context->rollup_from_popon && context->ts_first_char_rollup_transition == -1)
|
||||
context->ts_first_char_rollup_transition = get_fts(context->timing, context->my_field);
|
||||
context->ts_last_char_received = get_fts(context->timing, context->my_field);
|
||||
}
|
||||
}
|
||||
@@ -311,6 +318,17 @@ int write_cc_buffer(ccx_decoder_608_context *context, struct cc_subtitle *sub)
|
||||
context->ts_start_of_current_line != -1)
|
||||
context->current_visible_start_ms = context->ts_start_of_current_line;
|
||||
|
||||
// Pop-on -> roll-up transition that never saw a scrolling CR (e.g. EOF
|
||||
// with fewer lines than the roll-up window). The CR handler never ran,
|
||||
// so back-fill current_visible_start_ms from the first-char FTS instead
|
||||
// of emitting a caption starting at 0.
|
||||
if (context->rollup_from_popon && context->ts_first_char_rollup_transition > 0)
|
||||
{
|
||||
context->current_visible_start_ms = context->ts_first_char_rollup_transition;
|
||||
context->rollup_from_popon = 0;
|
||||
context->ts_first_char_rollup_transition = -1;
|
||||
}
|
||||
|
||||
start_time = context->current_visible_start_ms;
|
||||
end_time = get_visible_end(context->timing, context->my_field);
|
||||
sub->type = CC_608;
|
||||
@@ -758,6 +776,7 @@ void handle_command(unsigned char c1, const unsigned char c2, ccx_decoder_608_co
|
||||
// Start time will be set when CR causes scrolling (matching FFmpeg behavior)
|
||||
context->rollup_from_popon = 1;
|
||||
context->ts_start_of_current_line = -1;
|
||||
context->ts_first_char_rollup_transition = -1;
|
||||
}
|
||||
erase_memory(context, false);
|
||||
|
||||
@@ -817,6 +836,7 @@ void handle_command(unsigned char c1, const unsigned char c2, ccx_decoder_608_co
|
||||
{
|
||||
context->current_visible_start_ms = context->ts_start_of_current_line;
|
||||
context->rollup_from_popon = 0;
|
||||
context->ts_first_char_rollup_transition = -1;
|
||||
}
|
||||
|
||||
// Only if the roll up would actually cause a line to disappear we write the buffer
|
||||
|
||||
@@ -48,6 +48,7 @@ typedef struct ccx_decoder_608_context
|
||||
int my_field; // Used for sanity checks
|
||||
int my_channel; // Used for sanity checks
|
||||
int rollup_from_popon; // Track transition from pop-on/paint-on to roll-up mode
|
||||
LLONG ts_first_char_rollup_transition; // FTS of first char after pop-on -> roll-up (EOF fallback when no scrolling CR fires). -1 if unset.
|
||||
int64_t bytes_processed_608; // To be written ONLY by process_608
|
||||
int have_cursor_position;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user