Skip to content
Open
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
1 change: 1 addition & 0 deletions docs/CHANGES.TXT
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
0.95 (2025-09-15)
-----------------
- Fix: Enhanced ATSC EIT/VCT parsing with corrected bounds checks, improved event mapping, added support for extended EIT table IDs (0xCD–0xD0), and reliable XMLTV generation.
- Fix: ARM64/aarch64 build failure due to c_char type mismatch in nal.rs
- Fix: HardSubX OCR on Rust
- Removed the Share Module
Expand Down
53 changes: 44 additions & 9 deletions src/lib_ccx/ts_tables_epg.c
Original file line number Diff line number Diff line change
Expand Up @@ -414,15 +414,24 @@ void EPG_output(struct lib_ccx_ctx *ctx)
}
if (ccx_options.xmltvonlycurrent == 0)
{ // print all events
// Print events from mapped programs
for (i = 0; i < ctx->demux_ctx->nb_program; i++)
{
for (j = 0; j < ctx->eit_programs[i].array_len; j++)
EPG_print_event(&ctx->eit_programs[i].epg_events[j], ctx->demux_ctx->pinfo[i].program_number, f);
}

if (ctx->demux_ctx->nb_program == 0) // Stream has no PMT, fall back to unordered events
// CRITICAL FIX: Always check fallback storage, not just when nb_program==0
// This fixes ATSC streams where VCT creates programs but EIT events
// end up in fallback storage due to source_id mapping issues
if (ctx->eit_programs[TS_PMT_MAP_SIZE].array_len > 0)
{
for (j = 0; j < ctx->eit_programs[TS_PMT_MAP_SIZE].array_len; j++)
EPG_print_event(&ctx->eit_programs[TS_PMT_MAP_SIZE].epg_events[j], ctx->eit_programs[TS_PMT_MAP_SIZE].epg_events[j].service_id, f);
{
EPG_print_event(&ctx->eit_programs[TS_PMT_MAP_SIZE].epg_events[j],
ctx->eit_programs[TS_PMT_MAP_SIZE].epg_events[j].service_id, f);
}
}
}
else
{ // print current events only
Expand All @@ -435,6 +444,18 @@ void EPG_output(struct lib_ccx_ctx *ctx)
EPG_print_event(&ctx->eit_programs[i].epg_events[j], ctx->demux_ctx->pinfo[i].program_number, f);
}
}

// CRITICAL FIX: Also check fallback for current events
if (ctx->eit_programs[TS_PMT_MAP_SIZE].array_len > 0)
{
ce = ctx->eit_current_events[TS_PMT_MAP_SIZE];
for (j = 0; j < ctx->eit_programs[TS_PMT_MAP_SIZE].array_len; j++)
{
if (ce == ctx->eit_programs[TS_PMT_MAP_SIZE].epg_events[j].id)
EPG_print_event(&ctx->eit_programs[TS_PMT_MAP_SIZE].epg_events[j],
ctx->eit_programs[TS_PMT_MAP_SIZE].epg_events[j].service_id, f);
}
}
}
fprintf(f, "</tv>");
fclose(f);
Expand Down Expand Up @@ -816,8 +837,8 @@ void EPG_ATSC_decode_multiple_string(uint8_t *offset, uint32_t length, struct EP
int i, j;
char ISO_639_language_code[4];
uint8_t *offset_end = offset + length;
#define CHECK_OFFSET(val) \
if (offset + val < offset_end) \
#define CHECK_OFFSET(val) \
if (offset + (val) > offset_end) \
return

CHECK_OFFSET(1);
Expand Down Expand Up @@ -903,8 +924,8 @@ void EPG_ATSC_decode_EIT(struct lib_ccx_ctx *ctx, uint8_t *payload_start, uint32

num_events_in_section = payload_start[9];

#define CHECK_OFFSET(val) \
if (offset + val < (payload_start + size)) \
#define CHECK_OFFSET(val) \
if (offset + (val) > (payload_start + size)) \
return
offset = &payload_start[10];

Expand Down Expand Up @@ -1121,21 +1142,35 @@ void EPG_parse_table(struct lib_ccx_ctx *ctx, uint8_t *b, uint32_t size)
{
return;
}

payload_start = &b[pointer_field + 1];
table_id = payload_start[0];

switch (table_id)
{
case 0x0cb:
// ATSC EIT tables (EIT-0..EIT-3 and extended range)
case 0xCB:
case 0xCC:
case 0xCD:
case 0xCE:
case 0xCF: // Extended ATSC EIT
case 0xD0: // Extended ATSC EIT
EPG_ATSC_decode_EIT(ctx, payload_start, size - (payload_start - b));
break;
case 0xc8:

// ATSC VCT (Virtual Channel Table)
case 0xC8:
case 0xC9: // Cable VCT variant
EPG_ATSC_decode_VCT(ctx, payload_start, size - (payload_start - b));
break;

default:
if (table_id >= 0x4e && table_id <= 0x6f)
// DVB EIT tables
if (table_id >= 0x4E && table_id <= 0x6F)
EPG_DVB_decode_EIT(ctx, payload_start, size - (payload_start - b));
break;
}

EPG_handle_output(ctx);
}

Expand Down
Loading