Merge branch 'pr/n118_anshul1912'

This commit is contained in:
cfsmp3
2014-11-11 13:35:37 +01:00
25 changed files with 633 additions and 439 deletions

View File

@@ -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)

View File

@@ -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;
}

View File

@@ -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)

View File

@@ -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 )

View File

@@ -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

View File

@@ -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);
}

View File

@@ -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++;

View File

@@ -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

View File

@@ -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)

View File

@@ -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);

View File

@@ -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);
}

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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",

View File

@@ -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)

View File

@@ -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);
}

View File

@@ -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;

View File

@@ -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)

View File

@@ -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;

View File

@@ -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++)

View File

@@ -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();
}

View File

@@ -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

View File

@@ -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;

View File

@@ -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