mirror of
https://github.com/CCExtractor/ccextractor.git
synced 2026-02-12 05:25:06 +00:00
Compare commits
19 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9768555e7c | ||
|
|
72e422d76e | ||
|
|
8860be13e4 | ||
|
|
3b7ad97f0a | ||
|
|
5e305f2769 | ||
|
|
0a798606ee | ||
|
|
3775daf36c | ||
|
|
8c5de01034 | ||
|
|
1c352e67e4 | ||
|
|
79838077f2 | ||
|
|
058bb83a25 | ||
|
|
d2f840bb36 | ||
|
|
a576c90f4e | ||
|
|
a1bd01de5f | ||
|
|
9a5e817f36 | ||
|
|
bc20bc3f45 | ||
|
|
783a6e2aa0 | ||
|
|
992c56b262 | ||
|
|
c674cef79e |
@@ -1,3 +1,14 @@
|
||||
0.79 (2016-01-09)
|
||||
-----------------
|
||||
- Support for Grid Format (g608)
|
||||
- Show Correct number of teletext packet processed
|
||||
- Removed Segfault on incorrect mp4 detection
|
||||
- Remove xml header from transcript format
|
||||
- Help message updated for Teletext
|
||||
- Added --help and -h for help message
|
||||
- Added --nohtmlescape option
|
||||
- Added --noscte20 option
|
||||
|
||||
0.78 (2015-12-12)
|
||||
-----------------
|
||||
- Support to extract Closed Caption from MultiProgram at once.
|
||||
|
||||
58
docs/G608.TXT
Normal file
58
docs/G608.TXT
Normal file
@@ -0,0 +1,58 @@
|
||||
G608
|
||||
====
|
||||
G608 (for grid 608) is generated by CCExtractor by using -out=g608.
|
||||
|
||||
This is a verbose format that exports the contents of the 608 grid verbatim
|
||||
so there's no loss of positioning or colors due the limitations or complexy
|
||||
or other output formats.
|
||||
|
||||
G608 is a text file with a structure based on .srt and looks like this:
|
||||
|
||||
1
|
||||
00:00:02,019 --> 00:00:03,585
|
||||
99999999999999999999999999999999RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR
|
||||
99999999999999999999999999999999RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR
|
||||
99999999999999999999999999999999RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR
|
||||
99999999999999999999999999999999RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR
|
||||
99999999999999999999999999999999RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR
|
||||
99999999999999999999999999999999RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR
|
||||
99999999999999999999999999999999RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR
|
||||
99999999999999999999999999999999RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR
|
||||
99999999999999999999999999999999RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR
|
||||
99999999999999999999999999999999RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR
|
||||
99999999999999999999999999999999RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR
|
||||
99999999999999999999999999999999RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR
|
||||
99999999999999999999999999999999RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR
|
||||
- Previously on The Tudors... 90000000000000000000000000000009RIIIIIIIIIIIIIIIIRRRRRRRRRRRRRRR
|
||||
- Your Holy Father offs you 99000000000000000000000000000999RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR
|
||||
|
||||
For each subtitle frame there's exactly 15 rows (which represent the 15 rows of the 608 screen)
|
||||
of 96 characters each.
|
||||
|
||||
Each row is divided in 3 blocks: 32 characters for the text, 32 characters for the color, and
|
||||
32 characters for the font.
|
||||
|
||||
The possible color values are:
|
||||
COL_WHITE = 0,
|
||||
COL_GREEN = 1,
|
||||
COL_BLUE = 2,
|
||||
COL_CYAN = 3,
|
||||
COL_RED = 4,
|
||||
COL_YELLOW = 5,
|
||||
COL_MAGENTA = 6,
|
||||
COL_USERDEFINED = 7,
|
||||
COL_BLACK = 8,
|
||||
COL_TRANSPARENT = 9
|
||||
|
||||
And the possible font values are:
|
||||
R => Regular
|
||||
I => Italic
|
||||
U => Underlined
|
||||
B => Underlined + italic
|
||||
|
||||
If a 'E' is found in ether color or font that means a bug in CCExtractor. Should you ever get
|
||||
an E please send us a .bin file that causes it.
|
||||
|
||||
This format is intended for post processing tools that need to represent the output of a 608
|
||||
decoder accurately but that don't want to deal with the madness of other more generic subtitle
|
||||
formats.
|
||||
@@ -1,4 +1,4 @@
|
||||
ccextractor, 0.78
|
||||
ccextractor, 0.79
|
||||
-----------------
|
||||
Authors: Carlos Fernández (cfsmp3), Volker Quetschke.
|
||||
Maintainer: cfsmp3
|
||||
|
||||
@@ -41,6 +41,10 @@ int main(int argc, char *argv[])
|
||||
usage ();
|
||||
fatal (EXIT_NO_INPUT_FILES, "(This help screen was shown because there were no input files)\n");
|
||||
}
|
||||
else if (ret == EXIT_WITH_HELP)
|
||||
{
|
||||
return EXIT_OK;
|
||||
}
|
||||
else if (ret != EXIT_OK)
|
||||
{
|
||||
exit(ret);
|
||||
@@ -283,9 +287,12 @@ int main(int argc, char *argv[])
|
||||
dbg_print(CCX_DMT_DECODER_608, "Max. FTS: %s (without caption blocks since then)\n",
|
||||
print_mstime(get_fts_max(dec_ctx->timing)));
|
||||
|
||||
mprint ("\nTotal frames time: %s (%u frames at %.2ffps)\n",
|
||||
print_mstime( (LLONG)(total_frames_count*1000/current_fps) ),
|
||||
total_frames_count, current_fps);
|
||||
if (dec_ctx->codec == CCX_CODEC_ATSC_CC)
|
||||
{
|
||||
mprint ("\nTotal frames time: %s (%u frames at %.2ffps)\n",
|
||||
print_mstime( (LLONG)(total_frames_count*1000/current_fps) ),
|
||||
total_frames_count, current_fps);
|
||||
}
|
||||
|
||||
if (ctx->stat_hdtv)
|
||||
{
|
||||
@@ -337,10 +344,7 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
#endif
|
||||
dbg_print(CCX_DMT_708, "[CEA-708] The 708 decoder was reset [%d] times.\n", ctx->freport.data_from_708->reset_count);
|
||||
/*
|
||||
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 (is_decoder_processed_enough(ctx) == CCX_TRUE)
|
||||
{
|
||||
mprint ("\rNote: Processing was cancelled before all data was processed because\n");
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#define EXIT_UNABLE_TO_DETERMINE_FILE_SIZE 6
|
||||
#define EXIT_MALFORMED_PARAMETER 7
|
||||
#define EXIT_READ_ERROR 8
|
||||
#define EXIT_WITH_HELP 9
|
||||
#define EXIT_NOT_CLASSIFIED 300
|
||||
#define EXIT_ERROR_IN_CAPITALIZATION_FILE 501
|
||||
#define EXIT_BUFFER_FULL 502
|
||||
|
||||
@@ -165,6 +165,7 @@ enum ccx_output_format
|
||||
CCX_OF_DVDRAW = 8, // See -d at http://www.geocities.com/mcpoodle43/SCC_TOOLS/DOCS/SCC_TOOLS.HTML#CCExtract
|
||||
CCX_OF_WEBVTT = 9,
|
||||
CCX_OF_SIMPLE_XML = 10,
|
||||
CCX_OF_G608 = 11,
|
||||
};
|
||||
|
||||
enum ccx_output_date_format
|
||||
|
||||
@@ -14,6 +14,8 @@ void init_options (struct ccx_s_options *options)
|
||||
#endif
|
||||
options->nofontcolor=0; // 1 = don't put <font color> tags
|
||||
options->notypesetting=0; // 1 = Don't put <i>, <u>, etc typesetting tags
|
||||
options->no_rollup = 0;
|
||||
options->noscte20 = 0;
|
||||
|
||||
|
||||
options->settings_608.direct_rollup = 0;
|
||||
|
||||
@@ -70,9 +70,11 @@ struct ccx_s_options // Options from user parameters
|
||||
{
|
||||
int extract; // Extract 1st, 2nd or both fields
|
||||
int no_rollup;
|
||||
int noscte20;
|
||||
int cc_channel; // Channel we want to dump in srt mode
|
||||
int buffer_input;
|
||||
int nofontcolor;
|
||||
int nohtmlescape;
|
||||
int notypesetting;
|
||||
struct ccx_boundary_time extraction_start, extraction_end; // Segment we actually process
|
||||
int print_file_reports;
|
||||
|
||||
@@ -240,6 +240,7 @@ struct lib_cc_decode* init_cc_decode (struct ccx_decoders_common_settings_t *set
|
||||
setting->settings_608->no_rollup = setting->no_rollup;
|
||||
setting->settings_dtvcc->no_rollup = setting->no_rollup;
|
||||
ctx->no_rollup = setting->no_rollup;
|
||||
ctx->noscte20 = setting->noscte20;
|
||||
|
||||
ctx->dtvcc = ccx_dtvcc_init(setting->settings_dtvcc);
|
||||
ctx->dtvcc->is_active = setting->settings_dtvcc->enabled;
|
||||
@@ -301,6 +302,7 @@ struct lib_cc_decode* init_cc_decode (struct ccx_decoders_common_settings_t *set
|
||||
setting->output_format==CCX_OF_TRANSCRIPT ||
|
||||
setting->output_format==CCX_OF_SPUPNG ||
|
||||
setting->output_format==CCX_OF_SIMPLE_XML ||
|
||||
setting->output_format==CCX_OF_G608 ||
|
||||
setting->output_format==CCX_OF_NULL)
|
||||
ctx->writedata = process608;
|
||||
else
|
||||
|
||||
@@ -90,6 +90,7 @@ struct ccx_decoders_common_settings_t
|
||||
int extract; // Extract 1st, 2nd or both fields
|
||||
int fullbin; // Disable pruning of padding cc blocks
|
||||
int no_rollup;
|
||||
int noscte20;
|
||||
struct ccx_decoder_608_settings *settings_608; // Contains the settings for the 608 decoder.
|
||||
ccx_decoder_dtvcc_settings *settings_dtvcc; //Same for cea 708 captions decoder (dtvcc)
|
||||
int cc_channel; // Channel we want to dump in srt mode
|
||||
@@ -113,6 +114,7 @@ struct lib_cc_decode
|
||||
void *context_cc608_field_2;
|
||||
|
||||
int no_rollup; // If 1, write one line at a time
|
||||
int noscte20;
|
||||
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
|
||||
|
||||
@@ -99,7 +99,6 @@ int change_utf8_encoding(unsigned char* dest, unsigned char* src, int len, enum
|
||||
{
|
||||
unsigned char *orig = dest; // Keep for calculating length
|
||||
unsigned char *orig_src = src; // Keep for calculating length
|
||||
int bytes = 0;
|
||||
for (int i = 0; src < orig_src + len;)
|
||||
{
|
||||
unsigned char c = src[i];
|
||||
@@ -382,6 +381,7 @@ static int write_subtitle_file_header(struct encoder_ctx *ctx, struct ccx_s_writ
|
||||
switch (ctx->write_format)
|
||||
{
|
||||
case CCX_OF_SRT: // Subrip subtitles have no header
|
||||
case CCX_OF_G608:
|
||||
ret = write_bom(ctx, out);
|
||||
if(ret < 0)
|
||||
return -1;
|
||||
@@ -460,6 +460,7 @@ static int write_subtitle_file_header(struct encoder_ctx *ctx, struct ccx_s_writ
|
||||
ret = write_bom(ctx, out);
|
||||
if(ret < 0)
|
||||
return -1;
|
||||
break;
|
||||
case CCX_OF_SIMPLE_XML: // No header. Fall thru
|
||||
ret = write_bom(ctx, out);
|
||||
if(ret < 0)
|
||||
@@ -472,6 +473,7 @@ static int write_subtitle_file_header(struct encoder_ctx *ctx, struct ccx_s_writ
|
||||
mprint("WARNING: Unable to write complete Buffer \n");
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -495,7 +497,7 @@ int write_cc_subtitle_as_simplexml(struct cc_subtitle *sub, struct encoder_ctx *
|
||||
str = strtok_r(str, "\r\n", &save_str);
|
||||
do
|
||||
{
|
||||
length = get_str_basic(context->subline, str, context->trim_subs, sub->enc_type, context->encoding, strlen(str));
|
||||
length = get_str_basic(context->subline, (unsigned char*)str, context->trim_subs, sub->enc_type, context->encoding, strlen(str));
|
||||
if (length <= 0)
|
||||
{
|
||||
continue;
|
||||
@@ -506,7 +508,7 @@ int write_cc_subtitle_as_simplexml(struct cc_subtitle *sub, struct encoder_ctx *
|
||||
mprint("Warning:Loss of data\n");
|
||||
}
|
||||
|
||||
} while (str = strtok_r(NULL, "\r\n", &save_str) );
|
||||
} while ( (str = strtok_r(NULL, "\r\n", &save_str) ));
|
||||
|
||||
freep(&sub->data);
|
||||
lsub = sub;
|
||||
@@ -519,6 +521,7 @@ int write_cc_subtitle_as_simplexml(struct cc_subtitle *sub, struct encoder_ctx *
|
||||
lsub = sub;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int write_cc_subtitle_as_transcript(struct cc_subtitle *sub, struct encoder_ctx *context)
|
||||
@@ -559,7 +562,7 @@ int write_cc_subtitle_as_transcript(struct cc_subtitle *sub, struct encoder_ctx
|
||||
str = strtok_r(str, "\r\n", &save_str);
|
||||
do
|
||||
{
|
||||
length = get_str_basic(context->subline, str, context->trim_subs, sub->enc_type, context->encoding, strlen(str));
|
||||
length = get_str_basic(context->subline, (unsigned char*)str, context->trim_subs, sub->enc_type, context->encoding, strlen(str));
|
||||
if (length <= 0)
|
||||
{
|
||||
continue;
|
||||
@@ -625,7 +628,7 @@ int write_cc_subtitle_as_transcript(struct cc_subtitle *sub, struct encoder_ctx
|
||||
mprint("Warning:Loss of data\n");
|
||||
}
|
||||
|
||||
} while (str = strtok_r(NULL, "\r\n", &save_str) );
|
||||
} while ( (str = strtok_r(NULL, "\r\n", &save_str)) );
|
||||
|
||||
freep(&sub->data);
|
||||
lsub = sub;
|
||||
@@ -1346,6 +1349,9 @@ int encode_sub(struct encoder_ctx *context, struct cc_subtitle *sub)
|
||||
try_to_add_start_credits(context, data->start_time);
|
||||
wrote_something = write_cc_buffer_as_srt(data, context);
|
||||
break;
|
||||
case CCX_OF_G608:
|
||||
wrote_something = write_cc_buffer_as_g608(data, context);
|
||||
break;
|
||||
case CCX_OF_WEBVTT:
|
||||
if (!context->startcredits_displayed && context->start_credits_text != NULL)
|
||||
try_to_add_start_credits(context, data->start_time);
|
||||
|
||||
@@ -128,6 +128,8 @@ void dinit_encoder(struct encoder_ctx **arg, LLONG current_fts);
|
||||
*/
|
||||
int encode_sub(struct encoder_ctx *ctx,struct cc_subtitle *sub);
|
||||
|
||||
int write_cc_buffer_as_g608(struct eia608_screen *data, struct encoder_ctx *context);
|
||||
|
||||
int write_cc_buffer_as_srt(struct eia608_screen *data, struct encoder_ctx *context);
|
||||
int write_cc_subtitle_as_srt(struct cc_subtitle *sub, struct encoder_ctx *context);
|
||||
int write_stringz_as_srt(char *string, struct encoder_ctx *context, LLONG ms_start, LLONG ms_end);
|
||||
|
||||
109
src/lib_ccx/ccx_encoders_g608.c
Normal file
109
src/lib_ccx/ccx_encoders_g608.c
Normal file
@@ -0,0 +1,109 @@
|
||||
#include "lib_ccx.h"
|
||||
#include "ccx_encoders_common.h"
|
||||
#include "ccx_encoders_helpers.h"
|
||||
|
||||
static unsigned int get_line_encoded(struct encoder_ctx *ctx, unsigned char *buffer, int line_num, struct eia608_screen *data)
|
||||
{
|
||||
unsigned char *orig = buffer; // Keep for debugging
|
||||
unsigned char *line = data->characters[line_num];
|
||||
for (int i = 0; i < 32; i++)
|
||||
{
|
||||
int bytes = 0;
|
||||
switch (ctx->encoding)
|
||||
{
|
||||
case CCX_ENC_UTF_8:
|
||||
bytes = get_char_in_utf_8(buffer, line[i]);
|
||||
break;
|
||||
case CCX_ENC_LATIN_1:
|
||||
get_char_in_latin_1(buffer, line[i]);
|
||||
bytes = 1;
|
||||
break;
|
||||
case CCX_ENC_UNICODE:
|
||||
get_char_in_unicode(buffer, line[i]);
|
||||
bytes = 2;
|
||||
case CCX_ENC_ASCII:
|
||||
*buffer = line[i];
|
||||
bytes = 1;
|
||||
break;
|
||||
}
|
||||
buffer += bytes;
|
||||
}
|
||||
return (unsigned int)(buffer - orig); // Return length
|
||||
}
|
||||
static unsigned int get_color_encoded(struct encoder_ctx *ctx, unsigned char *buffer, int line_num, struct eia608_screen *data)
|
||||
{
|
||||
unsigned char *orig = buffer; // Keep for debugging
|
||||
for (int i = 0; i < 32; i++)
|
||||
{
|
||||
if (data->colors[line_num][i] < 10)
|
||||
*buffer++ = data->colors[line_num][i] + '0';
|
||||
else
|
||||
*buffer++ = 'E';
|
||||
}
|
||||
*buffer = 0;
|
||||
return (unsigned)(buffer - orig); // Return length
|
||||
}
|
||||
static unsigned int get_font_encoded(struct encoder_ctx *ctx, unsigned char *buffer, int line_num, struct eia608_screen *data)
|
||||
{
|
||||
unsigned char *orig = buffer; // Keep for debugging
|
||||
for (int i = 0; i < 32; i++)
|
||||
{
|
||||
if(data->fonts[line_num][i] == FONT_REGULAR)
|
||||
*buffer++ = 'R';
|
||||
else if(data->fonts[line_num][i] == FONT_UNDERLINED_ITALICS)
|
||||
*buffer++ = 'B';
|
||||
else if(data->fonts[line_num][i] == FONT_UNDERLINED)
|
||||
*buffer++ = 'U';
|
||||
else if(data->fonts[line_num][i] == FONT_ITALICS)
|
||||
*buffer++ = 'I';
|
||||
else
|
||||
*buffer++ = 'E';
|
||||
}
|
||||
return (unsigned)(buffer - orig); // Return length
|
||||
}
|
||||
int write_cc_buffer_as_g608(struct eia608_screen *data, struct encoder_ctx *context)
|
||||
{
|
||||
int used;
|
||||
unsigned h1,m1,s1,ms1;
|
||||
unsigned h2,m2,s2,ms2;
|
||||
LLONG ms_start, ms_end;
|
||||
int wrote_something = 0;
|
||||
ms_start = data->start_time;
|
||||
|
||||
ms_start+=context->subs_delay;
|
||||
if (ms_start<0) // Drop screens that because of subs_delay start too early
|
||||
return 0;
|
||||
|
||||
ms_end = data->end_time;
|
||||
|
||||
mstotime (ms_start,&h1,&m1,&s1,&ms1);
|
||||
mstotime (ms_end-1,&h2,&m2,&s2,&ms2); // -1 To prevent overlapping with next line.
|
||||
char timeline[128];
|
||||
context->srt_counter++;
|
||||
sprintf(timeline, "%u%s", context->srt_counter, context->encoded_crlf);
|
||||
used = encode_line(context, context->buffer,(unsigned char *) timeline);
|
||||
write(context->out->fh, context->buffer, used);
|
||||
sprintf (timeline, "%02u:%02u:%02u,%03u --> %02u:%02u:%02u,%03u%s",
|
||||
h1, m1, s1, ms1, h2, m2, s2, ms2, context->encoded_crlf);
|
||||
used = encode_line(context, context->buffer,(unsigned char *) timeline);
|
||||
|
||||
|
||||
write (context->out->fh, context->buffer, used);
|
||||
|
||||
for (int i=0;i<15;i++)
|
||||
{
|
||||
int length = get_line_encoded (context, context->subline, i, data);
|
||||
write(context->out->fh, context->subline, length);
|
||||
|
||||
length = get_color_encoded (context, context->subline, i, data);
|
||||
write(context->out->fh, context->subline, length);
|
||||
|
||||
length = get_font_encoded (context, context->subline, i, data);
|
||||
write(context->out->fh, context->subline, length);
|
||||
write(context->out->fh, context->encoded_crlf, context->encoded_crlf_length);
|
||||
wrote_something=1;
|
||||
}
|
||||
|
||||
write (context->out->fh, context->encoded_crlf, context->encoded_crlf_length);
|
||||
return wrote_something;
|
||||
}
|
||||
@@ -138,7 +138,7 @@ int user_data(struct lib_cc_decode *ctx, struct bitstream *ustream, int udtype,
|
||||
dbg_print(CCX_DMT_VERBOSE, "Read %d/%d DVD CC blocks\n", rcbcount, ecbcount);
|
||||
}
|
||||
// SCTE 20 user data
|
||||
else if (ud_header[0] == 0x03)
|
||||
else if (!ctx->noscte20 && ud_header[0] == 0x03)
|
||||
{
|
||||
if ((ud_header[1]&0x7F) == 0x01)
|
||||
{
|
||||
|
||||
@@ -915,6 +915,7 @@ void rcwt_loop(struct lib_ccx_ctx *ctx)
|
||||
dec_ctx = update_decoder_list(ctx);
|
||||
if (parsebuf[6] == 0 && parsebuf[7] == 2)
|
||||
{
|
||||
dec_ctx->codec = CCX_CODEC_TELETEXT;
|
||||
dec_ctx->private_data = telxcc_init();
|
||||
}
|
||||
dec_sub = &dec_ctx->dec_sub;
|
||||
|
||||
@@ -22,6 +22,7 @@ static struct ccx_decoders_common_settings_t *init_decoder_setting(
|
||||
setting->extract = opt->extract;
|
||||
setting->fullbin = opt->fullbin;
|
||||
setting->no_rollup = opt->no_rollup;
|
||||
setting->noscte20 = opt->noscte20;
|
||||
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;
|
||||
@@ -184,8 +185,8 @@ void dinit_libraries( struct lib_ccx_ctx **ctx)
|
||||
if (dec_ctx->codec == CCX_CODEC_DVB)
|
||||
dvbsub_close_decoder(&dec_ctx->private_data);
|
||||
//Test memory for teletext
|
||||
//else if (dec_ctx->codec == CCX_CODEC_TELETEXT)
|
||||
// telxcc_close(&dec_ctx->private_data, NULL);
|
||||
else if (dec_ctx->codec == CCX_CODEC_TELETEXT)
|
||||
telxcc_close(&dec_ctx->private_data, NULL);
|
||||
else if (dec_ctx->codec == CCX_CODEC_ISDB_CC)
|
||||
delete_isdb_decoder(&dec_ctx->private_data);
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef CCX_CCEXTRACTOR_H
|
||||
#define CCX_CCEXTRACTOR_H
|
||||
|
||||
#define VERSION "0.78"
|
||||
#define VERSION "0.79"
|
||||
|
||||
// Load common includes and constants for library usage
|
||||
#include "ccx_common_platform.h"
|
||||
@@ -57,6 +57,7 @@ struct ccx_s_teletext_config
|
||||
unsigned send_to_srv;
|
||||
enum ccx_encoding_type encoding;
|
||||
int nofontcolor;
|
||||
int nohtmlescape;
|
||||
char millis_separator;
|
||||
};
|
||||
|
||||
@@ -204,7 +205,7 @@ void flushbuffer (struct lib_ccx_ctx *ctx, struct ccx_s_write *wb, int closefile
|
||||
void writercwtdata (struct lib_cc_decode *ctx, const unsigned char *data, struct cc_subtitle *sub);
|
||||
|
||||
// stream_functions.c
|
||||
int isValidMP4Box(unsigned char *buffer, long position, long *nextBoxLocation, int *boxScore);
|
||||
int isValidMP4Box(unsigned char *buffer, size_t position, size_t *nextBoxLocation, int *boxScore);
|
||||
void detect_stream_type (struct ccx_demuxer *ctx);
|
||||
int detect_myth( struct ccx_demuxer *ctx );
|
||||
int read_video_pes_header (struct ccx_demuxer *ctx, struct demuxer_data *data, unsigned char *nextheader, int *headerlength, int sbuflen);
|
||||
|
||||
@@ -214,6 +214,8 @@ void set_output_format (struct ccx_s_options *opt, const char *format)
|
||||
opt->write_format=CCX_OF_SPUPNG;
|
||||
else if (strcmp (format,"simplexml")==0)
|
||||
opt->write_format=CCX_OF_SIMPLE_XML;
|
||||
else if (strcmp (format,"g608")==0)
|
||||
opt->write_format=CCX_OF_G608;
|
||||
else
|
||||
fatal (EXIT_MALFORMED_PARAMETER, "Unknown output file format: %s\n", format);
|
||||
}
|
||||
@@ -273,6 +275,7 @@ void usage (void)
|
||||
mprint (" Syntax:\n");
|
||||
mprint (" ccextractor [options] inputfile1 [inputfile2...] [-o outputfilename]\n");
|
||||
mprint (" [-o1 outputfilename1] [-o2 outputfilename2]\n\n");
|
||||
mprint ("To see This Help Message: -h or --help\n\n");
|
||||
mprint ("File name related options:\n");
|
||||
mprint (" inputfile: file(s) to process\n");
|
||||
mprint (" -o outputfilename: Use -o parameters to define output filename if you don't\n");
|
||||
@@ -372,7 +375,6 @@ void usage (void)
|
||||
mprint (" report -> Prints to stdout information about captions\n");
|
||||
mprint (" in specified input. Don't produce any file\n");
|
||||
mprint (" output\n\n");
|
||||
mprint (" Note: Teletext output can only be srt, webvtt, txt or ttxt for now.\n\n");
|
||||
|
||||
mprint ("Options that affect how input files will be processed.\n");
|
||||
|
||||
@@ -453,6 +455,7 @@ void usage (void)
|
||||
mprint (" reference to the received data. Use this parameter if\n");
|
||||
mprint (" you prefer your own reference. Note: Current this only\n");
|
||||
mprint (" affects Teletext in timed transcript with -datets.\n");
|
||||
mprint (" --noscte20: Ignore SCTE-20 data if present.\n");
|
||||
mprint ("\n");
|
||||
mprint ("Options that affect what kind of output will be produced:\n");
|
||||
mprint(" -bom: Append a BOM (Byte Order Mark) to output files.\n");
|
||||
@@ -467,6 +470,7 @@ void usage (void)
|
||||
mprint (" because UTF-8 is now the default).\n");
|
||||
mprint (" -latin1: Encode subtitles in Latin-1\n");
|
||||
mprint (" -nofc --nofontcolor: For .srt/.sami/.vtt, don't add font color tags.\n");
|
||||
mprint (" --nohtmlescape: For .srt/.sami/.vtt, don't covert html unsafe character\n");
|
||||
mprint ("-nots --notypesetting: For .srt/.sami/.vtt, don't add typesetting tags.\n");
|
||||
mprint (" -trim: Trim lines.\n");
|
||||
mprint (" -dc --defaultcolor: Select a different default color (instead of\n");
|
||||
@@ -829,6 +833,11 @@ int parse_parameters (struct ccx_s_options *opt, int argc, char *argv[])
|
||||
// Parse parameters
|
||||
for (int i=1; i<argc; i++)
|
||||
{
|
||||
if (!strcmp (argv[i],"--help") || !strcmp(argv[i], "-h"))
|
||||
{
|
||||
usage();
|
||||
return EXIT_WITH_HELP;
|
||||
}
|
||||
if (strcmp (argv[i], "-")==0 || strcmp(argv[i], "-stdin") == 0)
|
||||
{
|
||||
|
||||
@@ -885,6 +894,11 @@ int parse_parameters (struct ccx_s_options *opt, int argc, char *argv[])
|
||||
opt->nofontcolor=1;
|
||||
continue;
|
||||
}
|
||||
if (strcmp (argv[i],"--nohtmlescape")==0)
|
||||
{
|
||||
opt->nohtmlescape=1;
|
||||
continue;
|
||||
}
|
||||
if (strcmp(argv[i], "-bom") == 0){
|
||||
opt->enc_cfg.no_bom = 0;
|
||||
continue;
|
||||
@@ -1086,6 +1100,11 @@ int parse_parameters (struct ccx_s_options *opt, int argc, char *argv[])
|
||||
MPEG_CLOCK_FREQ=90090;
|
||||
continue;
|
||||
}
|
||||
if (strcmp (argv[i],"--noscte20")==0)
|
||||
{
|
||||
opt->noscte20 = 1;
|
||||
continue;
|
||||
}
|
||||
if (strcmp (argv[i],"-noru")==0 ||
|
||||
strcmp (argv[i],"--norollup")==0)
|
||||
{
|
||||
@@ -1713,6 +1732,7 @@ int parse_parameters (struct ccx_s_options *opt, int argc, char *argv[])
|
||||
tlt_config.noautotimeref = opt->noautotimeref;
|
||||
tlt_config.send_to_srv = opt->send_to_srv;
|
||||
tlt_config.nofontcolor = opt->nofontcolor;
|
||||
tlt_config.nohtmlescape = opt->nohtmlescape;
|
||||
tlt_config.millis_separator = opt->millis_separator;
|
||||
|
||||
// teletext page number out of range
|
||||
|
||||
@@ -64,11 +64,10 @@ void detect_stream_type (struct ccx_demuxer *ctx)
|
||||
if ((ctx->stream_mode == CCX_SM_ELEMENTARY_OR_NOT_FOUND || ccx_options.print_file_reports)
|
||||
&& ctx->startbytes_avail >= 4) // Still not found
|
||||
{
|
||||
long idx = 0, nextBoxLocation = 0, lastBoxLocation = 0;
|
||||
size_t idx = 0, nextBoxLocation = 0;
|
||||
int boxScore = 0;
|
||||
// Scan the buffer for valid succeeding MP4 boxes.
|
||||
while (idx < ctx->startbytes_avail - 7){
|
||||
lastBoxLocation = idx;
|
||||
while (idx < ctx->startbytes_avail - 8){
|
||||
// Check if we have a valid box
|
||||
if (isValidMP4Box(ctx->startbytes, idx, &nextBoxLocation, &boxScore))
|
||||
{
|
||||
@@ -431,7 +430,7 @@ ccx_stream_mp4_box ccx_stream_mp4_boxes[11] = {
|
||||
*
|
||||
* Returns 1 when a box is found, 0 when none is found.
|
||||
*/
|
||||
int isValidMP4Box(unsigned char *buffer, long position, long *nextBoxLocation, int *boxScore)
|
||||
int isValidMP4Box(unsigned char *buffer, size_t position, size_t *nextBoxLocation, int *boxScore)
|
||||
{
|
||||
for (int idx = 0; idx < 11; idx++)
|
||||
{
|
||||
@@ -439,7 +438,7 @@ int isValidMP4Box(unsigned char *buffer, long position, long *nextBoxLocation, i
|
||||
buffer[position + 6] == ccx_stream_mp4_boxes[idx].boxType[2] && buffer[position + 7] == ccx_stream_mp4_boxes[idx].boxType[3]){
|
||||
mprint("Detected MP4 box with name: %s\n", ccx_stream_mp4_boxes[idx].boxType);
|
||||
// Box name matches. Do crude validation of possible box size, and if valid, add points for "valid" box
|
||||
long boxSize = buffer[position] << 24;
|
||||
size_t boxSize = buffer[position] << 24;
|
||||
boxSize |= buffer[position + 1] << 16;
|
||||
boxSize |= buffer[position + 2] << 8;
|
||||
boxSize |= buffer[position + 3];
|
||||
|
||||
@@ -86,7 +86,6 @@ struct TeletextCtx
|
||||
enum ccx_output_date_format date_format;
|
||||
int noautotimeref; // Do NOT set time automatically?
|
||||
unsigned send_to_srv;
|
||||
int nofontcolor;
|
||||
char millis_separator;
|
||||
uint32_t global_timestamp;
|
||||
|
||||
@@ -756,7 +755,6 @@ void process_page(struct TeletextCtx *ctx, teletext_page_t *page, struct cc_subt
|
||||
{
|
||||
sprintf (c_tempb, "<font color=\"%s\">", TTXT_COLOURS[foreground_color]);
|
||||
page_buffer_add_string (ctx, c_tempb);
|
||||
// if (ctx->wbout1.fh!=-1) fdprintf(ctx->wbout1.fh, "<font color=\"%s\">", TTXT_COLOURS[foreground_color]);
|
||||
font_tag_opened = YES;
|
||||
}
|
||||
}
|
||||
@@ -772,7 +770,6 @@ void process_page(struct TeletextCtx *ctx, teletext_page_t *page, struct cc_subt
|
||||
if (font_tag_opened == YES)
|
||||
{
|
||||
page_buffer_add_string (ctx, "</font>");
|
||||
// if (ctx->wbout1.fh!=-1) fdprintf(ctx->wbout1.fh, "</font> ");
|
||||
font_tag_opened = NO;
|
||||
}
|
||||
|
||||
@@ -782,7 +779,6 @@ void process_page(struct TeletextCtx *ctx, teletext_page_t *page, struct cc_subt
|
||||
{
|
||||
sprintf (c_tempb, "<font color=\"%s\">", TTXT_COLOURS[v]);
|
||||
page_buffer_add_string (ctx, c_tempb);
|
||||
// if (ctx->wbout1.fh!=-1) fdprintf(ctx->wbout1.fh, "<font color=\"%s\">", TTXT_COLOURS[v]);
|
||||
font_tag_opened = YES;
|
||||
}
|
||||
}
|
||||
@@ -795,17 +791,13 @@ void process_page(struct TeletextCtx *ctx, teletext_page_t *page, struct cc_subt
|
||||
ucs2_to_utf8(u, v);
|
||||
uint64_t ucs2_char=(u[0]<<24) | (u[1]<<16) | (u[2]<<8) | u[3];
|
||||
ucs2_buffer_add_char(ctx, ucs2_char);
|
||||
}
|
||||
|
||||
if (v >= 0x20)
|
||||
{
|
||||
// translate some chars into entities, if in colour mode
|
||||
if (!tlt_config.nofontcolor)
|
||||
if (!tlt_config.nofontcolor && !tlt_config.nohtmlescape)
|
||||
{
|
||||
for (uint8_t i = 0; i < array_length(ENTITIES); i++)
|
||||
if (v == ENTITIES[i].character)
|
||||
{
|
||||
//if (ctx->wbout1.fh!=-1) fdprintf(ctx->wbout1.fh, "%s", ENTITIES[i].entity);
|
||||
page_buffer_add_string (ctx, ENTITIES[i].entity);
|
||||
// v < 0x20 won't be printed in next block
|
||||
v = 0;
|
||||
@@ -813,11 +805,8 @@ void process_page(struct TeletextCtx *ctx, teletext_page_t *page, struct cc_subt
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (v >= 0x20)
|
||||
{
|
||||
//if (ctx->wbout1.fh!=-1) fdprintf(ctx->wbout1.fh, "%s", u);
|
||||
page_buffer_add_string (ctx, u);
|
||||
if (tlt_config.gui_mode_reports) // For now we just handle the easy stuff
|
||||
fprintf (stderr,"%s",u);
|
||||
@@ -828,7 +817,6 @@ void process_page(struct TeletextCtx *ctx, teletext_page_t *page, struct cc_subt
|
||||
// no tag will left opened!
|
||||
if ((!tlt_config.nofontcolor) && (font_tag_opened == YES))
|
||||
{
|
||||
//if (ctx->wbout1.fh!=-1) fdprintf(ctx->wbout1.fh, "</font>");
|
||||
page_buffer_add_string (ctx, "</font>");
|
||||
font_tag_opened = NO;
|
||||
}
|
||||
@@ -882,17 +870,7 @@ void process_page(struct TeletextCtx *ctx, teletext_page_t *page, struct cc_subt
|
||||
ctx->prev_show_timestamp = page->show_timestamp;
|
||||
}
|
||||
break;
|
||||
case CCX_OF_SMPTETT:
|
||||
#if 0
|
||||
if (ctx->wbout1.fh!=-1)
|
||||
{
|
||||
timestamp_to_smptetttime(page->show_timestamp, timecode_show);
|
||||
timestamp_to_smptetttime(page->hide_timestamp, timecode_hide);
|
||||
fdprintf(ctx->wbout1.fh," <p region=\"speaker\" begin=\"%s\" end=\"%s\">%s</p>\n", timecode_show, timecode_hide, ctx->page_buffer_cur);
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
default: // Yes, this means everything else is .srt for now
|
||||
default:
|
||||
add_cc_sub_text(sub, ctx->page_buffer_cur, page->show_timestamp,
|
||||
page->hide_timestamp + 1, NULL, "TLT", CCX_ENC_UTF_8);
|
||||
}
|
||||
@@ -1220,6 +1198,7 @@ void tlt_read_rcwt(void *codec, unsigned char *buf, struct cc_subtitle *sub)
|
||||
|
||||
ctx->last_timestamp = t;
|
||||
|
||||
ctx->tlt_packet_counter++;
|
||||
process_telx_packet(ctx, id, pl, t, sub);
|
||||
}
|
||||
|
||||
@@ -1430,30 +1409,6 @@ void* telxcc_init(void)
|
||||
return ctx;
|
||||
}
|
||||
|
||||
void telxcc_configure (void *codec, struct ccx_s_teletext_config *cfg)
|
||||
{
|
||||
struct TeletextCtx *ctx = codec;
|
||||
ctx->verbose = cfg->verbose;
|
||||
ctx->page = cfg->page;
|
||||
ctx->tid = cfg->tid;
|
||||
ctx->offset = cfg->offset;
|
||||
ctx->bom = cfg->bom;
|
||||
ctx->nonempty = cfg->nonempty;
|
||||
ctx->user_page = cfg->user_page;
|
||||
ctx->levdistmincnt = cfg->levdistmincnt;
|
||||
ctx->levdistmaxpct = cfg->levdistmaxpct;
|
||||
ctx->extraction_start = cfg->extraction_start;
|
||||
ctx->extraction_end = cfg->extraction_end;
|
||||
ctx->write_format = cfg->write_format;
|
||||
ctx->gui_mode_reports = cfg->gui_mode_reports;
|
||||
ctx->date_format = cfg->date_format;
|
||||
ctx->noautotimeref = cfg->noautotimeref;
|
||||
ctx->send_to_srv = cfg->send_to_srv;
|
||||
ctx->nofontcolor = cfg->nofontcolor;
|
||||
ctx->millis_separator = cfg->millis_separator;
|
||||
|
||||
}
|
||||
|
||||
void telxcc_update_gt(void *codec, uint32_t global_timestamp)
|
||||
{
|
||||
struct TeletextCtx *ctx = codec;
|
||||
@@ -1468,6 +1423,7 @@ void telxcc_close(void **ctx, struct cc_subtitle *sub)
|
||||
if(!ttext)
|
||||
return;
|
||||
|
||||
mprint ( "\nTeletext decoder: %"PRIu32" packets processed \n", ttext->tlt_packet_counter);
|
||||
if (tlt_config.write_format != CCX_OF_RCWT && sub)
|
||||
{
|
||||
// output any pending close caption
|
||||
|
||||
@@ -422,6 +422,8 @@ char *get_file_extension(enum ccx_output_format write_format)
|
||||
return strdup(".dvdraw");
|
||||
case CCX_OF_SIMPLE_XML:
|
||||
return strdup(".xml");
|
||||
case CCX_OF_G608:
|
||||
return strdup(".g608");
|
||||
case CCX_OF_NULL:
|
||||
return NULL;
|
||||
default:
|
||||
|
||||
Reference in New Issue
Block a user