Skip to content
Closed
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
4 changes: 4 additions & 0 deletions src/lib_ccx/ccx_common_option.c
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,10 @@ void init_options(struct ccx_s_options *options)
options->noautotimeref = 0; // Do NOT set time automatically?
options->input_source = CCX_DS_FILE; // Files, stdin or network
options->multiprogram = 0;

// [ADD THIS]
options->split_dvb_subs = 0;

options->out_interval = -1;
options->segment_on_key_frames_only = 0;

Expand Down
4 changes: 4 additions & 0 deletions src/lib_ccx/ccx_common_option.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,10 @@ struct ccx_s_options // Options from user parameters
int nohtmlescape;
int notypesetting;
struct ccx_boundary_time extraction_start, extraction_end; // Segment we actually process

// [ADD THIS]
int split_dvb_subs; // If 1, extract each DVB stream to a separate file

int print_file_reports;

ccx_decoder_608_settings settings_608; // Contains the settings for the 608 decoder.
Expand Down
4 changes: 4 additions & 0 deletions src/lib_ccx/ccx_demuxer.c
Original file line number Diff line number Diff line change
Expand Up @@ -396,6 +396,10 @@ struct ccx_demuxer *init_demuxer(void *parent, struct demuxer_cfg *cfg)

ctx->warning_program_not_found_shown = CCX_FALSE;
ctx->strangeheader = 0;

// [ADD THIS]
ctx->potential_stream_count = 0;

memset(&ctx->freport, 0, sizeof(ctx->freport));

for (i = 0; i < MAX_PSI_PID; i++)
Expand Down
20 changes: 20 additions & 0 deletions src/lib_ccx/ccx_demuxer.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,21 @@
#include "activity.h"
#include "utility.h"

// [ADD THESE DEFINITIONS]
#define MAX_POTENTIAL_STREAMS 64
#define CCX_STREAM_TYPE_UNKNOWN 0
#define CCX_STREAM_TYPE_DVB_SUB 1
#define CCX_STREAM_TYPE_TELETEXT 2

struct ccx_stream_metadata
{
int pid;
int stream_type; // Logical type (CCX_STREAM_TYPE_*)
int mpeg_type; // Raw MPEG type (0x06)
char lang[4]; // ISO 639-2
struct ccx_decoders_dvb_context *dvb_decoder_ctx; // DVB decoder context for this stream
};

/* Report information */
#define SUB_STREAMS_CNT 10
#define MAX_PID 65536
Expand Down Expand Up @@ -64,6 +79,7 @@ struct cap_info
int prev_counter;
void *codec_private_data;
int ignore;
char language[4]; // ISO 639-2 language code

