mirror of
https://github.com/CCExtractor/ccextractor.git
synced 2026-02-14 13:35:43 +00:00
Merge branch 'pr/n118_anshul1912'
This commit is contained in:
@@ -18,6 +18,10 @@ include_directories ("${PROJECT_SOURCE_DIR}/lib_ccx")
|
||||
include_directories ("${PROJECT_SOURCE_DIR}/gpacmp4/")
|
||||
include_directories ("${PROJECT_SOURCE_DIR}/libccx_common/")
|
||||
|
||||
#Adding some platform specific library path
|
||||
LINK_DIRECTORIES(/opt/local/lib)
|
||||
LINK_DIRECTORIES(/usr/local/lib)
|
||||
|
||||
SET (CMAKE_C_FLAGS "-O0 -Wall -g -std=gnu99 -Wno-write-strings -D_FILE_OFFSET_BITS=64")
|
||||
add_subdirectory (lib_ccx)
|
||||
|
||||
@@ -28,3 +32,5 @@ set (EXTRA_LIBS ${EXTRA_LIBS} m)
|
||||
|
||||
add_executable(ccextractor ${SOURCEFILE})
|
||||
target_link_libraries (ccextractor ${EXTRA_LIBS})
|
||||
|
||||
install (TARGETS ccextractor DESTINATION bin)
|
||||
|
||||
@@ -30,10 +30,8 @@ int main(int argc, char *argv[])
|
||||
struct cc_subtitle dec_sub;
|
||||
void *ffmpeg_ctx = NULL;
|
||||
struct lib_ccx_ctx *ctx;
|
||||
struct lib_cc_decode *dec_ctx = NULL;
|
||||
|
||||
// Initialize some constants
|
||||
init_ts();
|
||||
init_avc();
|
||||
|
||||
init_options (&ccx_options);
|
||||
|
||||
@@ -42,23 +40,13 @@ int main(int argc, char *argv[])
|
||||
|
||||
// Initialize libraries
|
||||
ctx = init_libraries(&ccx_options);
|
||||
dec_ctx = ctx->dec_ctx;
|
||||
|
||||
// Init timing
|
||||
ccx_common_timing_init(&ctx->past,ccx_options.nosync);
|
||||
|
||||
// Prepare write structures
|
||||
init_write(&ctx->wbout1,ccx_options.wbout1.filename);
|
||||
init_write(&ctx->wbout2,ccx_options.wbout2.filename);
|
||||
|
||||
// Prepare time structures
|
||||
init_boundary_time (&ccx_options.extraction_start);
|
||||
init_boundary_time (&ccx_options.extraction_end);
|
||||
init_boundary_time (&ccx_options.startcreditsnotbefore);
|
||||
init_boundary_time (&ccx_options.startcreditsnotafter);
|
||||
init_boundary_time (&ccx_options.startcreditsforatleast);
|
||||
init_boundary_time (&ccx_options.startcreditsforatmost);
|
||||
init_boundary_time (&ccx_options.endcreditsforatleast);
|
||||
init_boundary_time (&ccx_options.endcreditsforatmost);
|
||||
|
||||
int show_myth_banner = 0;
|
||||
|
||||
@@ -162,9 +150,7 @@ int main(int argc, char *argv[])
|
||||
"CCExtractor's binary format can only be used simultaneously for input and\noutput if the output file name is specified given with -o.\n");
|
||||
}
|
||||
|
||||
ctx->buffer = (unsigned char *) malloc (BUFSIZE);
|
||||
subline = (unsigned char *) malloc (SUBLINESIZE);
|
||||
ctx->pesheaderbuf = (unsigned char *) malloc (188); // Never larger anyway
|
||||
|
||||
switch (ccx_options.input_source)
|
||||
{
|
||||
@@ -409,7 +395,7 @@ int main(int argc, char *argv[])
|
||||
time_t start, final;
|
||||
time(&start);
|
||||
|
||||
ctx->processed_enough=0;
|
||||
dec_ctx->processed_enough=0;
|
||||
if (ccx_options.binary_concat)
|
||||
{
|
||||
ctx->total_inputsize=gettotalfilessize(ctx);
|
||||
@@ -422,7 +408,7 @@ int main(int argc, char *argv[])
|
||||
m_signal(SIGINT, sigint_handler);
|
||||
#endif
|
||||
|
||||
while (switch_to_next_file(ctx, 0) && !ctx->processed_enough)
|
||||
while (switch_to_next_file(ctx, 0) && !dec_ctx->processed_enough)
|
||||
{
|
||||
prepare_for_new_file(ctx);
|
||||
#ifdef ENABLE_FFMPEG
|
||||
@@ -642,10 +628,10 @@ int main(int argc, char *argv[])
|
||||
|
||||
if (ctx->stat_hdtv)
|
||||
{
|
||||
mprint ("\rCC type 0: %d (%s)\n", ctx->cc_stats[0], cc_types[0]);
|
||||
mprint ("CC type 1: %d (%s)\n", ctx->cc_stats[1], cc_types[1]);
|
||||
mprint ("CC type 2: %d (%s)\n", ctx->cc_stats[2], cc_types[2]);
|
||||
mprint ("CC type 3: %d (%s)\n", ctx->cc_stats[3], cc_types[3]);
|
||||
mprint ("\rCC type 0: %d (%s)\n", dec_ctx->cc_stats[0], cc_types[0]);
|
||||
mprint ("CC type 1: %d (%s)\n", dec_ctx->cc_stats[1], cc_types[1]);
|
||||
mprint ("CC type 2: %d (%s)\n", dec_ctx->cc_stats[2], cc_types[2]);
|
||||
mprint ("CC type 3: %d (%s)\n", dec_ctx->cc_stats[3], cc_types[3]);
|
||||
}
|
||||
mprint ("\nTotal frames time: %s (%u frames at %.2ffps)\n",
|
||||
print_mstime( (LLONG)(total_frames_count*1000/current_fps) ),
|
||||
@@ -743,7 +729,7 @@ int main(int argc, char *argv[])
|
||||
ccx_options.write_format==CCX_OF_SRT || ccx_options.write_format==CCX_OF_TRANSCRIPT
|
||||
|| ccx_options.write_format==CCX_OF_SPUPNG )
|
||||
{
|
||||
handle_end_of_data(&ctx->context_cc608_field_1, &dec_sub);
|
||||
handle_end_of_data(dec_ctx->context_cc608_field_1, &dec_sub);
|
||||
if (dec_sub.got_output)
|
||||
{
|
||||
encode_sub(enc_ctx,&dec_sub);
|
||||
@@ -753,7 +739,7 @@ int main(int argc, char *argv[])
|
||||
else if(ccx_options.write_format==CCX_OF_RCWT)
|
||||
{
|
||||
// Write last header and data
|
||||
writercwtdata (ctx, NULL);
|
||||
writercwtdata (dec_ctx, NULL);
|
||||
}
|
||||
dinit_encoder(enc_ctx);
|
||||
}
|
||||
@@ -763,7 +749,7 @@ int main(int argc, char *argv[])
|
||||
ccx_options.write_format==CCX_OF_SRT || ccx_options.write_format==CCX_OF_TRANSCRIPT
|
||||
|| ccx_options.write_format==CCX_OF_SPUPNG )
|
||||
{
|
||||
handle_end_of_data(&ctx->context_cc608_field_2, &dec_sub);
|
||||
handle_end_of_data(dec_ctx->context_cc608_field_2, &dec_sub);
|
||||
if (dec_sub.got_output)
|
||||
{
|
||||
encode_sub(enc_ctx,&dec_sub);
|
||||
@@ -791,7 +777,7 @@ int main(int argc, char *argv[])
|
||||
if (ccx_options.teletext_mode == CCX_TXT_IN_USE)
|
||||
mprint ( "Teletext decoder: %"PRIu32" packets processed, %"PRIu32" SRT frames written.\n", tlt_packet_counter, tlt_frames_produced);
|
||||
|
||||
if (ctx->processed_enough)
|
||||
if (dec_ctx->processed_enough)
|
||||
{
|
||||
mprint ("\rNote: Processing was cancelled before all data was processed because\n");
|
||||
mprint ("\rone or more user-defined limits were reached.\n");
|
||||
@@ -809,5 +795,6 @@ int main(int argc, char *argv[])
|
||||
mprint ("code in the MythTV's branch. Please report results to the address above. If\n");
|
||||
mprint ("something is broken it will be fixed. Thanks\n");
|
||||
}
|
||||
dinit_libraries(&ctx);
|
||||
return EXIT_OK;
|
||||
}
|
||||
|
||||
@@ -350,7 +350,7 @@ int processmp4 (struct lib_ccx_ctx *ctx, char *file,void *enc_ctx)
|
||||
#endif
|
||||
do
|
||||
{
|
||||
ret = process608((unsigned char*)data, len, &ctx->context_cc608_field_1, &dec_sub);
|
||||
ret = process608((unsigned char*)data, len, ctx->dec_ctx->context_cc608_field_1, &dec_sub);
|
||||
len -= ret;
|
||||
data += ret;
|
||||
if(dec_sub.got_output)
|
||||
|
||||
@@ -7,5 +7,16 @@ AUX_SOURCE_DIRECTORY("${PROJECT_SOURCE_DIR}/gpacmp4/" SOURCEFILE)
|
||||
add_library(ccx ${SOURCEFILE})
|
||||
|
||||
FILE(GLOB HeaderFiles *.h)
|
||||
file(WRITE ccx.pc "prefix=${CMAKE_INSTALL_PREFIX}\n"
|
||||
"includedir=\${prefix}/include\n"
|
||||
"libdir=\${prefix}/lib\n\n"
|
||||
"Name: ccx\n"
|
||||
"Description: Closed Caption Extraction library\n"
|
||||
"Version: 0.75\n"
|
||||
"Cflags: -I\${includedir}/\n"
|
||||
"Libs: -L\${libdir} -lccx -lpng\n"
|
||||
"Libs.private: -lpng\n" )
|
||||
|
||||
install (TARGETS ccx DESTINATION lib)
|
||||
install (FILES ${HeaderFiles} DESTINATION include)
|
||||
install (FILES ccx.pc DESTINATION lib/pkgconfig )
|
||||
|
||||
@@ -13,5 +13,8 @@
|
||||
void fdprintf(int fd, const char *fmt, ...);
|
||||
void mstotime(LLONG milli, unsigned *hours, unsigned *minutes,unsigned *seconds, unsigned *ms);
|
||||
void freep(void *arg);
|
||||
void dbg_print(LLONG mask, const char *fmt, ...);
|
||||
unsigned char *debug_608toASC(unsigned char *ccdata, int channel);
|
||||
|
||||
#endif
|
||||
extern int cc608_parity_table[256]; // From myth
|
||||
#endif
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#include "ccx_common_option.h"
|
||||
#include "ccx_encoders_common.h"
|
||||
#include "utility.h"
|
||||
|
||||
struct ccx_s_options ccx_options;
|
||||
/* Parameters */
|
||||
void init_options (struct ccx_s_options *options)
|
||||
@@ -89,4 +91,15 @@ 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->auto_stream = CCX_SM_AUTODETECT;
|
||||
|
||||
// Prepare time structures
|
||||
init_boundary_time (&options->extraction_start);
|
||||
init_boundary_time (&options->extraction_end);
|
||||
init_boundary_time (&options->startcreditsnotbefore);
|
||||
init_boundary_time (&options->startcreditsnotafter);
|
||||
init_boundary_time (&options->startcreditsforatleast);
|
||||
init_boundary_time (&options->startcreditsforatmost);
|
||||
init_boundary_time (&options->endcreditsforatleast);
|
||||
init_boundary_time (&options->endcreditsforatmost);
|
||||
|
||||
}
|
||||
|
||||
@@ -116,42 +116,54 @@ void clear_eia608_cc_buffer(ccx_decoder_608_context *context, struct eia608_scre
|
||||
data->empty=1;
|
||||
}
|
||||
|
||||
ccx_decoder_608_context ccx_decoder_608_init_library(ccx_decoder_608_settings settings, int channel, int field, int trim_subs, enum ccx_encoding_type encoding, int *halt, int *cc_to_stdout)
|
||||
void ccx_decoder_608_dinit_library(void **ctx)
|
||||
{
|
||||
ccx_decoder_608_context data;
|
||||
freep(ctx);
|
||||
}
|
||||
ccx_decoder_608_context* ccx_decoder_608_init_library(ccx_decoder_608_settings settings, int channel,
|
||||
int field, int trim_subs,
|
||||
enum ccx_encoding_type encoding, int *halt,
|
||||
int cc_to_stdout, LLONG subs_delay,
|
||||
enum ccx_output_format output_format)
|
||||
{
|
||||
ccx_decoder_608_context *data = NULL;
|
||||
|
||||
data.cursor_column=0;
|
||||
data.cursor_row=0;
|
||||
data.visible_buffer=1;
|
||||
data.last_c1=0;
|
||||
data.last_c2=0;
|
||||
data.mode=MODE_POPON;
|
||||
// data.current_visible_start_cc=0;
|
||||
data.current_visible_start_ms=0;
|
||||
data.screenfuls_counter=0;
|
||||
data.channel=1;
|
||||
data.font=FONT_REGULAR;
|
||||
data.rollup_base_row=14;
|
||||
data.ts_start_of_current_line=-1;
|
||||
data.ts_last_char_received=-1;
|
||||
data.new_channel=1;
|
||||
data.bytes_processed_608 = 0;
|
||||
data.my_field = field;
|
||||
data.my_channel = channel;
|
||||
data.out = NULL;
|
||||
data.have_cursor_position = 0;
|
||||
data = malloc(sizeof(ccx_decoder_608_context));
|
||||
|
||||
data.trim_subs = trim_subs;
|
||||
data.encoding = encoding;
|
||||
data->cursor_column=0;
|
||||
data->cursor_row=0;
|
||||
data->visible_buffer=1;
|
||||
data->last_c1=0;
|
||||
data->last_c2=0;
|
||||
data->mode=MODE_POPON;
|
||||
// data->current_visible_start_cc=0;
|
||||
data->current_visible_start_ms=0;
|
||||
data->screenfuls_counter=0;
|
||||
data->channel=1;
|
||||
data->font=FONT_REGULAR;
|
||||
data->rollup_base_row=14;
|
||||
data->ts_start_of_current_line=-1;
|
||||
data->ts_last_char_received=-1;
|
||||
data->new_channel=1;
|
||||
data->bytes_processed_608 = 0;
|
||||
data->my_field = field;
|
||||
data->my_channel = channel;
|
||||
data->out = NULL;
|
||||
data->have_cursor_position = 0;
|
||||
|
||||
data.halt = halt;
|
||||
data.cc_to_stdout = cc_to_stdout;
|
||||
data->trim_subs = trim_subs;
|
||||
data->encoding = encoding;
|
||||
|
||||
data.settings = settings;
|
||||
data.current_color = data.settings.default_color;
|
||||
data->halt = halt;
|
||||
data->cc_to_stdout = cc_to_stdout;
|
||||
data->subs_delay = subs_delay;
|
||||
data->output_format = output_format;
|
||||
|
||||
clear_eia608_cc_buffer(&data, &data.buffer1);
|
||||
clear_eia608_cc_buffer(&data, &data.buffer2);
|
||||
data->settings = settings;
|
||||
data->current_color = data->settings.default_color;
|
||||
|
||||
clear_eia608_cc_buffer(data, &data->buffer1);
|
||||
clear_eia608_cc_buffer(data, &data->buffer2);
|
||||
|
||||
return data;
|
||||
}
|
||||
@@ -292,7 +304,7 @@ int write_cc_buffer(ccx_decoder_608_context *context, struct cc_subtitle *sub)
|
||||
context->current_visible_start_ms = context->ts_start_of_current_line;
|
||||
|
||||
start_time = context->current_visible_start_ms;
|
||||
end_time = get_visible_end() + ccx_decoders_common_settings.subs_delay;
|
||||
end_time = get_visible_end() + context->subs_delay;
|
||||
sub->type = CC_608;
|
||||
data->format = SFORMAT_CC_SCREEN;
|
||||
data->start_time = 0;
|
||||
@@ -348,8 +360,8 @@ int write_cc_line(ccx_decoder_608_context *context, struct cc_subtitle *sub)
|
||||
int ret = 0;
|
||||
data = get_current_visible_buffer(context);
|
||||
|
||||
start_time = context->ts_start_of_current_line + ccx_decoders_common_settings.subs_delay;
|
||||
end_time = get_fts() + ccx_decoders_common_settings.subs_delay;
|
||||
start_time = context->ts_start_of_current_line + context->subs_delay;
|
||||
end_time = get_fts() + context->subs_delay;
|
||||
sub->type = CC_608;
|
||||
data->format = SFORMAT_CC_LINE;
|
||||
data->start_time = 0;
|
||||
@@ -358,6 +370,7 @@ int write_cc_line(ccx_decoder_608_context *context, struct cc_subtitle *sub)
|
||||
data->channel = context->channel;
|
||||
data->my_field = context->my_field;
|
||||
|
||||
//TODO need to put below functionality in encoder context
|
||||
ret = get_decoder_line_basic (subline, context->cursor_row, data,context->trim_subs,context->encoding);
|
||||
if( ret > 0 )
|
||||
{
|
||||
@@ -728,7 +741,7 @@ void handle_command(/*const */ unsigned char c1, const unsigned char c2, ccx_dec
|
||||
context->cursor_row++;
|
||||
break;
|
||||
}
|
||||
if (ccx_decoders_common_settings.output_format == CCX_OF_TRANSCRIPT)
|
||||
if (context->output_format == CCX_OF_TRANSCRIPT)
|
||||
{
|
||||
write_cc_line(context,sub);
|
||||
}
|
||||
@@ -739,7 +752,7 @@ void handle_command(/*const */ unsigned char c1, const unsigned char c2, ccx_dec
|
||||
if (changes)
|
||||
{
|
||||
// Only if the roll up would actually cause a line to disappear we write the buffer
|
||||
if (ccx_decoders_common_settings.output_format != CCX_OF_TRANSCRIPT)
|
||||
if (context->output_format != CCX_OF_TRANSCRIPT)
|
||||
{
|
||||
if (write_cc_buffer(context, sub))
|
||||
context->screenfuls_counter++;
|
||||
@@ -759,7 +772,7 @@ void handle_command(/*const */ unsigned char c1, const unsigned char c2, ccx_dec
|
||||
case COM_ERASEDISPLAYEDMEMORY:
|
||||
// Write it to disk before doing this, and make a note of the new
|
||||
// time it became clear.
|
||||
if (ccx_decoders_common_settings.output_format == CCX_OF_TRANSCRIPT &&
|
||||
if (context->output_format == CCX_OF_TRANSCRIPT &&
|
||||
(context->mode == MODE_FAKE_ROLLUP_1 ||
|
||||
context->mode == MODE_ROLLUP_2 ||
|
||||
context->mode == MODE_ROLLUP_3 ||
|
||||
@@ -772,7 +785,7 @@ void handle_command(/*const */ unsigned char c1, const unsigned char c2, ccx_dec
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ccx_decoders_common_settings.output_format == CCX_OF_TRANSCRIPT)
|
||||
if (context->output_format == CCX_OF_TRANSCRIPT)
|
||||
context->ts_start_of_current_line = context->current_visible_start_ms;
|
||||
if (write_cc_buffer(context, sub))
|
||||
context->screenfuls_counter++;
|
||||
|
||||
@@ -56,6 +56,8 @@ typedef struct ccx_decoder_608_context
|
||||
int *halt; // Can be used to halt the feeding of caption data. Set to 1 if screens_to_progress != -1 && screenfuls_counter >= screens_to_process
|
||||
int cc_to_stdout; // If this is set to 1, the stdout will be flushed when data was written to the screen during a process_608 call.
|
||||
struct ccx_decoder_608_report report;
|
||||
LLONG subs_delay; // ms to delay (or advance) subs
|
||||
enum ccx_output_format output_format; // What kind of output format should be used?
|
||||
} ccx_decoder_608_context;
|
||||
|
||||
extern unsigned char *enc_buffer;
|
||||
@@ -115,10 +117,15 @@ enum command_code
|
||||
};
|
||||
|
||||
|
||||
void ccx_decoder_608_dinit_library(void **ctx);
|
||||
/*
|
||||
*
|
||||
*/
|
||||
ccx_decoder_608_context ccx_decoder_608_init_library(ccx_decoder_608_settings settings, int channel, int field, int trim_subs, enum ccx_encoding_type encoding, int *halt, int *cc_to_stdout);
|
||||
ccx_decoder_608_context* ccx_decoder_608_init_library(ccx_decoder_608_settings settings, int channel,
|
||||
int field, int trim_subs,
|
||||
enum ccx_encoding_type encoding, int *halt,
|
||||
int cc_to_stdout, LLONG subs_delay,
|
||||
enum ccx_output_format output_format);
|
||||
|
||||
/**
|
||||
* @param data raw cc608 data to be processed
|
||||
@@ -142,7 +149,6 @@ int process608(const unsigned char *data, int length, ccx_decoder_608_context *c
|
||||
void handle_end_of_data(ccx_decoder_608_context *context, struct cc_subtitle *sub);
|
||||
|
||||
int write_cc_buffer(ccx_decoder_608_context *context, struct cc_subtitle *sub);
|
||||
unsigned char *debug_608toASC(unsigned char *ccdata, int channel);
|
||||
|
||||
#define __608_H__
|
||||
#endif
|
||||
|
||||
@@ -121,16 +121,21 @@ void cc708_service_reset(cc708_service_decoder *decoder)
|
||||
decoder->inited=1;
|
||||
}
|
||||
|
||||
void cc708_reset()
|
||||
void cc708_reset(struct lib_cc_decode *ctx)
|
||||
{
|
||||
ccx_common_logging.debug_ftn(CCX_DMT_708, ">>> Entry in cc708_reset()\n");
|
||||
// Clear states of decoders
|
||||
cc708_service_reset(&decoders[0]);
|
||||
cc708_service_reset(&decoders[1]);
|
||||
// Empty packet buffer
|
||||
clear_packet();
|
||||
last_seq=-1;
|
||||
resets_708++;
|
||||
ccx_common_logging.debug_ftn(CCX_DMT_708, ">>> Entry in cc708_reset()\n");
|
||||
|
||||
decoders[0].output_format = ctx->write_format;
|
||||
decoders[1].output_format = ctx->write_format;
|
||||
decoders[0].subs_delay = ctx->subs_delay;
|
||||
decoders[1].subs_delay = ctx->subs_delay;
|
||||
// Clear states of decoders
|
||||
cc708_service_reset(&decoders[0]);
|
||||
cc708_service_reset(&decoders[1]);
|
||||
// Empty packet buffer
|
||||
clear_packet();
|
||||
last_seq=-1;
|
||||
resets_708++;
|
||||
}
|
||||
|
||||
int compWindowsPriorities (const void *a, const void *b)
|
||||
@@ -152,16 +157,16 @@ void clearTV (cc708_service_decoder *decoder, int buffer) // Buffer => 1 or 2
|
||||
|
||||
void printTVtoSRT (cc708_service_decoder *decoder, int which)
|
||||
{
|
||||
if (ccx_decoders_common_settings.output_format == CCX_OF_NULL)
|
||||
if (decoder->output_format == CCX_OF_NULL)
|
||||
return;
|
||||
|
||||
/* tvscreen *tv = (which==1)? &decoder->tv1:&decoder->tv2; */
|
||||
unsigned h1,m1,s1,ms1;
|
||||
unsigned h2,m2,s2,ms2;
|
||||
LLONG ms_start= decoder->current_visible_start_ms;
|
||||
LLONG ms_end = get_visible_end() + ccx_decoders_common_settings.subs_delay;
|
||||
LLONG ms_end = get_visible_end() + decoder->subs_delay;
|
||||
int empty=1;
|
||||
ms_start+= ccx_decoders_common_settings.subs_delay;
|
||||
ms_start+= decoder->subs_delay;
|
||||
if (ms_start<0) // Drop screens that because of subs_delay start too early
|
||||
return;
|
||||
|
||||
@@ -1083,7 +1088,7 @@ void process_service_block (cc708_service_decoder *decoder, unsigned char *data,
|
||||
}
|
||||
|
||||
|
||||
void process_current_packet (void)
|
||||
void process_current_packet (struct lib_cc_decode* ctx)
|
||||
{
|
||||
int seq=(current_packet[0] & 0xC0) >> 6; // Two most significants bits
|
||||
int len=current_packet[0] & 0x3F; // 6 least significants bits
|
||||
@@ -1105,14 +1110,14 @@ void process_current_packet (void)
|
||||
ccx_common_logging.debug_ftn(CCX_DMT_708, "Packet length mismatch (%s%d), first two data bytes %02X %02X, current picture:%s\n",
|
||||
current_packet_length-len>0?"+":"", current_packet_length-len,
|
||||
current_packet[0], current_packet[1], pict_types[current_picture_coding_type]);
|
||||
cc708_reset();
|
||||
cc708_reset(ctx);
|
||||
return;
|
||||
}
|
||||
if (last_seq!=-1 && (last_seq+1)%4!=seq)
|
||||
{
|
||||
ccx_common_logging.debug_ftn(CCX_DMT_708, "Unexpected sequence number, it was [%d] but should have been [%d]\n",
|
||||
seq,(last_seq+1)%4);
|
||||
cc708_reset();
|
||||
cc708_reset(ctx);
|
||||
return;
|
||||
}
|
||||
last_seq=seq;
|
||||
@@ -1170,7 +1175,7 @@ void process_current_packet (void)
|
||||
if (pos!=current_packet+len) // For some reason we didn't parse the whole packet
|
||||
{
|
||||
ccx_common_logging.debug_ftn(CCX_DMT_708, "There was a problem with this packet, reseting\n");
|
||||
cc708_reset();
|
||||
cc708_reset(ctx);
|
||||
}
|
||||
|
||||
if (len<128 && *pos) // Null header is mandatory if there is room
|
||||
@@ -1179,9 +1184,9 @@ void process_current_packet (void)
|
||||
}
|
||||
}
|
||||
|
||||
void do_708 (const unsigned char *data, int datalength)
|
||||
void do_708 (struct lib_cc_decode* ctx, const unsigned char *data, int datalength)
|
||||
{
|
||||
/* Note: The data has this format:
|
||||
/* Note: The data has this format:
|
||||
1 byte for cc_valid
|
||||
1 byte for cc_type
|
||||
2 bytes for the actual data */
|
||||
@@ -1198,7 +1203,7 @@ void do_708 (const unsigned char *data, int datalength)
|
||||
case 2:
|
||||
ccx_common_logging.debug_ftn (CCX_DMT_708, "708: DTVCC Channel Packet Data\n");
|
||||
if (cc_valid==0) // This ends the previous packet
|
||||
process_current_packet();
|
||||
process_current_packet(ctx);
|
||||
else
|
||||
{
|
||||
if (current_packet_length>253)
|
||||
@@ -1214,7 +1219,7 @@ void do_708 (const unsigned char *data, int datalength)
|
||||
break;
|
||||
case 3:
|
||||
ccx_common_logging.debug_ftn (CCX_DMT_708, "708: DTVCC Channel Packet Start\n");
|
||||
process_current_packet();
|
||||
process_current_packet(ctx);
|
||||
if (cc_valid)
|
||||
{
|
||||
if (current_packet_length>127)
|
||||
|
||||
@@ -291,6 +291,8 @@ typedef struct cc708_service_decoder
|
||||
char *filename; // Where we are going to write our output
|
||||
int fh; // Handle to output file. -1 if not yet open
|
||||
int srt_counter;
|
||||
enum ccx_output_format output_format; // What kind of output format should be used?
|
||||
LLONG subs_delay; // ms to delay (or advance) subs
|
||||
}
|
||||
cc708_service_decoder;
|
||||
|
||||
@@ -299,7 +301,7 @@ extern int cea708services[]; // [] -> 1 for services to be processed
|
||||
|
||||
extern int resets_708;
|
||||
|
||||
void do_708 (const unsigned char *data, int datalength);
|
||||
void do_708 (struct lib_cc_decode* ctx, const unsigned char *data, int datalength);
|
||||
|
||||
unsigned char get_internal_from_G0 (unsigned char g0_char);
|
||||
unsigned char get_internal_from_G1 (unsigned char g1_char);
|
||||
|
||||
@@ -6,8 +6,12 @@ made to reuse, not duplicate, as many functions as possible */
|
||||
#include "ccx_common_char_encoding.h"
|
||||
#include "ccx_common_constants.h"
|
||||
#include "ccx_common_timing.h"
|
||||
#include "ccx_common_common.h"
|
||||
#include "lib_ccx.h"
|
||||
|
||||
|
||||
uint64_t utc_refvalue = UINT64_MAX; /* _UI64_MAX means don't use UNIX, 0 = use current system time as reference, +1 use a specific reference */
|
||||
extern int in_xds_mode;
|
||||
|
||||
// Preencoded strings
|
||||
unsigned char encoded_crlf[16];
|
||||
@@ -15,11 +19,6 @@ unsigned int encoded_crlf_length;
|
||||
unsigned char encoded_br[16];
|
||||
unsigned int encoded_br_length;
|
||||
|
||||
void ccx_decoders_common_settings_init(LLONG subs_delay, enum ccx_output_format output_format){
|
||||
ccx_decoders_common_settings.subs_delay = subs_delay;
|
||||
ccx_decoders_common_settings.output_format = output_format;
|
||||
}
|
||||
|
||||
LLONG minimum_fts = 0; // No screen should start before this FTS
|
||||
|
||||
/* This function returns a FTS that is guaranteed to be at least 1 ms later than the end of the previous screen. It shouldn't be needed
|
||||
@@ -98,3 +97,223 @@ unsigned get_decoder_line_basic(unsigned char *buffer, int line_num, struct eia6
|
||||
*buffer = 0;
|
||||
return (unsigned)(buffer - orig); // Return length
|
||||
}
|
||||
|
||||
int process_cc_data (struct lib_cc_decode *ctx, unsigned char *cc_data, int cc_count, struct cc_subtitle *sub)
|
||||
{
|
||||
int ret = 0;
|
||||
for (int j = 0; j < cc_count * 3; j = j + 3)
|
||||
{
|
||||
if (validate_cc_data_pair( cc_data + j ) )
|
||||
continue;
|
||||
ret = do_cb(ctx, cc_data + j, sub);
|
||||
if (ret == 1) //1 means success here
|
||||
ret = 0;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
int validate_cc_data_pair (unsigned char *cc_data_pair)
|
||||
{
|
||||
unsigned char cc_valid = (*cc_data_pair & 4) >>2;
|
||||
unsigned char cc_type = *cc_data_pair & 3;
|
||||
|
||||
if (!cc_valid)
|
||||
return -1;
|
||||
|
||||
if (cc_type==0 || cc_type==1)
|
||||
{
|
||||
// For EIA-608 data we verify parity.
|
||||
if (!cc608_parity_table[cc_data_pair[2]])
|
||||
{
|
||||
// If the second byte doesn't pass parity, ignore pair
|
||||
return -1;
|
||||
}
|
||||
if (!cc608_parity_table[cc_data_pair[1]])
|
||||
{
|
||||
// The first byte doesn't pass parity, we replace it with a solid blank
|
||||
// and process the pair.
|
||||
cc_data_pair[1]=0x7F;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
||||
}
|
||||
int do_cb (struct lib_cc_decode *ctx, unsigned char *cc_block, struct cc_subtitle *sub)
|
||||
{
|
||||
unsigned char cc_valid = (*cc_block & 4) >>2;
|
||||
unsigned char cc_type = *cc_block & 3;
|
||||
|
||||
int timeok = 1;
|
||||
|
||||
if ( ctx->fix_padding
|
||||
&& cc_valid==0 && cc_type <= 1 // Only fix NTSC packets
|
||||
&& cc_block[1]==0 && cc_block[2]==0 )
|
||||
{
|
||||
/* Padding */
|
||||
cc_valid=1;
|
||||
cc_block[1]=0x80;
|
||||
cc_block[2]=0x80;
|
||||
}
|
||||
|
||||
if ( ctx->write_format!=CCX_OF_RAW && // In raw we cannot skip padding because timing depends on it
|
||||
ctx->write_format!=CCX_OF_DVDRAW &&
|
||||
(cc_block[0]==0xFA || cc_block[0]==0xFC || cc_block[0]==0xFD )
|
||||
&& (cc_block[1]&0x7F)==0 && (cc_block[2]&0x7F)==0) // CFS: Skip non-data, makes debugging harder.
|
||||
return 1;
|
||||
|
||||
// Print raw data with FTS.
|
||||
dbg_print(CCX_DMT_CBRAW, "%s %d %02X:%c%c:%02X", print_mstime(fts_now + fts_global),in_xds_mode,
|
||||
cc_block[0], cc_block[1]&0x7f,cc_block[2]&0x7f, cc_block[2]);
|
||||
|
||||
/* In theory the writercwtdata() function could return early and not
|
||||
* go through the 608/708 cases below. We do that to get accurate
|
||||
* counts for cb_field1, cb_field2 and cb_708.
|
||||
* Note that printdata() and do_708() must not be called for
|
||||
* the CCX_OF_RCWT case. */
|
||||
|
||||
if (cc_valid || cc_type==3)
|
||||
{
|
||||
ctx->cc_stats[cc_type]++;
|
||||
|
||||
switch (cc_type)
|
||||
{
|
||||
case 0:
|
||||
dbg_print(CCX_DMT_CBRAW, " %s .. ..\n", debug_608toASC( cc_block, 0));
|
||||
|
||||
current_field=1;
|
||||
ctx->saw_caption_block = 1;
|
||||
|
||||
if (ctx->extraction_start.set &&
|
||||
get_fts() < ctx->extraction_start.time_in_ms)
|
||||
timeok = 0;
|
||||
if (ctx->extraction_end.set &&
|
||||
get_fts() > ctx->extraction_end.time_in_ms)
|
||||
{
|
||||
timeok = 0;
|
||||
ctx->processed_enough=1;
|
||||
}
|
||||
if (timeok)
|
||||
{
|
||||
if(ctx->write_format!=CCX_OF_RCWT)
|
||||
printdata (ctx, cc_block+1,2,0,0, sub);
|
||||
else
|
||||
writercwtdata(ctx, cc_block);
|
||||
}
|
||||
cb_field1++;
|
||||
break;
|
||||
case 1:
|
||||
dbg_print(CCX_DMT_CBRAW, " .. %s ..\n", debug_608toASC( cc_block, 1));
|
||||
|
||||
current_field=2;
|
||||
ctx->saw_caption_block = 1;
|
||||
|
||||
if (ctx->extraction_start.set &&
|
||||
get_fts() < ctx->extraction_start.time_in_ms)
|
||||
timeok = 0;
|
||||
if (ctx->extraction_end.set &&
|
||||
get_fts() > ctx->extraction_end.time_in_ms)
|
||||
{
|
||||
timeok = 0;
|
||||
ctx->processed_enough=1;
|
||||
}
|
||||
if (timeok)
|
||||
{
|
||||
if(ctx->write_format!=CCX_OF_RCWT)
|
||||
printdata (ctx, 0,0,cc_block+1,2, sub);
|
||||
else
|
||||
writercwtdata(ctx, cc_block);
|
||||
}
|
||||
cb_field2++;
|
||||
break;
|
||||
case 2: //EIA-708
|
||||
// DTVCC packet data
|
||||
// Fall through
|
||||
case 3: //EIA-708
|
||||
dbg_print(CCX_DMT_CBRAW, " .. .. DD\n");
|
||||
|
||||
// DTVCC packet start
|
||||
current_field=3;
|
||||
|
||||
if (ctx->extraction_start.set &&
|
||||
get_fts() < ctx->extraction_start.time_in_ms)
|
||||
timeok = 0;
|
||||
if (ctx->extraction_end.set &&
|
||||
get_fts() > ctx->extraction_end.time_in_ms)
|
||||
{
|
||||
timeok = 0;
|
||||
ctx->processed_enough=1;
|
||||
}
|
||||
char temp[4];
|
||||
temp[0]=cc_valid;
|
||||
temp[1]=cc_type;
|
||||
temp[2]=cc_block[1];
|
||||
temp[3]=cc_block[2];
|
||||
if (timeok)
|
||||
{
|
||||
if(ctx->write_format!=CCX_OF_RCWT)
|
||||
do_708 (ctx,(const unsigned char *) temp, 4);
|
||||
else
|
||||
writercwtdata(ctx, cc_block);
|
||||
}
|
||||
cb_708++;
|
||||
// Check for bytes read
|
||||
// printf ("Warning: Losing EIA-708 data!\n");
|
||||
break;
|
||||
default:
|
||||
fatal(CCX_COMMON_EXIT_BUG_BUG, "Cannot be reached!");
|
||||
} // switch (cc_type)
|
||||
} // cc_valid
|
||||
else
|
||||
{
|
||||
dbg_print(CCX_DMT_CBRAW, " .. .. ..\n");
|
||||
dbg_print(CCX_DMT_VERBOSE, "Found !(cc_valid || cc_type==3) - ignore this block\n");
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
struct lib_cc_decode* init_cc_decode (struct ccx_decoders_common_settings_t *setting)
|
||||
{
|
||||
struct lib_cc_decode *ctx = NULL;
|
||||
|
||||
ctx = malloc(sizeof(struct lib_cc_decode));
|
||||
if(!ctx)
|
||||
return NULL;
|
||||
|
||||
// Prepare 608 context
|
||||
ctx->context_cc608_field_1 = ccx_decoder_608_init_library(
|
||||
ccx_options.settings_608,
|
||||
ccx_options.cc_channel,
|
||||
1,
|
||||
ccx_options.trim_subs,
|
||||
ccx_options.encoding,
|
||||
&ctx->processed_enough,
|
||||
setting->cc_to_stdout,
|
||||
setting->subs_delay,
|
||||
setting->output_format
|
||||
);
|
||||
ctx->context_cc608_field_2 = ccx_decoder_608_init_library(
|
||||
ccx_options.settings_608,
|
||||
ccx_options.cc_channel,
|
||||
2,
|
||||
ccx_options.trim_subs,
|
||||
ccx_options.encoding,
|
||||
&ctx->processed_enough,
|
||||
setting->cc_to_stdout,
|
||||
setting->subs_delay,
|
||||
setting->output_format
|
||||
);
|
||||
|
||||
ctx->fix_padding = setting->fix_padding;
|
||||
ctx->write_format = setting->output_format;
|
||||
ctx->subs_delay = setting->subs_delay;
|
||||
ctx->wbout1 = setting->wbout1;
|
||||
memcpy(&ctx->extraction_start, &setting->extraction_start,sizeof(struct ccx_boundary_time));
|
||||
memcpy(&ctx->extraction_end, &setting->extraction_end,sizeof(struct ccx_boundary_time));
|
||||
return ctx;
|
||||
}
|
||||
void dinit_cc_decode(struct lib_cc_decode **ctx)
|
||||
{
|
||||
struct lib_cc_decode *lctx = *ctx;
|
||||
ccx_decoder_608_dinit_library(&lctx->context_cc608_field_1);
|
||||
ccx_decoder_608_dinit_library(&lctx->context_cc608_field_2);
|
||||
freep(ctx);
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
#include "ccx_common_platform.h"
|
||||
#include "ccx_common_constants.h"
|
||||
#include "ccx_common_structs.h"
|
||||
#include "ccx_decoders_structs.h"
|
||||
|
||||
extern unsigned char encoded_crlf[16]; // We keep it encoded here so we don't have to do it many times
|
||||
@@ -22,4 +23,12 @@ void find_limit_characters(unsigned char *line, int *first_non_blank, int *last_
|
||||
unsigned get_decoder_line_basic(unsigned char *buffer, int line_num, struct eia608_screen *data, int trim_subs, enum ccx_encoding_type encoding);
|
||||
|
||||
void ccx_decoders_common_settings_init(LLONG subs_delay, enum ccx_output_format output_format);
|
||||
|
||||
int validate_cc_data_pair (unsigned char *cc_data_pair);
|
||||
int process_cc_data (struct lib_cc_decode *ctx, unsigned char *cc_data, int cc_count, struct cc_subtitle *sub);
|
||||
int do_cb (struct lib_cc_decode *ctx, unsigned char *cc_block, struct cc_subtitle *sub);
|
||||
void printdata (struct lib_cc_decode *ctx, const unsigned char *data1, int length1,
|
||||
const unsigned char *data2, int length2, struct cc_subtitle *sub);
|
||||
struct lib_cc_decode* init_cc_decode (struct ccx_decoders_common_settings_t *setting);
|
||||
void dinit_cc_decode(struct lib_cc_decode **ctx);
|
||||
#endif
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
#ifndef CCX_DECODERS_STRUCTS_H
|
||||
#define CCX_DECODERS_STRUCTS_H
|
||||
|
||||
#include "ccx_common_platform.h"
|
||||
#include "ccx_common_constants.h"
|
||||
#include "ccx_common_timing.h"
|
||||
|
||||
// Define max width in characters/columns on the screen
|
||||
#define CCX_DECODER_608_SCREEN_WIDTH 32
|
||||
@@ -70,11 +72,31 @@ typedef struct eia608_screen // A CC buffer
|
||||
int cur_xds_packet_class;
|
||||
} eia608_screen;
|
||||
|
||||
struct ccx_decoders_common_settings_t {
|
||||
struct ccx_decoders_common_settings_t
|
||||
{
|
||||
LLONG subs_delay; // ms to delay (or advance) subs
|
||||
enum ccx_output_format output_format; // What kind of output format should be used?
|
||||
int fix_padding; // Replace 0000 with 8080 in HDTV (needed for some cards)
|
||||
struct ccx_boundary_time extraction_start, extraction_end; // Segment we actually process
|
||||
void *wbout1;
|
||||
int cc_to_stdout;
|
||||
};
|
||||
struct lib_cc_decode
|
||||
{
|
||||
int cc_stats[4];
|
||||
int saw_caption_block;
|
||||
int processed_enough; // If 1, we have enough lines, time, etc.
|
||||
|
||||
/* 608 contexts - note that this shouldn't be global, they should be
|
||||
per program */
|
||||
void *context_cc608_field_1;
|
||||
void *context_cc608_field_2;
|
||||
|
||||
int fix_padding; // Replace 0000 with 8080 in HDTV (needed for some cards)
|
||||
enum ccx_output_format write_format; // 0=Raw, 1=srt, 2=SMI
|
||||
struct ccx_boundary_time extraction_start, extraction_end; // Segment we actually process
|
||||
void *wbout1;
|
||||
LLONG subs_delay; // ms to delay (or advance) subs
|
||||
};
|
||||
extern struct ccx_decoders_common_settings_t ccx_decoders_common_settings;
|
||||
|
||||
#define CCX_DECODERS_STRUCTS_H
|
||||
#endif
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
// is FALSE, parsing can set ustream->error to TRUE.
|
||||
int user_data(struct lib_ccx_ctx *ctx, struct bitstream *ustream, int udtype, struct cc_subtitle *sub)
|
||||
{
|
||||
struct lib_cc_decode *dec_ctx = NULL;
|
||||
dec_ctx = ctx->dec_ctx;
|
||||
dbg_print(CCX_DMT_VERBOSE, "user_data(%d)\n", udtype);
|
||||
|
||||
// Shall not happen
|
||||
@@ -92,7 +94,7 @@ int user_data(struct lib_ccx_ctx *ctx, struct bitstream *ustream, int udtype, st
|
||||
data[0]=0x04; // Field 1
|
||||
else
|
||||
data[0]=0x05; // Field 2
|
||||
do_cb(ctx, data, sub);
|
||||
do_cb(dec_ctx, data, sub);
|
||||
rcbcount++;
|
||||
}
|
||||
else
|
||||
@@ -123,7 +125,7 @@ int user_data(struct lib_ccx_ctx *ctx, struct bitstream *ustream, int udtype, st
|
||||
data[0]=0x04; // Field 1
|
||||
else
|
||||
data[0]=0x05; // Field 2
|
||||
do_cb(ctx, data, sub);
|
||||
do_cb(dec_ctx, data, sub);
|
||||
ecbcount++;
|
||||
}
|
||||
else
|
||||
@@ -214,12 +216,12 @@ int user_data(struct lib_ccx_ctx *ctx, struct bitstream *ustream, int udtype, st
|
||||
data[0]=0x05; // Field 2
|
||||
data[1]=read_u8(ustream);
|
||||
data[2]=read_u8(ustream);
|
||||
do_cb(ctx, data, sub);
|
||||
do_cb(dec_ctx, data, sub);
|
||||
read_bytes(ustream, 2); // Skip "CC 02" for R4000 or "AA 02" for R5000
|
||||
data[0]=0x04; // Field 1
|
||||
data[1]=read_u8(ustream);
|
||||
data[2]=read_u8(ustream);
|
||||
do_cb(ctx, data, sub);
|
||||
do_cb(dec_ctx, data, sub);
|
||||
}
|
||||
// HDTV - see A/53 Part 4 (Video)
|
||||
else if ( !memcmp(ud_header,"\x47\x41\x39\x34", 4 ) )
|
||||
@@ -460,7 +462,7 @@ int user_data(struct lib_ccx_ctx *ctx, struct bitstream *ustream, int udtype, st
|
||||
data[0]=0x04; // Field 1
|
||||
data[1]=read_u8(ustream);
|
||||
data[2]=read_u8(ustream);
|
||||
do_cb(ctx, data, sub);
|
||||
do_cb(dec_ctx, data, sub);
|
||||
// This is probably incomplete!
|
||||
}
|
||||
else
|
||||
|
||||
@@ -50,8 +50,10 @@ LLONG gettotalfilessize (struct lib_ccx_ctx *ctx) // -1 if one or more files fai
|
||||
|
||||
void prepare_for_new_file (struct lib_ccx_ctx *ctx)
|
||||
{
|
||||
// Init per file variables
|
||||
min_pts=0x01FFFFFFFFLL; // 33 bit
|
||||
struct lib_cc_decode *dec_ctx = NULL;
|
||||
dec_ctx = ctx->dec_ctx;
|
||||
// Init per file variables
|
||||
min_pts=0x01FFFFFFFFLL; // 33 bit
|
||||
sync_pts=0;
|
||||
pts_set = 0;
|
||||
// inputsize=0; Now responsibility of switch_to_next_file()
|
||||
@@ -67,7 +69,7 @@ void prepare_for_new_file (struct lib_ccx_ctx *ctx)
|
||||
total_frames_count = 0;
|
||||
ctx->total_pulldownfields = 0;
|
||||
ctx->total_pulldownframes = 0;
|
||||
ctx->cc_stats[0]=0; ctx->cc_stats[1]=0; ctx->cc_stats[2]=0; ctx->cc_stats[3]=0;
|
||||
dec_ctx->cc_stats[0]=0; dec_ctx->cc_stats[1]=0; dec_ctx->cc_stats[2]=0; dec_ctx->cc_stats[3]=0;
|
||||
ctx->false_pict_header=0;
|
||||
ctx->frames_since_last_gop=0;
|
||||
frames_since_ref_time=0;
|
||||
@@ -75,7 +77,7 @@ void prepare_for_new_file (struct lib_ccx_ctx *ctx)
|
||||
first_gop_time.inited=0;
|
||||
gop_rollover=0;
|
||||
printed_gop.inited=0;
|
||||
ctx->saw_caption_block=0;
|
||||
dec_ctx->saw_caption_block=0;
|
||||
ctx->past=0;
|
||||
pts_big_change=0;
|
||||
ctx->startbytes_pos=0;
|
||||
@@ -103,6 +105,8 @@ can be done */
|
||||
|
||||
int switch_to_next_file (struct lib_ccx_ctx *ctx, LLONG bytesinbuffer)
|
||||
{
|
||||
struct lib_cc_decode *dec_ctx = NULL;
|
||||
dec_ctx = ctx->dec_ctx;
|
||||
if (ctx->current_file==-1 || !ccx_options.binary_concat)
|
||||
{
|
||||
memset (ctx->PIDs_seen,0,65536*sizeof (int));
|
||||
@@ -159,7 +163,7 @@ int switch_to_next_file (struct lib_ccx_ctx *ctx, LLONG bytesinbuffer)
|
||||
if (ccx_options.print_file_reports)
|
||||
print_file_report(ctx);
|
||||
close_input_file (ctx);
|
||||
if (ctx->inputsize>0 && ((ctx->past+bytesinbuffer) < ctx->inputsize) && !ctx->processed_enough)
|
||||
if (ctx->inputsize>0 && ((ctx->past+bytesinbuffer) < ctx->inputsize) && !dec_ctx->processed_enough)
|
||||
{
|
||||
mprint("\n\n\n\nATTENTION!!!!!!\n");
|
||||
mprint("In switch_to_next_file(): Processing of %s %d ended prematurely %lld < %lld, please send bug report.\n\n",
|
||||
|
||||
@@ -474,28 +474,30 @@ void raw_loop (struct lib_ccx_ctx *ctx, void *enc_ctx)
|
||||
* The number of processed bytes is returned. */
|
||||
LLONG process_raw_with_field (struct lib_ccx_ctx *ctx, struct cc_subtitle *sub)
|
||||
{
|
||||
unsigned char data[3];
|
||||
data[0]=0x04; // Field 1
|
||||
current_field=1;
|
||||
unsigned char data[3];
|
||||
struct lib_cc_decode *dec_ctx = NULL;
|
||||
dec_ctx = ctx->dec_ctx;
|
||||
data[0]=0x04; // Field 1
|
||||
current_field=1;
|
||||
|
||||
for (unsigned long i=0; i<inbuf; i=i+3)
|
||||
{
|
||||
if ( !ctx->saw_caption_block && *(ctx->buffer+i)==0xff && *(ctx->buffer+i+1)==0xff)
|
||||
{
|
||||
// Skip broadcast header
|
||||
}
|
||||
else
|
||||
{
|
||||
for (unsigned long i=0; i<inbuf; i=i+3)
|
||||
{
|
||||
if ( !dec_ctx->saw_caption_block && *(ctx->buffer+i)==0xff && *(ctx->buffer+i+1)==0xff)
|
||||
{
|
||||
// Skip broadcast header
|
||||
}
|
||||
else
|
||||
{
|
||||
data[0]=ctx->buffer[i];
|
||||
data[1]=ctx->buffer[i+1];
|
||||
data[2]=ctx->buffer[i+2];
|
||||
data[1]=ctx->buffer[i+1];
|
||||
data[2]=ctx->buffer[i+2];
|
||||
|
||||
// do_cb increases the cb_field1 counter so that get_fts()
|
||||
// is correct.
|
||||
do_cb(ctx, data, sub);
|
||||
}
|
||||
}
|
||||
return inbuf;
|
||||
// do_cb increases the cb_field1 counter so that get_fts()
|
||||
// is correct.
|
||||
do_cb(dec_ctx, data, sub);
|
||||
}
|
||||
}
|
||||
return inbuf;
|
||||
}
|
||||
|
||||
|
||||
@@ -503,13 +505,15 @@ LLONG process_raw_with_field (struct lib_ccx_ctx *ctx, struct cc_subtitle *sub)
|
||||
* The number of processed bytes is returned. */
|
||||
LLONG process_raw (struct lib_ccx_ctx *ctx, struct cc_subtitle *sub)
|
||||
{
|
||||
unsigned char data[3];
|
||||
unsigned char data[3];
|
||||
struct lib_cc_decode *dec_ctx = NULL;
|
||||
dec_ctx = ctx->dec_ctx;
|
||||
data[0]=0x04; // Field 1
|
||||
current_field=1;
|
||||
|
||||
for (unsigned long i=0; i<inbuf; i=i+2)
|
||||
{
|
||||
if ( !ctx->saw_caption_block && *(ctx->buffer+i)==0xff && *(ctx->buffer+i+1)==0xff)
|
||||
if ( !dec_ctx->saw_caption_block && *(ctx->buffer+i)==0xff && *(ctx->buffer+i+1)==0xff)
|
||||
{
|
||||
// Skip broadcast header
|
||||
}
|
||||
@@ -520,7 +524,7 @@ LLONG process_raw (struct lib_ccx_ctx *ctx, struct cc_subtitle *sub)
|
||||
|
||||
// do_cb increases the cb_field1 counter so that get_fts()
|
||||
// is correct.
|
||||
do_cb(ctx, data, sub);
|
||||
do_cb(dec_ctx, data, sub);
|
||||
}
|
||||
}
|
||||
return inbuf;
|
||||
@@ -532,12 +536,14 @@ void general_loop(struct lib_ccx_ctx *ctx, void *enc_ctx)
|
||||
LLONG overlap=0;
|
||||
LLONG pos = 0; /* Current position in buffer */
|
||||
struct cc_subtitle dec_sub;
|
||||
struct lib_cc_decode *dec_ctx = NULL;
|
||||
dec_ctx = ctx->dec_ctx;
|
||||
inbuf = 0; // No data yet
|
||||
|
||||
end_of_file = 0;
|
||||
current_picture_coding_type = CCX_FRAME_TYPE_RESET_OR_UNKNOWN;
|
||||
memset(&dec_sub, 0,sizeof(dec_sub));
|
||||
while (!end_of_file && !ctx->processed_enough)
|
||||
while (!end_of_file && !dec_ctx->processed_enough)
|
||||
{
|
||||
/* Get rid of the bytes we already processed */
|
||||
overlap=inbuf-pos;
|
||||
@@ -707,7 +713,7 @@ void general_loop(struct lib_ccx_ctx *ctx, void *enc_ctx)
|
||||
if (has_ccdata_buffered)
|
||||
process_hdcc(ctx, &dec_sub);
|
||||
|
||||
if (ctx->total_past!=ctx->total_inputsize && ccx_options.binary_concat && !ctx->processed_enough)
|
||||
if (ctx->total_past!=ctx->total_inputsize && ccx_options.binary_concat && !dec_ctx->processed_enough)
|
||||
{
|
||||
mprint("\n\n\n\nATTENTION!!!!!!\n");
|
||||
mprint("Processing of %s %d ended prematurely %lld < %lld, please send bug report.\n\n",
|
||||
@@ -726,6 +732,8 @@ void rcwt_loop(struct lib_ccx_ctx *ctx, void *enc_ctx)
|
||||
static unsigned char *parsebuf;
|
||||
static long parsebufsize = 1024;
|
||||
struct cc_subtitle dec_sub;
|
||||
struct lib_cc_decode *dec_ctx = NULL;
|
||||
dec_ctx = ctx->dec_ctx;
|
||||
|
||||
memset(&dec_sub, 0,sizeof(dec_sub));
|
||||
// As BUFSIZE is a macro this is just a reminder
|
||||
@@ -831,7 +839,7 @@ void rcwt_loop(struct lib_ccx_ctx *ctx, void *enc_ctx)
|
||||
|
||||
for (int j=0; j<cbcount*3; j=j+3)
|
||||
{
|
||||
do_cb(ctx, parsebuf+j, &dec_sub);
|
||||
do_cb(dec_ctx, parsebuf+j, &dec_sub);
|
||||
}
|
||||
}
|
||||
if (dec_sub.got_output)
|
||||
|
||||
@@ -2,11 +2,33 @@
|
||||
#include "ccx_common_option.h"
|
||||
|
||||
struct ccx_common_logging_t ccx_common_logging;
|
||||
struct ccx_decoders_common_settings_t ccx_decoders_common_settings;
|
||||
static struct ccx_decoders_common_settings_t *init_decoder_setting(
|
||||
struct ccx_s_options *opt)
|
||||
{
|
||||
struct ccx_decoders_common_settings_t *setting;
|
||||
|
||||
setting = malloc(sizeof(struct ccx_decoders_common_settings_t));
|
||||
if(!setting)
|
||||
return NULL;
|
||||
|
||||
setting->subs_delay = opt->subs_delay;
|
||||
setting->output_format = opt->write_format;
|
||||
setting->fix_padding = opt->fix_padding;
|
||||
memcpy(&setting->extraction_start,&opt->extraction_start,sizeof(struct ccx_boundary_time));
|
||||
memcpy(&setting->extraction_end,&opt->extraction_end,sizeof(struct ccx_boundary_time));
|
||||
setting->cc_to_stdout = opt->cc_to_stdout;
|
||||
return setting;
|
||||
}
|
||||
static void dinit_decoder_setting (struct ccx_decoders_common_settings_t **setting)
|
||||
{
|
||||
freep(setting);
|
||||
}
|
||||
|
||||
struct lib_ccx_ctx* init_libraries(struct ccx_s_options *opt)
|
||||
{
|
||||
struct lib_ccx_ctx *ctx;
|
||||
struct ccx_decoder_608_report *report_608;
|
||||
struct ccx_decoders_common_settings_t *dec_setting;
|
||||
|
||||
ctx = malloc(sizeof(struct lib_ccx_ctx));
|
||||
if(!ctx)
|
||||
@@ -18,6 +40,14 @@ struct lib_ccx_ctx* init_libraries(struct ccx_s_options *opt)
|
||||
return NULL;
|
||||
memset(report_608,0,sizeof(struct ccx_decoder_608_report));
|
||||
|
||||
ctx->capbufsize = 20000;
|
||||
ctx->capbuf = NULL;
|
||||
ctx->capbuflen = 0; // Bytes read in capbuf
|
||||
|
||||
// Initialize some constants
|
||||
init_ts(ctx);
|
||||
init_avc();
|
||||
|
||||
ctx->stream_mode = CCX_SM_ELEMENTARY_OR_NOT_FOUND;
|
||||
ctx->auto_stream = opt->auto_stream;
|
||||
ctx->screens_to_process = -1;
|
||||
@@ -30,7 +60,7 @@ struct lib_ccx_ctx* init_libraries(struct ccx_s_options *opt)
|
||||
|
||||
// Set logging functions for libraries
|
||||
ccx_common_logging.debug_ftn = &dbg_print;
|
||||
ccx_common_logging.debug_mask = ccx_options.debug_mask;
|
||||
ccx_common_logging.debug_mask = opt->debug_mask;
|
||||
ccx_common_logging.fatal_ftn = &fatal;
|
||||
ccx_common_logging.log_ftn = &mprint;
|
||||
ccx_common_logging.gui_ftn = &activity_library_process;
|
||||
@@ -41,39 +71,22 @@ struct lib_ccx_ctx* init_libraries(struct ccx_s_options *opt)
|
||||
ctx->freport.data_from_708 = &ccx_decoder_708_report;
|
||||
|
||||
// Init shared decoder settings
|
||||
ccx_decoders_common_settings_init(ctx->subs_delay, ccx_options.write_format);
|
||||
// Init encoder helper variables
|
||||
ccx_encoders_helpers_setup(ccx_options.encoding, ccx_options.nofontcolor, ccx_options.notypesetting, ccx_options.trim_subs);
|
||||
dec_setting = init_decoder_setting(opt);
|
||||
ctx->dec_ctx = init_cc_decode(dec_setting);
|
||||
dinit_decoder_setting(&dec_setting);
|
||||
|
||||
// Prepare 608 context
|
||||
ctx->context_cc608_field_1 = ccx_decoder_608_init_library(
|
||||
ccx_options.settings_608,
|
||||
ccx_options.cc_channel,
|
||||
1,
|
||||
ccx_options.trim_subs,
|
||||
ccx_options.encoding,
|
||||
&ctx->processed_enough,
|
||||
&ctx->cc_to_stdout
|
||||
);
|
||||
ctx->context_cc608_field_2 = ccx_decoder_608_init_library(
|
||||
ccx_options.settings_608,
|
||||
ccx_options.cc_channel,
|
||||
2,
|
||||
ccx_options.trim_subs,
|
||||
ccx_options.encoding,
|
||||
&ctx->processed_enough,
|
||||
&ctx->cc_to_stdout
|
||||
);
|
||||
// Init encoder helper variables
|
||||
ccx_encoders_helpers_setup(opt->encoding, opt->nofontcolor, opt->notypesetting, opt->trim_subs);
|
||||
|
||||
// Init 708 decoder(s)
|
||||
ccx_decoders_708_init_library(ctx->basefilename,ctx->extension,ccx_options.print_file_reports);
|
||||
ccx_decoders_708_init_library(ctx->basefilename,ctx->extension,opt->print_file_reports);
|
||||
|
||||
// Set output structures for the 608 decoder
|
||||
ctx->context_cc608_field_1.out = &ctx->wbout1;
|
||||
ctx->context_cc608_field_2.out = &ctx->wbout2;
|
||||
//ctx->dec_ctx->context_cc608_field_1->out = ctx->dec_ctx->wbout1;
|
||||
//ctx->dec_ctx->context_cc608_field_2->out = ctx->dec_ctx->wbout2;
|
||||
|
||||
// Init XDS buffers
|
||||
ccx_decoders_xds_init_library(&ccx_options.transcript_settings, ctx->subs_delay, ccx_options.millis_separator);
|
||||
ccx_decoders_xds_init_library(&opt->transcript_settings, ctx->subs_delay, opt->millis_separator);
|
||||
//xds_cea608_test();
|
||||
|
||||
//Initialize input files
|
||||
@@ -82,8 +95,29 @@ struct lib_ccx_ctx* init_libraries(struct ccx_s_options *opt)
|
||||
ctx->subs_delay = opt->subs_delay;
|
||||
ctx->wbout1.filename = opt->wbout2.filename;
|
||||
ctx->wbout2.filename = opt->wbout2.filename;
|
||||
ctx->buffer = (unsigned char *) malloc (BUFSIZE);
|
||||
ctx->pesheaderbuf = (unsigned char *) malloc (188); // Never larger anyway
|
||||
|
||||
// Init timing
|
||||
ccx_common_timing_init(&ctx->past,opt->nosync);
|
||||
|
||||
build_parity_table();
|
||||
return ctx;
|
||||
}
|
||||
|
||||
void dinit_libraries( struct lib_ccx_ctx **ctx)
|
||||
{
|
||||
struct lib_ccx_ctx *lctx = *ctx;
|
||||
int i = 0;
|
||||
for (i = 0; i < MAX_PID; i++)
|
||||
{
|
||||
if( lctx->PIDs_programs[i])
|
||||
freep(lctx->PIDs_programs + i);
|
||||
}
|
||||
dinit_ts(lctx);
|
||||
dinit_cc_decode(&lctx->dec_ctx);
|
||||
freep(&lctx->buffer);
|
||||
freep(&lctx->pesheaderbuf);
|
||||
freep(&lctx->freport.data_from_608);
|
||||
freep(ctx);
|
||||
}
|
||||
|
||||
@@ -84,6 +84,7 @@ struct ccx_s_teletext_config {
|
||||
// uint64_t utc_refvalue; // UTC referential value => Moved to ccx_decoders_common, so can be used for other decoders (608/xds) too
|
||||
uint16_t user_page; // Page selected by user, which MIGHT be different to 'page' depending on autodetection stuff
|
||||
};
|
||||
#define MAX_PID 65536
|
||||
struct lib_ccx_ctx
|
||||
{
|
||||
// TODO relates to fts_global
|
||||
@@ -91,7 +92,6 @@ struct lib_ccx_ctx
|
||||
uint32_t min_global_timestamp;
|
||||
int global_timestamp_inited;
|
||||
|
||||
int saw_caption_block;
|
||||
|
||||
// Stuff common to both loops
|
||||
unsigned char *buffer;
|
||||
@@ -102,7 +102,6 @@ struct lib_ccx_ctx
|
||||
LLONG total_past; // Only in binary concat mode
|
||||
|
||||
int last_reported_progress;
|
||||
int processed_enough; // If 1, we have enough lines, time, etc.
|
||||
|
||||
// Small buffer to help us with the initial sync
|
||||
unsigned char startbytes[STARTBYTESLENGTH];
|
||||
@@ -120,7 +119,6 @@ struct lib_ccx_ctx
|
||||
int stat_divicom;
|
||||
unsigned total_pulldownfields;
|
||||
unsigned total_pulldownframes;
|
||||
int cc_stats[4];
|
||||
int false_pict_header;
|
||||
|
||||
/* GOP-based timing */
|
||||
@@ -134,10 +132,7 @@ struct lib_ccx_ctx
|
||||
|
||||
// int hex_mode=HEX_NONE; // Are we processing an hex file?
|
||||
|
||||
/* 608 contexts - note that this shouldn't be global, they should be
|
||||
per program */
|
||||
ccx_decoder_608_context context_cc608_field_1;
|
||||
ccx_decoder_608_context context_cc608_field_2;
|
||||
struct lib_cc_decode *dec_ctx;
|
||||
enum ccx_stream_mode_enum stream_mode;
|
||||
enum ccx_stream_mode_enum auto_stream;
|
||||
|
||||
@@ -175,9 +170,13 @@ struct lib_ccx_ctx
|
||||
int infd; // descriptor number to input.
|
||||
char *basefilename_for_stdin;
|
||||
char *basefilename_for_network;
|
||||
int PIDs_seen[65536];
|
||||
struct PMT_entry *PIDs_programs[65536];
|
||||
int PIDs_seen[MAX_PID];
|
||||
struct PMT_entry *PIDs_programs[MAX_PID];
|
||||
struct file_report freport;
|
||||
|
||||
long capbufsize;
|
||||
unsigned char *capbuf;
|
||||
long capbuflen; // Bytes read in capbuf
|
||||
};
|
||||
#ifdef DEBUG_TELEXCC
|
||||
int main_telxcc (int argc, char *argv[]);
|
||||
@@ -212,6 +211,7 @@ int main_telxcc (int argc, char *argv[]);
|
||||
LLONG buffered_read_opt (struct lib_ccx_ctx *ctx, unsigned char *buffer, unsigned int bytes);
|
||||
|
||||
struct lib_ccx_ctx* init_libraries(struct ccx_s_options *opt);
|
||||
void dinit_libraries( struct lib_ccx_ctx **ctx);
|
||||
|
||||
//params.c
|
||||
void parse_parameters (struct ccx_s_options *opt, int argc, char *argv[]);
|
||||
@@ -282,7 +282,6 @@ void store_hdcc(struct lib_ccx_ctx *ctx, unsigned char *cc_data, int cc_count, i
|
||||
LLONG current_fts_now,struct cc_subtitle *sub);
|
||||
void anchor_hdcc(int seq);
|
||||
void process_hdcc (struct lib_ccx_ctx *ctx, struct cc_subtitle *sub);
|
||||
int do_cb (struct lib_ccx_ctx *ctx, unsigned char *cc_block, struct cc_subtitle *sub);
|
||||
// mp4.c
|
||||
int processmp4 (struct lib_ccx_ctx *ctx, char *file,void *enc_ctx);
|
||||
|
||||
@@ -295,9 +294,7 @@ void init_write(struct ccx_s_write *wb, char *filename);
|
||||
void writeraw (const unsigned char *data, int length, struct ccx_s_write *wb);
|
||||
void writedata(const unsigned char *data, int length, ccx_decoder_608_context *context, struct cc_subtitle *sub);
|
||||
void flushbuffer (struct lib_ccx_ctx *ctx, struct ccx_s_write *wb, int closefile);
|
||||
void printdata (struct lib_ccx_ctx *ctx, const unsigned char *data1, int length1,
|
||||
const unsigned char *data2, int length2, struct cc_subtitle *sub);
|
||||
void writercwtdata (struct lib_ccx_ctx *ctx, const unsigned char *data);
|
||||
void writercwtdata (struct lib_cc_decode *ctx, const unsigned char *data);
|
||||
|
||||
// stream_functions.c
|
||||
void detect_stream_type (struct lib_ccx_ctx *ctx);
|
||||
@@ -306,7 +303,8 @@ int read_video_pes_header (struct lib_ccx_ctx *ctx, unsigned char *nextheader, i
|
||||
int read_pts_pes(unsigned char*header, int len);
|
||||
|
||||
// ts_functions.c
|
||||
void init_ts( void );
|
||||
void init_ts(struct lib_ccx_ctx *ctx);
|
||||
void dinit_ts (struct lib_ccx_ctx *ctx);
|
||||
int ts_readpacket(struct lib_ccx_ctx* ctx);
|
||||
long ts_readstream(struct lib_ccx_ctx *ctx);
|
||||
LLONG ts_getmoredata(struct lib_ccx_ctx *ctx);
|
||||
@@ -321,8 +319,6 @@ void myth_loop(struct lib_ccx_ctx *ctx, void *enc_ctx);
|
||||
void fatal(int exit_code, const char *fmt, ...);
|
||||
void dvprint(const char *fmt, ...);
|
||||
void mprint (const char *fmt, ...);
|
||||
void dbg_print(LLONG mask, const char *fmt, ...);
|
||||
void init_boundary_time (struct ccx_boundary_time *bt);
|
||||
void sleep_secs (int secs);
|
||||
void dump (LLONG mask, unsigned char *start, int l, unsigned long abs_start, unsigned clear_high_bit);
|
||||
bool_t in_array(uint16_t *array, uint16_t length, uint16_t element) ;
|
||||
@@ -378,7 +374,6 @@ extern int has_ccdata_buffered;
|
||||
|
||||
extern unsigned char *subline;
|
||||
|
||||
extern int cc608_parity_table[256]; // From myth
|
||||
|
||||
// From ts_functions
|
||||
extern unsigned cap_stream_type;
|
||||
|
||||
@@ -554,6 +554,7 @@ static int cc608_good_parity(const int *parity_table, unsigned int data)
|
||||
void ProcessVBIDataPacket(struct lib_ccx_ctx *ctx, struct cc_subtitle *sub)
|
||||
{
|
||||
|
||||
struct lib_cc_decode *dec_ctx = NULL;
|
||||
const unsigned char *meat = av.data;
|
||||
if (meat==NULL)
|
||||
{
|
||||
@@ -562,6 +563,7 @@ void ProcessVBIDataPacket(struct lib_ccx_ctx *ctx, struct cc_subtitle *sub)
|
||||
}
|
||||
|
||||
LLONG linemask = 0;
|
||||
dec_ctx = ctx->dec_ctx;
|
||||
// unsigned long long utc = lastccptsu;
|
||||
|
||||
// [i]tv0 means there is a linemask
|
||||
@@ -615,7 +617,7 @@ void ProcessVBIDataPacket(struct lib_ccx_ctx *ctx, struct cc_subtitle *sub)
|
||||
ccdata[0]=0x04; // Field 1
|
||||
ccdata[1]=meat[1];
|
||||
ccdata[2]=meat[2];
|
||||
do_cb(ctx, ccdata, sub);
|
||||
do_cb(dec_ctx, ccdata, sub);
|
||||
// processed_ccblocks++; // Not sure this is accurate
|
||||
}
|
||||
else
|
||||
@@ -623,7 +625,7 @@ void ProcessVBIDataPacket(struct lib_ccx_ctx *ctx, struct cc_subtitle *sub)
|
||||
ccdata[0]=0x05; // Field 1
|
||||
ccdata[1]=meat[1];
|
||||
ccdata[2]=meat[2];
|
||||
do_cb(ctx, ccdata, sub);
|
||||
do_cb(dec_ctx, ccdata, sub);
|
||||
}
|
||||
}
|
||||
// utc += 33367;
|
||||
@@ -830,9 +832,11 @@ void myth_loop(struct lib_ccx_ctx *ctx, void *enc_ctx)
|
||||
int has_vbi=0;
|
||||
LLONG saved = 0;
|
||||
struct cc_subtitle dec_sub;
|
||||
struct lib_cc_decode *dec_ctx = NULL;
|
||||
|
||||
av.data=NULL;
|
||||
ccx_options.buffer_input = 1;
|
||||
dec_ctx = ctx->dec_ctx;
|
||||
if (init_file_buffer())
|
||||
{
|
||||
fatal (EXIT_NOT_ENOUGH_MEMORY, "Not enough memory.\n");
|
||||
@@ -844,7 +848,7 @@ void myth_loop(struct lib_ccx_ctx *ctx, void *enc_ctx)
|
||||
saved=0;
|
||||
|
||||
memset(&dec_sub, 0, sizeof(dec_sub));
|
||||
while (!ctx->processed_enough && (rc=mpegps_read_packet(ctx))==0)
|
||||
while (!dec_ctx->processed_enough && (rc=mpegps_read_packet(ctx))==0)
|
||||
{
|
||||
position_sanity_check();
|
||||
if (av.codec_id==CODEC_ID_MPEG2VBI && av.type==CODEC_TYPE_DATA)
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
/* TODO remove dependency of encoder by removing writeDVDraw from this file */
|
||||
#include "ccx_encoders_structs.h"
|
||||
|
||||
void init_write (struct ccx_s_write *wb,char *filename)
|
||||
{
|
||||
@@ -102,21 +104,24 @@ void writeDVDraw (const unsigned char *data1, int length1,
|
||||
|
||||
}
|
||||
|
||||
void printdata (struct lib_ccx_ctx *ctx, const unsigned char *data1, int length1,
|
||||
void printdata (struct lib_cc_decode *ctx, const unsigned char *data1, int length1,
|
||||
const unsigned char *data2, int length2, struct cc_subtitle *sub)
|
||||
{
|
||||
if (ccx_options.write_format==CCX_OF_DVDRAW)
|
||||
writeDVDraw (data1,length1,data2,length2,&ctx->wbout1);
|
||||
struct ccx_decoder_608_context *field_1 = ctx->context_cc608_field_1;
|
||||
struct ccx_decoder_608_context *field_2 = ctx->context_cc608_field_2;
|
||||
struct ccx_s_write *wbout1 = ctx->wbout1;
|
||||
if (ctx->write_format==CCX_OF_DVDRAW)
|
||||
writeDVDraw (data1, length1, data2, length2, wbout1);
|
||||
else /* Broadcast raw or any non-raw */
|
||||
{
|
||||
if (length1 && ccx_options.extract != 2)
|
||||
{
|
||||
writedata(data1, length1, &ctx->context_cc608_field_1, sub);
|
||||
writedata(data1, length1, field_1, sub);
|
||||
}
|
||||
if (length2)
|
||||
{
|
||||
if (ccx_options.extract != 1)
|
||||
writedata(data2, length2, &ctx->context_cc608_field_2, sub);
|
||||
writedata(data2, length2, field_2, sub);
|
||||
else // User doesn't want field 2 data, but we want XDS.
|
||||
writedata (data2,length2,NULL, sub);
|
||||
}
|
||||
@@ -125,14 +130,15 @@ void printdata (struct lib_ccx_ctx *ctx, const unsigned char *data1, int length1
|
||||
|
||||
/* Buffer data with the same FTS and write when a new FTS or data==NULL
|
||||
* is encountered */
|
||||
void writercwtdata (struct lib_ccx_ctx *ctx, const unsigned char *data)
|
||||
void writercwtdata (struct lib_cc_decode *ctx, const unsigned char *data)
|
||||
{
|
||||
static LLONG prevfts = -1;
|
||||
LLONG currfts = fts_now + fts_global;
|
||||
static uint16_t cbcount = 0;
|
||||
static int cbempty=0;
|
||||
static unsigned char cbbuffer[0xFFFF*3]; // TODO: use malloc
|
||||
static unsigned char cbheader[8+2];
|
||||
static LLONG prevfts = -1;
|
||||
LLONG currfts = fts_now + fts_global;
|
||||
static uint16_t cbcount = 0;
|
||||
static int cbempty=0;
|
||||
static unsigned char cbbuffer[0xFFFF*3]; // TODO: use malloc
|
||||
static unsigned char cbheader[8+2];
|
||||
struct ccx_s_write *wbout1 = ctx->wbout1;
|
||||
|
||||
if ( (prevfts != currfts && prevfts != -1)
|
||||
|| data == NULL
|
||||
@@ -186,8 +192,8 @@ void writercwtdata (struct lib_ccx_ctx *ctx, const unsigned char *data)
|
||||
}
|
||||
else
|
||||
{
|
||||
writeraw(cbheader,10,&ctx->wbout1);
|
||||
writeraw(cbbuffer,3*cbcount, &ctx->wbout1);
|
||||
writeraw(cbheader,10,wbout1);
|
||||
writeraw(cbbuffer,3*cbcount, wbout1);
|
||||
}
|
||||
}
|
||||
cbcount = 0;
|
||||
@@ -238,8 +244,8 @@ void writercwtdata (struct lib_ccx_ctx *ctx, const unsigned char *data)
|
||||
}
|
||||
else
|
||||
{
|
||||
writeraw(cbheader,10,&ctx->wbout1);
|
||||
writeraw(cbbuffer,3*cbcount, &ctx->wbout1);
|
||||
writeraw(cbheader,10, wbout1);
|
||||
writeraw(cbbuffer,3*cbcount, wbout1);
|
||||
}
|
||||
|
||||
cbcount = 0;
|
||||
|
||||
@@ -207,6 +207,8 @@ void params_dump(struct lib_ccx_ctx *ctx)
|
||||
|
||||
void print_file_report(struct lib_ccx_ctx *ctx)
|
||||
{
|
||||
struct lib_cc_decode *dec_ctx = NULL;
|
||||
dec_ctx = ctx->dec_ctx;
|
||||
#define Y_N(cond) ((cond) ? "Yes" : "No")
|
||||
|
||||
printf("File: ");
|
||||
@@ -359,9 +361,9 @@ void print_file_report(struct lib_ccx_ctx *ctx)
|
||||
if (j == SUB_STREAMS_CNT)
|
||||
printf("No\n");
|
||||
|
||||
printf("EIA-608: %s\n", Y_N(ctx->cc_stats[0] > 0 || ctx->cc_stats[1] > 0));
|
||||
printf("EIA-608: %s\n", Y_N(dec_ctx->cc_stats[0] > 0 || dec_ctx->cc_stats[1] > 0));
|
||||
|
||||
if (ctx->cc_stats[0] > 0 || ctx->cc_stats[1] > 0)
|
||||
if (dec_ctx->cc_stats[0] > 0 || dec_ctx->cc_stats[1] > 0)
|
||||
{
|
||||
printf("XDS: %s\n", Y_N(ctx->freport.data_from_608->xds));
|
||||
|
||||
@@ -371,9 +373,9 @@ void print_file_report(struct lib_ccx_ctx *ctx)
|
||||
printf("CC4: %s\n", Y_N(ctx->freport.data_from_608->cc_channels[3]));
|
||||
}
|
||||
|
||||
printf("CEA-708: %s\n", Y_N(ctx->cc_stats[2] > 0 || ctx->cc_stats[3] > 0));
|
||||
printf("CEA-708: %s\n", Y_N(dec_ctx->cc_stats[2] > 0 || dec_ctx->cc_stats[3] > 0));
|
||||
|
||||
if (ctx->cc_stats[2] > 0 || ctx->cc_stats[3] > 0)
|
||||
if (dec_ctx->cc_stats[2] > 0 || dec_ctx->cc_stats[3] > 0)
|
||||
{
|
||||
printf("Services: ");
|
||||
for (int i = 0; i < CCX_DECODERS_708_MAX_SERVICES; i++)
|
||||
|
||||
@@ -19,9 +19,6 @@ int has_ccdata_buffered = 0;
|
||||
// B-Frames belong to this I- or P-frame.
|
||||
static int anchor_seq_number = -1;
|
||||
|
||||
|
||||
static int in_xds_mode ; // Stolen from 608.c We need this for debug
|
||||
|
||||
void init_hdcc (void)
|
||||
{
|
||||
for (int j=0; j<SORTBUF; j++)
|
||||
@@ -97,217 +94,61 @@ void anchor_hdcc(int seq)
|
||||
// Sort/flash caption block buffer
|
||||
void process_hdcc (struct lib_ccx_ctx *ctx, struct cc_subtitle *sub)
|
||||
{
|
||||
// Remember the current value
|
||||
LLONG store_fts_now = fts_now;
|
||||
// Remember the current value
|
||||
LLONG store_fts_now = fts_now;
|
||||
struct lib_cc_decode *dec_ctx;
|
||||
int reset_cb = -1;
|
||||
|
||||
dbg_print(CCX_DMT_VERBOSE, "Flush HD caption blocks\n");
|
||||
dbg_print(CCX_DMT_VERBOSE, "Flush HD caption blocks\n");
|
||||
dec_ctx = ctx->dec_ctx;
|
||||
|
||||
int reset_cb = -1;
|
||||
|
||||
for (int seq=0; seq<SORTBUF; seq++)
|
||||
{
|
||||
// We rely on this.
|
||||
if (ccx_bufferdatatype == CCX_H264)
|
||||
reset_cb = 1;
|
||||
|
||||
// If fts_now is unchanged we rely on cc block counting,
|
||||
// otherwise reset counters as they get changed by do_cb()
|
||||
// below. This only happens when current_pts does not get
|
||||
// updated, like it used do happen for elementary streams.
|
||||
// Since use_gop_as_pts this is not needed anymore, but left
|
||||
// here for posterity.
|
||||
if (reset_cb < 0 && cc_fts[seq] && seq<SORTBUF-1 && cc_fts[seq+1])
|
||||
for (int seq=0; seq<SORTBUF; seq++)
|
||||
{
|
||||
if (cc_fts[seq] != cc_fts[seq+1])
|
||||
// We rely on this.
|
||||
if (ccx_bufferdatatype == CCX_H264)
|
||||
reset_cb = 1;
|
||||
else
|
||||
reset_cb = 0;
|
||||
}
|
||||
if (reset_cb == 1)
|
||||
{
|
||||
cb_field1 = 0;
|
||||
cb_field2 = 0;
|
||||
cb_708 = 0;
|
||||
|
||||
// If fts_now is unchanged we rely on cc block counting,
|
||||
// otherwise reset counters as they get changed by do_cb()
|
||||
// below. This only happens when current_pts does not get
|
||||
// updated, like it used do happen for elementary streams.
|
||||
// Since use_gop_as_pts this is not needed anymore, but left
|
||||
// here for posterity.
|
||||
if (reset_cb < 0 && cc_fts[seq] && seq<SORTBUF-1 && cc_fts[seq+1])
|
||||
{
|
||||
if (cc_fts[seq] != cc_fts[seq+1])
|
||||
reset_cb = 1;
|
||||
else
|
||||
reset_cb = 0;
|
||||
}
|
||||
if (reset_cb == 1)
|
||||
{
|
||||
cb_field1 = 0;
|
||||
cb_field2 = 0;
|
||||
cb_708 = 0;
|
||||
}
|
||||
|
||||
// Skip sequence numbers without data
|
||||
if (cc_data_count[seq] == 0)
|
||||
continue;
|
||||
|
||||
if (cc_data_pkts[seq][cc_data_count[seq]*3]!=0xFF)
|
||||
{
|
||||
// This is not optional. Something is wrong.
|
||||
dbg_print(CCX_DMT_VERBOSE, "Missing 0xFF marker at end\n");
|
||||
// A "continue;" here would ignore this caption, but we
|
||||
// process it.
|
||||
}
|
||||
|
||||
// Re-create original time
|
||||
fts_now = cc_fts[seq];
|
||||
process_cc_data( dec_ctx, cc_data_pkts[seq], cc_data_count[seq], sub);
|
||||
|
||||
}
|
||||
|
||||
// Skip sequence numbers without data
|
||||
if (cc_data_count[seq] == 0)
|
||||
continue;
|
||||
// Restore the value
|
||||
fts_now = store_fts_now;
|
||||
|
||||
if (cc_data_pkts[seq][cc_data_count[seq]*3]!=0xFF)
|
||||
{
|
||||
// This is not optional. Something is wrong.
|
||||
dbg_print(CCX_DMT_VERBOSE, "Missing 0xFF marker at end\n");
|
||||
// A "continue;" here would ignore this caption, but we
|
||||
// process it.
|
||||
}
|
||||
|
||||
// Re-create original time
|
||||
fts_now = cc_fts[seq];
|
||||
|
||||
for (int j=0; j<(cc_data_count[seq])*3; j=j+3)
|
||||
{
|
||||
unsigned char cc_valid = (*(cc_data_pkts[seq]+j) & 4) >>2;
|
||||
unsigned char cc_type = (*(cc_data_pkts[seq]+j)) & 3;
|
||||
|
||||
if (cc_valid && (cc_type==0 || cc_type==1))
|
||||
{
|
||||
// For EIA-608 data we verify parity.
|
||||
if (!cc608_parity_table[cc_data_pkts[seq][j+2]])
|
||||
{
|
||||
// If the second byte doesn't pass parity, ignore pair
|
||||
continue;
|
||||
}
|
||||
if (!cc608_parity_table[cc_data_pkts[seq][j+1]])
|
||||
{
|
||||
// The first byte doesn't pass parity, we replace it with a solid blank
|
||||
// and process the pair.
|
||||
cc_data_pkts[seq][j+1]=0x7F;
|
||||
}
|
||||
}
|
||||
do_cb(ctx, cc_data_pkts[seq]+j, sub);
|
||||
|
||||
} // for loop over packets
|
||||
}
|
||||
|
||||
// Restore the value
|
||||
fts_now = store_fts_now;
|
||||
|
||||
// Now that we are done, clean up.
|
||||
init_hdcc();
|
||||
}
|
||||
|
||||
|
||||
int do_cb (struct lib_ccx_ctx *ctx, unsigned char *cc_block, struct cc_subtitle *sub)
|
||||
{
|
||||
unsigned char cc_valid = (*cc_block & 4) >>2;
|
||||
unsigned char cc_type = *cc_block & 3;
|
||||
|
||||
int timeok = 1;
|
||||
|
||||
if ( ccx_options.fix_padding
|
||||
&& cc_valid==0 && cc_type <= 1 // Only fix NTSC packets
|
||||
&& cc_block[1]==0 && cc_block[2]==0 )
|
||||
{
|
||||
/* Padding */
|
||||
cc_valid=1;
|
||||
cc_block[1]=0x80;
|
||||
cc_block[2]=0x80;
|
||||
}
|
||||
|
||||
if ( ccx_options.write_format!=CCX_OF_RAW && // In raw we cannot skip padding because timing depends on it
|
||||
ccx_options.write_format!=CCX_OF_DVDRAW &&
|
||||
(cc_block[0]==0xFA || cc_block[0]==0xFC || cc_block[0]==0xFD )
|
||||
&& (cc_block[1]&0x7F)==0 && (cc_block[2]&0x7F)==0) // CFS: Skip non-data, makes debugging harder.
|
||||
return 1;
|
||||
|
||||
// Print raw data with FTS.
|
||||
dbg_print(CCX_DMT_CBRAW, "%s %d %02X:%c%c:%02X", print_mstime(fts_now + fts_global),in_xds_mode,
|
||||
cc_block[0], cc_block[1]&0x7f,cc_block[2]&0x7f, cc_block[2]);
|
||||
|
||||
/* In theory the writercwtdata() function could return early and not
|
||||
* go through the 608/708 cases below. We do that to get accurate
|
||||
* counts for cb_field1, cb_field2 and cb_708.
|
||||
* Note that printdata() and do_708() must not be called for
|
||||
* the CCX_OF_RCWT case. */
|
||||
|
||||
if (cc_valid || cc_type==3)
|
||||
{
|
||||
ctx->cc_stats[cc_type]++;
|
||||
|
||||
switch (cc_type)
|
||||
{
|
||||
case 0:
|
||||
dbg_print(CCX_DMT_CBRAW, " %s .. ..\n", debug_608toASC( cc_block, 0));
|
||||
|
||||
current_field=1;
|
||||
ctx->saw_caption_block = 1;
|
||||
|
||||
if (ccx_options.extraction_start.set &&
|
||||
get_fts() < ccx_options.extraction_start.time_in_ms)
|
||||
timeok = 0;
|
||||
if (ccx_options.extraction_end.set &&
|
||||
get_fts() > ccx_options.extraction_end.time_in_ms)
|
||||
{
|
||||
timeok = 0;
|
||||
ctx->processed_enough=1;
|
||||
}
|
||||
if (timeok)
|
||||
{
|
||||
if(ccx_options.write_format!=CCX_OF_RCWT)
|
||||
printdata (ctx, cc_block+1,2,0,0, sub);
|
||||
else
|
||||
writercwtdata(ctx, cc_block);
|
||||
}
|
||||
cb_field1++;
|
||||
break;
|
||||
case 1:
|
||||
dbg_print(CCX_DMT_CBRAW, " .. %s ..\n", debug_608toASC( cc_block, 1));
|
||||
|
||||
current_field=2;
|
||||
ctx->saw_caption_block = 1;
|
||||
|
||||
if (ccx_options.extraction_start.set &&
|
||||
get_fts() < ccx_options.extraction_start.time_in_ms)
|
||||
timeok = 0;
|
||||
if (ccx_options.extraction_end.set &&
|
||||
get_fts() > ccx_options.extraction_end.time_in_ms)
|
||||
{
|
||||
timeok = 0;
|
||||
ctx->processed_enough=1;
|
||||
}
|
||||
if (timeok)
|
||||
{
|
||||
if(ccx_options.write_format!=CCX_OF_RCWT)
|
||||
printdata (ctx, 0,0,cc_block+1,2, sub);
|
||||
else
|
||||
writercwtdata(ctx, cc_block);
|
||||
}
|
||||
cb_field2++;
|
||||
break;
|
||||
case 2: //EIA-708
|
||||
// DTVCC packet data
|
||||
// Fall through
|
||||
case 3: //EIA-708
|
||||
dbg_print(CCX_DMT_CBRAW, " .. .. DD\n");
|
||||
|
||||
// DTVCC packet start
|
||||
current_field=3;
|
||||
|
||||
if (ccx_options.extraction_start.set &&
|
||||
get_fts() < ccx_options.extraction_start.time_in_ms)
|
||||
timeok = 0;
|
||||
if (ccx_options.extraction_end.set &&
|
||||
get_fts() > ccx_options.extraction_end.time_in_ms)
|
||||
{
|
||||
timeok = 0;
|
||||
ctx->processed_enough=1;
|
||||
}
|
||||
char temp[4];
|
||||
temp[0]=cc_valid;
|
||||
temp[1]=cc_type;
|
||||
temp[2]=cc_block[1];
|
||||
temp[3]=cc_block[2];
|
||||
if (timeok)
|
||||
{
|
||||
if(ccx_options.write_format!=CCX_OF_RCWT)
|
||||
do_708 ((const unsigned char *) temp, 4);
|
||||
else
|
||||
writercwtdata(ctx, cc_block);
|
||||
}
|
||||
cb_708++;
|
||||
// Check for bytes read
|
||||
// printf ("Warning: Losing EIA-708 data!\n");
|
||||
break;
|
||||
default:
|
||||
fatal(CCX_COMMON_EXIT_BUG_BUG, "Cannot be reached!");
|
||||
} // switch (cc_type)
|
||||
} // cc_valid
|
||||
else
|
||||
{
|
||||
dbg_print(CCX_DMT_CBRAW, " .. .. ..\n");
|
||||
dbg_print(CCX_DMT_VERBOSE, "Found !(cc_valid || cc_type==3) - ignore this block\n");
|
||||
}
|
||||
|
||||
return 1;
|
||||
// Now that we are done, clean up.
|
||||
init_hdcc();
|
||||
}
|
||||
|
||||
@@ -8,9 +8,6 @@ unsigned char *last_pat_payload=NULL;
|
||||
unsigned last_pat_length = 0;
|
||||
|
||||
|
||||
static long capbufsize = 20000;
|
||||
static unsigned char *capbuf = NULL;
|
||||
long capbuflen = 0; // Bytes read in capbuf
|
||||
static unsigned char *haup_capbuf = NULL;
|
||||
static long haup_capbufsize = 0;
|
||||
static long haup_capbuflen = 0; // Bytes read in haup_capbuf
|
||||
@@ -23,7 +20,11 @@ extern void *ccx_dvb_context;
|
||||
// Descriptions for ts ccx_stream_type
|
||||
const char *desc[256];
|
||||
|
||||
void init_ts(void)
|
||||
void dinit_ts (struct lib_ccx_ctx *ctx)
|
||||
{
|
||||
freep(&ctx->capbuf);
|
||||
}
|
||||
void init_ts(struct lib_ccx_ctx *ctx)
|
||||
{
|
||||
// Constants
|
||||
desc[CCX_STREAM_TYPE_UNKNOWNSTREAM] = "Unknown";
|
||||
@@ -49,7 +50,7 @@ void init_ts(void)
|
||||
desc[CCX_STREAM_TYPE_ISO_IEC_13818_6_TYPE_D] = "ISO/IEC 13818-6 type D";
|
||||
|
||||
//Buffer
|
||||
capbuf = (unsigned char*)malloc(capbufsize);
|
||||
ctx->capbuf = (unsigned char*)malloc(ctx->capbufsize);
|
||||
}
|
||||
|
||||
|
||||
@@ -221,7 +222,7 @@ long ts_readstream(struct lib_ccx_ctx *ctx)
|
||||
long pcount=0; // count all packets until PES is complete
|
||||
int saw_pesstart = 0;
|
||||
int packet_analysis_mode=0; // If we can't find any packet with CC based from PMT, look for captions in all packets
|
||||
capbuflen = 0;
|
||||
ctx->capbuflen = 0;
|
||||
|
||||
do
|
||||
{
|
||||
@@ -257,7 +258,7 @@ long ts_readstream(struct lib_ccx_ctx *ctx)
|
||||
if( payload.pid == 0) // This is a PAT
|
||||
{
|
||||
if (parse_PAT(ctx)) // Returns 1 if there was some data in the buffer already
|
||||
capbuflen = 0;
|
||||
ctx->capbuflen = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -403,10 +404,10 @@ long ts_readstream(struct lib_ccx_ctx *ctx)
|
||||
}
|
||||
|
||||
// If the buffer is empty we just started this function
|
||||
if (payload.pesstart && capbuflen > 0)
|
||||
if (payload.pesstart && ctx->capbuflen > 0)
|
||||
{
|
||||
dbg_print(CCX_DMT_PARSE, "\nPES finished (%ld bytes/%ld PES packets/%ld total packets)\n",
|
||||
capbuflen, pespcount, pcount);
|
||||
ctx->capbuflen, pespcount, pcount);
|
||||
|
||||
// Keep the data in capbuf to be worked on
|
||||
|
||||
@@ -425,15 +426,15 @@ long ts_readstream(struct lib_ccx_ctx *ctx)
|
||||
|
||||
pespcount++;
|
||||
// copy payload to capbuf
|
||||
int newcapbuflen = capbuflen + payload.length;
|
||||
if ( newcapbuflen > capbufsize) {
|
||||
capbuf = (unsigned char*)realloc(capbuf, newcapbuflen);
|
||||
if (!capbuf)
|
||||
int newcapbuflen = ctx->capbuflen + payload.length;
|
||||
if ( newcapbuflen > ctx->capbufsize) {
|
||||
ctx->capbuf = (unsigned char*)realloc(ctx->capbuf, newcapbuflen);
|
||||
if (!ctx->capbuf)
|
||||
fatal(EXIT_NOT_ENOUGH_MEMORY, "Out of memory");
|
||||
capbufsize = newcapbuflen;
|
||||
ctx->capbufsize = newcapbuflen;
|
||||
}
|
||||
memcpy(capbuf+capbuflen, payload.start, payload.length);
|
||||
capbuflen = newcapbuflen;
|
||||
memcpy(ctx->capbuf + ctx->capbuflen, payload.start, payload.length);
|
||||
ctx->capbuflen = newcapbuflen;
|
||||
}
|
||||
//else
|
||||
// if(debug_verbose)
|
||||
@@ -444,7 +445,7 @@ long ts_readstream(struct lib_ccx_ctx *ctx)
|
||||
}
|
||||
while( !gotpes ); // gotpes==1 never arrives here because of the breaks
|
||||
|
||||
return capbuflen;
|
||||
return ctx->capbuflen;
|
||||
}
|
||||
|
||||
|
||||
@@ -510,15 +511,15 @@ LLONG ts_getmoredata(struct lib_ccx_ctx *ctx)
|
||||
}
|
||||
// We read a video PES
|
||||
|
||||
if (capbuf[0]!=0x00 || capbuf[1]!=0x00 ||
|
||||
capbuf[2]!=0x01)
|
||||
if (ctx->capbuf[0]!=0x00 || ctx->capbuf[1]!=0x00 ||
|
||||
ctx->capbuf[2]!=0x01)
|
||||
{
|
||||
// ??? Shouldn't happen. Complain and try again.
|
||||
mprint("Missing PES header!\n");
|
||||
dump(CCX_DMT_GENERIC_NOTICES, capbuf,256, 0, 0);
|
||||
dump(CCX_DMT_GENERIC_NOTICES, ctx->capbuf,256, 0, 0);
|
||||
continue;
|
||||
}
|
||||
unsigned stream_id = capbuf[3];
|
||||
unsigned stream_id = ctx->capbuf[3];
|
||||
|
||||
if (ccx_options.teletext_mode == CCX_TXT_IN_USE)
|
||||
{
|
||||
@@ -526,14 +527,14 @@ LLONG ts_getmoredata(struct lib_ccx_ctx *ctx)
|
||||
{ // If here, the user forced teletext mode but didn't supply a PID, and we haven't found it yet.
|
||||
continue;
|
||||
}
|
||||
memcpy(ctx->buffer+inbuf, capbuf, capbuflen);
|
||||
payload_read = capbuflen;
|
||||
inbuf += capbuflen;
|
||||
memcpy(ctx->buffer+inbuf, ctx->capbuf, ctx->capbuflen);
|
||||
payload_read = ctx->capbuflen;
|
||||
inbuf += ctx->capbuflen;
|
||||
break;
|
||||
}
|
||||
if (ccx_bufferdatatype == CCX_PRIVATE_MPEG2_CC)
|
||||
{
|
||||
dump (CCX_DMT_GENERIC_NOTICES, capbuf, capbuflen,0, 1);
|
||||
dump (CCX_DMT_GENERIC_NOTICES, ctx->capbuf, ctx->capbuflen,0, 1);
|
||||
// Bogus data, so we return something
|
||||
ctx->buffer[inbuf++]=0xFA;
|
||||
ctx->buffer[inbuf++]=0x80;
|
||||
@@ -589,10 +590,10 @@ LLONG ts_getmoredata(struct lib_ccx_ctx *ctx)
|
||||
}
|
||||
|
||||
dbg_print(CCX_DMT_VERBOSE, "TS payload start video PES id: %d len: %ld\n",
|
||||
stream_id, capbuflen);
|
||||
stream_id, ctx->capbuflen);
|
||||
|
||||
int pesheaderlen;
|
||||
int vpesdatalen = read_video_pes_header(ctx, capbuf, &pesheaderlen, capbuflen);
|
||||
int vpesdatalen = read_video_pes_header(ctx, ctx->capbuf, &pesheaderlen, ctx->capbuflen);
|
||||
|
||||
if (vpesdatalen < 0)
|
||||
{ // Seems to be a broken PES
|
||||
@@ -600,8 +601,8 @@ LLONG ts_getmoredata(struct lib_ccx_ctx *ctx)
|
||||
break;
|
||||
}
|
||||
|
||||
unsigned char *databuf = capbuf + pesheaderlen;
|
||||
long databuflen = capbuflen - pesheaderlen;
|
||||
unsigned char *databuf = ctx->capbuf + pesheaderlen;
|
||||
long databuflen = ctx->capbuflen - pesheaderlen;
|
||||
|
||||
// If the package length is unknown vpesdatalen is zero.
|
||||
// If we know he package length, use it to quit
|
||||
|
||||
@@ -389,7 +389,7 @@ int parse_PMT (struct lib_ccx_ctx *ctx, unsigned char *buf, int len, int pos)
|
||||
TS_program_number = program_number;
|
||||
}
|
||||
// If we have data flush it
|
||||
if( capbuflen > 0 )
|
||||
if( ctx->capbuflen > 0 )
|
||||
must_flush=1;
|
||||
}
|
||||
return must_flush;
|
||||
@@ -614,7 +614,7 @@ int parse_PAT (struct lib_ccx_ctx *ctx)
|
||||
if (!ccx_options.ts_forced_cappid)
|
||||
ccx_options.ts_cappid = 0; // Reset caption stream pid
|
||||
// If we have data flush it
|
||||
if( capbuflen > 0 )
|
||||
if( ctx->capbuflen > 0 )
|
||||
gotpes = 1;
|
||||
}
|
||||
return gotpes;
|
||||
|
||||
@@ -11,4 +11,5 @@
|
||||
#define RB16(x) (ntohs(*(unsigned short int*)(x)))
|
||||
|
||||
extern int temp_debug;
|
||||
void init_boundary_time (struct ccx_boundary_time *bt);
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user