/**
List joining all stream in TS
Expand Down Expand Up @@ -144,6 +160,10 @@ struct ccx_demuxer
unsigned int filebuffer_pos; // Position of pointer relative to buffer start
unsigned int bytesinbuffer; // Number of bytes we actually have on buffer

// [ADD THESE]
struct ccx_stream_metadata potential_streams[MAX_POTENTIAL_STREAMS];
int potential_stream_count;

int warning_program_not_found_shown;

// Remember if the last header was valid. Used to suppress too much output
Expand Down
65 changes: 65 additions & 0 deletions src/lib_ccx/dvb_subtitle_decoder.c
Original file line number Diff line number Diff line change
Expand Up @@ -559,6 +559,71 @@ int dvbsub_close_decoder(void **dvb_ctx)
return 0;
}

// New context-based API for multi-stream support

struct ccx_decoders_dvb_context *dvb_init_decoder(struct dvb_config *cfg, int initialized_ocr)
{
struct ccx_decoders_dvb_context *dvb_ctx;
DVBSubContext *ctx;

dvb_ctx = (struct ccx_decoders_dvb_context *)malloc(sizeof(struct ccx_decoders_dvb_context));
if (!dvb_ctx)
{
fatal(EXIT_NOT_ENOUGH_MEMORY, "In dvb_init_decoder: Out of memory for context.");
}
memset(dvb_ctx, 0, sizeof(struct ccx_decoders_dvb_context));

// Initialize the internal DVB context using existing function
ctx = (DVBSubContext *)dvbsub_init_decoder(cfg, initialized_ocr);
if (!ctx)
{
free(dvb_ctx);
return NULL;
}

dvb_ctx->private_data = ctx;
dvb_ctx->cfg = cfg;
dvb_ctx->initialized_ocr = initialized_ocr;

return dvb_ctx;
}

void dvb_free_decoder(struct ccx_decoders_dvb_context **dvb_ctx)
{
if (!dvb_ctx || !*dvb_ctx)
return;

// Free the internal DVB context using existing function
if ((*dvb_ctx)->private_data)
{
void *ctx = (*dvb_ctx)->private_data;
dvbsub_close_decoder(&ctx);
}

free(*dvb_ctx);
*dvb_ctx = NULL;
}

int dvb_decode(struct ccx_decoders_dvb_context *dvb_ctx, struct encoder_ctx *enc_ctx,
struct lib_cc_decode *dec_ctx, const unsigned char *buf, int buf_size,
struct cc_subtitle *sub)
{
if (!dvb_ctx || !dvb_ctx->private_data)
return -1;

// Temporarily set the private_data for the existing decode function
void *original_private_data = dec_ctx->private_data;
dec_ctx->private_data = dvb_ctx->private_data;

// Call the existing decode function
int result = dvbsub_decode(enc_ctx, dec_ctx, buf, buf_size, sub);

// Restore original private_data
dec_ctx->private_data = original_private_data;

return result;
}

static int dvbsub_read_2bit_string(uint8_t *destbuf, int dbuf_len,
const uint8_t **srcbuf, int buf_size, int non_mod, uint8_t *map_table,
int x_pos)
Expand Down
38 changes: 38 additions & 0 deletions src/lib_ccx/dvb_subtitle_decoder.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,39 @@
#define MAX_LANGUAGE_PER_DESC 5

#include "lib_ccx.h"
#include "ccx_common_structs.h"
#include "ccx_decoders_structs.h"

#ifdef __cplusplus
extern "C"
{
#endif

// [ADD: Context structure]
typedef struct ccx_decoders_dvb_context
{
int page_time;
int prev_page_time;
int global_x;
int global_y;

// Internal lists (opaque pointers here, defined in .c)
void *page_composition;
void *region_composition_list;
void *clut_definition_list;
void *object_data_list;
void *display_definition;

// Dependencies
struct ccx_common_timing_ctx *timing;
struct encoder_ctx *encoder;

// Internal data for multi-stream support
void *private_data; // Internal DVBSubContext
struct dvb_config *cfg; // Configuration
int initialized_ocr; // OCR initialization flag
} ccx_decoders_dvb_context;

struct dvb_config
{
unsigned char n_language;
Expand All @@ -36,6 +64,16 @@ extern "C"
unsigned short ancillary_id[MAX_LANGUAGE_PER_DESC];
};

// [ADD: Lifecycle functions]
ccx_decoders_dvb_context *dvb_init_decoder(struct dvb_config *cfg, int initialized_ocr);
void dvb_free_decoder(ccx_decoders_dvb_context **dvb_ctx);

// [MODIFY: Decode signature]
int dvb_decode(ccx_decoders_dvb_context *dvb_ctx, struct encoder_ctx *enc_ctx,
struct lib_cc_decode *dec_ctx, const unsigned char *buf, int buf_size,
struct cc_subtitle *sub);

// Legacy API (kept for compatibility)
/**
* @param cfg Structure containg configuration
*
Expand Down
20 changes: 15 additions & 5 deletions src/lib_ccx/general_loop.c
Original file line number Diff line number Diff line change
Expand Up @@ -650,7 +650,7 @@ void delete_datalist(struct demuxer_data *list)
delete_demuxer_data(slist);
}
}
int process_data(struct encoder_ctx *enc_ctx, struct lib_cc_decode *dec_ctx, struct demuxer_data *data_node)
int process_data(struct lib_ccx_ctx *ctx, struct encoder_ctx *enc_ctx, struct lib_cc_decode *dec_ctx, struct demuxer_data *data_node)
{
size_t got; // Means 'consumed' from buffer actually
int ret = 0;
Expand All @@ -665,9 +665,19 @@ int process_data(struct encoder_ctx *enc_ctx, struct lib_cc_decode *dec_ctx, str
}
else if (data_node->bufferdatatype == CCX_DVB_SUBTITLE)
{
ret = dvbsub_decode(enc_ctx, dec_ctx, data_node->buffer + 2, data_node->len - 2, dec_sub);
// Check for multi-stream DVB processing
if (ctx->split_dvb_subs)
{
ret = process_dvb_multi_stream(ctx, data_node, dec_sub);
}
else
{
// Original single-stream processing
ret = dvbsub_decode(enc_ctx, dec_ctx, data_node->buffer + 2, data_node->len - 2, dec_sub);
}

if (ret < 0)
mprint("Return from dvbsub_decode: %d\n", ret);
mprint("Return from DVB decode: %d\n", ret);
set_fts(dec_ctx->timing);
got = data_node->len;
}
Expand Down Expand Up @@ -1034,7 +1044,7 @@ int process_non_multiprogram_general_loop(struct lib_ccx_ctx *ctx,
}
if ((*data_node)->bufferdatatype == CCX_TELETEXT && (*dec_ctx)->private_data) // if we have teletext subs, we set the min_pts here
set_tlt_delta(*dec_ctx, (*dec_ctx)->timing->current_pts);
ret = process_data(*enc_ctx, *dec_ctx, *data_node);
ret = process_data(ctx, *enc_ctx, *dec_ctx, *data_node);
if (*enc_ctx != NULL)
{
if ((*enc_ctx)->srt_counter || (*enc_ctx)->cea_708_counter || (*dec_ctx)->saw_caption_block || ret == 1)
Expand Down Expand Up @@ -1232,7 +1242,7 @@ int general_loop(struct lib_ccx_ctx *ctx)
}
}

ret = process_data(enc_ctx, dec_ctx, data_node);
ret = process_data(ctx, enc_ctx, dec_ctx, data_node);
if (enc_ctx != NULL)
{
if (
Expand Down
Loading
Loading