Compare commits

...

78 Commits
v0.71 ... v0.74

Author SHA1 Message Date
cfsmp3
18f781d099 0.74 2014-09-24 13:04:26 +02:00
Ruslan Kuchumov
84db812769 windows support 2014-09-08 18:49:37 +00:00
Ruslan Kuchumov
7763f8aeab pointer bugfix 2014-09-08 18:02:49 +00:00
Ruslan Kuchumov
faa879801e printing output on SIGINT 2014-09-08 09:02:10 +00:00
wforums
4635329a5b Changes.txt updated
-
2014-09-06 13:17:04 +02:00
wforums
b89cc3b6df UCLA TT format change
Switched around TEL & TT page number in ttxt format.
2014-09-06 13:16:51 +02:00
wforums
e9f8313f7c BOM parameter
BOM can be not written now if -nobom is passed as parameter.
2014-09-06 13:16:25 +02:00
wforums
324cd84ffe UCLA parameter fix
Added a new option to ensure that UCLA parameter doesn't get overriden
anymore.
2014-09-06 12:13:50 +02:00
wforums
9d7518c9ec -o1 -o2 -12 fix
Fixes the issue where when using multiple output files, everyting is
written to the -o2 output file.
2014-09-06 00:07:28 +02:00
Ruslan Kuchumov
32e0d6023d sending teletext to the server 2014-09-04 16:07:06 +00:00
Ruslan Kuchumov
c9465e476b segfault when no input files bugfix 2014-09-04 16:02:51 +00:00
Ruslan Kuchumov
45d237da40 removed bin output when sending to server 2014-09-04 15:33:02 +00:00
cfsmp3
631ae2e02f Version bump (0.72 to 0.73) 2014-08-19 07:45:00 +02:00
Anshul Maheshwari
695aa14cd7 Merge remote-tracking branch 'carlos/master' 2014-08-18 23:47:03 +05:30
Anshul Maheshwari
b638bb1d3a updated some grammer in Readme.md 2014-08-18 23:37:03 +05:30
Anshul Maheshwari
28950bf90e changes should not be in Readme.md 2014-08-18 23:22:43 +05:30
wforums
77f8289ca6 Version change
- Added description
2014-08-18 14:26:52 +02:00
wforums
cece92a828 Merge conflict resolve
Fixed merge conflicts
2014-08-18 13:50:30 +02:00
wforums
bd08454d66 Merge from upstream 2014-08-18 13:45:44 +02:00
wforums
c6e5dd5cf7 GPACMP4 filter
moved 2 files to filter
2014-08-18 13:43:12 +02:00
cfsmp3
bd8e3ad137 Merge branch 'pr/n98_rkuchumov' 2014-08-18 13:34:31 +02:00
cfsmp3
8a2e71fcfb Merge branch 'pr/n99_rkuchumov' 2014-08-18 13:33:06 +02:00
wforums
301c2a7138 Library - step one and half
- moved around some functions
- 608_helpers is gone now (moved last function)
2014-08-18 10:35:43 +02:00
Anshul Maheshwari
5368d7292f update version 2014-08-18 13:13:54 +05:30
Anshul Maheshwari
29689b10aa Merge branch 'master' of https://github.com/anshul1912/ccextractor 2014-08-18 13:11:03 +05:30
Anshul Maheshwari
4d8883d0f1 Documented FFmpeg Intigration 2014-08-18 13:10:06 +05:30
Anshul Maheshwari
efe6fceb3a add cflags for gpacmp4 on linux 2014-08-17 10:19:54 +02:00
Ruslan Kuchumov
d9a998b95f memory leak 2014-08-16 23:53:34 +00:00
Ruslan Kuchumov
bf94c2997d unusable variable 2014-08-16 23:41:14 +00:00
Ruslan Kuchumov
6405a3973d tlt support 2014-08-16 21:53:00 +00:00
Anshul Maheshwari
9270e22a65 Merge branch 'master' of https://github.com/anshul1912/ccextractor 2014-08-16 09:49:32 +02:00
Anshul Maheshwari
02e19cf617 corrected CFLAGS to be include in ffmpeg enable 2014-08-16 09:48:29 +02:00
Ruslan Kuchumov
1493b6c4f5 renaming 2014-08-15 21:29:28 +00:00
wforums
74ab732999 Library - fixes
-
2014-08-15 18:37:15 +02:00
wforums
5961d1b56e Library - fixes
-
2014-08-15 18:24:17 +02:00
wforums
87d6a6bf91 Library - fixes
Include fixes
2014-08-15 18:19:48 +02:00
wforums
456d23f547 Library - step one and half
- Cleaned out header files + adjusted accordingly
- Decoupled spupng_encoder from ccextractor.h
- Decoupled ccx_encoders_common from ccextractor.h
2014-08-15 17:47:58 +02:00
wforums
02da93d0e4 Merge conflict fix
-
2014-08-15 14:09:33 +02:00
wforums
597304e932 Merge from upstream
-
2014-08-15 12:34:18 +02:00
Anshul Maheshwari
918889c890 corrected timing in spupng xml file 2014-08-15 12:28:30 +02:00
Anshul Maheshwari
47bfe6bffc corrected timing for tudor using ffmpeg 2014-08-15 12:28:29 +02:00
cfsmp3
5789a0a224 Updated MD 2014-08-15 12:28:29 +02:00
Anshul Maheshwari
b15f54c7f9 Intigration of ffmpeg in ccextractor 2014-08-15 12:28:28 +02:00
wforums
bc3794eb14 Library - step one and hafl
-
2014-08-15 11:59:53 +02:00
wforums
4e66d290a6 Library - step one and half
Moved most of 608_helper functions to ccx_encoders_helpers, as they seem
more logical. No idea yet where the last one has to go (used in both
encoder/decoder 608 right now)
2014-08-15 11:44:14 +02:00
wforums
7b48b01fd1 Library - intermediate
This one has errors!
2014-08-15 09:00:16 +02:00
Anshul Maheshwari
883dfaae4a corrected timing in spupng xml file 2014-08-14 20:45:38 +05:30
wforums
884a25a7cd Commented unused vars
Added a ; too much.
2014-08-13 15:54:27 +02:00
wforums
8cc8767634 Commented unused variables
-
2014-08-13 15:48:08 +02:00
wforums
90a6902ad4 Library - step one and half
More removal of links.
2014-08-13 15:47:53 +02:00
wforums
b334acb426 Library - step one and half
Decoupled 708 from ccextractor.h (finally), reworked some things as
well.
2014-08-13 15:33:51 +02:00
Anshul Maheshwari
9c847aa4f1 Merge remote-tracking branch 'carlos/master' 2014-08-13 17:48:50 +05:30
Anshul Maheshwari
c3397d1949 corrected timing for tudor using ffmpeg 2014-08-13 17:48:00 +05:30
Ruslan Kuchumov
41ad0b4006 cc_name 2014-08-12 22:32:11 +00:00
cfsmp3
7fa59a14f7 Updated MD 2014-08-12 17:15:39 +02:00
wforums
170a57b9c6 Library - fix
-
2014-08-12 14:34:34 +02:00
wforums
0a15c2d16e Library - fix
Fix of includes
2014-08-12 14:32:28 +02:00
wforums
c52283676a Library - step one and half
- Moved enum & struct to more appropriate place (also fixes error with
compiling under linux)
2014-08-12 14:26:48 +02:00
wforums
ce3c2b5ae2 Merge fix 2
-
2014-08-12 12:25:35 +02:00
wforums
48e030d94c Merge fix
Fixing errors that popped up after trying to merge.
2014-08-12 12:14:36 +02:00
wforums
afaa7c8b76 Merge try
Trying to merge
2014-08-12 11:41:22 +02:00
wforums
4e6c0352b0 XDS segfault fix
Fixes segfault on using TTXT + XDS
2014-08-12 10:39:01 +02:00
Anshul Maheshwari
f84b69aca7 Intigration of ffmpeg in ccextractor 2014-08-12 10:43:07 +05:30
cfsmp3
cc7ebbc4d7 Replace g++ with gcc in OSX 2014-08-11 14:33:52 +02:00
Ruslan Kuchumov
7a74b815fa segfault on error fix 2014-08-09 21:23:27 +00:00
Ruslan Kuchumov
331038634d password bug fix 2014-08-09 21:17:41 +00:00
Ruslan Kuchumov
aa2c316093 Chris's patch 2014-08-09 20:52:15 +00:00
cfsmp3
3347f5d345 Version bump 2014-08-09 13:18:56 +02:00
cfsmp3
141792a299 Delete upgradelog. 2014-08-09 13:18:14 +02:00
cfsmp3
183e613981 Merge branch 'pr/n93_wforums' 2014-08-08 16:39:02 +02:00
wforums
19e2912a71 AVC fps fix
- Will now change current_fps based on AVC data (if present). Should fix
an issue with low fps video that was submitted.
2014-08-07 21:09:45 +02:00
wforums
dc82154a03 AVC fps fix
Changes.txt updated.
2014-08-07 21:09:31 +02:00
cfsmp3
2029dab3bf Merge branch 'pr/n92_anshul1912' 2014-08-05 21:24:08 +02:00
wforums
405d808d0b WTV fix
Fixed WTV
2014-08-04 21:10:17 +02:00
cfsmp3
ecc0714f48 Correction to text files 2014-07-29 10:12:22 +02:00
cfsmp3
26410b991d Version pump 2014-07-29 10:06:45 +02:00
cfsmp3
19b1bff7f4 Merge branch 'pr/n91_anshul1912'
Conflicts:
	docs/CHANGES.TXT
2014-07-29 09:28:28 +02:00
wforums
b765198d53 Updated for 0.71
-
2014-07-28 22:22:47 +02:00
76 changed files with 3037 additions and 2102 deletions

View File

@@ -4,7 +4,7 @@ MAINTAINER = Marc Espie <espie@openbsd.org>
CATEGORIES = multimedia
COMMENT = closed caption subtitles extractor
HOMEPAGE = http://ccextractor.sourceforge.net/
V = 0.70
V = 0.71
DISTFILES = ccextractor.${V:S/.//}-src.zip
MASTER_SITES = ${MASTER_SITE_SOURCEFORGE:=ccextractor/}
DISTNAME = ccextractor-$V

View File

@@ -1,15 +1,12 @@
ccextractor
===========
CCExtractor - Carlos' version (mainstream).
Carlos' version (mainstream) is most stable branch.
0.71
-----------
- Added feature to receive captions in BIN format according to CCExtractor's own
protocol over TCP (-tcp port [-tcppassword password])
- Added ability to send captions to the server described above or to the
online repository (-sendto host[:port])
- Added -stdin parameter for reading input stream from standard input
- Compilation in Cygwin using linux/Makefile
- Code tested with coverity for defect density 0.42
- Correction of mp4 timing, when one timestamp points timing of two atom
Extracting subtitles were never so easy then following command:
ccextrator "name of input"
Gui lovers please download Sorceforge version of CCExtractor, Git Version is not your cup of tea.
http://ccextractor.sourceforge.net/download-ccextractor.html
For News about release, please find CHANGES.TXT

View File

@@ -1,4 +1,25 @@
0.71
0.74
-----------
- Fixed issue with -o1 -o2 and -12 parameters (where it would write output only in the o2 file)
- Fixed UCLA parameter issue. Now the UCLA parameter settings can't be overwritten anymore by later parameters that affect the custom transcript
- Switched order around for TLT and TT page number in custom transcript to match UCLA settings
- Added nobom parameter, for when files are processed by tools that can't handle the BOM. If using this, files might be not readable under windows.
- Segfault fix when no input files were given
- No more bin output when sending to server + possibility to send TT to server for processing
- Windows: Added the Microsoft redistributable MSVCR120.DLL to both the installation package and the application zip.
0.73 - GSOC
-----------
- Added support of BIN format for Teletext
- Added start of librarisation. This will allow in the future for other programs to use encoder/decoder functions and more.
0.72 - GSOC
-----------
- Fix for WTV files with incorrect timing
- Added support for fps change using data from AVC video track in a H264 TS file.
- Added FFMpeg Support to enable all encapsulator and decoder provided by ffmpeg
0.71 - GSOC
-----------
- Added feature to receive captions in BIN format according to CCExtractor's own
protocol over TCP (-tcp port [-tcppassword password])
@@ -6,7 +27,7 @@
online repository (-sendto host[:port])
- Added -stdin parameter for reading input stream from standard input
- Compilation in Cygwin using linux/Makefile
- Code tested with coverity for defect density 0.42
- Fix for .bin files when not using latin1 charset
- Correction of mp4 timing, when one timestamp points timing of two atom
0.70 - GSOC

58
docs/FFMPEG.TXT Normal file
View File

@@ -0,0 +1,58 @@
Overview
========
FFmpeg Intigration was done to support multiple encapsulator.
Dependecy
=========
FFmpeg library's
Download and Install FFmpeg on your linux pc.
---------------------------------------------
Download latest source code from following link
https://ffmpeg.org/download.html
then following command to install ffmpeg
./configure && make && make install
Note:If you installed ffmpeg on non standurd location, please change/update your
enviorment variable $PATH and $LD_LIBRARY_PATH
Download and Install FFmpeg on your Windows pc.
----------------------------------------------
Download prebuild library from following link
http://ffmpeg.zeranoe.com/builds/
You need to download Shared Versions to run the program and Dev Versions to compile.
How to compile ccextractor
==========================
In Linux
--------
make ENABLE_FFMPEG=yes
On Windows
----------
put the path of libs/include of ffmpeg library in library paths.
step 1) In visual studio 2013 right click <Project> and select property.
step 2) Select Configuration properties in left panel(column) of property.
step 3) Select VC++ Directory.
step 4) In the right pane, in the right-hand column of the VC++ Directory property,
open the drop-down menu and choose Edit.
Step 5) Add path of Directory where you have kept uncompressed library of FFmpeg.
Set preprocessor flag ENABLE_FFMPEG=1
Step 1)In visual studio 2013 right click <Project> and select property.
Step 2)In the left panel, select Configuration Properties, C/C++, Preprocessor.
Step 3)In the right panel, in the right-hand column of the Preprocessor Definitions property, open the drop-down menu and choose Edit.
Step 4)In the Preprocessor Definitions dialog box, add ENABLE_FFMPEG=1. Choose OK to save your changes.
Add library in linker
step 1)Open property of project
Step 2)Select Configuration properties
Step 3)Select Linker in left panel(column)
Step 4)Select Input
Step 5)Select Additional dependencies in right panel
Step 6)Add all FFmpeg's lib in new line

View File

@@ -1,4 +1,4 @@
ccextractor, 0.63
ccextractor, 0.73
-----------------
Authors: Carlos Fernández (cfsmp3), Volker Quetschke.
Maintainer: cfsmp3
@@ -7,12 +7,17 @@ Lots of credit goes to other people, though:
McPoodle (author of the original SCC_RIP), Neuron2, and others (see source
code).
Home: http://ccextractor.sourceforge.net
Home: http://www.ccextractor.org
You can subscribe to new releases notifications at freshmeat:
http://freshmeat.net/projects/ccextractor
Google Summer of Code 2014 students
- Willem van iseghem
- Ruslan KuchumoV
- Anshul Maheshwari
License
-------
GPL 2.0.
@@ -67,21 +72,18 @@ If there are Spanish subtitles, one of them should work.
McPoodle's page
---------------
http://www.geocities.com/mcpoodle43/SCC_TOOLS/DOCS/SCC_TOOLS.HTML
http://www.theneitherworld.com/mcpoodle/SCC_TOOLS/DOCS/SCC_TOOLS.HTML
Essential CC related information and free (with source) tools.
Encoding
--------
This version, in both its Linux and Windows builds generates by
default Latin-1 encoded files. You can use -unicode and -utf8
if you prefer these encodings (usually it just depends on what
your specific player likes).
This has changed from the previous UTF-8 default which vobsub
can't handle.
default Unicode files. You can use -latin1 and -utf8 if you prefer
these encodings (usually it just depends on what your specific
player likes).
Future work
-----------
- Finish EIA-708 decoder
- Network support
- Please check www.ccextractor.org for news and future work.

View File

@@ -1,12 +1,15 @@
SHELL = /bin/sh
CC = gcc
SYS := $(shell gcc -dumpmachine)
CFLAGS = -O3 -std=gnu99
INCLUDE = -I../src/gpacmp4/ -I../src/libpng -I../src/zlib
ALL_FLAGS = -Wno-write-strings -D_FILE_OFFSET_BITS=64
LDFLAGS = -lm
ifneq (, $(findstring linux, $(SYS)))
CFLAGS +=-DGPAC_CONFIG_LINUX
endif
TARGET = ccextractor
OBJS_DIR = objs
@@ -39,6 +42,15 @@ CFLAGS+=-I/usr/local/include/tesseract -I/usr/local/include/leptonica
CFLAGS+=-DENABLE_OCR
LDFLAGS+= $(shell pkg-config --libs tesseract)
endif
ifeq ($(ENABLE_FFMPEG),yes)
CFLAGS+=-DENABLE_FFMPEG
CFLAGS+= $(shell pkg-config --cflags libavcodec)
CFLAGS+= $(shell pkg-config --cflags libavformat)
CFLAGS+= $(shell pkg-config --cflags libavutil)
LDFLAGS+= $(shell pkg-config --libs libavcodec )
LDFLAGS+= $(shell pkg-config --libs libavformat )
LDFLAGS+= $(shell pkg-config --libs libavutil )
endif
.PHONY: all
all: objs_dir $(TARGET)

View File

@@ -1 +1 @@
g++ -Dfopen64=fopen -Dopen64=open -Dlseek64=lseek -I../src/gpacmp4 -I ../src/libpng -I ../src/zlib -o ccextractor $(find ../src/ -name '*.cpp') $(find ../src/ -name '*.c')
gcc -std=gnu99 -Wno-write-strings -Dfopen64=fopen -Dopen64=open -Dlseek64=lseek -I../src/gpacmp4 -I ../src/libpng -I ../src/zlib -o ccextractor $(find ../src/ -name '*.cpp') $(find ../src/ -name '*.c')

166
src/608.h
View File

@@ -1,166 +0,0 @@
#ifndef __608_H__
enum cc_modes
{
MODE_POPON = 0,
MODE_ROLLUP_2 = 1,
MODE_ROLLUP_3 = 2,
MODE_ROLLUP_4 = 3,
MODE_TEXT = 4,
MODE_PAINTON = 5,
// Fake modes to emulate stuff
MODE_FAKE_ROLLUP_1 = 100
};
enum ccx_eia608_format
{
SFORMAT_CC_SCREEN,
SFORMAT_CC_LINE,
SFORMAT_XDS
};
/**
* This structure have fields which need to be ignored according to format,
* for example if format is SFORMAT_XDS then all fields other then
* xds related (xds_str, xds_len and cur_xds_packet_class) should be
* ignored and not to be derefrenced.
*
* TODO use union inside struct for each kind of fields
*/
struct eia608_screen // A CC buffer
{
/** format of data inside this structure */
enum ccx_eia608_format format;
unsigned char characters[15][33];
unsigned char colors[15][33];
unsigned char fonts[15][33]; // Extra char at the end for a 0
int row_used[15]; // Any data in row?
int empty; // Buffer completely empty?
/** start time of this CC buffer */
LLONG start_time;
/** end time of this CC buffer */
LLONG end_time;
enum cc_modes mode;
int channel; // Currently selected channel
int my_field; // Used for sanity checks
/** XDS string */
char *xds_str;
/** length of XDS string */
size_t xds_len;
/** Class of XDS string */
int cur_xds_packet_class;
};
struct s_context_cc608
{
struct eia608_screen buffer1;
struct eia608_screen buffer2;
int cursor_row, cursor_column;
int visible_buffer;
int screenfuls_counter; // Number of meaningful screenfuls written
LLONG current_visible_start_ms; // At what time did the current visible buffer became so?
enum cc_modes mode;
unsigned char last_c1, last_c2;
int channel; // Currently selected channel
unsigned char color; // Color we are currently using to write
unsigned char font; // Font we are currently using to write
int rollup_base_row;
LLONG ts_start_of_current_line; /* Time at which the first character for current line was received, =-1 no character received yet */
LLONG ts_last_char_received; /* Time at which the last written character was received, =-1 no character received yet */
int new_channel; // The new channel after a channel change
int my_field; // Used for sanity checks
long bytes_processed_608; // To be written ONLY by process_608
struct ccx_s_write *out;
int have_cursor_position;
};
extern unsigned char *enc_buffer;
extern unsigned char str[2048];
extern unsigned enc_buffer_used;
extern unsigned enc_buffer_capacity;
extern int new_sentence;
extern const char *color_text[][2];
unsigned get_decoder_line_encoded (unsigned char *buffer, int line_num, struct eia608_screen *data);
void capitalize (int line_num, struct eia608_screen *data);
void correct_case (int line_num, struct eia608_screen *data);
void correct_case (int line_num, struct eia608_screen *data);
void capitalize (int line_num, struct eia608_screen *data);
void find_limit_characters (unsigned char *line, int *first_non_blank, int *last_non_blank);
unsigned get_decoder_line_basic (unsigned char *buffer, int line_num, struct eia608_screen *data);
unsigned get_decoder_line_encoded_for_gui (unsigned char *buffer, int line_num, struct eia608_screen *data);
unsigned get_decoder_line_encoded (unsigned char *buffer, int line_num, struct eia608_screen *data);
void delete_all_lines_but_current (struct eia608_screen *data, int row);
void get_char_in_latin_1 (unsigned char *buffer, unsigned char c);
void get_char_in_unicode (unsigned char *buffer, unsigned char c);
int get_char_in_utf_8 (unsigned char *buffer, unsigned char c);
unsigned char cctolower (unsigned char c);
unsigned char cctoupper (unsigned char c);
int general_608_init (void);
LLONG get_visible_end (void);
#define CC608_SCREEN_WIDTH 32
#define REQUEST_BUFFER_CAPACITY(ctx,length) if (length>ctx->capacity) \
{ctx->capacity=length*2; ctx->buffer=(unsigned char*) realloc (ctx->buffer, ctx->capacity); \
if (ctx->buffer==NULL) { fatal (EXIT_NOT_ENOUGH_MEMORY, "Not enough memory, bailing out\n"); } \
}
enum color_code
{
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
};
enum font_bits
{
FONT_REGULAR = 0,
FONT_ITALICS = 1,
FONT_UNDERLINED = 2,
FONT_UNDERLINED_ITALICS = 3
};
enum command_code
{
COM_UNKNOWN = 0,
COM_ERASEDISPLAYEDMEMORY = 1,
COM_RESUMECAPTIONLOADING = 2,
COM_ENDOFCAPTION = 3,
COM_TABOFFSET1 = 4,
COM_TABOFFSET2 = 5,
COM_TABOFFSET3 = 6,
COM_ROLLUP2 = 7,
COM_ROLLUP3 = 8,
COM_ROLLUP4 = 9,
COM_CARRIAGERETURN = 10,
COM_ERASENONDISPLAYEDMEMORY = 11,
COM_BACKSPACE = 12,
COM_RESUMETEXTDISPLAY = 13,
COM_ALARMOFF =14,
COM_ALARMON = 15,
COM_DELETETOENDOFROW = 16,
COM_RESUMEDIRECTCAPTIONING = 17,
// Non existing commands we insert to have the decoder
// special stuff for us.
COM_FAKE_RULLUP1 = 18
};
#define __608_H__
#endif

View File

@@ -1,347 +0,0 @@
#include "ccextractor.h"
#include "utility.h"
#include "cc_encoders_common.h"
//extern unsigned char encoded_crlf[16];
// Encodes a generic string. Note that since we use the encoders for closed caption
// data, text would have to be encoded as CCs... so using special characters here
// it's a bad idea.
unsigned encode_line (unsigned char *buffer, unsigned char *text)
{
unsigned bytes=0;
while (*text)
{
switch (ccx_options.encoding)
{
case CCX_ENC_UTF_8:
case CCX_ENC_LATIN_1:
*buffer=*text;
bytes++;
buffer++;
break;
case CCX_ENC_UNICODE:
*buffer=*text;
*(buffer+1)=0;
bytes+=2;
buffer+=2;
break;
}
text++;
}
return bytes;
}
void correct_case(int line_num,struct eia608_screen *data)
{
char delim[64] = {
' ' ,'\n','\r', 0x89,0x99,
'!' , '"', '#', '%' , '&',
'\'', '(', ')', ';' , '<',
'=' , '>', '?', '[' ,'\\',
']' , '*', '+', ',' , '-',
'.' , '/', ':', '^' , '_',
'{' , '|', '}', '~' ,'\0' };
char *line = strdup(((char*)data->characters[line_num]));
char *oline = (char*)data->characters[line_num];
char *c = strtok(line,delim);
do
{
char **index = bsearch(&c,spell_lower,spell_words,sizeof(*spell_lower),string_cmp);
if(index)
{
char *correct_c = *(spell_correct + (index - spell_lower));
size_t len=strlen (correct_c);
memcpy(oline + (c - line),correct_c,len);
}
} while ( ( c = strtok(NULL,delim) ) != NULL );
free(line);
}
void capitalize (int line_num, struct eia608_screen *data)
{
for (int i=0;i<CC608_SCREEN_WIDTH;i++)
{
switch (data->characters[line_num][i])
{
case ' ':
case 0x89: // This is a transparent space
case '-':
break;
case '.': // Fallthrough
case '?': // Fallthrough
case '!':
case ':':
new_sentence=1;
break;
default:
if (new_sentence)
data->characters[line_num][i]=cctoupper (data->characters[line_num][i]);
else
data->characters[line_num][i]=cctolower (data->characters[line_num][i]);
new_sentence=0;
break;
}
}
}
void find_limit_characters (unsigned char *line, int *first_non_blank, int *last_non_blank)
{
*last_non_blank=-1;
*first_non_blank=-1;
for (int i=0;i<CC608_SCREEN_WIDTH;i++)
{
unsigned char c=line[i];
if (c!=' ' && c!=0x89)
{
if (*first_non_blank==-1)
*first_non_blank=i;
*last_non_blank=i;
}
}
}
unsigned get_decoder_line_basic (unsigned char *buffer, int line_num, struct eia608_screen *data)
{
unsigned char *line = data->characters[line_num];
int last_non_blank=-1;
int first_non_blank=-1;
unsigned char *orig=buffer; // Keep for debugging
find_limit_characters (line, &first_non_blank, &last_non_blank);
if (!ccx_options.trim_subs)
first_non_blank=0;
if (first_non_blank==-1)
{
*buffer=0;
return 0;
}
int bytes=0;
for (int i=first_non_blank;i<=last_non_blank;i++)
{
char c=line[i];
switch (ccx_options.encoding)
{
case CCX_ENC_UTF_8:
bytes=get_char_in_utf_8 (buffer,c);
break;
case CCX_ENC_LATIN_1:
get_char_in_latin_1 (buffer,c);
bytes=1;
break;
case CCX_ENC_UNICODE:
get_char_in_unicode (buffer,c);
bytes=2;
break;
}
buffer+=bytes;
}
*buffer=0;
return (unsigned) (buffer-orig); // Return length
}
unsigned get_decoder_line_encoded_for_gui (unsigned char *buffer, int line_num, struct eia608_screen *data)
{
unsigned char *line = data->characters[line_num];
unsigned char *orig=buffer; // Keep for debugging
int first=0, last=31;
find_limit_characters(line,&first,&last);
for (int i=first;i<=last;i++)
{
get_char_in_latin_1 (buffer,line[i]);
buffer++;
}
*buffer=0;
return (unsigned) (buffer-orig); // Return length
}
unsigned char *close_tag (unsigned char *buffer, char *tagstack, char tagtype, int *punderlined, int *pitalics, int *pchanged_font)
{
for (int l=strlen (tagstack)-1; l>=0;l--)
{
char cur=tagstack[l];
switch (cur)
{
case 'F':
buffer+= encode_line (buffer,(unsigned char *) "</font>");
(*pchanged_font)--;
break;
case 'U':
buffer+=encode_line (buffer, (unsigned char *) "</u>");
(*punderlined)--;
break;
case 'I':
buffer+=encode_line (buffer, (unsigned char *) "</i>");
(*pitalics)--;
break;
}
tagstack[l]=0; // Remove from stack
if (cur==tagtype) // We closed up to the required tag, done
return buffer;
}
if (tagtype!='A') // All
fatal (EXIT_BUG_BUG, "Mismatched tags in encoding, this is a bug, please report");
return buffer;
}
unsigned get_decoder_line_encoded (unsigned char *buffer, int line_num, struct eia608_screen *data)
{
int col = COL_WHITE;
int underlined = 0;
int italics = 0;
int changed_font=0;
char tagstack[128]=""; // Keep track of opening/closing tags
unsigned char *line = data->characters[line_num];
unsigned char *orig=buffer; // Keep for debugging
int first=0, last=31;
if (ccx_options.trim_subs)
find_limit_characters(line,&first,&last);
for (int i=first;i<=last;i++)
{
// Handle color
int its_col = data->colors[line_num][i];
if (its_col != col && !ccx_options.nofontcolor &&
!(col==COL_USERDEFINED && its_col==COL_WHITE)) // Don't replace user defined with white
{
if (changed_font)
buffer = close_tag(buffer,tagstack,'F',&underlined,&italics,&changed_font);
// Add new font tag
buffer+=encode_line (buffer, (unsigned char*) color_text[its_col][1]);
if (its_col==COL_USERDEFINED)
{
// The previous sentence doesn't copy the whole
// <font> tag, just up to the quote before the color
buffer+=encode_line (buffer, (unsigned char*) usercolor_rgb);
buffer+=encode_line (buffer, (unsigned char*) "\">");
}
if (color_text[its_col][1][0]) // That means a <font> was added to the buffer
{
strcat (tagstack,"F");
changed_font++;
}
col = its_col;
}
// Handle underlined
int is_underlined = data->fonts[line_num][i] & FONT_UNDERLINED;
if (is_underlined && underlined==0 && !ccx_options.notypesetting) // Open underline
{
buffer+=encode_line (buffer, (unsigned char *) "<u>");
strcat (tagstack,"U");
underlined++;
}
if (is_underlined==0 && underlined && !ccx_options.notypesetting) // Close underline
{
buffer = close_tag(buffer,tagstack,'U',&underlined,&italics,&changed_font);
}
// Handle italics
int has_ita = data->fonts[line_num][i] & FONT_ITALICS;
if (has_ita && italics==0 && !ccx_options.notypesetting) // Open italics
{
buffer+=encode_line (buffer, (unsigned char *) "<i>");
strcat (tagstack,"I");
italics++;
}
if (has_ita==0 && italics && !ccx_options.notypesetting) // Close italics
{
buffer = close_tag(buffer,tagstack,'I',&underlined,&italics,&changed_font);
}
int bytes=0;
switch (ccx_options.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;
break;
}
buffer+=bytes;
}
buffer = close_tag(buffer,tagstack,'A',&underlined,&italics,&changed_font);
if (underlined || italics || changed_font)
fatal (EXIT_BUG_BUG, "Not all tags closed in encoding, this is a bug, please report.\n");
*buffer=0;
return (unsigned) (buffer-orig); // Return length
}
void delete_all_lines_but_current (struct eia608_screen *data, int row)
{
for (int i=0;i<15;i++)
{
if (i!=row)
{
memset(data->characters[i],' ',CC608_SCREEN_WIDTH);
data->characters[i][CC608_SCREEN_WIDTH]=0;
memset (data->colors[i],ccx_options.cc608_default_color,CC608_SCREEN_WIDTH+1);
memset (data->fonts[i],FONT_REGULAR,CC608_SCREEN_WIDTH+1);
data->row_used[i]=0;
}
}
}
void fprintf_encoded (struct encoder_ctx *ctx,FILE *fh, const char *string)
{
int used;
REQUEST_BUFFER_CAPACITY(ctx,strlen (string)*3);
used=encode_line (ctx->buffer,(unsigned char *) string);
fwrite (ctx->buffer,used,1,fh);
}
void write_cc_buffer_to_gui(struct eia608_screen *data, struct encoder_ctx *context)
{
unsigned h1,m1,s1,ms1;
unsigned h2,m2,s2,ms2;
LLONG ms_start;
int with_data=0;
for (int i=0;i<15;i++)
{
if (data->row_used[i])
with_data=1;
}
if (!with_data)
return;
ms_start= data->start_time;
ms_start+=subs_delay;
if (ms_start<0) // Drop screens that because of subs_delay start too early
return;
int time_reported=0;
for (int i=0;i<15;i++)
{
if (data->row_used[i])
{
fprintf (stderr, "###SUBTITLE#");
if (!time_reported)
{
LLONG 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.
// Note, only MM:SS here as we need to save space in the preview window
fprintf (stderr, "%02u:%02u#%02u:%02u#",
h1*60+m1,s1, h2*60+m2,s2);
time_reported=1;
}
else
fprintf (stderr, "##");
// We don't capitalize here because whatever function that was used
// before to write to file already took care of it.
int length = get_decoder_line_encoded_for_gui (subline, i, data);
fwrite (subline, 1, length, stderr);
fwrite ("\n",1,1,stderr);
}
}
fflush (stderr);
}

View File

@@ -1,9 +1,10 @@
#include "ccextractor.h"
#include "cc_encoders_common.h"
#include "ccx_encoders_common.h"
#include "png.h"
#include "spupng_encoder.h"
#include "ocr.h"
#include "utility.h"
void write_stringz_as_sami(char *string, struct encoder_ctx *context, LLONG ms_start, LLONG ms_end)
{
int used;
@@ -12,7 +13,7 @@ void write_stringz_as_sami(char *string, struct encoder_ctx *context, LLONG ms_s
(unsigned long long)ms_start);
if (ccx_options.encoding!=CCX_ENC_UNICODE)
{
dbg_print(CCX_DMT_608, "\r%s\n", str);
dbg_print(CCX_DMT_DECODER_608, "\r%s\n", str);
}
used = encode_line(context->buffer,(unsigned char *) str);
@@ -47,8 +48,8 @@ void write_stringz_as_sami(char *string, struct encoder_ctx *context, LLONG ms_s
unsigned int u = encode_line (el, begin);
if (ccx_options.encoding!=CCX_ENC_UNICODE)
{
dbg_print(CCX_DMT_608, "\r");
dbg_print(CCX_DMT_608, "%s\n",subline);
dbg_print(CCX_DMT_DECODER_608, "\r");
dbg_print(CCX_DMT_DECODER_608, "%s\n",subline);
}
write(context->out->fh, el, u);
write(context->out->fh, encoded_br, encoded_br_length);
@@ -60,7 +61,7 @@ void write_stringz_as_sami(char *string, struct encoder_ctx *context, LLONG ms_s
sprintf ((char *) str,"</P></SYNC>\r\n");
if (ccx_options.encoding!=CCX_ENC_UNICODE)
{
dbg_print(CCX_DMT_608, "\r%s\n", str);
dbg_print(CCX_DMT_DECODER_608, "\r%s\n", str);
}
used=encode_line (context->buffer,(unsigned char *) str);
write(context->out->fh, context->buffer, used);
@@ -69,7 +70,7 @@ void write_stringz_as_sami(char *string, struct encoder_ctx *context, LLONG ms_s
(unsigned long long)ms_end);
if (ccx_options.encoding!=CCX_ENC_UNICODE)
{
dbg_print(CCX_DMT_608, "\r%s\n", str);
dbg_print(CCX_DMT_DECODER_608, "\r%s\n", str);
}
write(context->out->fh, context->buffer, used);
free(el);
@@ -83,18 +84,20 @@ int write_cc_bitmap_as_sami(struct cc_subtitle *sub, struct encoder_ctx *context
int x_pos, y_pos, width, height, i;
int x, y, y_off, x_off, ret;
uint8_t *pbuf;
char *filename;
//char *filename;
struct cc_bitmap* rect;
png_color *palette = NULL;
png_byte *alpha = NULL;
#ifdef ENABLE_OCR
char*str = NULL;
#endif
int used;
unsigned h1,m1,s1,ms1;
unsigned h2,m2,s2,ms2;
//int used;
#ifdef ENABLE_OCR
unsigned h1, m1, s1, ms1;
unsigned h2, m2, s2, ms2;
#endif
LLONG ms_start, ms_end;
char timeline[128];
//char timeline[128];
int len = 0;
x_pos = -1;
@@ -241,7 +244,7 @@ int write_cc_buffer_as_sami(struct eia608_screen *data, struct encoder_ctx *cont
(unsigned long long)startms);
if (ccx_options.encoding!=CCX_ENC_UNICODE)
{
dbg_print(CCX_DMT_608, "\r%s\n", str);
dbg_print(CCX_DMT_DECODER_608, "\r%s\n", str);
}
used = encode_line(context->buffer,(unsigned char *) str);
write (context->out->fh, context->buffer, used);
@@ -252,8 +255,8 @@ int write_cc_buffer_as_sami(struct eia608_screen *data, struct encoder_ctx *cont
int length = get_decoder_line_encoded (subline, i, data);
if (ccx_options.encoding!=CCX_ENC_UNICODE)
{
dbg_print(CCX_DMT_608, "\r");
dbg_print(CCX_DMT_608, "%s\n",subline);
dbg_print(CCX_DMT_DECODER_608, "\r");
dbg_print(CCX_DMT_DECODER_608, "%s\n",subline);
}
write (context->out->fh, subline, length);
wrote_something=1;
@@ -265,7 +268,7 @@ int write_cc_buffer_as_sami(struct eia608_screen *data, struct encoder_ctx *cont
sprintf ((char *) str,"</P></SYNC>\r\n");
if (ccx_options.encoding!=CCX_ENC_UNICODE)
{
dbg_print(CCX_DMT_608, "\r%s\n", str);
dbg_print(CCX_DMT_DECODER_608, "\r%s\n", str);
}
used = encode_line(context->buffer,(unsigned char *) str);
write (context->out->fh, context->buffer, used);
@@ -274,7 +277,7 @@ int write_cc_buffer_as_sami(struct eia608_screen *data, struct encoder_ctx *cont
(unsigned long long)endms);
if (ccx_options.encoding!=CCX_ENC_UNICODE)
{
dbg_print(CCX_DMT_608, "\r%s\n", str);
dbg_print(CCX_DMT_DECODER_608, "\r%s\n", str);
}
used = encode_line(context->buffer,(unsigned char *) str);
write (context->out->fh, context->buffer, used);

View File

@@ -1,5 +1,5 @@
#include "ccextractor.h"
#include "cc_encoders_common.h"
#include "ccx_encoders_common.h"
#include "png.h"
#include "spupng_encoder.h"
#include "ocr.h"
@@ -39,7 +39,7 @@ void write_stringz_as_smptett(char *string, struct encoder_ctx *context, LLONG m
sprintf ((char *) str,"<p begin=\"%02u:%02u:%02u,%03u\" end=\"%02u:%02u:%02u.%03u\">\r\n",h1,m1,s1,ms1, h2,m2,s2,ms2);
if (ccx_options.encoding!=CCX_ENC_UNICODE)
{
dbg_print(CCX_DMT_608, "\r%s\n", str);
dbg_print(CCX_DMT_DECODER_608, "\r%s\n", str);
}
used = encode_line(context->buffer,(unsigned char *) str);
write (context->out->fh, context->buffer, used);
@@ -73,8 +73,8 @@ void write_stringz_as_smptett(char *string, struct encoder_ctx *context, LLONG m
unsigned int u = encode_line (el, begin);
if (ccx_options.encoding!=CCX_ENC_UNICODE)
{
dbg_print(CCX_DMT_608, "\r");
dbg_print(CCX_DMT_608, "%s\n",subline);
dbg_print(CCX_DMT_DECODER_608, "\r");
dbg_print(CCX_DMT_DECODER_608, "%s\n",subline);
}
write(context->out->fh, el, u);
//write (wb->fh, encoded_br, encoded_br_length);
@@ -86,14 +86,14 @@ void write_stringz_as_smptett(char *string, struct encoder_ctx *context, LLONG m
sprintf ((char *) str,"</p>\n");
if (ccx_options.encoding!=CCX_ENC_UNICODE)
{
dbg_print(CCX_DMT_608, "\r%s\n", str);
dbg_print(CCX_DMT_DECODER_608, "\r%s\n", str);
}
used = encode_line(context->buffer,(unsigned char *) str);
write(context->out->fh, context->buffer, used);
sprintf ((char *) str,"<p begin=\"%02u:%02u:%02u,%03u\">\n\n",h2,m2,s2,ms2);
if (ccx_options.encoding!=CCX_ENC_UNICODE)
{
dbg_print(CCX_DMT_608, "\r%s\n", str);
dbg_print(CCX_DMT_DECODER_608, "\r%s\n", str);
}
used = encode_line(context->buffer,(unsigned char *) str);
write (context->out->fh, context->buffer, used);
@@ -109,18 +109,20 @@ int write_cc_bitmap_as_smptett(struct cc_subtitle *sub, struct encoder_ctx *cont
int x_pos, y_pos, width, height, i;
int x, y, y_off, x_off, ret;
uint8_t *pbuf;
char *filename;
//char *filename;
struct cc_bitmap* rect;
png_color *palette = NULL;
png_byte *alpha = NULL;
#ifdef ENABLE_OCR
char*str = NULL;
#endif
int used;
unsigned h1,m1,s1,ms1;
unsigned h2,m2,s2,ms2;
//int used;
#ifdef ENABLE_OCR
unsigned h1, m1, s1, ms1;
unsigned h2, m2, s2, ms2;
#endif
LLONG ms_start, ms_end;
char timeline[128];
//char timeline[128];
int len = 0;
x_pos = -1;
@@ -258,7 +260,7 @@ int write_cc_buffer_as_smptett(struct eia608_screen *data, struct encoder_ctx *c
if (ccx_options.encoding!=CCX_ENC_UNICODE)
{
dbg_print(CCX_DMT_608, "\r%s\n", str);
dbg_print(CCX_DMT_DECODER_608, "\r%s\n", str);
}
used = encode_line(context->buffer,(unsigned char *) str);
write (context->out->fh, context->buffer, used);
@@ -269,8 +271,8 @@ int write_cc_buffer_as_smptett(struct eia608_screen *data, struct encoder_ctx *c
int length = get_decoder_line_encoded (subline, i, data);
if (ccx_options.encoding!=CCX_ENC_UNICODE)
{
dbg_print(CCX_DMT_608, "\r");
dbg_print(CCX_DMT_608, "%s\n",subline);
dbg_print(CCX_DMT_DECODER_608, "\r");
dbg_print(CCX_DMT_DECODER_608, "%s\n",subline);
}
write(context->out->fh, subline, length);
wrote_something=1;
@@ -281,14 +283,14 @@ int write_cc_buffer_as_smptett(struct eia608_screen *data, struct encoder_ctx *c
sprintf ((char *) str,"</p>\n");
if (ccx_options.encoding!=CCX_ENC_UNICODE)
{
dbg_print(CCX_DMT_608, "\r%s\n", str);
dbg_print(CCX_DMT_DECODER_608, "\r%s\n", str);
}
used = encode_line(context->buffer,(unsigned char *) str);
write (context->out->fh, context->buffer, used);
if (ccx_options.encoding!=CCX_ENC_UNICODE)
{
dbg_print(CCX_DMT_608, "\r%s\n", str);
dbg_print(CCX_DMT_DECODER_608, "\r%s\n", str);
}
used = encode_line(context->buffer,(unsigned char *) str);
//write (wb->fh, enc_buffer,enc_buffer_used);

View File

@@ -225,12 +225,12 @@ spupng_write_ccbuffer(struct spupng_t *sp, struct eia608_screen* data,
sprintf(sp->pngfile, "%s/sub%04d.png", sp->dirname, sp->fileIndex++);
if ((sp->fppng = fopen(sp->pngfile, "wb")) == NULL)
{
fatal(EXIT_FILE_CREATION_FAILED, "Cannot open %s: %s\n",
fatal(CCX_COMMON_EXIT_FILE_CREATION_FAILED, "Cannot open %s: %s\n",
sp->pngfile, strerror(errno));
}
if (!spupng_export_png(sp, data))
{
fatal(EXIT_FILE_CREATION_FAILED, "Cannot write %s: %s\n",
fatal(CCX_COMMON_EXIT_FILE_CREATION_FAILED, "Cannot write %s: %s\n",
sp->pngfile, strerror(errno));
}
fclose(sp->fppng);

View File

@@ -2,7 +2,7 @@
#include "ccextractor.h"
#include "spupng_encoder.h"
#include "cc_encoders_common.h"
#include "ccx_encoders_common.h"
int write_cc_buffer_as_spupng(struct eia608_screen *data,struct encoder_ctx *context);

View File

@@ -1,5 +1,5 @@
#include "ccextractor.h"
#include "cc_encoders_common.h"
#include "ccx_encoders_common.h"
#include "png.h"
#include "spupng_encoder.h"
#include "ocr.h"
@@ -23,8 +23,8 @@ void write_stringz_as_srt(char *string, struct encoder_ctx *context, LLONG ms_st
sprintf (timeline, "%02u:%02u:%02u,%03u --> %02u:%02u:%02u,%03u\r\n",
h1,m1,s1,ms1, h2,m2,s2,ms2);
used = encode_line(context->buffer,(unsigned char *) timeline);
dbg_print(CCX_DMT_608, "\n- - - SRT caption - - -\n");
dbg_print(CCX_DMT_608, "%s",timeline);
dbg_print(CCX_DMT_DECODER_608, "\n- - - SRT caption - - -\n");
dbg_print(CCX_DMT_DECODER_608, "%s",timeline);
write(context->out->fh, context->buffer, used);
int len=strlen (string);
@@ -57,15 +57,15 @@ void write_stringz_as_srt(char *string, struct encoder_ctx *context, LLONG ms_st
unsigned int u = encode_line (el, begin);
if (ccx_options.encoding!=CCX_ENC_UNICODE)
{
dbg_print(CCX_DMT_608, "\r");
dbg_print(CCX_DMT_608, "%s\n",subline);
dbg_print(CCX_DMT_DECODER_608, "\r");
dbg_print(CCX_DMT_DECODER_608, "%s\n",subline);
}
write(context->out->fh, el, u);
write(context->out->fh, encoded_crlf, encoded_crlf_length);
begin+= strlen ((const char *) begin)+1;
}
dbg_print(CCX_DMT_608, "- - - - - - - - - - - -\r\n");
dbg_print(CCX_DMT_DECODER_608, "- - - - - - - - - - - -\r\n");
write(context->out->fh, encoded_crlf, encoded_crlf_length);
free(el);
@@ -78,19 +78,21 @@ int write_cc_bitmap_as_srt(struct cc_subtitle *sub, struct encoder_ctx *context)
int x_pos, y_pos, width, height, i;
int x, y, y_off, x_off, ret;
uint8_t *pbuf;
char *filename;
//char *filename;
struct cc_bitmap* rect;
png_color *palette = NULL;
png_byte *alpha = NULL;
#ifdef ENABLE_OCR
char*str = NULL;
#endif
int used;
#endif
LLONG ms_start, ms_end;
#ifdef ENABLE_OCR
unsigned h1,m1,s1,ms1;
unsigned h2,m2,s2,ms2;
LLONG ms_start, ms_end;
char timeline[128];
int len = 0;
int used;
#endif
x_pos = -1;
y_pos = -1;
@@ -248,8 +250,8 @@ int write_cc_buffer_as_srt(struct eia608_screen *data, struct encoder_ctx *conte
h1,m1,s1,ms1, h2,m2,s2,ms2);
used = encode_line(context->buffer,(unsigned char *) timeline);
dbg_print(CCX_DMT_608, "\n- - - SRT caption ( %d) - - -\n", context->srt_counter);
dbg_print(CCX_DMT_608, "%s",timeline);
dbg_print(CCX_DMT_DECODER_608, "\n- - - SRT caption ( %d) - - -\n", context->srt_counter);
dbg_print(CCX_DMT_DECODER_608, "%s",timeline);
write (context->out->fh, context->buffer, used);
for (int i=0;i<15;i++)
@@ -295,7 +297,7 @@ int write_cc_buffer_as_srt(struct eia608_screen *data, struct encoder_ctx *conte
center1=(first+last)/2;
if (colon_pos!=-1)
{
while (colon_pos<CC608_SCREEN_WIDTH &&
while (colon_pos<CCX_DECODER_608_SCREEN_WIDTH &&
(line[colon_pos]==':' ||
line[colon_pos]==' ' ||
line[colon_pos]==0x89))
@@ -321,8 +323,8 @@ int write_cc_buffer_as_srt(struct eia608_screen *data, struct encoder_ctx *conte
int length = get_decoder_line_encoded (subline, i, data);
if (ccx_options.encoding!=CCX_ENC_UNICODE)
{
dbg_print(CCX_DMT_608, "\r");
dbg_print(CCX_DMT_608, "%s\n",subline);
dbg_print(CCX_DMT_DECODER_608, "\r");
dbg_print(CCX_DMT_DECODER_608, "%s\n",subline);
}
write(context->out->fh, subline, length);
write(context->out->fh, encoded_crlf, encoded_crlf_length);
@@ -330,7 +332,7 @@ int write_cc_buffer_as_srt(struct eia608_screen *data, struct encoder_ctx *conte
// fprintf (wb->fh,encoded_crlf);
}
}
dbg_print(CCX_DMT_608, "- - - - - - - - - - - -\r\n");
dbg_print(CCX_DMT_DECODER_608, "- - - - - - - - - - - -\r\n");
// fprintf (wb->fh, encoded_crlf);
write (context->out->fh, encoded_crlf, encoded_crlf_length);

View File

@@ -33,44 +33,32 @@ void activity_input_file_open (const char *filename)
}
}
void activity_xds_program_identification_number (unsigned minutes, unsigned hours, unsigned date, unsigned month)
{
if (ccx_options.gui_mode_reports)
{
fprintf (stderr, "###XDSPROGRAMIDENTIFICATIONNUMBER#%u#%u#%u#%u\n", minutes,hours,date,month);
fflush (stderr);
}
void activity_library_process(enum ccx_common_logging_gui message_type, ...){
if (ccx_options.gui_mode_reports){
va_list args;
va_start(args, message_type);
switch (message_type)
{
case CCX_COMMON_LOGGING_GUI_XDS_CALL_LETTERS:
vfprintf(stderr, "###XDSNETWORKCALLLETTERS#%s\n",args);
break;
case CCX_COMMON_LOGGING_GUI_XDS_PROGRAM_DESCRIPTION:
vfprintf(stderr, "###XDSPROGRAMDESC#%d#%s\n", args);
break;
case CCX_COMMON_LOGGING_GUI_XDS_PROGRAM_ID_NR:
vfprintf(stderr, "###XDSPROGRAMIDENTIFICATIONNUMBER#%u#%u#%u#%u\n", args);
break;
case CCX_COMMON_LOGGING_GUI_XDS_PROGRAM_NAME:
vfprintf(stderr, "###XDSPROGRAMNAME#%s\n", args);
break;
default:
break;
}
fflush(stderr);
va_end(args);
}
}
void activity_xds_network_call_letters (const char *program_name)
{
if (ccx_options.gui_mode_reports)
{
fprintf (stderr, "###XDSNETWORKCALLLETTERS#%s\n", program_name);
fflush (stderr);
}
}
void activity_xds_program_name (const char *program_name)
{
if (ccx_options.gui_mode_reports)
{
fprintf (stderr, "###XDSPROGRAMNAME#%s\n", program_name);
fflush (stderr);
}
}
void activity_xds_program_description (int line_num, const char *program_desc)
{
if (ccx_options.gui_mode_reports)
{
fprintf (stderr, "###XDSPROGRAMDESC#%d#%s\n", line_num, program_desc);
fflush (stderr);
}
}
void activity_video_info (int hor_size,int vert_size,
const char *aspect_ratio, const char *framerate)
{

View File

@@ -28,7 +28,7 @@ uint32_t asf_readval(void *val, int ltype)
rval = *((uint32_t*)val);
break;
default:
fatal (EXIT_BUG_BUG, "Wrong type ...\n");
fatal (CCX_COMMON_EXIT_BUG_BUG, "Wrong type ...\n");
break;
}
return rval;
@@ -273,7 +273,7 @@ LLONG asf_getmoredata(void)
StreamNumber, StreamNameCount, PayloadExtensionSystemCount);
if ( StreamNumber >= STREAMNUM )
fatal(EXIT_BUG_BUG, "STREAMNUM too small. Send bug report!/n");
fatal(CCX_COMMON_EXIT_BUG_BUG, "STREAMNUM too small. Send bug report!/n");
for(int i=0; i<StreamNameCount; i++)
{
@@ -285,7 +285,7 @@ LLONG asf_getmoredata(void)
int extensionsysteminfolength;
if ( PayloadExtensionSystemCount > PAYEXTNUM )
fatal(EXIT_BUG_BUG, "PAYEXTNUM too small. Send bug report!/n");
fatal(CCX_COMMON_EXIT_BUG_BUG, "PAYEXTNUM too small. Send bug report!/n");
for(int i=0; i<PayloadExtensionSystemCount; i++)
{
@@ -455,7 +455,7 @@ LLONG asf_getmoredata(void)
dbg_print(CCX_DMT_PARSE, "%u (WORD)\n",(int)*((uint16_t*)edescval));
break;
default:
fatal(EXIT_BUG_BUG, "Wrong type ...\n");
fatal(CCX_COMMON_EXIT_BUG_BUG, "Wrong type ...\n");
break;
}
@@ -918,9 +918,9 @@ LLONG asf_getmoredata(void)
// a jump this needs synchronizing, otherwise it was
// just a gap in the captions.
if (!asf_data_container.StreamProperties.VideoJump)
CaptionGap = 1;
ccx_common_timing_settings.disable_sync_check = 1;
else
CaptionGap = 0;
ccx_common_timing_settings.disable_sync_check = 0;
}
asf_data_container.StreamProperties.VideoJump = 0;
}
@@ -973,7 +973,7 @@ LLONG asf_getmoredata(void)
int want = (long)((BUFSIZE - inbuf)>asf_data_container.PayloadLength ?
asf_data_container.PayloadLength : (BUFSIZE - inbuf));
if (want < (long)asf_data_container.PayloadLength)
fatal(EXIT_BUG_BUG, "Buffer size to small for ASF payload!\nPlease file a bug report!\n");
fatal(CCX_COMMON_EXIT_BUG_BUG, "Buffer size to small for ASF payload!\nPlease file a bug report!\n");
buffered_read (buffer+inbuf,want);
payload_read+=(int) result;
inbuf+=result;

View File

@@ -108,14 +108,14 @@ LLONG process_avc (unsigned char *avcbuf, LLONG avcbuflen ,struct cc_subtitle *s
// At least 5 bytes are needed for a NAL unit
if(avcbuflen <= 5)
{
fatal(EXIT_BUG_BUG,
fatal(CCX_COMMON_EXIT_BUG_BUG,
"NAL unit need at last 5 bytes ...");
}
// Warning there should be only leading zeros, nothing else
if( !(bpos[0]==0x00 && bpos[1]==0x00) )
{
fatal(EXIT_BUG_BUG,
fatal(CCX_COMMON_EXIT_BUG_BUG,
"Broken AVC stream - no 0x0000 ...");
}
bpos = bpos+2;
@@ -138,7 +138,7 @@ LLONG process_avc (unsigned char *avcbuf, LLONG avcbuflen ,struct cc_subtitle *s
else if(firstloop && *bpos != 0x00)
{
// Not 0x00 or 0x01
fatal(EXIT_BUG_BUG,
fatal(CCX_COMMON_EXIT_BUG_BUG,
"Broken AVC stream - no 0x00 ...");
}
bpos++;
@@ -193,7 +193,7 @@ LLONG process_avc (unsigned char *avcbuf, LLONG avcbuflen ,struct cc_subtitle *s
if(*NALstart & 0x80)
{
dump(CCX_DMT_GENERIC_NOTICES, NALstart-4,10, 0, 0);
fatal(EXIT_BUG_BUG,
fatal(CCX_COMMON_EXIT_BUG_BUG,
"Broken AVC stream - forbidden_zero_bit not zero ...");
}
@@ -450,15 +450,15 @@ void user_data_registered_itu_t_t35 (unsigned char *userbuf, unsigned char *user
/* TODO: I don't think we have user_data_len here
if (cc_count*3+3 != user_data_len)
fatal(EXIT_BUG_BUG,
fatal(CCX_COMMON_EXIT_BUG_BUG,
"Syntax problem: user_data_len != cc_count*3+3."); */
// Enough room for CC captions?
if (cc_tmpdata+local_cc_count*3 >= userend)
fatal(EXIT_BUG_BUG,
fatal(CCX_COMMON_EXIT_BUG_BUG,
"Syntax problem: Too many caption blocks.");
if (cc_tmpdata[local_cc_count*3]!=0xFF)
fatal(EXIT_BUG_BUG,
fatal(CCX_COMMON_EXIT_BUG_BUG,
"Syntax problem: Final 0xFF marker missing.");
// Save the data and process once we know the sequence number
@@ -522,15 +522,15 @@ void user_data_registered_itu_t_t35 (unsigned char *userbuf, unsigned char *user
cc_tmpdata = tbuf+2;
if (local_cc_count*3+3 != user_data_len)
fatal(EXIT_BUG_BUG,
fatal(CCX_COMMON_EXIT_BUG_BUG,
"Syntax problem: user_data_len != cc_count*3+3.");
// Enough room for CC captions?
if (cc_tmpdata+local_cc_count*3 >= userend)
fatal(EXIT_BUG_BUG,
fatal(CCX_COMMON_EXIT_BUG_BUG,
"Syntax problem: Too many caption blocks.");
if (cc_tmpdata[local_cc_count*3]!=0xFF)
fatal(EXIT_BUG_BUG,
fatal(CCX_COMMON_EXIT_BUG_BUG,
"Syntax problem: Final 0xFF marker missing.");
// Save the data and process once we know the sequence number
@@ -563,151 +563,223 @@ void seq_parameter_set_rbsp (unsigned char *seqbuf, unsigned char *seqend)
dvprint("SEQUENCE PARAMETER SET (bitlen: %lld)\n", q1.bitsleft);
tmp=u(&q1,8);
dvprint("profile_idc= %llX\n", tmp);
LLONG profile_idc = tmp;
dvprint("profile_idc= % 4lld (%#llX)\n",tmp,tmp);
tmp=u(&q1,1);
dvprint("constraint_set0_flag= %llX\n", tmp);
dvprint("constraint_set0_flag= % 4lld (%#llX)\n",tmp,tmp);
tmp=u(&q1,1);
dvprint("constraint_set1_flag= %llX\n", tmp);
dvprint("constraint_set1_flag= % 4lld (%#llX)\n",tmp,tmp);
tmp=u(&q1,1);
dvprint("constraint_set2_flag= %llX\n", tmp);
tmp=u(&q1,5);
dvprint("reserved= %llX\n", tmp);
dvprint("constraint_set2_flag= % 4lld (%#llX)\n",tmp,tmp);
tmp = u(&q1, 1);
dvprint("constraint_set3_flag= % 4lld (%#llX)\n",tmp,tmp);
tmp = u(&q1, 1);
dvprint("constraint_set4_flag= % 4lld (%#llX)\n",tmp,tmp);
tmp = u(&q1, 1);
dvprint("constraint_set5_flag= % 4lld (%#llX)\n",tmp,tmp);
tmp=u(&q1,2);
dvprint("reserved= % 4lld (%#llX)\n",tmp,tmp);
tmp=u(&q1,8);
dvprint("level_idc= %llX\n", tmp);
dvprint("level_idc= % 4lld (%#llX)\n",tmp,tmp);
seq_parameter_set_id = ue(&q1);
dvprint("seq_parameter_set_id= %llX\n", seq_parameter_set_id);
log2_max_frame_num = (int)ue(&q1)+4;
dvprint("log2_max_frame_num4= %X\n", log2_max_frame_num);
dvprint("seq_parameter_set_id= % 4lld (%#llX)\n", seq_parameter_set_id,seq_parameter_set_id);
if (profile_idc == 100 || profile_idc == 110 || profile_idc == 122
|| profile_idc == 244 || profile_idc == 44 || profile_idc == 83
|| profile_idc == 86 || profile_idc == 118 || profile_idc == 128){
LLONG chroma_format_idc = ue(&q1);
dvprint("chroma_format_idc= % 4lld (%#llX)\n", chroma_format_idc,chroma_format_idc);
if (chroma_format_idc == 3){
tmp = u(&q1, 1);
dvprint("separate_colour_plane_flag= % 4lld (%#llX)\n", tmp, tmp);
}
tmp = ue(&q1);
dvprint("bit_depth_luma_minus8= % 4lld (%#llX)\n", tmp, tmp);
tmp = ue(&q1);
dvprint("bit_depth_chroma_minus8= % 4lld (%#llX)\n", tmp, tmp);
tmp = u(&q1,1);
dvprint("qpprime_y_zero_transform_bypass_flag= % 4lld (%#llX)\n", tmp, tmp);
tmp = u(&q1, 1);
dvprint("seq_scaling_matrix_present_flag= % 4lld (%#llX)\n", tmp, tmp);
if (tmp == 1){
// WVI: untested, just copied from specs.
for (int i = 0; i < ((chroma_format_idc != 3) ? 8 : 12); i++){
tmp = u(&q1, 1);
dvprint("seq_scaling_list_present_flag[%d]= % 4lld (%#llX)\n",i,tmp, tmp);
if (tmp){
// We use a "dummy"/slimmed-down replacement here. Actual/full code can be found in the spec (ISO/IEC 14496-10:2012(E)) chapter 7.3.2.1.1.1 - Scaling list syntax
if (i < 6){
// Scaling list size 16
// TODO: replace with full scaling list implementation?
int nextScale = 8;
int lastScale = 8;
for (int j = 0; j < 16; j++){
if (nextScale != 0){
int64_t delta_scale = se(&q1);
nextScale = (lastScale + delta_scale + 256) % 256;
}
lastScale = (nextScale == 0) ? lastScale : nextScale;
}
// END of TODO
}
else {
// Scaling list size 64
// TODO: replace with full scaling list implementation?
int nextScale = 8;
int lastScale = 8;
for (int j = 0; j < 64; j++){
if (nextScale != 0){
int64_t delta_scale = se(&q1);
nextScale = (lastScale + delta_scale + 256) % 256;
}
lastScale = (nextScale == 0) ? lastScale : nextScale;
}
// END of TODO
}
}
}
}
}
log2_max_frame_num = (int)ue(&q1);
dvprint("log2_max_frame_num4_minus4= % 4d (%#X)\n", log2_max_frame_num,log2_max_frame_num);
log2_max_frame_num += 4; // 4 is added due to the formula.
pic_order_cnt_type = (int)ue(&q1);
dvprint("pic_order_cnt_type= %X\n", pic_order_cnt_type);
dvprint("pic_order_cnt_type= % 4d (%#X)\n", pic_order_cnt_type,pic_order_cnt_type);
if( pic_order_cnt_type == 0 )
{
log2_max_pic_order_cnt_lsb = (int)ue(&q1)+4;
dvprint("log2_max_pic_order_cnt_lsb= %X\n", log2_max_pic_order_cnt_lsb);
log2_max_pic_order_cnt_lsb = (int)ue(&q1);
dvprint("log2_max_pic_order_cnt_lsb_minus4= % 4d (%#X)\n", log2_max_pic_order_cnt_lsb,log2_max_pic_order_cnt_lsb);
log2_max_pic_order_cnt_lsb += 4; // 4 is added due to formula.
}
else if( pic_order_cnt_type == 1 )
{
// CFS: Untested, just copied from specs.
tmp= u(&q1,1);
dvprint("delta_pic_order_always_zero_flag= %llX\n", tmp);
dvprint("delta_pic_order_always_zero_flag= % 4lld (%#llX)\n",tmp,tmp);
tmp = se(&q1);
dvprint("offset_for_non_ref_pic= %llX\n", tmp);
dvprint("offset_for_non_ref_pic= % 4lld (%#llX)\n",tmp,tmp);
tmp = se(&q1);
dvprint("offset_for_top_to_bottom_field %llX\n", tmp);
dvprint("offset_for_top_to_bottom_field % 4lld (%#llX)\n",tmp,tmp);
LLONG num_ref_frame_in_pic_order_cnt_cycle = ue (&q1);
dvprint("num_ref_frame_in_pic_order_cnt_cycle %llX\n", num_ref_frame_in_pic_order_cnt_cycle);
dvprint("num_ref_frame_in_pic_order_cnt_cycle % 4lld (%#llX)\n", num_ref_frame_in_pic_order_cnt_cycle,num_ref_frame_in_pic_order_cnt_cycle);
for (int i=0; i<num_ref_frame_in_pic_order_cnt_cycle; i++)
{
tmp=se(&q1);
dvprint("offset_for_ref_frame [%d / %d] = %llX\n", i, num_ref_frame_in_pic_order_cnt_cycle, tmp);
}
dvprint("offset_for_ref_frame [%d / %d] = % 4lld (%#llX)\n", i, num_ref_frame_in_pic_order_cnt_cycle, tmp,tmp);
}
}
else
{
// CFS: Looks like nothing needs to be parsed for pic_order_cnt_type==2 ?
// fatal(EXIT_BUG_BUG, "AVC: pic_order_cnt_type > 1 is not yet supported.");
// Nothing needs to be parsed when pic_order_cnt_type == 2
}
tmp=ue(&q1);
dvprint("num_ref_frames= %llX\n", tmp);
dvprint("max_num_ref_frames= % 4lld (%#llX)\n",tmp,tmp);
tmp=u(&q1,1);
dvprint("gaps allowed= %llX\n", tmp);
dvprint("gaps_in_frame_num_value_allowed_flag= % 4lld (%#llX)\n",tmp,tmp);
tmp=ue(&q1);
dvprint("pic_width_in_mbs_minus1= %llX\n", tmp);
dvprint("pic_width_in_mbs_minus1= % 4lld (%#llX)\n",tmp,tmp);
tmp=ue(&q1);
dvprint("pic_height_in_map_units_minus1= %llX\n", tmp);
dvprint("pic_height_in_map_units_minus1= % 4lld (%#llX)\n",tmp,tmp);
frame_mbs_only_flag = (int)u(&q1,1);
dvprint("frame_mbs_only_flag= %X\n", frame_mbs_only_flag);
dvprint("frame_mbs_only_flag= % 4d (%#X)\n", frame_mbs_only_flag,frame_mbs_only_flag);
if ( !frame_mbs_only_flag )
{
tmp=u(&q1,1);
dvprint("mb_adaptive_fr_fi_flag= %llX\n", tmp);
dvprint("mb_adaptive_fr_fi_flag= % 4lld (%#llX)\n",tmp,tmp);
}
tmp=u(&q1,1);
dvprint("direct_8x8_inference_f= %llX\n", tmp);
dvprint("direct_8x8_inference_f= % 4lld (%#llX)\n",tmp,tmp);
tmp=u(&q1,1);
dvprint("frame_cropping_flag= %llX\n", tmp);
dvprint("frame_cropping_flag= % 4lld (%#llX)\n",tmp,tmp);
if ( tmp )
{
tmp=ue(&q1);
dvprint("frame_crop_left_offset= %llX\n", tmp);
dvprint("frame_crop_left_offset= % 4lld (%#llX)\n",tmp,tmp);
tmp=ue(&q1);
dvprint("frame_crop_right_offset= %llX\n", tmp);
dvprint("frame_crop_right_offset= % 4lld (%#llX)\n",tmp,tmp);
tmp=ue(&q1);
dvprint("frame_crop_top_offset= %llX\n", tmp);
dvprint("frame_crop_top_offset= % 4lld (%#llX)\n",tmp,tmp);
tmp=ue(&q1);
dvprint("frame_crop_bottom_offset= %llX\n", tmp);
dvprint("frame_crop_bottom_offset= % 4lld (%#llX)\n",tmp,tmp);
}
tmp=u(&q1,1);
dvprint("vui_parameters_present= %llX\n", tmp);
dvprint("vui_parameters_present= % 4lld (%#llX)\n",tmp,tmp);
if ( tmp )
{
dvprint("\nVUI parameters\n");
tmp=u(&q1,1);
dvprint("aspect_ratio_info_pres= %llX\n", tmp);
dvprint("aspect_ratio_info_pres= % 4lld (%#llX)\n",tmp,tmp);
if ( tmp )
{
tmp=u(&q1,8);
dvprint("aspect_ratio_idc= %llX\n", tmp);
dvprint("aspect_ratio_idc= % 4lld (%#llX)\n",tmp,tmp);
if ( tmp == 255 )
{
tmp=u(&q1,16);
dvprint("sar_width= %llX\n", tmp);
dvprint("sar_width= % 4lld (%#llX)\n",tmp,tmp);
tmp=u(&q1,16);
dvprint("sar_height= %llX\n", tmp);
dvprint("sar_height= % 4lld (%#llX)\n",tmp,tmp);
}
}
tmp=u(&q1,1);
dvprint("overscan_info_pres_flag= %llX\n", tmp);
dvprint("overscan_info_pres_flag= % 4lld (%#llX)\n",tmp,tmp);
if ( tmp )
{
tmp=u(&q1,1);
dvprint("overscan_appropriate_flag= %llX\n", tmp);
dvprint("overscan_appropriate_flag= % 4lld (%#llX)\n",tmp,tmp);
}
tmp=u(&q1,1);
dvprint("video_signal_type_present_flag= %llX\n", tmp);
dvprint("video_signal_type_present_flag= % 4lld (%#llX)\n",tmp,tmp);
if ( tmp )
{
tmp=u(&q1,3);
dvprint("video_format= %llX\n", tmp);
dvprint("video_format= % 4lld (%#llX)\n",tmp,tmp);
tmp=u(&q1,1);
dvprint("video_full_range_flag= %llX\n", tmp);
dvprint("video_full_range_flag= % 4lld (%#llX)\n",tmp,tmp);
tmp=u(&q1,1);
dvprint("colour_description_present_flag= %llX\n", tmp);
dvprint("colour_description_present_flag= % 4lld (%#llX)\n",tmp,tmp);
if ( tmp )
{
tmp=u(&q1,8);
dvprint("colour_primaries= %llX\n", tmp);
dvprint("colour_primaries= % 4lld (%#llX)\n",tmp,tmp);
tmp=u(&q1,8);
dvprint("transfer_characteristics= %llX\n", tmp);
dvprint("transfer_characteristics= % 4lld (%#llX)\n",tmp,tmp);
tmp=u(&q1,8);
dvprint("matrix_coefficients= %llX\n", tmp);
dvprint("matrix_coefficients= % 4lld (%#llX)\n",tmp,tmp);
}
}
tmp=u(&q1,1);
dvprint("chroma_loc_info_present_flag= %llX\n", tmp);
dvprint("chroma_loc_info_present_flag= % 4lld (%#llX)\n",tmp,tmp);
if ( tmp )
{
tmp=ue(&q1);
dvprint("chroma_sample_loc_type_top_field= %llX\n", tmp);
dvprint("chroma_sample_loc_type_top_field= % 4lld (%#llX)\n",tmp,tmp);
tmp=ue(&q1);
dvprint("chroma_sample_loc_type_bottom_field= %llX\n", tmp);
dvprint("chroma_sample_loc_type_bottom_field= % 4lld (%#llX)\n",tmp,tmp);
}
tmp=u(&q1,1);
dvprint("timing_info_present_flag= %llX\n", tmp);
dvprint("timing_info_present_flag= % 4lld (%#llX)\n",tmp,tmp);
if ( tmp )
{
tmp=u(&q1,32);
dvprint("num_units_in_tick= %llX\n", tmp);
LLONG num_units_in_tick = tmp;
dvprint("num_units_in_tick= % 4lld (%#llX)\n",tmp,tmp);
tmp=u(&q1,32);
dvprint("time_scale= %llX\n", tmp);
LLONG time_scale = tmp;
dvprint("time_scale= % 4lld (%#llX)\n",tmp,tmp);
tmp=u(&q1,1);
dvprint("fixed_frame_rate_flag= %llX\n", tmp);
int fixed_frame_rate_flag = (int) tmp;
dvprint("fixed_frame_rate_flag= % 4lld (%#llX)\n",tmp,tmp);
// Change: use num_units_in_tick and time_scale to calculate FPS. (ISO/IEC 14496-10:2012(E), page 397 & further)
if (fixed_frame_rate_flag){
double clock_tick = (double) num_units_in_tick / time_scale;
dvprint("clock_tick= %f\n", clock_tick);
current_fps = (double)time_scale / (2 * num_units_in_tick); // Based on formula D-2, p. 359 of the ISO/IEC 14496-10:2012(E) spec.
mprint("Changed fps using NAL to: %f\n", current_fps);
}
}
tmp=u(&q1,1);
dvprint("nal_hrd_parameters_present_flag= %llX\n", tmp);
dvprint("nal_hrd_parameters_present_flag= % 4lld (%#llX)\n",tmp,tmp);
if ( tmp )
{
dvprint ("nal_hrd. Not implemented for now. Hopefully not needed. Skiping rest of NAL\n");
@@ -728,13 +800,13 @@ void seq_parameter_set_rbsp (unsigned char *seqbuf, unsigned char *seqend)
if ( tmp || tmp1 )
{
tmp=u(&q1,1);
dvprint("low_delay_hrd_flag= %llX\n", tmp);
dvprint("low_delay_hrd_flag= % 4lld (%#llX)\n",tmp,tmp);
return;
}
tmp=u(&q1,1);
dvprint("pic_struct_present_flag= %llX\n", tmp);
dvprint("pic_struct_present_flag= % 4lld (%#llX)\n",tmp,tmp);
tmp=u(&q1,1);
dvprint("bitstream_restriction_flag= %llX\n", tmp);
dvprint("bitstream_restriction_flag= % 4lld (%#llX)\n",tmp,tmp);
// ..
// The hope was to find the GOP length in max_dec_frame_buffering, but
// it was not set in the testfile. Ignore the rest here, it's
@@ -772,11 +844,11 @@ void slice_header (unsigned char *heabuf, unsigned char *heaend, int nal_unit_ty
dvprint("\nSLICE HEADER\n");
tmp=ue(&q1);
dvprint("first_mb_in_slice= %llX\n", tmp);
dvprint("first_mb_in_slice= % 4lld (%#llX)\n",tmp,tmp);
slice_type=ue(&q1);
dvprint("slice_type= %llX\n", slice_type);
tmp=ue(&q1);
dvprint("pic_parameter_set_id= %llX\n", tmp);
dvprint("pic_parameter_set_id= % 4lld (%#llX)\n",tmp,tmp);
lastframe_num = frame_num;
int maxframe_num = (int) ((1<<log2_max_frame_num) - 1);
@@ -808,7 +880,7 @@ void slice_header (unsigned char *heabuf, unsigned char *heaend, int nal_unit_ty
if( nal_unit_type == 5 )
{
tmp=ue(&q1);
dvprint("idr_pic_id= %llX\n", tmp);
dvprint("idr_pic_id= % 4lld (%#llX)\n",tmp,tmp);
//TODO
}
if( pic_order_cnt_type == 0 )
@@ -818,7 +890,7 @@ void slice_header (unsigned char *heabuf, unsigned char *heaend, int nal_unit_ty
}
if( pic_order_cnt_type == 1 )
{
fatal(EXIT_BUG_BUG, "AVC: pic_order_cnt_type == 1 not yet supported.");
fatal(CCX_COMMON_EXIT_BUG_BUG, "AVC: pic_order_cnt_type == 1 not yet supported.");
}
#if 0
else
@@ -853,7 +925,7 @@ void slice_header (unsigned char *heabuf, unsigned char *heaend, int nal_unit_ty
//pic_order_cnt_lsb=tempPicOrderCnt;
//pic_order_cnt_lsb=u(&q1,tempPicOrderCnt);
//fatal(EXIT_BUG_BUG, "AVC: pic_order_cnt_type != 0 not yet supported.");
//fatal(CCX_COMMON_EXIT_BUG_BUG, "AVC: pic_order_cnt_type != 0 not yet supported.");
//TODO
// Calculate picture order count (POC) according to 8.2.1
}

View File

@@ -40,11 +40,11 @@ uint64_t next_bits(struct bitstream *bstr, unsigned bnum)
uint64_t res = 0;
if(bnum > 64)
fatal(EXIT_BUG_BUG, "next_bits: 64 is maximum bit number, argument: %u!", bnum);
fatal(CCX_COMMON_EXIT_BUG_BUG, "next_bits: 64 is maximum bit number, argument: %u!", bnum);
// Sanity check
if(bstr->end - bstr->pos < 0)
fatal(EXIT_BUG_BUG, "next_bits: bitstream has negative length!");
fatal(CCX_COMMON_EXIT_BUG_BUG, "next_bits: bitstream has negative length!");
// Keep a negative bitstream.bitsleft, but correct it.
if (bstr->bitsleft <= 0)
@@ -67,7 +67,7 @@ uint64_t next_bits(struct bitstream *bstr, unsigned bnum)
if(vbit < 1 || vbit > 8)
{
fatal(EXIT_BUG_BUG, "next_bits: Illegal bit position value %d!", vbit);
fatal(CCX_COMMON_EXIT_BUG_BUG, "next_bits: Illegal bit position value %d!", vbit);
}
while( 1 )
@@ -75,7 +75,7 @@ uint64_t next_bits(struct bitstream *bstr, unsigned bnum)
if(vpos >= bstr->end)
{
// We should not get here ...
fatal(EXIT_BUG_BUG, "next_bits: Reading after end of data ...");
fatal(CCX_COMMON_EXIT_BUG_BUG, "next_bits: Reading after end of data ...");
}
res |= (*vpos & (0x01 << (vbit-1)) ? 1 : 0);
@@ -130,7 +130,7 @@ int skip_bits(struct bitstream *bstr, unsigned bnum)
{
// Sanity check
if(bstr->end - bstr->pos < 0)
fatal(EXIT_BUG_BUG, "skip_bits: bitstream has negative length!");
fatal(CCX_COMMON_EXIT_BUG_BUG, "skip_bits: bitstream has negative length!");
// Keep a negative bstr->bitsleft, but correct it.
if (bstr->bitsleft < 0)
@@ -167,13 +167,13 @@ int is_byte_aligned(struct bitstream *bstr)
{
// Sanity check
if(bstr->end - bstr->pos < 0)
fatal(EXIT_BUG_BUG, "is_byte_aligned: bitstream has negative length!");
fatal(CCX_COMMON_EXIT_BUG_BUG, "is_byte_aligned: bitstream has negative length!");
int vbit = bstr->bpos;
if(vbit == 0 || vbit > 8)
{
fatal(EXIT_BUG_BUG, "is_byte_aligned: Illegal bit position value %d!\n", vbit);
fatal(CCX_COMMON_EXIT_BUG_BUG, "is_byte_aligned: Illegal bit position value %d!\n", vbit);
}
if (vbit == 8)
@@ -188,13 +188,13 @@ void make_byte_aligned(struct bitstream *bstr)
{
// Sanity check
if(bstr->end - bstr->pos < 0)
fatal(EXIT_BUG_BUG, "make_byte_aligned: bitstream has negative length!");
fatal(CCX_COMMON_EXIT_BUG_BUG, "make_byte_aligned: bitstream has negative length!");
int vbit = bstr->bpos;
if(vbit == 0 || vbit > 8)
{
fatal(EXIT_BUG_BUG, "make_byte_aligned: Illegal bit position value %d!\n", vbit);
fatal(CCX_COMMON_EXIT_BUG_BUG, "make_byte_aligned: Illegal bit position value %d!\n", vbit);
}
// Keep a negative bstr->bitsleft, but correct it.
@@ -226,7 +226,7 @@ unsigned char *next_bytes(struct bitstream *bstr, unsigned bynum)
{
// Sanity check
if(bstr->end - bstr->pos < 0)
fatal(EXIT_BUG_BUG, "next_bytes: bitstream has negative length!");
fatal(CCX_COMMON_EXIT_BUG_BUG, "next_bytes: bitstream has negative length!");
// Keep a negative bstr->bitsleft, but correct it.
if (bstr->bitsleft < 0)
@@ -294,7 +294,7 @@ uint64_t bitstream_get_num(struct bitstream *bstr, unsigned bytes, int advance)
case 8:
break;
default:
fatal (EXIT_BUG_BUG, "bitstream_get_num: Illegal precision value [%u]!",
fatal (CCX_COMMON_EXIT_BUG_BUG, "bitstream_get_num: Illegal precision value [%u]!",
bytes);
break;
}

View File

@@ -1,25 +0,0 @@
/* Functions used by both the 608 and 708 decoders. An effort should be
made to reuse, not duplicate, as many functions as possible */
#include "ccextractor.h"
/* 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
obviously but it guarantees there's no timing overlap */
LLONG get_visible_start (void)
{
LLONG fts = get_fts();
if (fts <= minimum_fts)
fts = minimum_fts+1;
dbg_print(CCX_DMT_608, "Visible Start time=%s\n", print_mstime(fts));
return fts;
}
/* This function returns the current FTS and saves it so it can be used by get_visible_start */
LLONG get_visible_end (void)
{
LLONG fts = get_fts();
if (fts>minimum_fts)
minimum_fts=fts;
dbg_print(CCX_DMT_608, "Visible End time=%s\n", print_mstime(fts));
return fts;
}

View File

@@ -1,63 +0,0 @@
#ifndef _CC_DECODER_COMMON
#define _CC_DECODER_COMMON
/* flag raised when end of display marker arrives in Dvb Subtitle */
#define SUB_EOD_MARKER (1 << 0 )
struct cc_bitmap
{
int x;
int y;
int w;
int h;
int nb_colors;
unsigned char *data[2];
int linesize[2];
};
/**
* Raw Subtitle struct used as output of decoder (cc608)
* and input for encoder (sami, srt, transcript or smptett etc)
*/
struct cc_subtitle
{
/**
* A generic data which contain data according to decoder
* just now only struct cc_eia608_screen is placed here
* @warn decoder cant output multiple types of data
*/
void *data;
/** number of data */
unsigned int nb_data;
/** type of subtitle */
enum subtype type;
/* set only when all the data is to be displayed at same time */
LLONG start_time;
LLONG end_time;
/* flags */
int flags;
/* index of language table */
int lang_index;
/** flag to tell that decoder has given output */
int got_output;
};
/**
* @param data raw cc608 data to be processed
*
* @param length length of data passed
*
* @param context context of cc608 where important information related to 608
* are stored.
*
* @param sub pointer to subtitle should be memset to 0 when passed first time
* subtitle are stored when structure return
*
* @return number of bytes used from data, -1 when any error is encountered
*/
int process608(const unsigned char *data, int length, struct s_context_cc608 *context, struct cc_subtitle *sub);
/**
* Issue a EraseDisplayedMemory here so if there's any captions pending
* they get written to cc_subtitle
*/
void handle_end_of_data(struct s_context_cc608 *context, struct cc_subtitle *sub);
#endif

View File

@@ -5,51 +5,24 @@ License: GPL 2.0
#include <stdio.h>
#include "ccextractor.h"
#include "configuration.h"
#include "cc_encoders_common.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <signal.h>
#include "ffmpeg_intgr.h"
void xds_cea608_test();
struct ccx_s_options ccx_options;
// These are the default settings for plain transcripts. No times, no CC or caption mode, and no XDS.
ccx_transcript_format ccx_default_transcript_settings =
{
.showStartTime = 0,
.showEndTime = 0,
.showMode = 0,
.showCC = 0,
.relativeTimestamp = 1,
.xds = 0,
.useColors = 1
};
extern unsigned char *filebuffer;
extern int bytesinbuffer; // Number of bytes we actually have on buffer
// PTS timing related stuff
LLONG min_pts, max_pts, sync_pts;
LLONG fts_now; // Time stamp of current file (w/ fts_offset, w/o fts_global)
LLONG fts_offset; // Time before first sync_pts
LLONG fts_fc_offset; // Time before first GOP
LLONG fts_max; // Remember the maximum fts that we saw in current file
LLONG fts_global=0; // Duration of previous files (-ve mode), see c1global
// global TS PCR value, moved from telxcc. TODO: Rename, see if how to relates to fts_global
uint32_t global_timestamp = 0, min_global_timestamp=0;
int global_timestamp_inited=0;
// Count 608 (per field) and 708 blocks since last set_fts() call
int cb_field1, cb_field2, cb_708;
int saw_caption_block;
int pts_set; //0 = No, 1 = received, 2 = min_pts set
unsigned long long max_dif = 5;
unsigned pts_big_change;
int MPEG_CLOCK_FREQ = 90000; // This "constant" is part of the standard
// Stuff common to both loops
unsigned char *buffer = NULL;
LLONG past; /* Position in file, if in sync same as ftell() */
@@ -75,7 +48,6 @@ int stat_replay4000headers;
int stat_dishheaders;
int stat_hdtv;
int stat_divicom;
unsigned total_frames_count;
unsigned total_pulldownfields;
unsigned total_pulldownframes;
int cc_stats[4];
@@ -83,28 +55,19 @@ int false_pict_header;
int resets_708=0;
/* GOP-based timing */
struct gop_time_code gop_time, first_gop_time, printed_gop;
int saw_gop_header=0;
int frames_since_last_gop=0;
LLONG fts_at_gop_start=0;
/* Time info for timed-transcript */
LLONG ts_start_of_xds=-1; // Time at which we switched to XDS mode, =-1 hasn't happened yet
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 */
int max_gop_length=0; // (Maximum) length of a group of pictures
int last_gop_length=0; // Length of the previous group of pictures
int frames_since_ref_time=0;
int gop_rollover=0;
// int hex_mode=HEX_NONE; // Are we processing an hex file?
/* Detect gaps in caption stream - only used for dvr-ms/NTSC. */
int CaptionGap=0;
/* 608 contexts - note that this shouldn't be global, they should be
per program */
struct s_context_cc608 context_cc608_field_1, context_cc608_field_2;
ccx_decoder_608_context context_cc608_field_1, context_cc608_field_2;
/* Parameters */
void init_options (struct ccx_s_options *options)
@@ -113,11 +76,18 @@ void init_options (struct ccx_s_options *options)
options->buffer_input = 1; // In Windows buffering seems to help
#else
options->buffer_input = 0; // In linux, not so much.
#endif
options->direct_rollup=0; // Write roll-up captions directly instead of line by line?
#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_bom = 0; // Use BOM by default.
options->settings_608.direct_rollup = 0;
options->settings_608.no_rollup = 0;
options->settings_608.force_rollup = 0;
options->settings_608.screens_to_process = -1;
options->settings_608.default_color = COL_TRANSPARENT; // Defaults to transparant/no-color.
/* Select subtitle codec */
options->codec = CCX_CODEC_ANY;
options->nocodec = CCX_CODEC_NONE;
@@ -130,8 +100,6 @@ void init_options (struct ccx_s_options *options)
options->binary_concat=1; // Disabled by -ve or --videoedited
options->use_gop_as_pts = 0; // Use GOP instead of PTS timing (0=do as needed, 1=always, -1=never)
options->fix_padding = 0; // Replace 0000 with 8080 in HDTV (needed for some cards)
options->norollup=0; // If 1, write one line at a time
options->forced_ru=0; // 0=Disabled, 1, 2 or 3=max lines in roll-up mode
options->trim_subs=0; // " Remove spaces at sides? "
options->gui_mode_reports=0; // If 1, output in stderr progress updates so the GUI can grab them
options->no_progress_bar=0; // If 1, suppress the output of the progress to stdout
@@ -157,9 +125,9 @@ void init_options (struct ccx_s_options *options)
options->autodash=0; // Add dashes (-) before each speaker automatically?
options->teletext_mode=CCX_TXT_AUTO_NOT_YET_FOUND; // 0=Disabled, 1 = Not found, 2=Found
options->transcript_settings = ccx_default_transcript_settings;
options->transcript_settings = ccx_encoders_default_transcript_settings;
options->millis_separator=',';
options->screens_to_process=-1; // How many screenfuls we want?
options->encoding = CCX_ENC_UTF_8;
options->write_format=CCX_OF_SRT; // 0=Raw, 1=srt, 2=SMI
options->date_format=ODF_NONE;
@@ -180,12 +148,12 @@ void init_options (struct ccx_s_options *options)
options->send_to_srv = 0;
options->tcpport = NULL;
options->tcp_password = NULL;
options->tcp_desc = NULL;
options->srv_addr = NULL;
options->srv_port = NULL;
options->line_terminator_lf=0; // 0 = CRLF
options->noautotimeref=0; // Do NOT set time automatically?
options->input_source=CCX_DS_FILE; // Files, stdin or network
options->cc608_default_color=COL_TRANSPARENT;
options->input_source=CCX_DS_FILE; // Files, stdin or network
}
enum ccx_stream_mode_enum stream_mode = CCX_SM_ELEMENTARY_OR_NOT_FOUND; // Data parse mode: 0=elementary, 1=transport, 2=program stream, 3=ASF container
@@ -210,15 +178,6 @@ const char *extension; // Output extension
int current_file=-1; // If current_file!=1, we are processing *inputfile[current_file]
int num_input_files=0; // How many?
int do_cea708=0; // Process 708 data?
int cea708services[63]; // [] -> 1 for services to be processed
// Case arrays
char **spell_lower=NULL;
char **spell_correct=NULL;
int spell_words=0;
int spell_capacity=0;
/* Hauppauge support */
unsigned hauppauge_warning_shown=0; // Did we detect a possible Hauppauge capture and told the user already?
@@ -242,6 +201,13 @@ int main_telxcc (int argc, char *argv[]);
#endif
LLONG process_raw_with_field (void);
void sigint_handler()
{
if (ccx_options.print_file_reports)
print_file_report();
exit(EXIT_SUCCESS);
}
int main(int argc, char *argv[])
@@ -249,6 +215,12 @@ int main(int argc, char *argv[])
char *c;
struct encoder_ctx enc_ctx[2];
struct cc_subtitle dec_sub;
void *ffmpeg_ctx = NULL;
// Need to set the 608 data for the report to the correct variable.
file_report.data_from_608 = &ccx_decoder_608_report;
// Same applies for 708 data
file_report.data_from_708 = &ccx_decoder_708_report;
// Initialize some constants
init_ts();
@@ -256,19 +228,12 @@ int main(int argc, char *argv[])
init_options (&ccx_options);
// Init timing
ccx_common_timing_init(&past,ccx_options.nosync);
// Prepare write structures
init_write(&wbout1);
init_write(&wbout2);
// Prepare 608 context
init_context_cc608(&context_cc608_field_1,1);
init_context_cc608(&context_cc608_field_2,2);
context_cc608_field_1.out = &wbout1;
context_cc608_field_2.out = &wbout2;
// Init XDS buffers
xds_init();
//xds_cea608_test();
init_write(&wbout2);
// Prepare time structures
init_boundary_time (&ccx_options.extraction_start);
@@ -282,10 +247,11 @@ int main(int argc, char *argv[])
int show_myth_banner = 0;
memset (&cea708services[0],0,63*sizeof (int));
memset (&cea708services[0],0,CCX_DECODERS_708_MAX_SERVICES*sizeof (int)); // Cannot (yet) be moved because it's needed in parse_parameters.
memset (&dec_sub, 0,sizeof(dec_sub));
parse_configuration(&ccx_options);
parse_parameters (argc,argv);
parse_parameters (argc,argv);
if (num_input_files==0 && ccx_options.input_source==CCX_DS_FILE)
{
@@ -309,6 +275,14 @@ int main(int argc, char *argv[])
fatal(EXIT_TOO_MANY_INPUT_FILES, "TCP mode is not compatible with input files.\n");
}
if (num_input_files > 0)
{
wbout1.multiple_files = 1;
wbout1.first_input_file = inputfile[0];
wbout2.multiple_files = 1;
wbout2.first_input_file = inputfile[0];
}
// teletext page number out of range
if ((tlt_config.page != 0) && ((tlt_config.page < 100) || (tlt_config.page > 899))) {
fatal (EXIT_NOT_CLASSIFIED, "Teletext page number could not be lower than 100 or higher than 899\n");
@@ -355,7 +329,7 @@ int main(int argc, char *argv[])
extension = ".dvdraw";
break;
default:
fatal (EXIT_BUG_BUG, "write_format doesn't have any legal value, this is a bug.\n");
fatal (CCX_COMMON_EXIT_BUG_BUG, "write_format doesn't have any legal value, this is a bug.\n");
}
params_dump();
@@ -431,7 +405,7 @@ int main(int argc, char *argv[])
if (ccx_options.send_to_srv)
{
connect_to_srv(ccx_options.srv_addr, ccx_options.srv_port);
connect_to_srv(ccx_options.srv_addr, ccx_options.srv_port, ccx_options.tcp_desc);
}
if (ccx_options.write_format!=CCX_OF_NULL)
@@ -455,7 +429,7 @@ int main(int argc, char *argv[])
wbout1.fh=open (wbout1.filename, O_RDWR | O_CREAT | O_TRUNC | O_BINARY, S_IREAD | S_IWRITE);
if (wbout1.fh==-1)
{
fatal (EXIT_FILE_CREATION_FAILED, "Failed\n");
fatal(CCX_COMMON_EXIT_FILE_CREATION_FAILED, "Failed\n");
}
}
}
@@ -474,7 +448,7 @@ int main(int argc, char *argv[])
wbout1.fh=STDOUT_FILENO;
mprint ("Sending captions to stdout.\n");
}
else
else if (!ccx_options.send_to_srv)
{
if (wbout1.filename[0]==0)
{
@@ -487,27 +461,32 @@ int main(int argc, char *argv[])
wbout1.fh=open (wbout1.filename, O_RDWR | O_CREAT | O_TRUNC | O_BINARY, S_IREAD | S_IWRITE);
if (wbout1.fh==-1)
{
fatal (EXIT_FILE_CREATION_FAILED, "Failed (errno=%d)\n",errno);
fatal(CCX_COMMON_EXIT_FILE_CREATION_FAILED, "Failed (errno=%d)\n", errno);
}
}
switch (ccx_options.write_format)
{
case CCX_OF_RAW:
writeraw (BROADCAST_HEADER,sizeof (BROADCAST_HEADER),&wbout1);
break;
case CCX_OF_DVDRAW:
break;
case CCX_OF_RCWT:
if( init_encoder(enc_ctx,&wbout1) )
fatal (EXIT_NOT_ENOUGH_MEMORY, "Not enough memory\n");
break;
default:
if (ccx_options.encoding==CCX_ENC_UTF_8) // Write BOM
writeraw (UTF8_BOM, sizeof (UTF8_BOM), &wbout1);
if (ccx_options.encoding==CCX_ENC_UNICODE) // Write BOM
writeraw (LITTLE_ENDIAN_BOM, sizeof (LITTLE_ENDIAN_BOM), &wbout1);
if( init_encoder(enc_ctx,&wbout1) )
fatal (EXIT_NOT_ENOUGH_MEMORY, "Not enough memory\n");
case CCX_OF_RAW:
writeraw(BROADCAST_HEADER, sizeof(BROADCAST_HEADER), &wbout1);
break;
case CCX_OF_DVDRAW:
break;
case CCX_OF_RCWT:
if (init_encoder(enc_ctx, &wbout1))
fatal(EXIT_NOT_ENOUGH_MEMORY, "Not enough memory\n");
break;
default:
if (!ccx_options.no_bom){
if (ccx_options.encoding == CCX_ENC_UTF_8){ // Write BOM
writeraw(UTF8_BOM, sizeof(UTF8_BOM), &wbout1);
}
if (ccx_options.encoding == CCX_ENC_UNICODE){ // Write BOM
writeraw(LITTLE_ENDIAN_BOM, sizeof(LITTLE_ENDIAN_BOM), &wbout1);
}
}
if (init_encoder(enc_ctx, &wbout1)){
fatal(EXIT_NOT_ENOUGH_MEMORY, "Not enough memory\n");
}
}
}
if (ccx_options.extract == 12 && ccx_options.write_format != CCX_OF_RAW)
@@ -524,7 +503,7 @@ int main(int argc, char *argv[])
{
memcpy(&wbout2, &wbout1,sizeof(wbout1));
}
else
else if (!ccx_options.send_to_srv)
{
if (wbout2.filename[0]==0)
{
@@ -537,7 +516,7 @@ int main(int argc, char *argv[])
wbout2.fh=open (wbout2.filename, O_RDWR | O_CREAT | O_TRUNC | O_BINARY, S_IREAD | S_IWRITE);
if (wbout2.fh==-1)
{
fatal (EXIT_FILE_CREATION_FAILED, "Failed\n");
fatal(CCX_COMMON_EXIT_FILE_CREATION_FAILED, "Failed\n");
}
if(ccx_options.write_format == CCX_OF_RAW)
writeraw (BROADCAST_HEADER,sizeof (BROADCAST_HEADER),&wbout2);
@@ -553,12 +532,17 @@ int main(int argc, char *argv[])
fatal (EXIT_NOT_ENOUGH_MEMORY, "Not enough memory\n");
break;
default:
if (ccx_options.encoding==CCX_ENC_UTF_8) // Write BOM
writeraw (UTF8_BOM, sizeof (UTF8_BOM), &wbout2);
if (ccx_options.encoding==CCX_ENC_UNICODE) // Write BOM
writeraw (LITTLE_ENDIAN_BOM, sizeof (LITTLE_ENDIAN_BOM), &wbout2);
if( init_encoder(enc_ctx+1,&wbout2) )
fatal (EXIT_NOT_ENOUGH_MEMORY, "Not enough memory\n");
if (!ccx_options.no_bom){
if (ccx_options.encoding == CCX_ENC_UTF_8){ // Write BOM
writeraw(UTF8_BOM, sizeof(UTF8_BOM), &wbout2);
}
if (ccx_options.encoding == CCX_ENC_UNICODE){ // Write BOM
writeraw(LITTLE_ENDIAN_BOM, sizeof(LITTLE_ENDIAN_BOM), &wbout2);
}
}
if (init_encoder(enc_ctx + 1, &wbout2)){
fatal(EXIT_NOT_ENOUGH_MEMORY, "Not enough memory\n");
}
}
}
}
@@ -581,22 +565,25 @@ int main(int argc, char *argv[])
{
if ((fh_out_elementarystream = fopen (ccx_options.out_elementarystream_filename,"wb"))==NULL)
{
fatal (EXIT_FILE_CREATION_FAILED, "Unable to open clean file: %s\n",ccx_options.out_elementarystream_filename);
fatal(CCX_COMMON_EXIT_FILE_CREATION_FAILED, "Unable to open clean file: %s\n", ccx_options.out_elementarystream_filename);
}
}
if (ccx_options.line_terminator_lf)
encoded_crlf_length = encode_line (encoded_crlf,(unsigned char *) "\n");
else
encoded_crlf_length = encode_line (encoded_crlf,(unsigned char *) "\r\n");
encoded_br_length = encode_line (encoded_br, (unsigned char *) "<br>");
}
build_parity_table();
// Initialize HDTV caption buffer
init_hdcc();
init_708(); // Init 708 decoders
// Initialize libraries
init_libraries();
if (ccx_options.line_terminator_lf)
encoded_crlf_length = encode_line(encoded_crlf, (unsigned char *) "\n");
else
encoded_crlf_length = encode_line(encoded_crlf, (unsigned char *) "\r\n");
encoded_br_length = encode_line(encoded_br, (unsigned char *) "<br>");
time_t start, final;
time(&start);
@@ -609,9 +596,61 @@ int main(int argc, char *argv[])
fatal (EXIT_UNABLE_TO_DETERMINE_FILE_SIZE, "Failed to determine total file size.\n");
}
#ifndef _WIN32
m_signal(SIGINT, sigint_handler);
#endif
while (switch_to_next_file(0) && !processed_enough)
{
prepare_for_new_file();
#ifdef ENABLE_FFMPEG
close_input_file();
ffmpeg_ctx = init_ffmpeg(inputfile[0]);
if(ffmpeg_ctx)
{
int i =0;
buffer = malloc(1024);
if(!buffer)
{
mprint("no memory left\n");
break;
}
do
{
int ret = 0;
char *bptr = buffer;
memset(bptr,0,1024);
int len = ff_get_ccframe(ffmpeg_ctx, bptr, 1024);
if(len == AVERROR(EAGAIN))
{
continue;
}
else if(len == AVERROR_EOF)
break;
else if(len == 0)
continue;
else if(len < 0 )
{
mprint("Error extracting Frame\n");
break;
}
store_hdcc(bptr,len, i++,fts_now,&dec_sub);
if(dec_sub.got_output)
{
encode_sub(enc_ctx, &dec_sub);
dec_sub.got_output = 0;
}
}while(1);
free(buffer);
continue;
}
else
{
mprint ("\rFailed to initialized ffmpeg falling back to legacy\n");
}
#endif
if (auto_stream == CCX_SM_AUTODETECT)
{
@@ -649,7 +688,7 @@ int main(int argc, char *argv[])
#endif
case CCX_SM_MYTH:
case CCX_SM_AUTODETECT:
fatal(EXIT_BUG_BUG, "Cannot be reached!");
fatal(CCX_COMMON_EXIT_BUG_BUG, "Cannot be reached!");
break;
}
}
@@ -690,12 +729,31 @@ int main(int argc, char *argv[])
}
break;
}
// Disable sync check for raw formats - they have the right timeline.
// Also true for bin formats, but -nosync might have created a
// broken timeline for debug purposes.
// Disable too in MP4, specs doesn't say that there can't be a jump
switch (stream_mode)
{
case CCX_SM_MCPOODLESRAW:
case CCX_SM_RCWT:
case CCX_SM_MP4:
#ifdef WTV_DEBUG
case CCX_SM_HEX_DUMP:
#endif
ccx_common_timing_settings.disable_sync_check = 1;
break;
default:
break;
}
switch (stream_mode)
{
case CCX_SM_ELEMENTARY_OR_NOT_FOUND:
if (!ccx_options.use_gop_as_pts) // If !0 then the user selected something
ccx_options.use_gop_as_pts = 1; // Force GOP timing for ES
ccx_common_timing_settings.is_elementary_stream = 1;
case CCX_SM_TRANSPORT:
case CCX_SM_PROGRAM:
case CCX_SM_ASF:
@@ -730,31 +788,31 @@ int main(int argc, char *argv[])
break;
#endif
case CCX_SM_AUTODETECT:
fatal(EXIT_BUG_BUG, "Cannot be reached!");
fatal(CCX_COMMON_EXIT_BUG_BUG, "Cannot be reached!");
break;
}
mprint("\n");
dbg_print(CCX_DMT_608, "\nTime stamps after last caption block was written:\n");
dbg_print(CCX_DMT_608, "Last time stamps: PTS: %s (%+2dF) ",
dbg_print(CCX_DMT_DECODER_608, "\nTime stamps after last caption block was written:\n");
dbg_print(CCX_DMT_DECODER_608, "Last time stamps: PTS: %s (%+2dF) ",
print_mstime( (LLONG) (sync_pts/(MPEG_CLOCK_FREQ/1000)
+frames_since_ref_time*1000.0/current_fps) ),
frames_since_ref_time);
dbg_print(CCX_DMT_608, "GOP: %s \n", print_mstime(gop_time.ms) );
dbg_print(CCX_DMT_DECODER_608, "GOP: %s \n", print_mstime(gop_time.ms) );
// Blocks since last PTS/GOP time stamp.
dbg_print(CCX_DMT_608, "Calc. difference: PTS: %s (%+3lldms incl.) ",
dbg_print(CCX_DMT_DECODER_608, "Calc. difference: PTS: %s (%+3lldms incl.) ",
print_mstime( (LLONG) ((sync_pts-min_pts)/(MPEG_CLOCK_FREQ/1000)
+ fts_offset + frames_since_ref_time*1000.0/current_fps)),
fts_offset + (LLONG) (frames_since_ref_time*1000.0/current_fps) );
dbg_print(CCX_DMT_608, "GOP: %s (%+3dms incl.)\n",
dbg_print(CCX_DMT_DECODER_608, "GOP: %s (%+3dms incl.)\n",
print_mstime((LLONG)(gop_time.ms
-first_gop_time.ms
+get_fts_max()-fts_at_gop_start)),
(int)(get_fts_max()-fts_at_gop_start));
// When padding is active the CC block time should be within
// 1000/29.97 us of the differences.
dbg_print(CCX_DMT_608, "Max. FTS: %s (without caption blocks since then)\n",
dbg_print(CCX_DMT_DECODER_608, "Max. FTS: %s (without caption blocks since then)\n",
print_mstime(get_fts_max()));
if (stat_hdtv)
@@ -928,3 +986,48 @@ int main(int argc, char *argv[])
}
return EXIT_OK;
}
void init_libraries(){
// Set logging functions for libraries
ccx_common_logging.debug_ftn = &dbg_print;
ccx_common_logging.debug_mask = ccx_options.debug_mask;
ccx_common_logging.fatal_ftn = &fatal;
ccx_common_logging.log_ftn = &mprint;
ccx_common_logging.gui_ftn = &activity_library_process;
// Init shared decoder settings
ccx_decoders_common_settings_init(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);
// Prepare 608 context
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,
&processed_enough,
&cc_to_stdout
);
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,
&processed_enough,
&cc_to_stdout
);
// Init 708 decoder(s)
ccx_decoders_708_init_library(basefilename,extension,ccx_options.print_file_reports);
// Set output structures for the 608 decoder
context_cc608_field_1.out = &wbout1;
context_cc608_field_2.out = &wbout2;
// Init XDS buffers
ccx_decoders_xds_init_library(&ccx_options.transcript_settings, subs_delay, ccx_options.millis_separator);
//xds_cea608_test();
}

View File

@@ -1,31 +1,28 @@
#ifndef CCX_CCEXTRACTOR_H
#define CCX_CCEXTRACTOR_H
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <time.h>
#include <fcntl.h>
#include <stdarg.h>
#include <errno.h>
#define VERSION "0.74"
// compatibility across platforms
#include "platform.h"
// Load common includes and constants for library usage
#include "ccx_common_platform.h"
#include "ccx_common_constants.h"
#include "ccx_common_common.h"
#include "ccx_common_char_encoding.h"
#include "ccx_common_structs.h"
#include "ccx_common_timing.h"
#define VERSION "0.70"
#include "ccx_encoders_common.h"
#include "ccx_decoders_608.h"
#include "ccx_decoders_xds.h"
#include "ccx_decoders_708.h"
#include "bitstream.h"
#include "networking.h"
extern int cc_buffer_saved; // Do we have anything in the CC buffer already?
extern int ccblocks_in_avc_total; // Total CC blocks found by the AVC code
extern int ccblocks_in_avc_lost; // CC blocks found by the AVC code lost due to overwrites (should be 0)
#include "608.h"
#include "708.h"
#include "bitstream.h"
#include "constants.h"
#include "cc_decoders_common.h"
#include "networking.h"
#define TS_PMT_MAP_SIZE 128
struct ccx_boundary_time
@@ -35,30 +32,20 @@ struct ccx_boundary_time
int set;
};
typedef struct {
// TODO: add more options, and (perhaps) reduce other ccextractor options?
int showStartTime, showEndTime; // Show start and/or end time.
int showMode; // Show which mode if available (E.G.: POP, RU1, ...)
int showCC; // Show which CC channel has been captured.
int relativeTimestamp; // Timestamps relative to start of sample or in UTC?
int xds; // Show XDS or not
int useColors; // Add colors or no colors
} ccx_transcript_format;
extern ccx_transcript_format ccx_default_transcript_settings;
struct ccx_s_options // Options from user parameters
{
int extract; // Extract 1st, 2nd or both fields
int cc_channel; // Channel we want to dump in srt mode
int buffer_input;
int direct_rollup;
int buffer_input;
int nofontcolor;
int notypesetting;
struct ccx_boundary_time extraction_start, extraction_end; // Segment we actually process
int print_file_reports;
int no_bom; // Set to 1 when no BOM (Byte Order Mark) should be used for files. Note, this might make files unreadable in windows!
ccx_decoder_608_settings settings_608; // Contains the settings for the 608 decoder.
/* subtitle codec type */
enum cxx_code_type codec;
enum cxx_code_type nocodec;
@@ -71,8 +58,6 @@ struct ccx_s_options // Options from user parameters
int binary_concat; // Disabled by -ve or --videoedited
int use_gop_as_pts; // Use GOP instead of PTS timing (0=do as needed, 1=always, -1=never)
int fix_padding; // Replace 0000 with 8080 in HDTV (needed for some cards)
int norollup; // If 1, write one line at a time
int forced_ru; // 0=Disabled, 1, 2 or 3=max lines in roll-up mode
int trim_subs; // " Remove spaces at sides? "
int gui_mode_reports; // If 1, output in stderr progress updates so the GUI can grab them
int no_progress_bar; // If 1, suppress the output of the progress to stdout
@@ -97,13 +82,11 @@ struct ccx_s_options // Options from user parameters
int usepicorder; // Force the use of pic_order_cnt_lsb in AVC/H.264 data streams
int autodash; // Add dashes (-) before each speaker automatically?
unsigned teletext_mode; // 0=Disabled, 1 = Not found, 2=Found
ccx_transcript_format transcript_settings; // Keeps the settings for generating transcript output files.
ccx_encoders_transcript_format transcript_settings; // Keeps the settings for generating transcript output files.
char millis_separator;
LLONG screens_to_process; // How many screenfuls we want?
enum ccx_encoding_type encoding;
enum ccx_output_format write_format; // 0=Raw, 1=srt, 2=SMI
enum ccx_output_date_format date_format;
enum color_code cc608_default_color;
char *output_filename;
char *out_elementarystream_filename;
LLONG debug_mask; // dbg_print will use this mask to print or ignore different types
@@ -121,12 +104,12 @@ struct ccx_s_options // Options from user parameters
unsigned send_to_srv;
char *tcpport;
char *tcp_password;
char *tcp_desc;
char *srv_addr;
char *srv_port;
int line_terminator_lf; // 0 = CRLF, 1=LF
int noautotimeref; // Do NOT set time automatically?
enum ccx_datasource input_source; // Files, stdin or network
enum ccx_datasource input_source; // Files, stdin or network
};
struct ts_payload
@@ -159,28 +142,6 @@ struct PMT_entry
unsigned printable_stream_type;
};
struct ccx_s_write
{
int fh;
char *filename;
void* spupng_data;
};
struct gop_time_code
{
int drop_frame_flag;
int time_code_hours;
int time_code_minutes;
int marker_bit;
int time_code_seconds;
int time_code_pictures;
int inited;
LLONG ms;
};
/* Report information */
#define SUB_STREAMS_CNT 10
struct file_report_t
@@ -190,15 +151,13 @@ struct file_report_t
unsigned height;
unsigned aspect_ratio;
unsigned frame_rate;
unsigned xds : 1;
unsigned cc_channels_608[4];
unsigned services708[63];
struct ccx_decoder_608_report_t *data_from_608;
struct ccx_decoder_708_report_t *data_from_708;
unsigned dvb_sub_pid[SUB_STREAMS_CNT];
unsigned tlt_sub_pid[SUB_STREAMS_CNT];
unsigned mp4_cc_track_cnt;
} file_report;
// Stuff for telcc.c
struct ccx_s_teletext_config {
uint8_t verbose : 1; // should telxcc be verbose?
@@ -208,7 +167,7 @@ struct ccx_s_teletext_config {
uint8_t bom : 1; // print UTF-8 BOM characters at the beginning of output
uint8_t nonempty : 1; // produce at least one (dummy) frame
// uint8_t se_mode : 1; // search engine compatible mode => Uses CCExtractor's write_format
// uint64_t utc_refvalue; // UTC referential value => Moved to CCExtractor global, so can be used for 608 too
// 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
};
@@ -240,6 +199,9 @@ struct ccx_s_teletext_config {
extern LLONG buffered_read_opt (unsigned char *buffer, unsigned int bytes);
// ccextractor.c
void init_libraries();
//params.c
void parse_parameters (int argc, char *argv[]);
void usage (void);
@@ -257,11 +219,6 @@ void general_loop(void *enc_ctx);
void processhex (char *filename);
void rcwt_loop(void *enc_ctx);
#ifndef __cplusplus
#define false 0
#define true 1
#endif
// activity.c
void activity_header (void);
void activity_progress (int percentaje, int cur_min, int cur_sec);
@@ -272,10 +229,7 @@ void activity_message (const char *fmt, ...);
void activity_video_info (int hor_size,int vert_size,
const char *aspect_ratio, const char *framerate);
void activity_program_number (unsigned program_number);
void activity_xds_program_name (const char *program_name);
void activity_xds_network_call_letters (const char *program_name);
void activity_xds_program_identification_number (unsigned minutes, unsigned hours, unsigned date, unsigned month);
void activity_xds_program_description (int line_num, const char *program_desc);
void activity_library_process(enum ccx_common_logging_gui message_type, ...);
void activity_report_data_read (void);
extern LLONG result;
@@ -303,15 +257,6 @@ int user_data(struct bitstream *ustream, int udtype, struct cc_subtitle *sub);
// bitstream.c - see bitstream.h
// 608.c
int write_cc_buffer(struct s_context_cc608 *context, struct cc_subtitle *sub);
unsigned char *debug_608toASC (unsigned char *ccdata, int channel);
// cc_decoders_common.c
LLONG get_visible_start (void);
LLONG get_visible_end (void);
// file_functions.c
LLONG getfilesize (int in);
LLONG gettotalfilessize (void);
@@ -320,16 +265,6 @@ void close_input_file (void);
int switch_to_next_file (LLONG bytesinbuffer);
void return_to_buffer (unsigned char *buffer, unsigned int bytes);
// timing.c
void set_fts(void);
LLONG get_fts(void);
LLONG get_fts_max(void);
char *print_mstime( LLONG mstime );
char *print_mstime2buf( LLONG mstime , char *buf );
void print_debug_timing( void );
int gop_accepted(struct gop_time_code* g );
void calculate_ms_gop_time (struct gop_time_code *g);
// sequencing.c
void init_hdcc (void);
void store_hdcc(unsigned char *cc_data, int cc_count, int sequence_number, LLONG current_fts, struct cc_subtitle *sub);
@@ -346,7 +281,7 @@ void print_file_report(void);
// output.c
void init_write (struct ccx_s_write *wb);
void writeraw (const unsigned char *data, int length, struct ccx_s_write *wb);
void writedata(const unsigned char *data, int length, struct s_context_cc608 *context, struct cc_subtitle *sub);
void writedata(const unsigned char *data, int length, ccx_decoder_608_context *context, struct cc_subtitle *sub);
void flushbuffer (struct ccx_s_write *wb, int closefile);
void printdata (const unsigned char *data1, int length1,const unsigned char *data2, int length2, struct cc_subtitle *sub);
void writercwtdata (const unsigned char *data);
@@ -369,17 +304,11 @@ int parse_PAT (void);
// myth.c
void myth_loop(void *enc_ctx);
// xds.c
void process_xds_bytes (const unsigned char hi, int lo);
void do_end_of_xds (struct cc_subtitle *sub, unsigned char expected_checksum);
void xds_init();
// utility.c
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 fdprintf (int fd, 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);
@@ -388,8 +317,11 @@ int hex2int (char high, char low);
void timestamp_to_srttime(uint64_t timestamp, char *buffer);
void millis_to_date (uint64_t timestamp, char *buffer) ;
int levenshtein_dist (const uint64_t *s1, const uint64_t *s2, unsigned s1len, unsigned s2len);
#ifndef _WIN32
void m_signal(int sig, void (*func)(int));
#endif
void init_context_cc608(struct s_context_cc608 *data, int field);
unsigned encode_line (unsigned char *buffer, unsigned char *text);
void buffered_seek (int offset);
extern void build_parity_table(void);
@@ -397,22 +329,14 @@ extern void build_parity_table(void);
void tlt_process_pes_packet(uint8_t *buffer, uint16_t size) ;
void telxcc_init(void);
void telxcc_close(void);
void tlt_read_rcwt();
void mstotime(LLONG milli, unsigned *hours, unsigned *minutes,
unsigned *seconds, unsigned *ms);
extern struct gop_time_code gop_time, first_gop_time, printed_gop;
extern int gop_rollover;
extern LLONG min_pts, sync_pts, current_pts;
extern unsigned rollover_bits;
extern uint32_t global_timestamp, min_global_timestamp;
extern int global_timestamp_inited;
extern LLONG fts_now; // Time stamp of current file (w/ fts_offset, w/o fts_global)
extern LLONG fts_offset; // Time before first sync_pts
extern LLONG fts_fc_offset; // Time before first GOP
extern LLONG fts_max; // Remember the maximum fts that we saw in current file
extern LLONG fts_global; // Duration of previous files (-ve mode)
// Count 608 (per field) and 708 blocks since last set_fts() call
extern int cb_field1, cb_field2, cb_708;
extern int saw_caption_block;
@@ -432,24 +356,16 @@ extern unsigned int startbytes_pos;
extern int startbytes_avail; // Needs to be able to hold -1 result.
extern unsigned char *pesheaderbuf;
extern int pts_set; //0 = No, 1 = received, 2 = min_pts set
extern unsigned long long max_dif;
extern int MPEG_CLOCK_FREQ; // This is part of the standard
extern unsigned pts_big_change;
extern unsigned total_frames_count;
extern unsigned total_pulldownfields;
extern unsigned total_pulldownframes;
extern int CaptionGap;
extern unsigned char *filebuffer;
extern LLONG filebuffer_start; // Position of buffer start relative to file
extern int filebuffer_pos; // Position of pointer relative to buffer start
extern int bytesinbuffer; // Number of bytes we actually have on buffer
extern struct s_context_cc608 context_cc608_field_1, context_cc608_field_2;
extern ccx_decoder_608_context context_cc608_field_1, context_cc608_field_2;
extern const char *desc[256];
@@ -473,7 +389,6 @@ extern LLONG subs_delay;
extern int startcredits_displayed, end_credits_displayed;
extern LLONG last_displayed_subs_ms;
extern int processed_enough;
extern unsigned char usercolor_rgb[8];
extern const char *extension;
extern long FILEBUFFERSIZE; // Uppercase because it used to be a define
@@ -486,7 +401,6 @@ extern unsigned current_hor_size;
extern unsigned current_vert_size;
extern unsigned current_aspect_ratio;
extern unsigned current_frame_rate;
extern double current_fps;
extern int end_of_file;
extern LLONG inbuf;
@@ -495,14 +409,12 @@ extern enum ccx_bufferdata_type bufferdatatype; // Can be CCX_BUFFERDATA_TYPE_RA
extern unsigned top_field_first;
extern int firstcall;
extern LLONG minimum_fts; // No screen should start before this FTS
#define MAXBFRAMES 50
#define SORTBUF (2*MAXBFRAMES+1)
extern int cc_data_count[SORTBUF];
extern unsigned char cc_data_pkts[SORTBUF][10*31*3+1];
extern int has_ccdata_buffered;
extern int current_field;
extern int last_reported_progress;
extern int cc_to_stdout;
@@ -513,29 +425,11 @@ extern int saw_gop_header;
extern int max_gop_length;
extern int last_gop_length;
extern int frames_since_last_gop;
extern LLONG fts_at_gop_start;
extern int frames_since_ref_time;
extern enum ccx_stream_mode_enum auto_stream;
extern int num_input_files;
extern char *basefilename;
extern int do_cea708; // Process 708 data?
extern int cea708services[63]; // [] -> 1 for services to be processed
extern struct ccx_s_write wbout1, wbout2, *wbxdsout;
extern char **spell_lower;
extern char **spell_correct;
extern int spell_words;
extern int spell_capacity;
extern unsigned char encoded_crlf[16]; // We keep it encoded here so we don't have to do it many times
extern unsigned int encoded_crlf_length;
extern unsigned char encoded_br[16];
extern unsigned int encoded_br_length;
extern enum ccx_frame_type current_picture_coding_type;
extern int current_tref; // Store temporal reference of current frame
extern int cc608_parity_table[256]; // From myth
// From ts_functions
@@ -558,28 +452,24 @@ extern long capbuflen;
<100 means display whatever was output to stderr as a warning
>=100 means display whatever was output to stdout as an error
*/
// Some moved to ccx_common_common.h
#define EXIT_OK 0
#define EXIT_NO_INPUT_FILES 2
#define EXIT_TOO_MANY_INPUT_FILES 3
#define EXIT_INCOMPATIBLE_PARAMETERS 4
#define EXIT_FILE_CREATION_FAILED 5
#define EXIT_UNABLE_TO_DETERMINE_FILE_SIZE 6
#define EXIT_MALFORMED_PARAMETER 7
#define EXIT_READ_ERROR 8
#define EXIT_UNSUPPORTED 9
#define EXIT_NOT_CLASSIFIED 300
#define EXIT_NOT_ENOUGH_MEMORY 500
#define EXIT_ERROR_IN_CAPITALIZATION_FILE 501
#define EXIT_BUFFER_FULL 502
#define EXIT_BUG_BUG 1000
#define EXIT_MISSING_ASF_HEADER 1001
#define EXIT_MISSING_RCWT_HEADER 1002
extern int PIDs_seen[65536];
extern struct PMT_entry *PIDs_programs[65536];
extern LLONG ts_start_of_xds;
// extern LLONG ts_start_of_xds; // Moved to 608.h, only referenced in 608.c & xds.c
//extern int timestamps_on_transcript;
extern unsigned teletext_mode;
@@ -587,7 +477,6 @@ extern unsigned teletext_mode;
#define MAX_TLT_PAGES 1000
extern short int seen_sub_page[MAX_TLT_PAGES];
extern uint64_t utc_refvalue; // UTC referential value
extern struct ccx_s_teletext_config tlt_config;
extern uint32_t tlt_packet_counter;
extern uint32_t tlt_frames_produced;

View File

@@ -0,0 +1,10 @@
#ifndef __CCX_COMMON_CHAR_ENCODING__
#define __CCX_COMMON_CHAR_ENCODING__
void get_char_in_latin_1(unsigned char *buffer, unsigned char c);
void get_char_in_unicode(unsigned char *buffer, unsigned char c);
int get_char_in_utf_8(unsigned char *buffer, unsigned char c);
unsigned char cctolower(unsigned char c);
unsigned char cctoupper(unsigned char c);
#endif

65
src/ccx_common_common.c Normal file
View File

@@ -0,0 +1,65 @@
#include "ccx_common_common.h"
/* printf() for fd instead of FILE*, since dprintf is not portable */
void fdprintf(int fd, const char *fmt, ...)
{
/* Guess we need no more than 100 bytes. */
int n, size = 100;
char *p, *np;
va_list ap;
if (fd < 0)
return;
if ((p = (char *)malloc(size)) == NULL)
return;
while (1)
{
/* Try to print in the allocated space. */
va_start(ap, fmt);
n = vsnprintf(p, size, fmt, ap);
va_end(ap);
/* If that worked, return the string. */
if (n > -1 && n < size)
{
write(fd, p, n);
free(p);
return;
}
/* Else try again with more space. */
if (n > -1) /* glibc 2.1 */
size = n + 1; /* precisely what is needed */
else /* glibc 2.0 */
size *= 2; /* twice the old size */
if ((np = (char *)realloc(p, size)) == NULL)
{
free(p);
return;
}
else {
p = np;
}
}
}
/* Converts the given milli to separate hours,minutes,seconds and ms variables */
void mstotime(LLONG milli, unsigned *hours, unsigned *minutes,
unsigned *seconds, unsigned *ms)
{
// LLONG milli = (LLONG) ((ccblock*1000)/29.97);
*ms = (unsigned)(milli % 1000); // milliseconds
milli = (milli - *ms) / 1000; // Remainder, in seconds
*seconds = (int)(milli % 60);
milli = (milli - *seconds) / 60; // Remainder, in minutes
*minutes = (int)(milli % 60);
milli = (milli - *minutes) / 60; // Remainder, in hours
*hours = (int)milli;
}
/* Frees the given pointer */
void freep(void *arg)
{
void **ptr = (void **)arg;
if (*ptr)
free(*ptr);
*ptr = NULL;
}

17
src/ccx_common_common.h Normal file
View File

@@ -0,0 +1,17 @@
#ifndef _CC_COMMON_COMMON
#define _CC_COMMON_COMMON
#include "ccx_common_platform.h"
// Define possible exit codes that will be passed on to the fatal function
#define CCX_COMMON_EXIT_FILE_CREATION_FAILED 5
#define CCX_COMMON_EXIT_UNSUPPORTED 9
#define EXIT_NOT_ENOUGH_MEMORY 500
#define CCX_COMMON_EXIT_BUG_BUG 1000
// Declarations
void fdprintf(int fd, const char *fmt, ...);
void mstotime(LLONG milli, unsigned *hours, unsigned *minutes,unsigned *seconds, unsigned *ms);
void freep(void *arg);
#endif

View File

@@ -1,4 +1,4 @@
#include "ccextractor.h"
#include "ccx_common_constants.h"
// RCWT header (11 bytes):
//byte(s) value description (All values below are hex numbers, not
@@ -8,7 +8,7 @@
//4-5 0050 Program version number
//6-7 0001 File format version
//8-10 000000 Padding, required :-)
const unsigned char rcwt_header[11]={0xCC, 0xCC, 0xED, 0xCC, 0x00, 0x50, 0, 1, 0, 0, 0};
unsigned char rcwt_header[11]={0xCC, 0xCC, 0xED, 0xCC, 0x00, 0x50, 0, 1, 0, 0, 0};
const unsigned char BROADCAST_HEADER[]={0xff, 0xff, 0xff, 0xff};
const unsigned char LITTLE_ENDIAN_BOM[]={0xff, 0xfe};

View File

@@ -1,6 +1,13 @@
#ifndef CCX_CONSTANTS_H
#define CCX_CONSTANTS_H
#include "stdio.h"
#ifndef __cplusplus
#define false 0
#define true 1
#endif
extern const char *framerates_types[16];
extern const double framerates_values[16];
@@ -20,7 +27,7 @@ extern const unsigned char lc4[2];
extern const unsigned char lc5[1];
extern const unsigned char lc6[1];
extern const unsigned char rcwt_header[11];
extern unsigned char rcwt_header[11];
#define ONEPASS 120 /* Bytes we can always look ahead without going out of limits */
#define BUFSIZE (2048*1024+ONEPASS) /* 2 Mb plus the safety pass */
@@ -40,9 +47,9 @@ enum ccx_debug_message_types
CCX_DMT_VIDES=2,// Show video stream related information
CCX_DMT_TIME=4, // Show GOP and PTS timing information
CCX_DMT_VERBOSE=8, // Show lots of debugging output
CCX_DMT_608=0x10, // Show CC-608 decoder debug?
CCX_DMT_DECODER_608=0x10, // Show CC-608 decoder debug?
CCX_DMT_708=0x20, // Show CC-708 decoder debug?
CCX_DMT_XDS=0x40, // Show XDS decoder debug?
CCX_DMT_DECODER_XDS=0x40, // Show XDS decoder debug?
CCX_DMT_CBRAW=0x80, // Caption blocks with FTS timing
CCX_DMT_GENERIC_NOTICES=0x100, // Generic, always displayed even if no debug is selected
CCX_DMT_TELETEXT=0x200, // Show teletext debug?
@@ -258,11 +265,5 @@ enum cxx_code_type
#define CCX_TXT_AUTO_NOT_YET_FOUND 1
#define CCX_TXT_IN_USE 2 // Positive autodetected, or forced, etc
enum subtype
{
CC_BITMAP,
CC_608,
CC_TEXT,
};
extern const char *language[4];
#endif

113
src/ccx_common_platform.h Normal file
View File

@@ -0,0 +1,113 @@
#ifndef CCX_PLATFORM_H
#define CCX_PLATFORM_H
// Default includes (cross-platform)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <time.h>
#include <fcntl.h>
#include <stdarg.h>
#include <errno.h>
#define __STDC_FORMAT_MACROS
#ifdef _WIN32
#include <io.h>
#include <ws2tcpip.h>
#include <windows.h>
#define STDIN_FILENO 0
#define STDOUT_FILENO 1
#define STDERR_FILENO 2
#include "inttypes.h"
#define UINT64_MAX _UI64_MAX
typedef int socklen_t;
typedef int ssize_t;
typedef uint32_t in_addr_t;
#ifndef IN_CLASSD
#define IN_CLASSD(i) (((INT32)(i) & 0xf0000000) == 0xe0000000)
#define IN_MULTICAST(i) IN_CLASSD(i)
#endif
#include <direct.h>
#define mkdir(path, mode) _mkdir(path)
#ifndef snprintf
// Added ifndef because VS2013 warns for macro redefinition.
#define snprintf(buf, len, fmt, ...) _snprintf(buf, len, fmt, __VA_ARGS__)
#endif
#define sleep(sec) Sleep((sec) * 1000)
#include <fcntl.h>
#else // _WIN32
#include <unistd.h>
#define __STDC_LIMIT_MACROS
#include <inttypes.h>
#include <stdint.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <sys/stat.h>
#include <sys/types.h>
#endif // _WIN32
#include "disable_warnings.h"
#ifdef _MSC_VER
#include "stdintmsc.h"
// Don't bug me with strcpy() deprecation warnings
#pragma warning(disable : 4996)
#else
#include <stdint.h>
#endif
#ifdef __OpenBSD__
#define FOPEN64 fopen
#define OPEN open
#define FSEEK fseek
#define FTELL ftell
#define LSEEK lseek
#define FSTAT fstat
#else
#ifdef _WIN32
#define OPEN _open
// 64 bit file functions
#if defined(MSC_VER)
extern "C" int __cdecl _fseeki64(FILE *, __int64, int);
extern "C" __int64 __cdecl _ftelli64(FILE *);
#define FSEEK _fseeki64
#define FTELL _ftelli64
#else
// For MinGW
#define FSEEK fseeko64
#define FTELL ftello64
#endif
#define TELL _telli64
#define LSEEK _lseeki64
typedef struct _stati64 FSTATSTRUCT;
#else
// Linux internally maps these functions to 64bit usage,
// if _FILE_OFFSET_BITS macro is set to 64
#define FOPEN64 fopen
#define OPEN open
#define LSEEK lseek
#define FSEEK fseek
#define FTELL ftell
#define FSTAT fstat
#define TELL tell
#include <stdint.h>
#endif
#endif
#ifndef int64_t_C
#define int64_t_C(c) (c ## LL)
#define uint64_t_C(c) (c ## ULL)
#endif
#ifndef O_BINARY
#define O_BINARY 0 // Not present in Linux because it's always binary
#endif
typedef int64_t LLONG;
#endif // CCX_PLATFORM_H

52
src/ccx_common_structs.h Normal file
View File

@@ -0,0 +1,52 @@
#ifndef _CC_COMMON_STRUCTS
#define _CC_COMMON_STRUCTS
enum ccx_common_logging_gui {
CCX_COMMON_LOGGING_GUI_XDS_PROGRAM_NAME, // Called with xds_program_name
CCX_COMMON_LOGGING_GUI_XDS_PROGRAM_ID_NR, // Called with current_xds_min, current_xds_hour, current_xds_date, current_xds_month
CCX_COMMON_LOGGING_GUI_XDS_PROGRAM_DESCRIPTION, // Called with line_num, xds_desc
CCX_COMMON_LOGGING_GUI_XDS_CALL_LETTERS // Called with current_xds_call_letters
};
struct ccx_common_logging_t {
int debug_mask; // The debug mask that is used to determine if things should be printed or not.
void(*fatal_ftn) (int exit_code, const char *fmt, ...); // Used when an unrecoverable error happens. This should log output/save the error and then exit the program.
void(*debug_ftn) (LLONG mask, const char *fmt, ...); // Used to process debug output. Mask can be ignored (custom set by debug_mask).
void(*log_ftn)(const char *fmt, ...); // Used to print things. Replacement of standard printf, to allow more control.
void(*gui_ftn)(enum ccx_common_logging_gui message_type, ...); // Used to display things in a gui (if appropriate). Is called with the message_type and appropriate variables (described in enum)
} ccx_common_logging;
enum subtype
{
CC_BITMAP,
CC_608,
CC_TEXT,
};
/**
* Raw Subtitle struct used as output of decoder (cc608)
* and input for encoder (sami, srt, transcript or smptett etc)
*/
struct cc_subtitle
{
/**
* A generic data which contain data according to decoder
* just now only struct cc_eia608_screen is placed here
* @warn decoder cant output multiple types of data
*/
void *data;
/** number of data */
unsigned int nb_data;
/** type of subtitle */
enum subtype type;
/* set only when all the data is to be displayed at same time */
LLONG start_time;
LLONG end_time;
/* flags */
int flags;
/* index of language table */
int lang_index;
/** flag to tell that decoder has given output */
int got_output;
};
#endif

View File

@@ -1,66 +1,86 @@
#include "ccextractor.h"
#include "ccx_common_timing.h"
#include "ccx_common_constants.h"
#include "ccx_common_structs.h"
#include "ccx_common_common.h"
/* Provide the current time since the file (or the first file) started
* in ms using PTS time information.
* Requires: frames_since_ref_time, current_tref
*/
// int ignore_fts=1; // Don't do any kind of timing stuff. Assume it's being done externally (as happens in MP4)
// Count 608 (per field) and 708 blocks since last set_fts() call
int cb_field1, cb_field2, cb_708;
int pts_set; //0 = No, 1 = received, 2 = min_pts set
int MPEG_CLOCK_FREQ = 90000; // This "constant" is part of the standard
LLONG min_pts, max_pts, sync_pts;
LLONG current_pts = 0;
int max_dif = 5;
unsigned pts_big_change;
// PTS timing related stuff
LLONG fts_now; // Time stamp of current file (w/ fts_offset, w/o fts_global)
LLONG fts_offset; // Time before first sync_pts
LLONG fts_fc_offset; // Time before first GOP
LLONG fts_max; // Remember the maximum fts that we saw in current file
LLONG fts_global = 0; // Duration of previous files (-ve mode), see c1global
enum ccx_frame_type current_picture_coding_type = CCX_FRAME_TYPE_RESET_OR_UNKNOWN;
int current_tref = 0; // Store temporal reference of current frame
double current_fps = (double) 30000.0 / 1001; /* 29.97 */ // TODO: Get from framerates_values[] instead
int frames_since_ref_time = 0;
unsigned total_frames_count;
// Remember the current field for 608 decoding
int current_field = 1; // 1 = field 1, 2 = field 2, 3 = 708
struct gop_time_code gop_time, first_gop_time, printed_gop;
LLONG fts_at_gop_start = 0;
int gop_rollover = 0;
void ccx_common_timing_init(LLONG *file_position,int no_sync){
ccx_common_timing_settings.disable_sync_check = 0;
ccx_common_timing_settings.is_elementary_stream = 0;
ccx_common_timing_settings.file_position = file_position;
ccx_common_timing_settings.no_sync = no_sync;
}
void set_fts(void)
{
int pts_jump = 0;
// ES don't have PTS unless GOP timing is used
if (!pts_set && stream_mode==CCX_SM_ELEMENTARY_OR_NOT_FOUND)
if (!pts_set && ccx_common_timing_settings.is_elementary_stream)
return;
// First check for timeline jump (only when min_pts was
// set (implies sync_pts).
// First check for timeline jump (only when min_pts was set (implies sync_pts)).
int dif = 0;
if (pts_set == 2)
{
dif=(int) (current_pts-sync_pts)/MPEG_CLOCK_FREQ;
// Used to distinguish gaps with missing caption information from
// jumps in the timeline. (Currently only used for dvr-ms/NTSC
// recordings)
if ( CaptionGap )
dif = 0;
if (ccx_common_timing_settings.disable_sync_check){
// Disables sync check. Used for several input formats.
dif = 0;
}
// Disable sync check for raw formats - they have the right timeline.
// Also true for bin formats, but -nosync might have created a
// broken timeline for debug purposes.
// Disable too in MP4, specs doesn't say that there can't be a jump
switch (stream_mode)
{
case CCX_SM_MCPOODLESRAW:
case CCX_SM_RCWT:
case CCX_SM_MP4:
#ifdef WTV_DEBUG
case CCX_SM_HEX_DUMP:
#endif
dif = 0;
break;
default:
break;
}
if (dif < -0.2 || dif >=max_dif )
if (dif < -0.2 || dif >= max_dif )
{
// ATSC specs: More than 3501 ms means missing component
mprint ("\nWarning: Reference clock has changed abruptly (%d seconds filepos=%lld), attempting to synchronize\n", (int) dif, past);
mprint ("Last sync PTS value: %lld\n",sync_pts);
mprint ("Current PTS value: %lld\n",current_pts);
ccx_common_logging.log_ftn ("\nWarning: Reference clock has changed abruptly (%d seconds filepos=%lld), attempting to synchronize\n", (int) dif, *ccx_common_timing_settings.file_position);
ccx_common_logging.log_ftn ("Last sync PTS value: %lld\n",sync_pts);
ccx_common_logging.log_ftn ("Current PTS value: %lld\n",current_pts);
pts_jump = 1;
pts_big_change=1;
// Discard the gap if it is not on an I-frame or temporal reference
// zero.
// Discard the gap if it is not on an I-frame or temporal reference zero.
if(current_tref != 0 && current_picture_coding_type != CCX_FRAME_TYPE_I_FRAME)
{
fts_now = fts_max;
mprint ("Change did not occur on first frame - probably a broken GOP\n");
ccx_common_logging.log_ftn ("Change did not occur on first frame - probably a broken GOP\n");
return;
}
}
@@ -103,15 +123,15 @@ void set_fts(void)
-frames_since_ref_time+1)
*1000.0/current_fps);
}
dbg_print(CCX_DMT_TIME, "\nFirst sync time PTS: %s %+lldms (time before this PTS)\n",
ccx_common_logging.debug_ftn(CCX_DMT_TIME, "\nFirst sync time PTS: %s %+lldms (time before this PTS)\n",
print_mstime(min_pts/(MPEG_CLOCK_FREQ/1000)),
fts_offset );
dbg_print(CCX_DMT_TIME, "Total_frames_count %u frames_since_ref_time %u\n",
ccx_common_logging.debug_ftn(CCX_DMT_TIME, "Total_frames_count %u frames_since_ref_time %u\n",
total_frames_count, frames_since_ref_time);
}
// -nosync diasbles syncing
if (pts_jump && !ccx_options.nosync)
// -nosync disables syncing
if (pts_jump && !ccx_common_timing_settings.no_sync)
{
// The current time in the old time base is calculated using
// sync_pts (set at the beginning of the last GOP) plus the
@@ -132,7 +152,7 @@ void set_fts(void)
// Set min_pts = sync_pts as this is used for fts_now
min_pts = sync_pts;
dbg_print(CCX_DMT_TIME, "\nNew min PTS time: %s %+lldms (time before this PTS)\n",
ccx_common_logging.debug_ftn(CCX_DMT_TIME, "\nNew min PTS time: %s %+lldms (time before this PTS)\n",
print_mstime(min_pts/(MPEG_CLOCK_FREQ/1000)),
fts_offset );
}
@@ -160,7 +180,7 @@ void set_fts(void)
else
{
// No PTS info at all!!
fatal(EXIT_BUG_BUG,
ccx_common_logging.fatal_ftn(CCX_COMMON_EXIT_BUG_BUG,
"No PTS info. Please write bug report.");
}
}
@@ -187,7 +207,7 @@ LLONG get_fts(void)
fts = fts_now + fts_global + cb_708*1001/30;
break;
default:
fatal(EXIT_BUG_BUG, "Cannot be reached!");
ccx_common_logging.fatal_ftn(CCX_COMMON_EXIT_BUG_BUG, "Cannot be reached!");
}
return fts;
@@ -235,9 +255,9 @@ void print_debug_timing( void )
// for uninitialized min_pts
LLONG tempmin_pts = (min_pts==0x01FFFFFFFFLL ? sync_pts : min_pts);
mprint("Sync time stamps: PTS: %s ",
ccx_common_logging.log_ftn("Sync time stamps: PTS: %s ",
print_mstime((sync_pts)/(MPEG_CLOCK_FREQ/1000)) );
mprint("GOP: %s \n", print_mstime(gop_time.ms));
ccx_common_logging.log_ftn("GOP: %s \n", print_mstime(gop_time.ms));
// Length first GOP to last GOP
LLONG goplenms = (LLONG) (gop_time.ms - first_gop_time.ms);
@@ -245,13 +265,13 @@ void print_debug_timing( void )
LLONG ptslenms = (unsigned)((sync_pts-tempmin_pts)/(MPEG_CLOCK_FREQ/1000)
+ fts_offset);
mprint("Last FTS: %s",
ccx_common_logging.log_ftn("Last FTS: %s",
print_mstime(get_fts_max()));
mprint(" GOP start FTS: %s\n",
ccx_common_logging.log_ftn(" GOP start FTS: %s\n",
print_mstime(fts_at_gop_start));
// Times are based on last GOP and/or sync time
mprint("Max FTS diff. to PTS: %6lldms GOP: %6lldms\n\n",
ccx_common_logging.log_ftn("Max FTS diff. to PTS: %6lldms GOP: %6lldms\n\n",
get_fts_max()+(LLONG)(1000.0/current_fps)-ptslenms,
get_fts_max()+(LLONG)(1000.0/current_fps)-goplenms);
}

64
src/ccx_common_timing.h Normal file
View File

@@ -0,0 +1,64 @@
#ifndef __Timing_H__
#include "ccx_common_platform.h"
struct gop_time_code
{
int drop_frame_flag;
int time_code_hours;
int time_code_minutes;
int marker_bit;
int time_code_seconds;
int time_code_pictures;
int inited;
LLONG ms;
};
struct ccx_common_timing_settings_t {
int disable_sync_check; // If 1, timeline jumps will be ignored. This is important in several input formats that are assumed to have correct timing, no matter what.
int no_sync; // If 1, there will be no sync at all. Mostly useful for debugging.
int is_elementary_stream; // Needs to be set, as it's used in set_fts.
LLONG *file_position; // The position of the file
} ccx_common_timing_settings;
// Count 608 (per field) and 708 blocks since last set_fts() call
extern int cb_field1, cb_field2, cb_708;
extern int pts_set; //0 = No, 1 = received, 2 = min_pts set
extern int MPEG_CLOCK_FREQ; // This is part of the standard
extern LLONG min_pts, max_pts, sync_pts, current_pts;
extern int max_dif;
extern unsigned pts_big_change;
extern LLONG fts_now; // Time stamp of current file (w/ fts_offset, w/o fts_global)
extern LLONG fts_offset; // Time before first sync_pts
extern LLONG fts_fc_offset; // Time before first GOP
extern LLONG fts_max; // Remember the maximum fts that we saw in current file
extern LLONG fts_global; // Duration of previous files (-ve mode)
extern enum ccx_frame_type current_picture_coding_type;
extern int current_tref; // Store temporal reference of current frame
extern double current_fps;
extern int frames_since_ref_time;
extern unsigned total_frames_count;
extern int current_field;
extern struct gop_time_code gop_time, first_gop_time, printed_gop;
extern LLONG fts_at_gop_start;
extern int gop_rollover;
void ccx_common_timing_init(LLONG *file_position, int no_sync);
void set_fts(void);
LLONG get_fts(void);
LLONG get_fts_max(void);
char *print_mstime(LLONG mstime);
char *print_mstime2buf(LLONG mstime, char *buf);
void print_debug_timing(void);
int gop_accepted(struct gop_time_code* g);
void calculate_ms_gop_time(struct gop_time_code *g);
#define __Timing_H__
#endif

View File

@@ -1,7 +1,10 @@
#include "ccextractor.h"
#include "608_spupng.h"
#include "cc_decoders_common.h"
#include "utility.h"
#include "ccx_decoders_608.h"
#include "ccx_common_common.h"
#include "ccx_common_structs.h"
#include "ccx_common_constants.h"
#include "ccx_common_timing.h"
#include "ccx_decoders_structs.h"
#include "ccx_decoders_xds.h"
static const int rowdata[] = {11,-1,1,2,3,4,12,13,14,15,5,6,7,8,9,10};
// Relationship between the first PAC byte and the row number
@@ -9,7 +12,6 @@ int in_xds_mode=0;
unsigned char str[2048]; // Another generic general purpose buffer
LLONG minimum_fts=0; // No screen should start before this FTS
const unsigned char pac2_attribs[][3] = // Color, font, ident
{
{ COL_WHITE, FONT_REGULAR, 0 }, // 0x40 || 0x60
@@ -45,19 +47,10 @@ const unsigned char pac2_attribs[][3] = // Color, font, ident
{ COL_WHITE, FONT_REGULAR, 28 }, // 0x5e || 0x7e
{ COL_WHITE, FONT_UNDERLINED, 28 } // 0x5f || 0x7f
};
// Preencoded strings
unsigned char encoded_crlf[16];
unsigned int encoded_crlf_length;
unsigned char encoded_br[16];
unsigned int encoded_br_length;
unsigned char *subline; // Temp storage for .srt lines
int new_sentence=1; // Capitalize next letter?
// Default color
unsigned char usercolor_rgb[8]="";
static const char *command_type[] =
{
"Unknown",
@@ -110,46 +103,60 @@ const char *color_text[][2]=
};
void clear_eia608_cc_buffer (struct eia608_screen *data)
void clear_eia608_cc_buffer(ccx_decoder_608_context *context, struct eia608_screen *data)
{
for (int i=0;i<15;i++)
{
memset(data->characters[i],' ',CC608_SCREEN_WIDTH);
data->characters[i][CC608_SCREEN_WIDTH]=0;
memset (data->colors[i],ccx_options.cc608_default_color,CC608_SCREEN_WIDTH+1);
memset (data->fonts[i],FONT_REGULAR,CC608_SCREEN_WIDTH+1);
memset(data->characters[i], ' ', CCX_DECODER_608_SCREEN_WIDTH);
data->characters[i][CCX_DECODER_608_SCREEN_WIDTH] = 0;
memset(data->colors[i], context->settings.default_color, CCX_DECODER_608_SCREEN_WIDTH + 1);
memset(data->fonts[i], FONT_REGULAR, CCX_DECODER_608_SCREEN_WIDTH + 1);
data->row_used[i]=0;
}
data->empty=1;
}
void init_context_cc608(struct s_context_cc608 *data, int field)
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)
{
data->cursor_column=0;
data->cursor_row=0;
clear_eia608_cc_buffer (&data->buffer1);
clear_eia608_cc_buffer (&data->buffer2);
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->color=ccx_options.cc608_default_color;
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->out = NULL;
data->have_cursor_position = 0;
ccx_decoder_608_context data;
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.trim_subs = trim_subs;
data.encoding = encoding;
data.halt = halt;
data.cc_to_stdout = cc_to_stdout;
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;
}
struct eia608_screen *get_writing_buffer(struct s_context_cc608 *context)
struct eia608_screen *get_writing_buffer(ccx_decoder_608_context *context)
{
struct eia608_screen *use_buffer=NULL;
switch (context->mode)
@@ -173,37 +180,37 @@ struct eia608_screen *get_writing_buffer(struct s_context_cc608 *context)
use_buffer = &context->buffer2;
break;
default:
fatal (EXIT_BUG_BUG, "Caption mode has an illegal value at get_writing_buffer(), this is a bug.\n");
ccx_common_logging.fatal_ftn(CCX_COMMON_EXIT_BUG_BUG, "Caption mode has an illegal value at get_writing_buffer(), this is a bug.\n");
}
return use_buffer;
}
void delete_to_end_of_row(struct s_context_cc608 *context)
void delete_to_end_of_row(ccx_decoder_608_context *context)
{
if (context->mode != MODE_TEXT)
{
struct eia608_screen * use_buffer = get_writing_buffer(context);
for (int i = context->cursor_column; i <= 31; i++)
struct eia608_screen *use_buffer = get_writing_buffer(context);
for (int i = context->cursor_column; i <= CCX_DECODER_608_SCREEN_WIDTH-1; i++)
{
// TODO: This can change the 'used' situation of a column, so we'd
// need to check and correct.
use_buffer->characters[context->cursor_row][i] = ' ';
use_buffer->colors[context->cursor_row][i] = ccx_options.cc608_default_color;
use_buffer->colors[context->cursor_row][i] = context->settings.default_color;
use_buffer->fonts[context->cursor_row][i] = context->font;
}
}
}
void write_char(const unsigned char c, struct s_context_cc608 *context)
void write_char(const unsigned char c, ccx_decoder_608_context *context)
{
if (context->mode != MODE_TEXT)
{
struct eia608_screen * use_buffer = get_writing_buffer(context);
struct eia608_screen *use_buffer = get_writing_buffer(context);
/* printf ("\rWriting char [%c] at %s:%d:%d\n",c,
use_buffer == &wb->data608->buffer1?"B1":"B2",
wb->data608->cursor_row,wb->data608->cursor_column); */
use_buffer->characters[context->cursor_row][context->cursor_column] = c;
use_buffer->colors[context->cursor_row][context->cursor_column] = context->color;
use_buffer->colors[context->cursor_row][context->cursor_column] = context->current_color;
use_buffer->fonts[context->cursor_row][context->cursor_column] = context->font;
use_buffer->row_used[context->cursor_row] = 1;
@@ -214,7 +221,7 @@ void write_char(const unsigned char c, struct s_context_cc608 *context)
}
use_buffer->empty=0;
if (context->cursor_column<31)
if (context->cursor_column<CCX_DECODER_608_SCREEN_WIDTH - 1)
context->cursor_column++;
if (context->ts_start_of_current_line == -1)
context->ts_start_of_current_line = get_fts();
@@ -223,25 +230,27 @@ void write_char(const unsigned char c, struct s_context_cc608 *context)
}
/* Handle MID-ROW CODES. */
void handle_text_attr(const unsigned char c1, const unsigned char c2, struct s_context_cc608 *context)
void handle_text_attr(const unsigned char c1, const unsigned char c2, ccx_decoder_608_context *context)
{
// Handle channel change
context->channel = context->new_channel;
if (context->channel != ccx_options.cc_channel)
if (context->channel != context->my_channel)
return;
dbg_print(CCX_DMT_608, "\r608: text_attr: %02X %02X",c1,c2);
ccx_common_logging.debug_ftn(CCX_DMT_DECODER_608, "\r608: text_attr: %02X %02X", c1, c2);
if ( ((c1!=0x11 && c1!=0x19) ||
(c2<0x20 || c2>0x2f)))
{
dbg_print(CCX_DMT_608, "\rThis is not a text attribute!\n");
ccx_common_logging.debug_ftn(CCX_DMT_DECODER_608, "\rThis is not a text attribute!\n");
}
else
{
int i = c2-0x20;
context->color = pac2_attribs[i][0];
context->current_color = pac2_attribs[i][0];
context->font = pac2_attribs[i][1];
dbg_print(CCX_DMT_608, " -- Color: %s, font: %s\n",
color_text[context->color][0],
ccx_common_logging.debug_ftn(
CCX_DMT_DECODER_608,
" -- Color: %s, font: %s\n",
color_text[context->current_color][0],
font_text[context->font]);
// Mid-row codes should put a non-transparent space at the current position
// and advance the cursor
@@ -250,7 +259,7 @@ void handle_text_attr(const unsigned char c1, const unsigned char c2, struct s_c
}
}
struct eia608_screen *get_current_visible_buffer(struct s_context_cc608 *context)
struct eia608_screen *get_current_visible_buffer(ccx_decoder_608_context *context)
{
struct eia608_screen *data;
if (context->visible_buffer == 1)
@@ -260,7 +269,7 @@ struct eia608_screen *get_current_visible_buffer(struct s_context_cc608 *context
return data;
}
int write_cc_buffer(struct s_context_cc608 *context, struct cc_subtitle *sub)
int write_cc_buffer(ccx_decoder_608_context *context, struct cc_subtitle *sub)
{
struct eia608_screen *data;
int wrote_something=0;
@@ -268,11 +277,11 @@ int write_cc_buffer(struct s_context_cc608 *context, struct cc_subtitle *sub)
LLONG end_time;
if (ccx_options.screens_to_process!=-1 &&
context->screenfuls_counter >= ccx_options.screens_to_process)
if (context->settings.screens_to_process != -1 &&
context->screenfuls_counter >= context->settings.screens_to_process)
{
// We are done.
processed_enough=1;
*context->halt=1;
return 0;
}
@@ -283,7 +292,7 @@ int write_cc_buffer(struct s_context_cc608 *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() + subs_delay;
end_time = get_visible_end() + ccx_decoders_common_settings.subs_delay;
sub->type = CC_608;
data->format = SFORMAT_CC_SCREEN;
data->start_time = 0;
@@ -297,7 +306,7 @@ int write_cc_buffer(struct s_context_cc608 *context, struct cc_subtitle *sub)
sub->data = (struct eia608_screen *) realloc(sub->data,( sub->nb_data + 1 ) * sizeof(*data));
if (!sub->data)
{
mprint("No Memory left");
ccx_common_logging.log_ftn("No Memory left");
return 0;
}
@@ -309,7 +318,7 @@ int write_cc_buffer(struct s_context_cc608 *context, struct cc_subtitle *sub)
int i = 0;
int nb_data = sub->nb_data;
data = (struct eia608_screen *)sub->data;
for(i = 0; i < sub->nb_data; i++)
for(i = 0;(unsigned) i < sub->nb_data; i++)
{
if(!data->start_time)
break;
@@ -329,7 +338,7 @@ int write_cc_buffer(struct s_context_cc608 *context, struct cc_subtitle *sub)
}
return wrote_something;
}
int write_cc_line(struct s_context_cc608 *context, struct cc_subtitle *sub)
int write_cc_line(ccx_decoder_608_context *context, struct cc_subtitle *sub)
{
struct eia608_screen *data;
LLONG start_time;
@@ -339,8 +348,8 @@ int write_cc_line(struct s_context_cc608 *context, struct cc_subtitle *sub)
int ret = 0;
data = get_current_visible_buffer(context);
start_time = context->ts_start_of_current_line + subs_delay;
end_time = get_fts() + subs_delay;
start_time = context->ts_start_of_current_line + ccx_decoders_common_settings.subs_delay;
end_time = get_fts() + ccx_decoders_common_settings.subs_delay;
sub->type = CC_608;
data->format = SFORMAT_CC_LINE;
data->start_time = 0;
@@ -349,13 +358,13 @@ int write_cc_line(struct s_context_cc608 *context, struct cc_subtitle *sub)
data->channel = context->channel;
data->my_field = context->my_field;
ret = get_decoder_line_basic (subline, context->cursor_row, data);
ret = get_decoder_line_basic (subline, context->cursor_row, data,context->trim_subs,context->encoding);
if( ret > 0 )
{
sub->data = (struct eia608_screen *) realloc(sub->data,(sub->nb_data +1) * sizeof(*data));
if (!sub->data)
{
mprint("No Memory left");
ccx_common_logging.log_ftn("No Memory left");
return 0;
}
memcpy(((struct eia608_screen *)sub->data) + sub->nb_data, data, sizeof(*data));
@@ -374,14 +383,14 @@ int write_cc_line(struct s_context_cc608 *context, struct cc_subtitle *sub)
{
int nb_data = sub->nb_data;
data = (struct eia608_screen *)sub->data;
for(i = 0; i < sub->nb_data; i++)
for(i = 0;(unsigned) i < sub->nb_data; i++)
{
if(!data->start_time)
break;
nb_data--;
data++;
}
for(i = 0; i < nb_data; i++)
for(i = 0;(int) i < nb_data; i++)
{
data->start_time = start_time + ( ( (end_time - start_time)/nb_data ) * i );
data->end_time = start_time + ( ( (end_time - start_time)/nb_data ) * (i + 1) );
@@ -395,7 +404,7 @@ int write_cc_line(struct s_context_cc608 *context, struct cc_subtitle *sub)
}
// Check if a rollup would cause a line to go off the visible area
int check_roll_up(struct s_context_cc608 *context)
int check_roll_up(ccx_decoder_608_context *context)
{
int keep_lines=0;
int firstrow=-1, lastrow=-1;
@@ -451,7 +460,7 @@ int check_roll_up(struct s_context_cc608 *context)
// Roll-up: Returns true if a line was rolled over the visible area (it dissapears from screen), false
// if the rollup didn't delete any line.
int roll_up(struct s_context_cc608 *context)
int roll_up(ccx_decoder_608_context *context)
{
struct eia608_screen *use_buffer;
if (context->visible_buffer == 1)
@@ -494,7 +503,7 @@ int roll_up(struct s_context_cc608 *context)
}
}
dbg_print(CCX_DMT_608, "\rIn roll-up: %d lines used, first: %d, last: %d\n", rows_orig, firstrow, lastrow);
ccx_common_logging.debug_ftn(CCX_DMT_DECODER_608, "\rIn roll-up: %d lines used, first: %d, last: %d\n", rows_orig, firstrow, lastrow);
if (lastrow==-1) // Empty screen, nothing to rollup
return 0;
@@ -503,25 +512,25 @@ int roll_up(struct s_context_cc608 *context)
{
if (j>=0)
{
memcpy (use_buffer->characters[j],use_buffer->characters[j+1],CC608_SCREEN_WIDTH+1);
memcpy (use_buffer->colors[j],use_buffer->colors[j+1],CC608_SCREEN_WIDTH+1);
memcpy (use_buffer->fonts[j],use_buffer->fonts[j+1],CC608_SCREEN_WIDTH+1);
memcpy(use_buffer->characters[j], use_buffer->characters[j + 1], CCX_DECODER_608_SCREEN_WIDTH + 1);
memcpy(use_buffer->colors[j], use_buffer->colors[j + 1], CCX_DECODER_608_SCREEN_WIDTH + 1);
memcpy(use_buffer->fonts[j], use_buffer->fonts[j + 1], CCX_DECODER_608_SCREEN_WIDTH + 1);
use_buffer->row_used[j]=use_buffer->row_used[j+1];
}
}
for (int j = 0; j<(1 + context->cursor_row - keep_lines); j++)
{
memset(use_buffer->characters[j],' ',CC608_SCREEN_WIDTH);
memset(use_buffer->colors[j],ccx_options.cc608_default_color,CC608_SCREEN_WIDTH);
memset(use_buffer->fonts[j],FONT_REGULAR,CC608_SCREEN_WIDTH);
use_buffer->characters[j][CC608_SCREEN_WIDTH]=0;
memset(use_buffer->characters[j], ' ', CCX_DECODER_608_SCREEN_WIDTH);
memset(use_buffer->colors[j], context->settings.default_color, CCX_DECODER_608_SCREEN_WIDTH);
memset(use_buffer->fonts[j], FONT_REGULAR, CCX_DECODER_608_SCREEN_WIDTH);
use_buffer->characters[j][CCX_DECODER_608_SCREEN_WIDTH] = 0;
use_buffer->row_used[j]=0;
}
memset(use_buffer->characters[lastrow],' ',CC608_SCREEN_WIDTH);
memset(use_buffer->colors[lastrow],ccx_options.cc608_default_color,CC608_SCREEN_WIDTH);
memset(use_buffer->fonts[lastrow],FONT_REGULAR,CC608_SCREEN_WIDTH);
memset(use_buffer->characters[lastrow], ' ', CCX_DECODER_608_SCREEN_WIDTH);
memset(use_buffer->colors[lastrow], context->settings.default_color, CCX_DECODER_608_SCREEN_WIDTH);
memset(use_buffer->fonts[lastrow], FONT_REGULAR, CCX_DECODER_608_SCREEN_WIDTH);
use_buffer->characters[lastrow][CC608_SCREEN_WIDTH]=0;
use_buffer->characters[lastrow][CCX_DECODER_608_SCREEN_WIDTH] = 0;
use_buffer->row_used[lastrow]=0;
// Sanity check
@@ -530,7 +539,7 @@ int roll_up(struct s_context_cc608 *context)
if (use_buffer->row_used[i])
rows_now++;
if (rows_now>keep_lines)
mprint ("Bug in roll_up, should have %d lines but I have %d.\n",
ccx_common_logging.log_ftn("Bug in roll_up, should have %d lines but I have %d.\n",
keep_lines, rows_now);
// If the buffer is now empty, let's set the flag
@@ -541,7 +550,7 @@ int roll_up(struct s_context_cc608 *context)
return (rows_now != rows_orig);
}
void erase_memory(struct s_context_cc608 *context, int displayed)
void erase_memory(ccx_decoder_608_context *context, int displayed)
{
struct eia608_screen *buf;
if (displayed)
@@ -558,17 +567,17 @@ void erase_memory(struct s_context_cc608 *context, int displayed)
else
buf = &context->buffer1;
}
clear_eia608_cc_buffer (buf);
clear_eia608_cc_buffer (context,buf);
}
int is_current_row_empty(struct s_context_cc608 *context)
int is_current_row_empty(ccx_decoder_608_context *context)
{
struct eia608_screen *use_buffer;
if (context->visible_buffer == 1)
use_buffer = &context->buffer1;
else
use_buffer = &context->buffer2;
for (int i=0;i<CC608_SCREEN_WIDTH;i++)
for (int i = 0; i<CCX_DECODER_608_SCREEN_WIDTH; i++)
{
if (use_buffer->characters[context->rollup_base_row][i] != ' ')
return 0;
@@ -577,13 +586,13 @@ int is_current_row_empty(struct s_context_cc608 *context)
}
/* Process GLOBAL CODES */
void handle_command(/*const */ unsigned char c1, const unsigned char c2, struct s_context_cc608 *context, struct cc_subtitle *sub)
void handle_command(/*const */ unsigned char c1, const unsigned char c2, ccx_decoder_608_context *context, struct cc_subtitle *sub)
{
int changes=0;
// Handle channel change
context->channel = context->new_channel;
if (context->channel != ccx_options.cc_channel)
if (context->channel != context->my_channel)
return;
enum command_code command = COM_UNKNOWN;
@@ -624,16 +633,16 @@ void handle_command(/*const */ unsigned char c1, const unsigned char c2, struct
if ((c1==0x14 || c1==0x1C) && c2==0x2b)
command = COM_RESUMETEXTDISPLAY;
if ((command == COM_ROLLUP2 || command == COM_ROLLUP3 || command==COM_ROLLUP4) && ccx_options.forced_ru==1)
if ((command == COM_ROLLUP2 || command == COM_ROLLUP3 || command == COM_ROLLUP4) && context->settings.force_rollup == 1)
command=COM_FAKE_RULLUP1;
if ((command == COM_ROLLUP3 || command==COM_ROLLUP4) && ccx_options.forced_ru==2)
if ((command == COM_ROLLUP3 || command == COM_ROLLUP4) && context->settings.force_rollup == 2)
command=COM_ROLLUP2;
else if (command==COM_ROLLUP4 && ccx_options.forced_ru==3)
else if (command == COM_ROLLUP4 && context->settings.force_rollup == 3)
command=COM_ROLLUP3;
dbg_print(CCX_DMT_608, "\rCommand begin: %02X %02X (%s)\n",c1,c2,command_type[command]);
dbg_print(CCX_DMT_608, "\rCurrent mode: %d Position: %d,%d VisBuf: %d\n", context->mode,
ccx_common_logging.debug_ftn(CCX_DMT_DECODER_608, "\rCommand begin: %02X %02X (%s)\n", c1, c2, command_type[command]);
ccx_common_logging.debug_ftn(CCX_DMT_DECODER_608, "\rCurrent mode: %d Position: %d,%d VisBuf: %d\n", context->mode,
context->cursor_row, context->cursor_column, context->visible_buffer);
switch (command)
@@ -646,18 +655,18 @@ void handle_command(/*const */ unsigned char c1, const unsigned char c2, struct
}
break;
case COM_TABOFFSET1:
if (context->cursor_column<31)
if (context->cursor_column<CCX_DECODER_608_SCREEN_WIDTH - 1)
context->cursor_column++;
break;
case COM_TABOFFSET2:
context->cursor_column += 2;
if (context->cursor_column>31)
context->cursor_column = 31;
if (context->cursor_column>CCX_DECODER_608_SCREEN_WIDTH - 1)
context->cursor_column = CCX_DECODER_608_SCREEN_WIDTH - 1;
break;
case COM_TABOFFSET3:
context->cursor_column += 3;
if (context->cursor_column>31)
context->cursor_column = 31;
if (context->cursor_column>CCX_DECODER_608_SCREEN_WIDTH - 1)
context->cursor_column = CCX_DECODER_608_SCREEN_WIDTH - 1;
break;
case COM_RESUMECAPTIONLOADING:
context->mode = MODE_POPON;
@@ -719,7 +728,7 @@ void handle_command(/*const */ unsigned char c1, const unsigned char c2, struct
context->cursor_row++;
break;
}
if (ccx_options.write_format==CCX_OF_TRANSCRIPT)
if (ccx_decoders_common_settings.output_format == CCX_OF_TRANSCRIPT)
{
write_cc_line(context,sub);
}
@@ -730,11 +739,11 @@ void handle_command(/*const */ unsigned char c1, const unsigned char c2, struct
if (changes)
{
// Only if the roll up would actually cause a line to disappear we write the buffer
if (ccx_options.write_format!=CCX_OF_TRANSCRIPT)
if (ccx_decoders_common_settings.output_format != CCX_OF_TRANSCRIPT)
{
if (write_cc_buffer(context, sub))
context->screenfuls_counter++;
if (ccx_options.norollup)
if (context->settings.no_rollup)
erase_memory(context, true); // Make sure the lines we just wrote aren't written again
}
}
@@ -750,7 +759,7 @@ void handle_command(/*const */ unsigned char c1, const unsigned char c2, struct
case COM_ERASEDISPLAYEDMEMORY:
// Write it to disk before doing this, and make a note of the new
// time it became clear.
if (ccx_options.write_format==CCX_OF_TRANSCRIPT &&
if (ccx_decoders_common_settings.output_format == CCX_OF_TRANSCRIPT &&
(context->mode == MODE_FAKE_ROLLUP_1 ||
context->mode == MODE_ROLLUP_2 ||
context->mode == MODE_ROLLUP_3 ||
@@ -763,7 +772,7 @@ void handle_command(/*const */ unsigned char c1, const unsigned char c2, struct
}
else
{
if (ccx_options.write_format==CCX_OF_TRANSCRIPT)
if (ccx_decoders_common_settings.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++;
@@ -780,7 +789,7 @@ void handle_command(/*const */ unsigned char c1, const unsigned char c2, struct
context->current_visible_start_ms = get_visible_start();
context->cursor_column = 0;
context->cursor_row = 0;
context->color = ccx_options.cc608_default_color;
context->current_color = context->settings.default_color;
context->font = FONT_REGULAR;
context->mode = MODE_POPON;
break;
@@ -793,20 +802,20 @@ void handle_command(/*const */ unsigned char c1, const unsigned char c2, struct
break;
case COM_RESUMEDIRECTCAPTIONING:
context->mode = MODE_PAINTON;
//mprint ("\nWarning: Received ResumeDirectCaptioning, this mode is almost impossible.\n");
//mprint ("to transcribe to a text file.\n");
//ccx_common_logging.log_ftn ("\nWarning: Received ResumeDirectCaptioning, this mode is almost impossible.\n");
//ccx_common_logging.log_ftn ("to transcribe to a text file.\n");
break;
default:
dbg_print(CCX_DMT_608, "\rNot yet implemented.\n");
ccx_common_logging.debug_ftn(CCX_DMT_DECODER_608, "\rNot yet implemented.\n");
break;
}
dbg_print(CCX_DMT_608, "\rCurrent mode: %d Position: %d,%d VisBuf: %d\n", context->mode,
ccx_common_logging.debug_ftn(CCX_DMT_DECODER_608, "\rCurrent mode: %d Position: %d,%d VisBuf: %d\n", context->mode,
context->cursor_row, context->cursor_column, context->visible_buffer);
dbg_print(CCX_DMT_608, "\rCommand end: %02X %02X (%s)\n",c1,c2,command_type[command]);
ccx_common_logging.debug_ftn(CCX_DMT_DECODER_608, "\rCommand end: %02X %02X (%s)\n", c1, c2, command_type[command]);
}
void handle_end_of_data(struct s_context_cc608 *context, struct cc_subtitle *sub)
void handle_end_of_data(ccx_decoder_608_context *context, struct cc_subtitle *sub)
{
// We issue a EraseDisplayedMemory here so if there's any captions pending
// they get written to Subtitle.
@@ -814,36 +823,36 @@ void handle_end_of_data(struct s_context_cc608 *context, struct cc_subtitle *sub
}
// CEA-608, Anex F 1.1.1. - Character Set Table / Special Characters
void handle_double(const unsigned char c1, const unsigned char c2, struct s_context_cc608 *context)
void handle_double(const unsigned char c1, const unsigned char c2, ccx_decoder_608_context *context)
{
unsigned char c;
if (context->channel != ccx_options.cc_channel)
if (context->channel != context->my_channel)
return;
if (c2>=0x30 && c2<=0x3f)
{
c=c2 + 0x50; // So if c>=0x80 && c<=0x8f, it comes from here
dbg_print(CCX_DMT_608, "\rDouble: %02X %02X --> %c\n",c1,c2,c);
ccx_common_logging.debug_ftn(CCX_DMT_DECODER_608, "\rDouble: %02X %02X --> %c\n", c1, c2, c);
write_char(c, context);
}
}
/* Process EXTENDED CHARACTERS */
unsigned char handle_extended(unsigned char hi, unsigned char lo, struct s_context_cc608 *context)
unsigned char handle_extended(unsigned char hi, unsigned char lo, ccx_decoder_608_context *context)
{
// Handle channel change
if (context->new_channel > 2)
{
context->new_channel -= 2;
dbg_print(CCX_DMT_608, "\nChannel correction, now %d\n", context->new_channel);
ccx_common_logging.debug_ftn(CCX_DMT_DECODER_608, "\nChannel correction, now %d\n", context->new_channel);
}
context->channel = context->new_channel;
if (context->channel != ccx_options.cc_channel)
if (context->channel != context->my_channel)
return 0;
// For lo values between 0x20-0x3f
unsigned char c=0;
dbg_print(CCX_DMT_608, "\rExtended: %02X %02X\n",hi,lo);
ccx_common_logging.debug_ftn(CCX_DMT_DECODER_608, "\rExtended: %02X %02X\n", hi, lo);
if (lo>=0x20 && lo<=0x3f && (hi==0x12 || hi==0x13))
{
switch (hi)
@@ -867,21 +876,21 @@ unsigned char handle_extended(unsigned char hi, unsigned char lo, struct s_conte
}
/* Process PREAMBLE ACCESS CODES (PAC) */
void handle_pac(unsigned char c1, unsigned char c2, struct s_context_cc608 *context)
void handle_pac(unsigned char c1, unsigned char c2, ccx_decoder_608_context *context)
{
// Handle channel change
if (context->new_channel > 2)
{
context->new_channel -= 2;
dbg_print(CCX_DMT_608, "\nChannel correction, now %d\n", context->new_channel);
ccx_common_logging.debug_ftn(CCX_DMT_DECODER_608, "\nChannel correction, now %d\n", context->new_channel);
}
context->channel = context->new_channel;
if (context->channel != ccx_options.cc_channel)
if (context->channel != context->my_channel)
return;
int row=rowdata[((c1<<1)&14)|((c2>>5)&1)];
dbg_print(CCX_DMT_608, "\rPAC: %02X %02X",c1,c2);
ccx_common_logging.debug_ftn(CCX_DMT_DECODER_608, "\rPAC: %02X %02X", c1, c2);
if (c2>=0x40 && c2<=0x5f)
{
@@ -895,17 +904,17 @@ void handle_pac(unsigned char c1, unsigned char c2, struct s_context_cc608 *cont
}
else
{
dbg_print(CCX_DMT_608, "\rThis is not a PAC!!!!!\n");
ccx_common_logging.debug_ftn(CCX_DMT_DECODER_608, "\rThis is not a PAC!!!!!\n");
return;
}
}
context->color = pac2_attribs[c2][0];
context->current_color = pac2_attribs[c2][0];
context->font = pac2_attribs[c2][1];
int indent=pac2_attribs[c2][2];
dbg_print(CCX_DMT_608, " -- Position: %d:%d, color: %s, font: %s\n",row,
indent, color_text[context->color][0], font_text[context->font]);
if (ccx_options.cc608_default_color == COL_USERDEFINED && (context->color == COL_WHITE || context->color == COL_TRANSPARENT))
context->color = COL_USERDEFINED;
ccx_common_logging.debug_ftn(CCX_DMT_DECODER_608, " -- Position: %d:%d, color: %s, font: %s\n", row,
indent, color_text[context->current_color][0], font_text[context->font]);
if (context->settings.default_color == COL_USERDEFINED && (context->current_color == COL_WHITE || context->current_color == COL_TRANSPARENT))
context->current_color = COL_USERDEFINED;
if (context->mode != MODE_TEXT)
{
// According to Robson, row info is discarded in text mode
@@ -926,10 +935,10 @@ void handle_pac(unsigned char c1, unsigned char c2, struct s_context_cc608 *cont
{
if (use_buffer->row_used[j])
{
memset(use_buffer->characters[j],' ',CC608_SCREEN_WIDTH);
memset(use_buffer->colors[j],ccx_options.cc608_default_color,CC608_SCREEN_WIDTH);
memset(use_buffer->fonts[j],FONT_REGULAR,CC608_SCREEN_WIDTH);
use_buffer->characters[j][CC608_SCREEN_WIDTH]=0;
memset(use_buffer->characters[j], ' ', CCX_DECODER_608_SCREEN_WIDTH);
memset(use_buffer->colors[j], context->settings.default_color, CCX_DECODER_608_SCREEN_WIDTH);
memset(use_buffer->fonts[j], FONT_REGULAR, CCX_DECODER_608_SCREEN_WIDTH);
use_buffer->characters[j][CCX_DECODER_608_SCREEN_WIDTH] = 0;
use_buffer->row_used[j]=0;
}
}
@@ -938,16 +947,16 @@ void handle_pac(unsigned char c1, unsigned char c2, struct s_context_cc608 *cont
}
void handle_single(const unsigned char c1, struct s_context_cc608 *context)
void handle_single(const unsigned char c1, ccx_decoder_608_context *context)
{
if (c1<0x20 || context->channel != ccx_options.cc_channel)
if (c1<0x20 || context->channel != context->my_channel)
return; // We don't allow special stuff here
dbg_print(CCX_DMT_608, "%c",c1);
ccx_common_logging.debug_ftn(CCX_DMT_DECODER_608, "%c", c1);
write_char (c1,context);
}
void erase_both_memories(struct s_context_cc608 *context, struct cc_subtitle *sub)
void erase_both_memories(ccx_decoder_608_context *context, struct cc_subtitle *sub)
{
erase_memory(context, false);
// For the visible memory, we write the contents to disk
@@ -958,13 +967,13 @@ void erase_both_memories(struct s_context_cc608 *context, struct cc_subtitle *su
context->current_visible_start_ms = get_visible_start();
context->cursor_column = 0;
context->cursor_row = 0;
context->color = ccx_options.cc608_default_color;
context->current_color = context->settings.default_color;
context->font = FONT_REGULAR;
erase_memory(context, true);
}
int check_channel(unsigned char c1, struct s_context_cc608 *context)
int check_channel(unsigned char c1, ccx_decoder_608_context *context)
{
int newchan = context->channel;
if (c1>=0x10 && c1<=0x17)
@@ -973,7 +982,7 @@ int check_channel(unsigned char c1, struct s_context_cc608 *context)
newchan=2;
if (newchan != context->channel)
{
dbg_print(CCX_DMT_608, "\nChannel change, now %d\n", newchan);
ccx_common_logging.debug_ftn(CCX_DMT_DECODER_608, "\nChannel change, now %d\n", newchan);
if (context->channel != 3) // Don't delete memories if returning from XDS.
{
// erase_both_memories (wb); // 47cfr15.119.pdf, page 859, part f
@@ -987,7 +996,7 @@ int check_channel(unsigned char c1, struct s_context_cc608 *context)
/* Handle Command, special char or attribute and also check for
* channel changes.
* Returns 1 if something was written to screen, 0 otherwise */
int disCommand(unsigned char hi, unsigned char lo, struct s_context_cc608 *context, struct cc_subtitle *sub)
int disCommand(unsigned char hi, unsigned char lo, ccx_decoder_608_context *context, struct cc_subtitle *sub)
{
int wrote_to_screen=0;
@@ -1054,7 +1063,7 @@ int disCommand(unsigned char hi, unsigned char lo, struct s_context_cc608 *conte
}
/* If wb is NULL, then only XDS will be processed */
int process608(const unsigned char *data, int length, struct s_context_cc608 *context, struct cc_subtitle *sub)
int process608(const unsigned char *data, int length, ccx_decoder_608_context *context, struct cc_subtitle *sub)
{
static int textprinted = 0;
int i;
@@ -1079,10 +1088,10 @@ int process608(const unsigned char *data, int length, struct s_context_cc608 *co
if (hi>=0x10 && hi<=0x1e) {
int ch = (hi<=0x17)? 1 : 2;
if (current_field == 2)
if (context == NULL || context->my_field == 2) // Originally: current_field from sequencing.c. Seems to be just to change channel, so context->my_field seems good.
ch+=2;
file_report.cc_channels_608[ch - 1] = 1;
ccx_decoder_608_report.cc_channels[ch - 1] = 1;
}
if (hi >= 0x01 && hi <= 0x0E && (context == NULL || context->my_field == 2)) // XDS can only exist in field 2.
@@ -1095,7 +1104,7 @@ int process608(const unsigned char *data, int length, struct s_context_cc608 *co
in_xds_mode=1;
}
file_report.xds=1;
ccx_decoder_608_report.xds=1;
}
if (hi == 0x0F && in_xds_mode && (context == NULL || context->my_field == 2)) // End of XDS block
{
@@ -1113,7 +1122,7 @@ int process608(const unsigned char *data, int length, struct s_context_cc608 *co
// diagnostic output from disCommand()
if (textprinted == 1 )
{
dbg_print(CCX_DMT_608, "\n");
ccx_common_logging.debug_ftn(CCX_DMT_DECODER_608, "\n");
textprinted = 0;
}
if (!context || context->my_field == 2)
@@ -1124,7 +1133,7 @@ int process608(const unsigned char *data, int length, struct s_context_cc608 *co
{
// Duplicate dual code, discard. Correct to do it only in
// non-XDS, XDS codes shall not be repeated.
dbg_print(CCX_DMT_608, "Skipping command %02X,%02X Duplicate\n", hi, lo);
ccx_common_logging.debug_ftn(CCX_DMT_DECODER_608, "Skipping command %02X,%02X Duplicate\n", hi, lo);
// Ignore only the first repetition
context->last_c1=-1;
context->last_c2 = -1;
@@ -1152,12 +1161,12 @@ int process608(const unsigned char *data, int length, struct s_context_cc608 *co
if (hi>=0x20) // Standard characters (always in pairs)
{
// Only print if the channel is active
if (context->channel != ccx_options.cc_channel)
if (context->channel != context->my_channel)
continue;
if( textprinted == 0 )
{
dbg_print(CCX_DMT_608, "\n");
ccx_common_logging.debug_ftn(CCX_DMT_DECODER_608, "\n");
textprinted = 1;
}
@@ -1168,16 +1177,16 @@ int process608(const unsigned char *data, int length, struct s_context_cc608 *co
context->last_c2 = 0;
}
if (!textprinted && context->channel == ccx_options.cc_channel)
if (!textprinted && context->channel == context->my_channel)
{ // Current FTS information after the characters are shown
dbg_print(CCX_DMT_608, "Current FTS: %s\n", print_mstime(get_fts()));
ccx_common_logging.debug_ftn(CCX_DMT_DECODER_608, "Current FTS: %s\n", print_mstime(get_fts()));
//printf(" N:%u", unsigned(fts_now) );
//printf(" G:%u", unsigned(fts_global) );
//printf(" F:%d %d %d %d\n",
// current_field, cb_field1, cb_field2, cb_708 );
}
if (wrote_to_screen && ccx_options.direct_rollup && // If direct_rollup is enabled and
if (wrote_to_screen && context->settings.direct_rollup && // If direct_rollup is enabled and
(context->mode == MODE_FAKE_ROLLUP_1 || // we are in rollup mode, write now.
context->mode == MODE_ROLLUP_2 ||
context->mode == MODE_ROLLUP_3 ||
@@ -1188,7 +1197,7 @@ int process608(const unsigned char *data, int length, struct s_context_cc608 *co
context->current_visible_start_ms = get_visible_start();
}
}
if (wrote_to_screen && cc_to_stdout)
if (wrote_to_screen && *context->cc_to_stdout)
fflush (stdout);
} // for
return i;

149
src/ccx_decoders_608.h Normal file
View File

@@ -0,0 +1,149 @@
#ifndef __608_H__
#include "ccx_common_platform.h"
#include "ccx_common_structs.h"
#include "ccx_decoders_structs.h"
extern LLONG ts_start_of_xds;
/*
This variable (ccx_decoder_608_report) holds data on the cc channels & xds packets that are encountered during file parse.
This can be interesting if you just want to know what kind of data a file holds that has 608 packets. CCExtractor uses it
for the report functionality.
*/
struct ccx_decoder_608_report_t {
unsigned xds : 1;
unsigned cc_channels[4];
} ccx_decoder_608_report;
typedef struct ccx_decoder_608_settings {
int direct_rollup; // Write roll-up captions directly instead of line by line?
int force_rollup; // 0=Disabled, 1, 2 or 3=max lines in roll-up mode
int no_rollup; // If 1, write one line at a time
unsigned char default_color; // Default color to use.
int screens_to_process; // How many screenfuls we want? Use -1 for unlimited
} ccx_decoder_608_settings;
typedef struct ccx_decoder_608_context
{
ccx_decoder_608_settings settings;
eia608_screen buffer1;
eia608_screen buffer2;
int cursor_row, cursor_column;
int visible_buffer;
int screenfuls_counter; // Number of meaningful screenfuls written
LLONG current_visible_start_ms; // At what time did the current visible buffer became so?
enum cc_modes mode;
unsigned char last_c1, last_c2;
int channel; // Currently selected channel
unsigned char current_color; // Color we are currently using to write
unsigned char font; // Font we are currently using to write
int rollup_base_row;
LLONG ts_start_of_current_line; /* Time at which the first character for current line was received, =-1 no character received yet */
LLONG ts_last_char_received; /* Time at which the last written character was received, =-1 no character received yet */
int new_channel; // The new channel after a channel change
int my_field; // Used for sanity checks
int my_channel; // Used for sanity checks
long bytes_processed_608; // To be written ONLY by process_608
struct ccx_s_write *out;
int have_cursor_position;
int trim_subs;
enum ccx_encoding_type encoding;
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.
} ccx_decoder_608_context;
extern unsigned char *enc_buffer;
extern unsigned char str[2048];
extern unsigned enc_buffer_used;
extern unsigned enc_buffer_capacity;
extern int new_sentence;
extern const char *color_text[][2];
typedef enum ccx_decoder_608_color_code
{
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
} ccx_decoder_608_color_code;
enum font_bits
{
FONT_REGULAR = 0,
FONT_ITALICS = 1,
FONT_UNDERLINED = 2,
FONT_UNDERLINED_ITALICS = 3
};
enum command_code
{
COM_UNKNOWN = 0,
COM_ERASEDISPLAYEDMEMORY = 1,
COM_RESUMECAPTIONLOADING = 2,
COM_ENDOFCAPTION = 3,
COM_TABOFFSET1 = 4,
COM_TABOFFSET2 = 5,
COM_TABOFFSET3 = 6,
COM_ROLLUP2 = 7,
COM_ROLLUP3 = 8,
COM_ROLLUP4 = 9,
COM_CARRIAGERETURN = 10,
COM_ERASENONDISPLAYEDMEMORY = 11,
COM_BACKSPACE = 12,
COM_RESUMETEXTDISPLAY = 13,
COM_ALARMOFF =14,
COM_ALARMON = 15,
COM_DELETETOENDOFROW = 16,
COM_RESUMEDIRECTCAPTIONING = 17,
// Non existing commands we insert to have the decoder
// special stuff for us.
COM_FAKE_RULLUP1 = 18
};
/*
*
*/
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);
/**
* @param data raw cc608 data to be processed
*
* @param length length of data passed
*
* @param context context of cc608 where important information related to 608
* are stored.
*
* @param sub pointer to subtitle should be memset to 0 when passed first time
* subtitle are stored when structure return
*
* @return number of bytes used from data, -1 when any error is encountered
*/
int process608(const unsigned char *data, int length, ccx_decoder_608_context *context, struct cc_subtitle *sub);
/**
* Issue a EraseDisplayedMemory here so if there's any captions pending
* they get written to cc_subtitle
*/
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);
//void delete_all_lines_but_current(ccx_decoder_608_context *context, struct eia608_screen *data, int row);
LLONG get_visible_end(void);
#define __608_H__
#endif

View File

@@ -1,10 +1,17 @@
#include "ccextractor.h"
#include <sys/stat.h>
#include "ccx_decoders_708.h"
#include "ccx_common_common.h"
#include "ccx_common_constants.h"
#include "ccx_common_structs.h"
#include "ccx_common_timing.h"
/* Portions by Daniel Kristjansson, extracted from MythTV's source */
// #define DEBUG_708_PACKETS // Already working.
int do_cea708 = 0; // Process 708 data?
int cea708services[CCX_DECODERS_708_MAX_SERVICES]; // [] -> 1 for services to be processed
int ccx_decoders_708_report = 0;
static unsigned char current_packet[MAX_708_PACKET_LENGTH]; // Length according to EIA-708B, part 5
static int current_packet_length=0;
static int last_seq=-1; // -1 -> No last sequence yet
@@ -114,7 +121,7 @@ void cc708_service_reset(cc708_service_decoder *decoder)
void cc708_reset()
{
dbg_print(CCX_DMT_708, ">>> Entry in cc708_reset()\n");
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]);
@@ -143,16 +150,16 @@ void clearTV (cc708_service_decoder *decoder, int buffer) // Buffer => 1 or 2
void printTVtoSRT (cc708_service_decoder *decoder, int which)
{
if (CCX_OF_NULL == ccx_options.write_format)
if (ccx_decoders_common_settings.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()+subs_delay;
LLONG ms_end = get_visible_end() + ccx_decoders_common_settings.subs_delay;
int empty=1;
ms_start+=subs_delay;
ms_start+= ccx_decoders_common_settings.subs_delay;
if (ms_start<0) // Drop screens that because of subs_delay start too early
return;
@@ -171,11 +178,11 @@ void printTVtoSRT (cc708_service_decoder *decoder, int which)
return; // Nothing to write
if (decoder->fh==-1) // File not yet open, do it now
{
mprint ("Creating %s\n", wbout1.filename);
decoder->fh=open (decoder->filename, O_RDWR | O_CREAT | O_TRUNC | O_BINARY, S_IREAD | S_IWRITE);
ccx_common_logging.log_ftn("Creating %s\n", decoder->filename); // originally wbout1.filename, but since line below uses decoder->filename, assume it's good to use?
decoder->fh= open(decoder->filename, O_RDWR | O_CREAT | O_TRUNC | O_BINARY, S_IREAD | S_IWRITE);
if (decoder->fh==-1)
{
fatal (EXIT_FILE_CREATION_FAILED, "Failed\n");
ccx_common_logging.fatal_ftn(CCX_COMMON_EXIT_FILE_CREATION_FAILED, "Failed\n");
}
}
mstotime (ms_start,&h1,&m1,&s1,&ms1);
@@ -216,7 +223,7 @@ void printTVtoConsole (cc708_service_decoder *decoder, int which)
char tbuf1[15],tbuf2[15];
print_mstime2buf (decoder->current_visible_start_ms,tbuf1);
print_mstime2buf (get_visible_end(),tbuf2);
dbg_print(CCX_DMT_GENERIC_NOTICES, "\r%s --> %s\n", tbuf1,tbuf2);
ccx_common_logging.debug_ftn(CCX_DMT_GENERIC_NOTICES, "\r%s --> %s\n", tbuf1,tbuf2);
for (int i=0;i<75;i++)
{
int empty=1;
@@ -233,8 +240,8 @@ void printTVtoConsole (cc708_service_decoder *decoder, int which)
if (decoder->tv->chars[i][l]!=' ')
break;
for (int j=f;j<=l;j++)
dbg_print(CCX_DMT_GENERIC_NOTICES, "%c", decoder->tv->chars[i][j]);
dbg_print(CCX_DMT_GENERIC_NOTICES, "\n");
ccx_common_logging.debug_ftn(CCX_DMT_GENERIC_NOTICES, "%c", decoder->tv->chars[i][j]);
ccx_common_logging.debug_ftn(CCX_DMT_GENERIC_NOTICES, "\n");
}
}
}
@@ -271,12 +278,12 @@ void updateScreen (cc708_service_decoder *decoder)
wnd[visible++]=&decoder->windows[i];
}
qsort (wnd,visible,sizeof (e708Window *),compWindowsPriorities);
dbg_print(CCX_DMT_708, "Visible (and populated) windows in priority order: ");
ccx_common_logging.debug_ftn(CCX_DMT_708, "Visible (and populated) windows in priority order: ");
for (int i=0;i<visible;i++)
{
dbg_print(CCX_DMT_708, "%d (%d) | ",wnd[i]->number, wnd[i]->priority);
ccx_common_logging.debug_ftn(CCX_DMT_708, "%d (%d) | ",wnd[i]->number, wnd[i]->priority);
}
dbg_print(CCX_DMT_708, "\n");
ccx_common_logging.debug_ftn(CCX_DMT_708, "\n");
for (int i=0;i<visible;i++)
{
int top,left;
@@ -323,7 +330,7 @@ void updateScreen (cc708_service_decoder *decoder)
default: // Shouldn't happen, but skip the window just in case
continue;
}
dbg_print(CCX_DMT_708, "For window %d: Anchor point -> %d, size %d:%d, real position %d:%d\n",
ccx_common_logging.debug_ftn(CCX_DMT_708, "For window %d: Anchor point -> %d, size %d:%d, real position %d:%d\n",
wnd[i]->number, wnd[i]->anchor_point, wnd[i]->row_count,wnd[i]->col_count,
top,left);
if (top<0)
@@ -334,7 +341,7 @@ void updateScreen (cc708_service_decoder *decoder)
I708_SCREENGRID_ROWS - top : wnd[i]->row_count;
int copycols=left + wnd[i]->col_count >= I708_SCREENGRID_COLUMNS ?
I708_SCREENGRID_COLUMNS - left : wnd[i]->col_count;
dbg_print(CCX_DMT_708, "%d*%d will be copied to the TV.\n", copyrows, copycols);
ccx_common_logging.debug_ftn(CCX_DMT_708, "%d*%d will be copied to the TV.\n", copyrows, copycols);
for (int j=0;j<copyrows;j++)
{
memcpy (decoder->tv->chars[top+j],wnd[i]->rows[j],copycols);
@@ -362,7 +369,7 @@ int handle_708_C2 (cc708_service_decoder *decoder, unsigned char *data, int data
int handle_708_C3 (cc708_service_decoder *decoder, unsigned char *data, int data_length)
{
if (data[0]<0x80 || data[0]>0x9F)
fatal (EXIT_BUG_BUG, "Entry in handle_708_C3 with an out of range value.");
ccx_common_logging.fatal_ftn (CCX_COMMON_EXIT_BUG_BUG, "Entry in handle_708_C3 with an out of range value.");
if (data[0]<=0x87) // 80-87...
return 5; // ... Five-byte control bytes (4 additional bytes)
else if (data[0]<=0x8F) // 88-8F ...
@@ -372,7 +379,7 @@ int handle_708_C3 (cc708_service_decoder *decoder, unsigned char *data, int data
// These are variable length commands, that can even span several segments
// (they allow even downloading fonts or graphics).
// TODO: Implemen if a sample ever appears
fatal (EXIT_UNSUPPORTED, "This sample contains unsupported 708 data. PLEASE help us improve CCExtractor by submitting it.\n");
ccx_common_logging.fatal_ftn(CCX_COMMON_EXIT_UNSUPPORTED, "This sample contains unsupported 708 data. PLEASE help us improve CCExtractor by submitting it.\n");
return 0; // Unreachable, but otherwise there's compilers warnings
}
@@ -385,7 +392,7 @@ int handle_708_C3 (cc708_service_decoder *decoder, unsigned char *data, int data
int handle_708_extended_char (cc708_service_decoder *decoder, unsigned char *data, int data_length)
{
int used;
dbg_print(CCX_DMT_708, "In handle_708_extended_char, first data code: [%c], length: [%u]\n",data[0], data_length);
ccx_common_logging.debug_ftn(CCX_DMT_708, "In handle_708_extended_char, first data code: [%c], length: [%u]\n",data[0], data_length);
unsigned char c=0x20; // Default to space
unsigned char code=data[0];
if (/* data[i]>=0x00 && */ code<=0x1F) // Comment to silence warning
@@ -447,7 +454,7 @@ int handle_708_C0 (cc708_service_decoder *decoder, unsigned char *data, int data
const char *name=COMMANDS_C0[data[0]];
if (name==NULL)
name="Reserved";
dbg_print(CCX_DMT_708, "C0: [%02X] (%d) [%s]\n",data[0],data_length, name);
ccx_common_logging.debug_ftn(CCX_DMT_708, "C0: [%02X] (%d) [%s]\n",data[0],data_length, name);
int len=-1;
// These commands have a known length even if they are reserved.
if (/* data[0]>=0x00 && */ data[0]<=0xF) // Comment to silence warning
@@ -483,12 +490,12 @@ int handle_708_C0 (cc708_service_decoder *decoder, unsigned char *data, int data
}
if (len==-1)
{
dbg_print(CCX_DMT_708, "In handle_708_C0. Len == -1, this is not possible!");
ccx_common_logging.debug_ftn(CCX_DMT_708, "In handle_708_C0. Len == -1, this is not possible!");
return -1;
}
if (len>data_length)
{
dbg_print(CCX_DMT_708, "handle_708_C0, command is %d bytes long but we only have %d\n",len, data_length);
ccx_common_logging.debug_ftn(CCX_DMT_708, "handle_708_C0, command is %d bytes long but we only have %d\n",len, data_length);
return -1;
}
// TODO: Do something useful eventually
@@ -498,7 +505,7 @@ int handle_708_C0 (cc708_service_decoder *decoder, unsigned char *data, int data
void process_character (cc708_service_decoder *decoder, unsigned char internal_char)
{
dbg_print(CCX_DMT_708, ">>> Process_character: %c [%02X] - Window: %d %s, Pen: %d:%d\n", internal_char, internal_char,
ccx_common_logging.debug_ftn(CCX_DMT_708, ">>> Process_character: %c [%02X] - Window: %d %s, Pen: %d:%d\n", internal_char, internal_char,
decoder->current_window,
(decoder->windows[decoder->current_window].is_defined?"[OK]":"[undefined]"),
decoder->current_window!=-1 ? decoder->windows[decoder->current_window].pen_row:-1,
@@ -544,7 +551,7 @@ void process_character (cc708_service_decoder *decoder, unsigned char internal_c
int handle_708_G0 (cc708_service_decoder *decoder, unsigned char *data, int data_length)
{
// TODO: Substitution of the music note character for the ASCII DEL character
dbg_print(CCX_DMT_708, "G0: [%02X] (%c)\n",data[0],data[0]);
ccx_common_logging.debug_ftn(CCX_DMT_708, "G0: [%02X] (%c)\n",data[0],data[0]);
unsigned char c=get_internal_from_G0 (data[0]);
process_character (decoder, c);
return 1;
@@ -553,7 +560,7 @@ int handle_708_G0 (cc708_service_decoder *decoder, unsigned char *data, int data
// G1 Code Set - ISO 8859-1 LATIN-1 Character Set
int handle_708_G1 (cc708_service_decoder *decoder, unsigned char *data, int data_length)
{
dbg_print(CCX_DMT_708, "G1: [%02X] (%c)\n",data[0],data[0]);
ccx_common_logging.debug_ftn(CCX_DMT_708, "G1: [%02X] (%c)\n",data[0],data[0]);
unsigned char c=get_internal_from_G1 (data[0]);
process_character (decoder, c);
return 1;
@@ -564,7 +571,7 @@ int handle_708_G1 (cc708_service_decoder *decoder, unsigned char *data, int data
------------------------------------------------------- */
void handle_708_CWx_SetCurrentWindow (cc708_service_decoder *decoder, int new_window)
{
dbg_print(CCX_DMT_708, " Entry in handle_708_CWx_SetCurrentWindow, new window: [%d]\n",new_window);
ccx_common_logging.debug_ftn(CCX_DMT_708, " Entry in handle_708_CWx_SetCurrentWindow, new window: [%d]\n",new_window);
if (decoder->windows[new_window].is_defined)
decoder->current_window=new_window;
}
@@ -577,29 +584,29 @@ void clearWindow (cc708_service_decoder *decoder, int window)
void handle_708_CLW_ClearWindows (cc708_service_decoder *decoder, int windows_bitmap)
{
dbg_print(CCX_DMT_708, " Entry in handle_708_CLW_ClearWindows, windows: ");
ccx_common_logging.debug_ftn(CCX_DMT_708, " Entry in handle_708_CLW_ClearWindows, windows: ");
if (windows_bitmap==0)
dbg_print(CCX_DMT_708, "None\n");
ccx_common_logging.debug_ftn(CCX_DMT_708, "None\n");
else
{
for (int i=0; i<8; i++)
{
if (windows_bitmap & 1)
{
dbg_print(CCX_DMT_708, "[Window %d] ",i );
ccx_common_logging.debug_ftn(CCX_DMT_708, "[Window %d] ",i );
clearWindow (decoder, i);
}
windows_bitmap>>=1;
}
}
dbg_print(CCX_DMT_708, "\n");
ccx_common_logging.debug_ftn(CCX_DMT_708, "\n");
}
void handle_708_DSW_DisplayWindows (cc708_service_decoder *decoder, int windows_bitmap)
{
dbg_print(CCX_DMT_708, " Entry in handle_708_DSW_DisplayWindows, windows: ");
ccx_common_logging.debug_ftn(CCX_DMT_708, " Entry in handle_708_DSW_DisplayWindows, windows: ");
if (windows_bitmap==0)
dbg_print(CCX_DMT_708, "None\n");
ccx_common_logging.debug_ftn(CCX_DMT_708, "None\n");
else
{
int changes=0;
@@ -607,7 +614,7 @@ void handle_708_DSW_DisplayWindows (cc708_service_decoder *decoder, int windows_
{
if (windows_bitmap & 1)
{
dbg_print(CCX_DMT_708, "[Window %d] ",i );
ccx_common_logging.debug_ftn(CCX_DMT_708, "[Window %d] ",i );
if (!decoder->windows[i].visible)
{
changes=1;
@@ -616,7 +623,7 @@ void handle_708_DSW_DisplayWindows (cc708_service_decoder *decoder, int windows_
}
windows_bitmap>>=1;
}
dbg_print(CCX_DMT_708, "\n");
ccx_common_logging.debug_ftn(CCX_DMT_708, "\n");
if (changes)
updateScreen (decoder);
}
@@ -624,9 +631,9 @@ void handle_708_DSW_DisplayWindows (cc708_service_decoder *decoder, int windows_
void handle_708_HDW_HideWindows (cc708_service_decoder *decoder, int windows_bitmap)
{
dbg_print(CCX_DMT_708, " Entry in handle_708_HDW_HideWindows, windows: ");
ccx_common_logging.debug_ftn(CCX_DMT_708, " Entry in handle_708_HDW_HideWindows, windows: ");
if (windows_bitmap==0)
dbg_print(CCX_DMT_708, "None\n");
ccx_common_logging.debug_ftn(CCX_DMT_708, "None\n");
else
{
int changes=0;
@@ -634,7 +641,7 @@ void handle_708_HDW_HideWindows (cc708_service_decoder *decoder, int windows_bit
{
if (windows_bitmap & 1)
{
dbg_print(CCX_DMT_708, "[Window %d] ",i );
ccx_common_logging.debug_ftn(CCX_DMT_708, "[Window %d] ",i );
if (decoder->windows[i].is_defined && decoder->windows[i].visible && !decoder->windows[i].is_empty)
{
changes=1;
@@ -644,7 +651,7 @@ void handle_708_HDW_HideWindows (cc708_service_decoder *decoder, int windows_bit
}
windows_bitmap>>=1;
}
dbg_print(CCX_DMT_708, "\n");
ccx_common_logging.debug_ftn(CCX_DMT_708, "\n");
if (changes)
updateScreen (decoder);
}
@@ -652,23 +659,23 @@ void handle_708_HDW_HideWindows (cc708_service_decoder *decoder, int windows_bit
void handle_708_TGW_ToggleWindows (cc708_service_decoder *decoder, int windows_bitmap)
{
dbg_print(CCX_DMT_708, " Entry in handle_708_TGW_ToggleWindows, windows: ");
ccx_common_logging.debug_ftn(CCX_DMT_708, " Entry in handle_708_TGW_ToggleWindows, windows: ");
if (windows_bitmap==0)
dbg_print(CCX_DMT_708, "None\n");
ccx_common_logging.debug_ftn(CCX_DMT_708, "None\n");
else
{
for (int i=0; i<8; i++)
{
if (windows_bitmap & 1)
{
dbg_print(CCX_DMT_708, "[Window %d] ",i );
ccx_common_logging.debug_ftn(CCX_DMT_708, "[Window %d] ",i );
decoder->windows[i].visible=!decoder->windows[i].visible;
}
windows_bitmap>>=1;
}
updateScreen(decoder);
}
dbg_print(CCX_DMT_708, "\n");
ccx_common_logging.debug_ftn(CCX_DMT_708, "\n");
}
void clearWindowText (e708Window *window)
@@ -685,14 +692,14 @@ void clearWindowText (e708Window *window)
void handle_708_DFx_DefineWindow (cc708_service_decoder *decoder, int window, unsigned char *data)
{
dbg_print(CCX_DMT_708, " Entry in handle_708_DFx_DefineWindow, window [%d], attributes: \n", window);
ccx_common_logging.debug_ftn(CCX_DMT_708, " Entry in handle_708_DFx_DefineWindow, window [%d], attributes: \n", window);
if (decoder->windows[window].is_defined &&
memcmp (decoder->windows[window].commands, data+1, 6)==0)
{
// When a decoder receives a DefineWindow command for an existing window, the
// command is to be ignored if the command parameters are unchanged from the
// previous window definition.
dbg_print(CCX_DMT_708, " Repeated window definition, ignored.\n");
ccx_common_logging.debug_ftn(CCX_DMT_708, " Repeated window definition, ignored.\n");
return;
}
decoder->windows[window].number=window;
@@ -708,13 +715,13 @@ void handle_708_DFx_DefineWindow (cc708_service_decoder *decoder, int window, un
int col_count = data[5] & 0x3f;
int pen_style = data[6] & 0x7;
int win_style = (data[6]>>3) & 0x7;
dbg_print(CCX_DMT_708, " Priority: [%d] Column lock: [%3s] Row lock: [%3s]\n",
ccx_common_logging.debug_ftn(CCX_DMT_708, " Priority: [%d] Column lock: [%3s] Row lock: [%3s]\n",
priority, col_lock?"Yes": "No", row_lock?"Yes": "No");
dbg_print(CCX_DMT_708, " Visible: [%3s] Anchor vertical: [%2d] Relative pos: [%s]\n",
ccx_common_logging.debug_ftn(CCX_DMT_708, " Visible: [%3s] Anchor vertical: [%2d] Relative pos: [%s]\n",
visible?"Yes": "No", anchor_vertical, relative_pos?"Yes": "No");
dbg_print(CCX_DMT_708, " Anchor horizontal: [%3d] Row count: [%2d]+1 Anchor point: [%d]\n",
ccx_common_logging.debug_ftn(CCX_DMT_708, " Anchor horizontal: [%3d] Row count: [%2d]+1 Anchor point: [%d]\n",
anchor_horizontal, row_count, anchor_point);
dbg_print(CCX_DMT_708, " Column count: [%2d]1 Pen style: [%d] Win style: [%d]\n",
ccx_common_logging.debug_ftn(CCX_DMT_708, " Column count: [%2d]1 Pen style: [%d] Win style: [%d]\n",
col_count, pen_style, win_style);
col_count++; // These increments seems to be needed but no documentation
row_count++; // backs it up
@@ -770,7 +777,7 @@ void handle_708_DFx_DefineWindow (cc708_service_decoder *decoder, int window, un
void handle_708_SWA_SetWindowAttributes (cc708_service_decoder *decoder, unsigned char *data)
{
dbg_print(CCX_DMT_708, " Entry in handle_708_SWA_SetWindowAttributes, attributes: \n");
ccx_common_logging.debug_ftn(CCX_DMT_708, " Entry in handle_708_SWA_SetWindowAttributes, attributes: \n");
int fill_color = (data[1] ) & 0x3f;
int fill_opacity = (data[1]>>6) & 0x03;
int border_color = (data[2] ) & 0x3f;
@@ -783,11 +790,11 @@ void handle_708_SWA_SetWindowAttributes (cc708_service_decoder *decoder, unsigne
int display_eff = (data[4] ) & 0x03;
int effect_dir = (data[4]>>2) & 0x03;
int effect_speed = (data[4]>>4) & 0x0f;
dbg_print(CCX_DMT_708, " Fill color: [%d] Fill opacity: [%d] Border color: [%d] Border type: [%d]\n",
ccx_common_logging.debug_ftn(CCX_DMT_708, " Fill color: [%d] Fill opacity: [%d] Border color: [%d] Border type: [%d]\n",
fill_color, fill_opacity, border_color, border_type01);
dbg_print(CCX_DMT_708, " Justify: [%d] Scroll dir: [%d] Print dir: [%d] Word wrap: [%d]\n",
ccx_common_logging.debug_ftn(CCX_DMT_708, " Justify: [%d] Scroll dir: [%d] Print dir: [%d] Word wrap: [%d]\n",
justify, scroll_dir, print_dir, word_wrap);
dbg_print(CCX_DMT_708, " Border type: [%d] Display eff: [%d] Effect dir: [%d] Effect speed: [%d]\n",
ccx_common_logging.debug_ftn(CCX_DMT_708, " Border type: [%d] Display eff: [%d] Effect dir: [%d] Effect speed: [%d]\n",
border_type, display_eff, effect_dir, effect_speed);
if (decoder->current_window==-1)
{
@@ -830,16 +837,16 @@ void deleteWindow (cc708_service_decoder *decoder, int window)
void handle_708_DLW_DeleteWindows (cc708_service_decoder *decoder, int windows_bitmap)
{
int changes=0;
dbg_print(CCX_DMT_708, " Entry in handle_708_DLW_DeleteWindows, windows: ");
ccx_common_logging.debug_ftn(CCX_DMT_708, " Entry in handle_708_DLW_DeleteWindows, windows: ");
if (windows_bitmap==0)
dbg_print(CCX_DMT_708, "None\n");
ccx_common_logging.debug_ftn(CCX_DMT_708, "None\n");
else
{
for (int i=0; i<8; i++)
{
if (windows_bitmap & 1)
{
dbg_print(CCX_DMT_708, "[Window %d] ",i );
ccx_common_logging.debug_ftn(CCX_DMT_708, "[Window %d] ",i );
if (decoder->windows[i].is_defined && decoder->windows[i].visible && !decoder->windows[i].is_empty)
changes=1;
deleteWindow (decoder, i);
@@ -847,7 +854,7 @@ void handle_708_DLW_DeleteWindows (cc708_service_decoder *decoder, int windows_b
windows_bitmap>>=1;
}
}
dbg_print(CCX_DMT_708, "\n");
ccx_common_logging.debug_ftn(CCX_DMT_708, "\n");
if (changes)
updateScreen (decoder);
@@ -858,7 +865,7 @@ void handle_708_DLW_DeleteWindows (cc708_service_decoder *decoder, int windows_b
------------------------------------------------------- */
void handle_708_SPA_SetPenAttributes (cc708_service_decoder *decoder, unsigned char *data)
{
dbg_print(CCX_DMT_708, " Entry in handle_708_SPA_SetPenAttributes, attributes: \n");
ccx_common_logging.debug_ftn(CCX_DMT_708, " Entry in handle_708_SPA_SetPenAttributes, attributes: \n");
int pen_size = (data[1] ) & 0x3;
int offset = (data[1]>>2) & 0x3;
int text_tag = (data[1]>>4) & 0xf;
@@ -866,9 +873,9 @@ void handle_708_SPA_SetPenAttributes (cc708_service_decoder *decoder, unsigned c
int edge_type = (data[2]>>3) & 0x7;
int underline = (data[2]>>4) & 0x1;
int italic = (data[2]>>5) & 0x1;
dbg_print(CCX_DMT_708, " Pen size: [%d] Offset: [%d] Text tag: [%d] Font tag: [%d]\n",
ccx_common_logging.debug_ftn(CCX_DMT_708, " Pen size: [%d] Offset: [%d] Text tag: [%d] Font tag: [%d]\n",
pen_size, offset, text_tag, font_tag);
dbg_print(CCX_DMT_708, " Edge type: [%d] Underline: [%d] Italic: [%d]\n",
ccx_common_logging.debug_ftn(CCX_DMT_708, " Edge type: [%d] Underline: [%d] Italic: [%d]\n",
edge_type, underline, italic);
if (decoder->current_window==-1)
{
@@ -886,17 +893,17 @@ void handle_708_SPA_SetPenAttributes (cc708_service_decoder *decoder, unsigned c
void handle_708_SPC_SetPenColor (cc708_service_decoder *decoder, unsigned char *data)
{
dbg_print(CCX_DMT_708, " Entry in handle_708_SPC_SetPenColor, attributes: \n");
ccx_common_logging.debug_ftn(CCX_DMT_708, " Entry in handle_708_SPC_SetPenColor, attributes: \n");
int fg_color = (data[1] ) & 0x3f;
int fg_opacity = (data[1]>>6) & 0x03;
int bg_color = (data[2] ) & 0x3f;
int bg_opacity = (data[2]>>6) & 0x03;
int edge_color = (data[3]>>6) & 0x3f;
dbg_print(CCX_DMT_708, " Foreground color: [%d] Foreground opacity: [%d]\n",
ccx_common_logging.debug_ftn(CCX_DMT_708, " Foreground color: [%d] Foreground opacity: [%d]\n",
fg_color, fg_opacity);
dbg_print(CCX_DMT_708, " Background color: [%d] Background opacity: [%d]\n",
ccx_common_logging.debug_ftn(CCX_DMT_708, " Background color: [%d] Background opacity: [%d]\n",
bg_color, bg_opacity);
dbg_print(CCX_DMT_708, " Edge color: [%d]\n",
ccx_common_logging.debug_ftn(CCX_DMT_708, " Edge color: [%d]\n",
edge_color);
if (decoder->current_window==-1)
{
@@ -914,10 +921,10 @@ void handle_708_SPC_SetPenColor (cc708_service_decoder *decoder, unsigned char *
void handle_708_SPL_SetPenLocation (cc708_service_decoder *decoder, unsigned char *data)
{
dbg_print(CCX_DMT_708, " Entry in handle_708_SPL_SetPenLocation, attributes: \n");
ccx_common_logging.debug_ftn(CCX_DMT_708, " Entry in handle_708_SPL_SetPenLocation, attributes: \n");
int row = data[1] & 0x0f;
int col = data[2] & 0x3f;
dbg_print(CCX_DMT_708, " row: [%d] Column: [%d]\n",
ccx_common_logging.debug_ftn(CCX_DMT_708, " row: [%d] Column: [%d]\n",
row, col);
if (decoder->current_window==-1)
{
@@ -934,14 +941,14 @@ void handle_708_SPL_SetPenLocation (cc708_service_decoder *decoder, unsigned cha
------------------------------------------------------- */
void handle_708_DLY_Delay (cc708_service_decoder *decoder, int tenths_of_sec)
{
dbg_print(CCX_DMT_708, " Entry in handle_708_DLY_Delay, delay for [%d] tenths of second.", tenths_of_sec);
ccx_common_logging.debug_ftn(CCX_DMT_708, " Entry in handle_708_DLY_Delay, delay for [%d] tenths of second.", tenths_of_sec);
// TODO: Probably ask for the current FTS and wait for this time before resuming -
// not sure it's worth it though
}
void handle_708_DLC_DelayCancel (cc708_service_decoder *decoder)
{
dbg_print(CCX_DMT_708, " Entry in handle_708_DLC_DelayCancel.");
ccx_common_logging.debug_ftn(CCX_DMT_708, " Entry in handle_708_DLC_DelayCancel.");
// TODO: See above
}
@@ -949,12 +956,12 @@ void handle_708_DLC_DelayCancel (cc708_service_decoder *decoder)
int handle_708_C1 (cc708_service_decoder *decoder, unsigned char *data, int data_length)
{
struct S_COMMANDS_C1 com=COMMANDS_C1[data[0]-0x80];
dbg_print(CCX_DMT_708, "%s | C1: [%02X] [%s] [%s] (%d)\n",
ccx_common_logging.debug_ftn(CCX_DMT_708, "%s | C1: [%02X] [%s] [%s] (%d)\n",
print_mstime(get_fts()),
data[0],com.name,com.description, com.length);
if (com.length>data_length)
{
dbg_print(CCX_DMT_708, "C1: Warning: Not enough bytes for command.\n");
ccx_common_logging.debug_ftn(CCX_DMT_708, "C1: Warning: Not enough bytes for command.\n");
return -1;
}
switch (com.code)
@@ -1006,7 +1013,7 @@ int handle_708_C1 (cc708_service_decoder *decoder, unsigned char *data, int data
case RSV94:
case RSV95:
case RSV96:
dbg_print(CCX_DMT_708, "Warning, found Reserved codes, ignored.\n");
ccx_common_logging.debug_ftn(CCX_DMT_708, "Warning, found Reserved codes, ignored.\n");
break;
case SWA:
handle_708_SWA_SetWindowAttributes (decoder, data);
@@ -1022,7 +1029,7 @@ int handle_708_C1 (cc708_service_decoder *decoder, unsigned char *data, int data
handle_708_DFx_DefineWindow (decoder, com.code-DF0, data); /* Window 0 to 7 */
break;
default:
mprint ("BUG: Unhandled code in handle_708_C1.\n");
ccx_common_logging.log_ftn ("BUG: Unhandled code in handle_708_C1.\n");
break;
}
@@ -1058,7 +1065,7 @@ void process_service_block (cc708_service_decoder *decoder, unsigned char *data,
used=handle_708_G1 (decoder,data+i,data_length-i);
if (used==-1)
{
dbg_print(CCX_DMT_708, "There was a problem handling the data. Reseting service decoder\n");
ccx_common_logging.debug_ftn(CCX_DMT_708, "There was a problem handling the data. Reseting service decoder\n");
// TODO: Not sure if a local reset is going to be helpful here.
cc708_service_reset (decoder);
return;
@@ -1079,7 +1086,7 @@ void process_current_packet (void)
int seq=(current_packet[0] & 0xC0) >> 6; // Two most significants bits
int len=current_packet[0] & 0x3F; // 6 least significants bits
#ifdef DEBUG_708_PACKETS
mprint ("Processing EIA-708 packet, length=%d, seq=%d\n",current_packet_length, seq);
ccx_common_logging.log_ftn ("Processing EIA-708 packet, length=%d, seq=%d\n",current_packet_length, seq);
#endif
if (current_packet_length==0)
return;
@@ -1089,11 +1096,11 @@ void process_current_packet (void)
len=len*2;
// Note that len here is the length including the header
#ifdef DEBUG_708_PACKETS
mprint ("Sequence: %d, packet length: %d\n",seq,len);
ccx_common_logging.log_ftn ("Sequence: %d, packet length: %d\n",seq,len);
#endif
if (current_packet_length!=len) // Is this possible?
{
dbg_print(CCX_DMT_708, "Packet length mismatch (%s%d), first two data bytes %02X %02X, current picture:%s\n",
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();
@@ -1101,7 +1108,7 @@ void process_current_packet (void)
}
if (last_seq!=-1 && (last_seq+1)%4!=seq)
{
dbg_print(CCX_DMT_708, "Unexpected sequence number, it was [%d] but should have been [%d]\n",
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();
return;
@@ -1115,7 +1122,7 @@ void process_current_packet (void)
int service_number=(pos[0] & 0xE0)>>5; // 3 more significant bits
int block_length = (pos[0] & 0x1F); // 5 less significant bits
dbg_print (CCX_DMT_708, "Standard header: Service number: [%d] Block length: [%d]\n",service_number,
ccx_common_logging.debug_ftn (CCX_DMT_708, "Standard header: Service number: [%d] Block length: [%d]\n",service_number,
block_length);
if (service_number==7) // There is an extended header
@@ -1125,7 +1132,7 @@ void process_current_packet (void)
// printf ("Extended header: Service number: [%d]\n",service_number);
if (service_number<7)
{
dbg_print(CCX_DMT_708, "Illegal service number in extended header: [%d]\n",service_number);
ccx_common_logging.debug_ftn(CCX_DMT_708, "Illegal service number in extended header: [%d]\n",service_number);
}
}
/*
@@ -1141,13 +1148,14 @@ void process_current_packet (void)
pos++; // Move to service data
if (service_number==0 && block_length!=0) // Illegal, but specs say what to do...
{
dbg_print(CCX_DMT_708, "Data received for service 0, skipping rest of packet.");
ccx_common_logging.debug_ftn(CCX_DMT_708, "Data received for service 0, skipping rest of packet.");
pos = current_packet+len; // Move to end
break;
}
if (block_length != 0)
file_report.services708[service_number] = 1;
if (block_length != 0){
ccx_decoder_708_report.services[service_number] = 1;
}
if (service_number>0 && decoders[service_number-1].inited)
process_service_block (&decoders[service_number-1], pos, block_length);
@@ -1159,13 +1167,13 @@ void process_current_packet (void)
if (pos!=current_packet+len) // For some reason we didn't parse the whole packet
{
dbg_print(CCX_DMT_708, "There was a problem with this packet, reseting\n");
ccx_common_logging.debug_ftn(CCX_DMT_708, "There was a problem with this packet, reseting\n");
cc708_reset();
}
if (len<128 && *pos) // Null header is mandatory if there is room
{
dbg_print(CCX_DMT_708, "Warning: Null header expected but not found.\n");
ccx_common_logging.debug_ftn(CCX_DMT_708, "Warning: Null header expected but not found.\n");
}
}
@@ -1175,7 +1183,7 @@ void do_708 (const unsigned char *data, int datalength)
1 byte for cc_valid
1 byte for cc_type
2 bytes for the actual data */
if (!do_cea708 && !ccx_options.print_file_reports)
if (!do_cea708 && !ccx_decoders_708_report)
return;
for (int i=0;i<datalength;i+=4)
@@ -1186,14 +1194,14 @@ void do_708 (const unsigned char *data, int datalength)
switch (cc_type)
{
case 2:
dbg_print (CCX_DMT_708, "708: DTVCC Channel Packet Data\n");
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();
else
{
if (current_packet_length>253)
{
dbg_print(CCX_DMT_708, "Warning: Legal packet size exceeded, data not added.\n");
ccx_common_logging.debug_ftn(CCX_DMT_708, "Warning: Legal packet size exceeded, data not added.\n");
}
else
{
@@ -1203,13 +1211,13 @@ void do_708 (const unsigned char *data, int datalength)
}
break;
case 3:
dbg_print (CCX_DMT_708, "708: DTVCC Channel Packet Start\n");
ccx_common_logging.debug_ftn (CCX_DMT_708, "708: DTVCC Channel Packet Start\n");
process_current_packet();
if (cc_valid)
{
if (current_packet_length>127)
{
dbg_print(CCX_DMT_708, "Warning: Legal packet size exceeded, data not added.\n");
ccx_common_logging.debug_ftn(CCX_DMT_708, "Warning: Legal packet size exceeded, data not added.\n");
}
else
{
@@ -1219,14 +1227,14 @@ void do_708 (const unsigned char *data, int datalength)
}
break;
default:
fatal (EXIT_BUG_BUG, "708: shouldn't be here - cc_type: %d\n", cc_type);
ccx_common_logging.fatal_ftn (CCX_COMMON_EXIT_BUG_BUG, "708: shouldn't be here - cc_type: %d\n", cc_type);
}
}
}
void init_708(void)
void ccx_decoders_708_init_library(char *basefilename,const char *extension,int report)
{
for (int i=0;i<63;i++)
for (int i = 0; i<CCX_DECODERS_708_MAX_SERVICES; i++)
{
if (!cea708services[i])
continue;
@@ -1238,5 +1246,6 @@ void init_708(void)
}
decoders[i].fh=-1;
decoders[i].srt_counter=0;
}
}
ccx_decoders_708_report = report;
}

View File

@@ -1,6 +1,11 @@
#ifndef _INCLUDE_708_
#define _INCLUDE_708_
#include <sys/stat.h>
#include "ccx_decoders_common.h"
#define MAX_708_PACKET_LENGTH 128
#define CCX_DECODERS_708_MAX_SERVICES 63
#define I708_MAX_ROWS 15
#define I708_MAX_COLUMNS 42
@@ -10,6 +15,15 @@
#define I708_MAX_WINDOWS 8
/*
This variable (ccx_decoder_708_report) holds data on the cc channels & xds packets that are encountered during file parse.
This can be interesting if you just want to know what kind of data a file holds that has 608 packets. CCExtractor uses it
for the report functionality.
*/
struct ccx_decoder_708_report_t {
unsigned services[CCX_DECODERS_708_MAX_SERVICES];
} ccx_decoder_708_report;
enum COMMANDS_C0_CODES
{
NUL=0,
@@ -278,10 +292,12 @@ typedef struct cc708_service_decoder
}
cc708_service_decoder;
extern int do_cea708; // Process 708 data?
extern int cea708services[]; // [] -> 1 for services to be processed
extern int resets_708;
void do_708 (const unsigned char *data, int datalength);
void init_708(void);
unsigned char get_internal_from_G0 (unsigned char g0_char);
unsigned char get_internal_from_G1 (unsigned char g1_char);
@@ -289,4 +305,5 @@ unsigned char get_internal_from_G2 (unsigned char g2_char);
unsigned char get_internal_from_G3 (unsigned char g3_char);
void process_character (cc708_service_decoder *decoder, unsigned char internal_char);
#endif
void ccx_decoders_708_init_library(char *basefilename,const char *extension, int report);
#endif

100
src/ccx_decoders_common.c Normal file
View File

@@ -0,0 +1,100 @@
/* Functions used by both the 608 and 708 decoders. An effort should be
made to reuse, not duplicate, as many functions as possible */
#include "ccx_decoders_common.h"
#include "ccx_common_structs.h"
#include "ccx_common_char_encoding.h"
#include "ccx_common_constants.h"
#include "ccx_common_timing.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 */
// Preencoded strings
unsigned char encoded_crlf[16];
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
obviously but it guarantees there's no timing overlap */
LLONG get_visible_start (void)
{
LLONG fts = get_fts();
if (fts <= minimum_fts)
fts = minimum_fts+1;
ccx_common_logging.debug_ftn(CCX_DMT_DECODER_608, "Visible Start time=%s\n", print_mstime(fts));
return fts;
}
/* This function returns the current FTS and saves it so it can be used by get_visible_start */
LLONG get_visible_end (void)
{
LLONG fts = get_fts();
if (fts>minimum_fts)
minimum_fts=fts;
ccx_common_logging.debug_ftn(CCX_DMT_DECODER_608, "Visible End time=%s\n", print_mstime(fts));
return fts;
}
void find_limit_characters(unsigned char *line, int *first_non_blank, int *last_non_blank)
{
*last_non_blank = -1;
*first_non_blank = -1;
for (int i = 0; i<CCX_DECODER_608_SCREEN_WIDTH; i++)
{
unsigned char c = line[i];
if (c != ' ' && c != 0x89)
{
if (*first_non_blank == -1)
*first_non_blank = i;
*last_non_blank = i;
}
}
}
unsigned get_decoder_line_basic(unsigned char *buffer, int line_num, struct eia608_screen *data, int trim_subs, enum ccx_encoding_type encoding)
{
unsigned char *line = data->characters[line_num];
int last_non_blank = -1;
int first_non_blank = -1;
unsigned char *orig = buffer; // Keep for debugging
find_limit_characters(line, &first_non_blank, &last_non_blank);
if (!trim_subs)
first_non_blank = 0;
if (first_non_blank == -1)
{
*buffer = 0;
return 0;
}
int bytes = 0;
for (int i = first_non_blank; i <= last_non_blank; i++)
{
char c = line[i];
switch (encoding)
{
case CCX_ENC_UTF_8:
bytes = get_char_in_utf_8(buffer, c);
break;
case CCX_ENC_LATIN_1:
get_char_in_latin_1(buffer, c);
bytes = 1;
break;
case CCX_ENC_UNICODE:
get_char_in_unicode(buffer, c);
bytes = 2;
break;
}
buffer += bytes;
}
*buffer = 0;
return (unsigned)(buffer - orig); // Return length
}

25
src/ccx_decoders_common.h Normal file
View File

@@ -0,0 +1,25 @@
#ifndef _CC_DECODER_COMMON
#define _CC_DECODER_COMMON
#include "ccx_common_platform.h"
#include "ccx_common_constants.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
extern unsigned int encoded_crlf_length;
extern unsigned char encoded_br[16];
extern unsigned int encoded_br_length;
extern LLONG minimum_fts; // No screen should start before this FTS
extern uint64_t utc_refvalue; // UTC referential value
// Declarations
LLONG get_visible_start(void);
LLONG get_visible_end(void);
void find_limit_characters(unsigned char *line, int *first_non_blank, int *last_non_blank);
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);
#endif

View File

@@ -0,0 +1,79 @@
#ifndef CCX_DECODERS_STRUCTS_H
#include "ccx_common_platform.h"
#include "ccx_common_constants.h"
// Define max width in characters/columns on the screen
#define CCX_DECODER_608_SCREEN_WIDTH 32
/* flag raised when end of display marker arrives in Dvb Subtitle */
#define SUB_EOD_MARKER (1 << 0 )
struct cc_bitmap
{
int x;
int y;
int w;
int h;
int nb_colors;
unsigned char *data[2];
int linesize[2];
};
enum ccx_eia608_format
{
SFORMAT_CC_SCREEN,
SFORMAT_CC_LINE,
SFORMAT_XDS
};
enum cc_modes
{
MODE_POPON = 0,
MODE_ROLLUP_2 = 1,
MODE_ROLLUP_3 = 2,
MODE_ROLLUP_4 = 3,
MODE_TEXT = 4,
MODE_PAINTON = 5,
// Fake modes to emulate stuff
MODE_FAKE_ROLLUP_1 = 100
};
/**
* This structure have fields which need to be ignored according to format,
* for example if format is SFORMAT_XDS then all fields other then
* xds related (xds_str, xds_len and cur_xds_packet_class) should be
* ignored and not to be derefrenced.
*
* TODO use union inside struct for each kind of fields
*/
typedef struct eia608_screen // A CC buffer
{
/** format of data inside this structure */
enum ccx_eia608_format format;
unsigned char characters[15][33];
unsigned char colors[15][33];
unsigned char fonts[15][33]; // Extra char at the end for a 0
int row_used[15]; // Any data in row?
int empty; // Buffer completely empty?
/** start time of this CC buffer */
LLONG start_time;
/** end time of this CC buffer */
LLONG end_time;
enum cc_modes mode;
int channel; // Currently selected channel
int my_field; // Used for sanity checks
/** XDS string */
char *xds_str;
/** length of XDS string */
size_t xds_len;
/** Class of XDS string */
int cur_xds_packet_class;
} eia608_screen;
struct ccx_decoderrs_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?
} ccx_decoders_common_settings;
#define CCX_DECODERS_STRUCTS_H
#endif

View File

@@ -1,5 +1,14 @@
#include "ccextractor.h"
#include "utility.h"
#include "ccx_decoders_xds.h"
#include "ccx_common_constants.h"
#include "ccx_common_timing.h"
LLONG ts_start_of_xds = -1; // Time at which we switched to XDS mode, =-1 hasn't happened yet
struct ccx_decoders_xds_context_t {
ccx_encoders_transcript_format transcriptFormat;
LLONG subsDelay;
char millisSeparator;
} ccx_decoders_xds_context;
// Program Identification Number (Start Time) for current program
static int current_xds_min=-1;
@@ -119,6 +128,28 @@ static unsigned char *cur_xds_payload;
static int cur_xds_payload_length;
static int cur_xds_packet_type;
void ccx_decoders_xds_init_library(ccx_encoders_transcript_format *transcriptSettings, LLONG subs_delay, char millis_separator)
{
ccx_decoders_xds_context.transcriptFormat = *transcriptSettings;
ccx_decoders_xds_context.subsDelay = subs_delay;
ccx_decoders_xds_context.millisSeparator = millis_separator;
for (int i = 0; i<NUM_XDS_BUFFERS; i++)
{
xds_buffers[i].in_use = 0;
xds_buffers[i].xds_class = -1;
xds_buffers[i].xds_type = -1;
xds_buffers[i].used_bytes = 0;
memset(xds_buffers[i].bytes, 0, NUM_BYTES_PER_PACKET);
}
for (int i = 0; i<9; i++)
memset(xds_program_description, 0, 32);
memset(current_xds_network_name, 0, 33);
memset(current_xds_program_name, 0, 33);
memset(current_xds_call_letters, 0, 7);
memset(current_xds_program_type, 0, 33);
}
int write_xds_string(struct cc_subtitle *sub,char *p,size_t len)
{
@@ -128,7 +159,7 @@ int write_xds_string(struct cc_subtitle *sub,char *p,size_t len)
{
freep(&sub->data);
sub->nb_data = 0;
mprint("No Memory left");
ccx_common_logging.log_ftn("No Memory left");
return -1;
}
else
@@ -142,30 +173,14 @@ int write_xds_string(struct cc_subtitle *sub,char *p,size_t len)
data->xds_len = len;
data->cur_xds_packet_class = cur_xds_packet_class;
sub->nb_data++;
sub->type = CC_608;
sub->got_output = 1;
}
return 0;
}
void xds_init()
{
for (int i=0;i<NUM_XDS_BUFFERS;i++)
{
xds_buffers[i].in_use=0;
xds_buffers[i].xds_class=-1;
xds_buffers[i].xds_type=-1;
xds_buffers[i].used_bytes=0;
memset (xds_buffers[i].bytes , 0, NUM_BYTES_PER_PACKET);
}
for (int i=0; i<9; i++)
memset (xds_program_description,0,32);
memset (current_xds_network_name,0,33);
memset (current_xds_program_name,0,33);
memset (current_xds_call_letters,0,7);
memset (current_xds_program_type,0,33);
}
void xds_write_transcript_line_suffix (struct ccx_s_write *wb)
{
@@ -184,61 +199,60 @@ void xds_write_transcript_line_prefix (struct ccx_s_write *wb, LLONG start_time,
if (start_time == -1)
{
// Means we entered XDS mode without making a note of the XDS start time. This is a bug.
fatal (EXIT_BUG_BUG, "Bug in timedtranscript (XDS). Please report.");
;
ccx_common_logging.fatal_ftn(CCX_COMMON_EXIT_BUG_BUG, "Bug in timedtranscript (XDS). Please report.");
}
if (ccx_options.transcript_settings.showStartTime){
if (ccx_decoders_xds_context.transcriptFormat.showStartTime){
char buffer[80];
if (ccx_options.transcript_settings.relativeTimestamp){
if (ccx_decoders_xds_context.transcriptFormat.relativeTimestamp){
if (utc_refvalue == UINT64_MAX)
{
mstotime(start_time + subs_delay, &h1, &m1, &s1, &ms1);
fdprintf(wb->fh, "%02u:%02u:%02u%c%03u|", h1, m1, s1, ccx_options.millis_separator, ms1);
mstotime(start_time + ccx_decoders_xds_context.subsDelay, &h1, &m1, &s1, &ms1);
fdprintf(wb->fh, "%02u:%02u:%02u%c%03u|", h1, m1, s1, ccx_decoders_xds_context.millisSeparator, ms1);
}
else {
fdprintf(wb->fh, "%lld%c%03d|", (start_time + subs_delay) / 1000, ccx_options.millis_separator, (start_time + subs_delay) % 1000);
fdprintf(wb->fh, "%lld%c%03d|", (start_time + ccx_decoders_xds_context.subsDelay) / 1000, ccx_decoders_xds_context.millisSeparator, (start_time + ccx_decoders_xds_context.subsDelay) % 1000);
}
}
else {
mstotime(start_time + subs_delay, &h1, &m1, &s1, &ms1);
time_t start_time_int = (start_time + subs_delay) / 1000;
int start_time_dec = (start_time + subs_delay) % 1000;
mstotime(start_time + ccx_decoders_xds_context.subsDelay, &h1, &m1, &s1, &ms1);
time_t start_time_int = (start_time + ccx_decoders_xds_context.subsDelay) / 1000;
int start_time_dec = (start_time + ccx_decoders_xds_context.subsDelay) % 1000;
struct tm *start_time_struct = gmtime(&start_time_int);
strftime(buffer, sizeof(buffer), "%Y%m%d%H%M%S", start_time_struct);
fdprintf(wb->fh, "%s%c%03d|", buffer,ccx_options.millis_separator,start_time_dec);
fdprintf(wb->fh, "%s%c%03d|", buffer, ccx_decoders_xds_context.millisSeparator, start_time_dec);
}
}
if (ccx_options.transcript_settings.showEndTime){
if (ccx_decoders_xds_context.transcriptFormat.showEndTime){
char buffer[80];
if (ccx_options.transcript_settings.relativeTimestamp){
if (ccx_decoders_xds_context.transcriptFormat.relativeTimestamp){
if (utc_refvalue == UINT64_MAX)
{
mstotime(end_time + subs_delay, &h2, &m2, &s2, &ms2);
fdprintf(wb->fh, "%02u:%02u:%02u%c%03u|", h2, m2, s2, ccx_options.millis_separator, ms2);
mstotime(end_time + ccx_decoders_xds_context.subsDelay, &h2, &m2, &s2, &ms2);
fdprintf(wb->fh, "%02u:%02u:%02u%c%03u|", h2, m2, s2, ccx_decoders_xds_context.millisSeparator, ms2);
}
else
{
fdprintf(wb->fh, "%lld%s%03d|", (end_time + subs_delay) / 1000, ccx_options.millis_separator, (end_time + subs_delay) % 1000);
fdprintf(wb->fh, "%lld%s%03d|", (end_time + ccx_decoders_xds_context.subsDelay) / 1000, ccx_decoders_xds_context.millisSeparator, (end_time + ccx_decoders_xds_context.subsDelay) % 1000);
}
}
else {
mstotime(end_time + subs_delay, &h2, &m2, &s2, &ms2);
time_t end_time_int = (end_time + subs_delay) / 1000;
int end_time_dec = (end_time + subs_delay) % 1000;
mstotime(end_time + ccx_decoders_xds_context.subsDelay, &h2, &m2, &s2, &ms2);
time_t end_time_int = (end_time + ccx_decoders_xds_context.subsDelay) / 1000;
int end_time_dec = (end_time + ccx_decoders_xds_context.subsDelay) % 1000;
struct tm *end_time_struct = gmtime(&end_time_int);
strftime(buffer, sizeof(buffer), "%Y%m%d%H%M%S", end_time_struct);
fdprintf(wb->fh, "%s%c%03d|", buffer, ccx_options.millis_separator, end_time_dec);
fdprintf(wb->fh, "%s%c%03d|", buffer, ccx_decoders_xds_context.millisSeparator, end_time_dec);
}
}
if (ccx_options.transcript_settings.showMode){
if (ccx_decoders_xds_context.transcriptFormat.showMode){
const char *mode = "XDS";
fdprintf(wb->fh, "%s|", mode);
}
if (ccx_options.transcript_settings.showCC){
if (ccx_decoders_xds_context.transcriptFormat.showCC){
fdprintf(wb->fh, "%s|", XDSclasses_short[cur_xds_packet_class]);
}
}
@@ -328,7 +342,7 @@ void process_xds_bytes (const unsigned char hi, int lo)
{
int xds_class=(hi-1)/2; // Start codes 1 and 2 are "class type" 0, 3-4 are 2, and so on.
is_new=hi%2; // Start codes are even
dbg_print(CCX_DMT_XDS, "XDS Start: %u.%u Is new: %d | Class: %d (%s), Used buffers: %d\n",hi,lo, is_new,xds_class, XDSclasses[xds_class], how_many_used());
ccx_common_logging.debug_ftn(CCX_DMT_DECODER_XDS, "XDS Start: %u.%u Is new: %d | Class: %d (%s), Used buffers: %d\n",hi,lo, is_new,xds_class, XDSclasses[xds_class], how_many_used());
int first_free_buf=-1;
int matching_buf=-1;
for (int i=0;i<NUM_XDS_BUFFERS;i++)
@@ -350,7 +364,7 @@ void process_xds_bytes (const unsigned char hi, int lo)
*/
if (matching_buf==-1 && first_free_buf==-1)
{
mprint ("Note: All XDS buffers full (bug or suicidal stream). Ignoring this one (%d,%d).\n",xds_class,lo);
ccx_common_logging.log_ftn ("Note: All XDS buffers full (bug or suicidal stream). Ignoring this one (%d,%d).\n",xds_class,lo);
cur_xds_buffer_idx=-1;
return;
@@ -375,10 +389,10 @@ void process_xds_bytes (const unsigned char hi, int lo)
else
{
// Informational: 00, or 0x20-0x7F, so 01-0x1f forbidden
dbg_print(CCX_DMT_XDS, "XDS: %02X.%02X (%c, %c)\n",hi,lo,hi,lo);
ccx_common_logging.debug_ftn(CCX_DMT_DECODER_XDS, "XDS: %02X.%02X (%c, %c)\n",hi,lo,hi,lo);
if ((hi>0 && hi<=0x1f) || (lo>0 && lo<=0x1f))
{
mprint ("\rNote: Illegal XDS data");
ccx_common_logging.log_ftn ("\rNote: Illegal XDS data");
return;
}
}
@@ -430,7 +444,7 @@ void xds_do_copy_generation_management_system (struct cc_subtitle *sub, unsigned
}
if (ccx_options.transcript_settings.xds)
if (ccx_decoders_xds_context.transcriptFormat.xds)
{
xdsprint(sub, copy_permited);
xdsprint(sub, aps);
@@ -438,13 +452,13 @@ void xds_do_copy_generation_management_system (struct cc_subtitle *sub, unsigned
}
if (changed)
{
mprint ("\rXDS: %s\n",copy_permited);
mprint ("\rXDS: %s\n",aps);
mprint ("\rXDS: %s\n",rcd);
ccx_common_logging.log_ftn ("\rXDS: %s\n",copy_permited);
ccx_common_logging.log_ftn ("\rXDS: %s\n",aps);
ccx_common_logging.log_ftn ("\rXDS: %s\n",rcd);
}
dbg_print(CCX_DMT_XDS, "\rXDS: %s\n",copy_permited);
dbg_print(CCX_DMT_XDS, "\rXDS: %s\n",aps);
dbg_print(CCX_DMT_XDS, "\rXDS: %s\n",rcd);
ccx_common_logging.debug_ftn(CCX_DMT_DECODER_XDS, "\rXDS: %s\n",copy_permited);
ccx_common_logging.debug_ftn(CCX_DMT_DECODER_XDS, "\rXDS: %s\n",aps);
ccx_common_logging.debug_ftn(CCX_DMT_DECODER_XDS, "\rXDS: %s\n",rcd);
}
void xds_do_content_advisory (struct cc_subtitle *sub, unsigned c1, unsigned c2)
@@ -523,32 +537,32 @@ void xds_do_content_advisory (struct cc_subtitle *sub, unsigned c1, unsigned c2)
// Bits a1 and a0 determine the encoding. I'll add parsing as more samples become available
if (!a1 && a0) // US TV parental guidelines
{
if (ccx_options.transcript_settings.xds)
if (ccx_decoders_xds_context.transcriptFormat.xds)
{
xdsprint(sub, age);
xdsprint(sub, content);
}
if (changed)
{
mprint ("\rXDS: %s\n ",age);
mprint ("\rXDS: %s\n ",content);
ccx_common_logging.log_ftn ("\rXDS: %s\n ",age);
ccx_common_logging.log_ftn ("\rXDS: %s\n ",content);
}
dbg_print(CCX_DMT_XDS, "\rXDS: %s\n",age);
dbg_print(CCX_DMT_XDS, "\rXDS: %s\n",content);
ccx_common_logging.debug_ftn(CCX_DMT_DECODER_XDS, "\rXDS: %s\n",age);
ccx_common_logging.debug_ftn(CCX_DMT_DECODER_XDS, "\rXDS: %s\n",content);
}
if (!a0 || // MPA
(a0 && a1 && !Da2 && !La3) // Canadian English Language Rating
)
{
if (ccx_options.transcript_settings.xds)
if (ccx_decoders_xds_context.transcriptFormat.xds)
xdsprint(sub, rating);
if (changed)
mprint ("\rXDS: %s\n ",rating);
dbg_print(CCX_DMT_XDS, "\rXDS: %s\n",rating);
ccx_common_logging.log_ftn ("\rXDS: %s\n ",rating);
ccx_common_logging.debug_ftn(CCX_DMT_DECODER_XDS, "\rXDS: %s\n",rating);
}
if (changed && !supported)
mprint ("XDS: Unsupported ContentAdvisory encoding, please submit sample.\n");
ccx_common_logging.log_ftn ("XDS: Unsupported ContentAdvisory encoding, please submit sample.\n");
}
@@ -586,20 +600,19 @@ int xds_do_current_and_future (struct cc_subtitle *sub)
current_xds_month=month;
}
dbg_print(CCX_DMT_XDS, "PIN (Start Time): %s %02d-%02d %02d:%02d\n",
ccx_common_logging.debug_ftn(CCX_DMT_DECODER_XDS, "PIN (Start Time): %s %02d-%02d %02d:%02d\n",
(cur_xds_packet_class==XDS_CLASS_CURRENT?"Current":"Future"),
date,month,hour,min);
if (ccx_options.transcript_settings.xds)
if (ccx_decoders_xds_context.transcriptFormat.xds)
xdsprint (sub, "PIN (Start Time): %s %02d-%02d %02d:%02d\n",
(cur_xds_packet_class==XDS_CLASS_CURRENT?"Current":"Future"),
date,month,hour,min);
if (!xds_start_time_shown && cur_xds_packet_class==XDS_CLASS_CURRENT)
{
mprint ("\rXDS: Program changed.\n");
mprint ("XDS program start time (DD/MM HH:MM) %02d-%02d %02d:%02d\n",date,month,hour,min);
activity_xds_program_identification_number (current_xds_min,
current_xds_hour, current_xds_date, current_xds_month);
ccx_common_logging.log_ftn("\rXDS: Program changed.\n");
ccx_common_logging.log_ftn ("XDS program start time (DD/MM HH:MM) %02d-%02d %02d:%02d\n",date,month,hour,min);
ccx_common_logging.gui_ftn(CCX_COMMON_LOGGING_GUI_XDS_PROGRAM_ID_NR, current_xds_min, current_xds_hour, current_xds_date, current_xds_month);
xds_start_time_shown=1;
}
}
@@ -612,11 +625,11 @@ int xds_do_current_and_future (struct cc_subtitle *sub)
int min=cur_xds_payload[2] & 0x3f; // 6 bits
int hour = cur_xds_payload[3] & 0x1f; // 5 bits
if (!xds_program_length_shown)
mprint ("\rXDS: Program length (HH:MM): %02d:%02d ",hour,min);
ccx_common_logging.log_ftn ("\rXDS: Program length (HH:MM): %02d:%02d ",hour,min);
else
dbg_print(CCX_DMT_XDS, "\rXDS: Program length (HH:MM): %02d:%02d ",hour,min);
ccx_common_logging.debug_ftn(CCX_DMT_DECODER_XDS, "\rXDS: Program length (HH:MM): %02d:%02d ",hour,min);
if (ccx_options.transcript_settings.xds)
if (ccx_decoders_xds_context.transcriptFormat.xds)
xdsprint(sub, "Program length (HH:MM): %02d:%02d ",hour,min);
if (cur_xds_payload_length>6) // Next two bytes (optional) available
@@ -624,10 +637,10 @@ int xds_do_current_and_future (struct cc_subtitle *sub)
int el_min=cur_xds_payload[4] & 0x3f; // 6 bits
int el_hour = cur_xds_payload[5] & 0x1f; // 5 bits
if (!xds_program_length_shown)
mprint ("Elapsed (HH:MM): %02d:%02d",el_hour,el_min);
ccx_common_logging.log_ftn ("Elapsed (HH:MM): %02d:%02d",el_hour,el_min);
else
dbg_print(CCX_DMT_XDS, "Elapsed (HH:MM): %02d:%02d",el_hour,el_min);
if (ccx_options.transcript_settings.xds)
ccx_common_logging.debug_ftn(CCX_DMT_DECODER_XDS, "Elapsed (HH:MM): %02d:%02d",el_hour,el_min);
if (ccx_decoders_xds_context.transcriptFormat.xds)
xdsprint(sub, "Elapsed (HH:MM): %02d:%02d",el_hour,el_min);
}
@@ -635,14 +648,14 @@ int xds_do_current_and_future (struct cc_subtitle *sub)
{
int el_sec=cur_xds_payload[6] & 0x3f; // 6 bits
if (!xds_program_length_shown)
dbg_print(CCX_DMT_XDS, ":%02d",el_sec);
if (ccx_options.transcript_settings.xds)
ccx_common_logging.debug_ftn(CCX_DMT_DECODER_XDS, ":%02d",el_sec);
if (ccx_decoders_xds_context.transcriptFormat.xds)
xdsprint(sub, "Elapsed (SS) :%02d",el_sec);
}
if (!xds_program_length_shown)
mprint("\n");
ccx_common_logging.log_ftn("\n");
else
dbg_print(CCX_DMT_XDS, "\n");
ccx_common_logging.debug_ftn(CCX_DMT_DECODER_XDS, "\n");
xds_program_length_shown=1;
}
break;
@@ -654,16 +667,16 @@ int xds_do_current_and_future (struct cc_subtitle *sub)
for (i=2;i<cur_xds_payload_length-1;i++)
xds_program_name[i-2]=cur_xds_payload[i];
xds_program_name[i-2]=0;
dbg_print(CCX_DMT_XDS, "\rXDS Program name: %s\n",xds_program_name);
if (ccx_options.transcript_settings.xds)
ccx_common_logging.debug_ftn(CCX_DMT_DECODER_XDS, "\rXDS Program name: %s\n",xds_program_name);
if (ccx_decoders_xds_context.transcriptFormat.xds)
xdsprint(sub, "Program name: %s",xds_program_name);
if (cur_xds_packet_class==XDS_CLASS_CURRENT &&
strcmp (xds_program_name, current_xds_program_name)) // Change of program
{
if (!ccx_options.gui_mode_reports)
mprint ("\rXDS Notice: Program is now %s\n", xds_program_name);
//if (!ccx_options.gui_mode_reports)
ccx_common_logging.log_ftn ("\rXDS Notice: Program is now %s\n", xds_program_name);
strncpy (current_xds_program_name,xds_program_name, 33);
activity_xds_program_name (xds_program_name);
ccx_common_logging.gui_ftn(CCX_COMMON_LOGGING_GUI_XDS_PROGRAM_NAME, xds_program_name);
}
break;
}
@@ -684,14 +697,14 @@ int xds_do_current_and_future (struct cc_subtitle *sub)
}
}
}
if (!(ccx_options.debug_mask & CCX_DMT_XDS) && current_program_type_reported &&
ccx_options.transcript_settings.xds == 0)
//ccx_options.export_xds==0)
if (!(ccx_common_logging.debug_mask & CCX_DMT_DECODER_XDS) && current_program_type_reported &&
ccx_decoders_xds_context.transcriptFormat.xds == 0){
break;
}
memcpy (current_xds_program_type,cur_xds_payload,cur_xds_payload_length);
current_xds_program_type[cur_xds_payload_length]=0;
if (!current_program_type_reported)
mprint ("\rXDS Program Type: ");
ccx_common_logging.log_ftn ("\rXDS Program Type: ");
*str = '\0';
tstr = str;
@@ -700,8 +713,8 @@ int xds_do_current_and_future (struct cc_subtitle *sub)
if (cur_xds_payload[i]==0) // Padding
continue;
if (!current_program_type_reported)
mprint ("[%02X-", cur_xds_payload[i]);
if (ccx_options.transcript_settings.xds)
ccx_common_logging.log_ftn ("[%02X-", cur_xds_payload[i]);
if (ccx_decoders_xds_context.transcriptFormat.xds)
{
if (cur_xds_payload[i]>=0x20 && cur_xds_payload[i]<0x7F)
{
@@ -712,16 +725,16 @@ int xds_do_current_and_future (struct cc_subtitle *sub)
if (!current_program_type_reported)
{
if (cur_xds_payload[i]>=0x20 && cur_xds_payload[i]<0x7F)
mprint ("%s",XDSProgramTypes[cur_xds_payload[i]-0x20]);
ccx_common_logging.log_ftn ("%s",XDSProgramTypes[cur_xds_payload[i]-0x20]);
else
mprint ("ILLEGAL VALUE");
mprint ("] ");
ccx_common_logging.log_ftn ("ILLEGAL VALUE");
ccx_common_logging.log_ftn ("] ");
}
}
if (ccx_options.transcript_settings.xds)
if (ccx_decoders_xds_context.transcriptFormat.xds)
xdsprint(sub,"Program type %s",str);
if (!current_program_type_reported)
mprint ("\n");
ccx_common_logging.log_ftn ("\n");
current_program_type_reported=1;
break;
case XDS_TYPE_CONTENT_ADVISORY:
@@ -761,16 +774,16 @@ int xds_do_current_and_future (struct cc_subtitle *sub)
changed=1;
if (changed)
{
mprint ("\rXDS description line %d: %s\n",line_num,xds_desc);
ccx_common_logging.log_ftn ("\rXDS description line %d: %s\n",line_num,xds_desc);
strcpy (xds_program_description[line_num], xds_desc);
}
else
{
dbg_print(CCX_DMT_XDS, "\rXDS description line %d: %s\n",line_num,xds_desc);
ccx_common_logging.debug_ftn(CCX_DMT_DECODER_XDS, "\rXDS description line %d: %s\n",line_num,xds_desc);
}
if (ccx_options.transcript_settings.xds)
if (ccx_decoders_xds_context.transcriptFormat.xds)
xdsprint(sub, "XDS description line %d: %s",line_num,xds_desc);
activity_xds_program_description (line_num, xds_desc);
ccx_common_logging.gui_ftn(CCX_COMMON_LOGGING_GUI_XDS_PROGRAM_DESCRIPTION, line_num, xds_desc);
}
break;
}
@@ -792,12 +805,12 @@ int xds_do_channel (struct cc_subtitle *sub)
for (i=2;i<cur_xds_payload_length-1;i++)
xds_network_name[i-2]=cur_xds_payload[i];
xds_network_name[i-2]=0;
dbg_print(CCX_DMT_XDS, "XDS Network name: %s\n",xds_network_name);
if (ccx_options.transcript_settings.xds)
ccx_common_logging.debug_ftn(CCX_DMT_DECODER_XDS, "XDS Network name: %s\n",xds_network_name);
if (ccx_decoders_xds_context.transcriptFormat.xds)
xdsprint (sub, "Network: %s",xds_network_name);
if (strcmp (xds_network_name, current_xds_network_name)) // Change of station
{
mprint ("XDS Notice: Network is now %s\n", xds_network_name);
ccx_common_logging.log_ftn ("XDS Notice: Network is now %s\n", xds_network_name);
strcpy (current_xds_network_name,xds_network_name);
}
break;
@@ -813,14 +826,14 @@ int xds_do_channel (struct cc_subtitle *sub)
xds_call_letters[i-2]=cur_xds_payload[i];
}
xds_call_letters[i-2]=0;
dbg_print(CCX_DMT_XDS, "XDS Network call letters: %s\n",xds_call_letters);
if (ccx_options.transcript_settings.xds)
ccx_common_logging.debug_ftn(CCX_DMT_DECODER_XDS, "XDS Network call letters: %s\n",xds_call_letters);
if (ccx_decoders_xds_context.transcriptFormat.xds)
xdsprint (sub, "Call Letters: %s",xds_call_letters);
if (strncmp (xds_call_letters, current_xds_call_letters, 7)) // Change of station
{
mprint ("XDS Notice: Network call letters now %s\n", xds_call_letters);
ccx_common_logging.log_ftn ("XDS Notice: Network call letters now %s\n", xds_call_letters);
strncpy (current_xds_call_letters, xds_call_letters, 7);
activity_xds_network_call_letters (current_xds_call_letters);
ccx_common_logging.gui_ftn(CCX_COMMON_LOGGING_GUI_XDS_CALL_LETTERS, current_xds_call_letters);
}
}
break;
@@ -835,7 +848,7 @@ int xds_do_channel (struct cc_subtitle *sub)
unsigned b3=(cur_xds_payload[4])&0x10;
unsigned b4=(cur_xds_payload[5])&0x10;
unsigned tsid=(b4<<12) | (b3<<8) | (b2<<4) | b1;
if (tsid && ccx_options.transcript_settings.xds)
if (tsid && ccx_decoders_xds_context.transcriptFormat.xds)
xdsprint (sub, "TSID: %u",tsid);
break;
}
@@ -874,7 +887,7 @@ int xds_do_misc ()
int reset_seconds = (cur_xds_payload[5] & 0x20);
int day_of_week = cur_xds_payload[6] & 0x7;
int year = (cur_xds_payload[7] & 0x3f) + 1990;
dbg_print(CCX_DMT_XDS, "Time of day: (YYYY/MM/DD) %04d/%02d/%02d (HH:SS) %02d:%02d DoW: %d Reset seconds: %d\n",
ccx_common_logging.debug_ftn(CCX_DMT_DECODER_XDS, "Time of day: (YYYY/MM/DD) %04d/%02d/%02d (HH:SS) %02d:%02d DoW: %d Reset seconds: %d\n",
year,month,date,hour,min, day_of_week, reset_seconds);
break;
}
@@ -886,7 +899,7 @@ int xds_do_misc ()
// int b6 = (cur_xds_payload[2] & 0x40) >>6; // Bit 6 should always be 1
int dst = (cur_xds_payload[2] & 0x20) >>5; // Daylight Saving Time
int hour = cur_xds_payload[2] & 0x1f; // 5 bits
dbg_print(CCX_DMT_XDS, "Local Time Zone: %02d DST: %d\n",
ccx_common_logging.debug_ftn(CCX_DMT_DECODER_XDS, "Local Time Zone: %02d DST: %d\n",
hour, dst);
break;
}
@@ -914,19 +927,19 @@ void do_end_of_xds (struct cc_subtitle *sub, unsigned char expected_checksum)
cs=cs+cur_xds_payload[i];
cs=cs & 0x7f; // Keep 7 bits only
int c=cur_xds_payload[i]&0x7F;
dbg_print(CCX_DMT_XDS, "%02X - %c cs: %02X\n",
ccx_common_logging.debug_ftn(CCX_DMT_DECODER_XDS, "%02X - %c cs: %02X\n",
c,(c>=0x20)?c:'?', cs);
}
cs=(128-cs) & 0x7F; // Convert to 2's complement & discard high-order bit
dbg_print(CCX_DMT_XDS, "End of XDS. Class=%d (%s), size=%d Checksum OK: %d Used buffers: %d\n",
ccx_common_logging.debug_ftn(CCX_DMT_DECODER_XDS, "End of XDS. Class=%d (%s), size=%d Checksum OK: %d Used buffers: %d\n",
cur_xds_packet_class,XDSclasses[cur_xds_packet_class],
cur_xds_payload_length,
cs==expected_checksum, how_many_used());
if (cs!=expected_checksum || cur_xds_payload_length<3)
{
dbg_print(CCX_DMT_XDS, "Expected checksum: %02X Calculated: %02X\n", expected_checksum, cs);
ccx_common_logging.debug_ftn(CCX_DMT_DECODER_XDS, "Expected checksum: %02X Calculated: %02X\n", expected_checksum, cs);
clear_xds_buffer (cur_xds_buffer_idx);
return; // Bad packets ignored as per specs
}
@@ -940,7 +953,7 @@ void do_end_of_xds (struct cc_subtitle *sub, unsigned char expected_checksum)
switch (cur_xds_packet_class)
{
case XDS_CLASS_FUTURE: // Info on future program
if (!(ccx_options.debug_mask & CCX_DMT_XDS)) // Don't bother processing something we don't need
if (!(ccx_common_logging.debug_mask & CCX_DMT_DECODER_XDS)) // Don't bother processing something we don't need
{
was_proc=1;
break;
@@ -958,18 +971,18 @@ void do_end_of_xds (struct cc_subtitle *sub, unsigned char expected_checksum)
case XDS_CLASS_PRIVATE: // CEA-608:
// The Private Data Class is for use in any closed system for whatever that
// system wishes. It shall not be defined by this standard now or in the future.
if (ccx_options.transcript_settings.xds)
if (ccx_decoders_xds_context.transcriptFormat.xds)
was_proc=xds_do_private_data(sub);
break;
case XDS_CLASS_OUT_OF_BAND:
dbg_print(CCX_DMT_XDS, "Out-of-band data, ignored.");
ccx_common_logging.debug_ftn(CCX_DMT_DECODER_XDS, "Out-of-band data, ignored.");
was_proc = 1;
break;
}
if (!was_proc)
{
mprint ("Note: We found an currently unsupported XDS packet.\n");
ccx_common_logging.log_ftn ("Note: We found an currently unsupported XDS packet.\n");
}
clear_xds_buffer (cur_xds_buffer_idx);

15
src/ccx_decoders_xds.h Normal file
View File

@@ -0,0 +1,15 @@
#ifndef _XDS_H
#define _XDS_H
#include "ccx_decoders_common.h"
#include "ccx_encoders_common.h"
void process_xds_bytes(const unsigned char hi, int lo);
void do_end_of_xds(struct cc_subtitle *sub, unsigned char expected_checksum);
void ccx_decoders_xds_init_library(ccx_encoders_transcript_format *transcriptSettings, LLONG subs_delay, char millis_separator);
void xds_write_transcript_line_suffix (struct ccx_s_write *wb);
void xds_write_transcript_line_prefix (struct ccx_s_write *wb, LLONG start_time, LLONG end_time, int cur_xds_packet_class);
#endif

View File

@@ -1,11 +1,25 @@
#include "ccextractor.h"
#include "cc_decoders_common.h"
#include "cc_encoders_common.h"
//#include "ccextractor.h"
#include "ccx_decoders_common.h"
#include "ccx_encoders_common.h"
#include "spupng_encoder.h"
#include "608_spupng.h"
#include "utility.h"
#include "xds.h"
#include "ocr.h"
#include "ccx_decoders_608.h"
#include "ccx_decoders_xds.h"
// These are the default settings for plain transcripts. No times, no CC or caption mode, and no XDS.
ccx_encoders_transcript_format ccx_encoders_default_transcript_settings =
{
.showStartTime = 0,
.showEndTime = 0,
.showMode = 0,
.showCC = 0,
.relativeTimestamp = 1,
.xds = 0,
.useColors = 1,
.isFinal = 0
};
static const char *sami_header= // TODO: Revise the <!-- comments
"<SAMI>\n\
@@ -34,7 +48,7 @@ void write_subtitle_file_footer(struct encoder_ctx *ctx,struct ccx_s_write *out)
sprintf ((char *) str,"</BODY></SAMI>\n");
if (ccx_options.encoding!=CCX_ENC_UNICODE)
{
dbg_print(CCX_DMT_608, "\r%s\n", str);
dbg_print(CCX_DMT_DECODER_608, "\r%s\n", str);
}
used=encode_line (ctx->buffer,(unsigned char *) str);
write(out->fh, ctx->buffer, used);
@@ -43,7 +57,7 @@ void write_subtitle_file_footer(struct encoder_ctx *ctx,struct ccx_s_write *out)
sprintf ((char *) str,"</div></body></tt>\n");
if (ccx_options.encoding!=CCX_ENC_UNICODE)
{
dbg_print(CCX_DMT_608, "\r%s\n", str);
dbg_print(CCX_DMT_DECODER_608, "\r%s\n", str);
}
used=encode_line (ctx->buffer,(unsigned char *) str);
write (out->fh, ctx->buffer,used);
@@ -76,10 +90,13 @@ void write_subtitle_file_header(struct encoder_ctx *ctx,struct ccx_s_write *out)
write(out->fh, ctx->buffer, used);
break;
case CCX_OF_RCWT: // Write header
write(out->fh, rcwt_header, sizeof(rcwt_header));
if (ccx_options.teletext_mode == CCX_TXT_IN_USE)
rcwt_header[7] = 2; // sets file format version
if (ccx_options.send_to_srv)
net_send_header(rcwt_header, sizeof(rcwt_header));
else
write(out->fh, rcwt_header, sizeof(rcwt_header));
break;
case CCX_OF_SPUPNG:
@@ -103,11 +120,11 @@ void write_cc_line_as_transcript2(struct eia608_screen *data, struct encoder_ctx
capitalize (line_number,data);
correct_case(line_number,data);
}
int length = get_decoder_line_basic (subline, line_number, data);
int length = get_decoder_line_basic (subline, line_number, data,ccx_options.trim_subs,ccx_options.encoding);
if (ccx_options.encoding!=CCX_ENC_UNICODE)
{
dbg_print(CCX_DMT_608, "\r");
dbg_print(CCX_DMT_608, "%s\n",subline);
dbg_print(CCX_DMT_DECODER_608, "\r");
dbg_print(CCX_DMT_DECODER_608, "%s\n",subline);
}
if (length>0)
{
@@ -193,7 +210,7 @@ void write_cc_line_as_transcript2(struct eia608_screen *data, struct encoder_ctx
int write_cc_buffer_as_transcript2(struct eia608_screen *data, struct encoder_ctx *context)
{
int wrote_something = 0;
dbg_print(CCX_DMT_608, "\n- - - TRANSCRIPT caption - - -\n");
dbg_print(CCX_DMT_DECODER_608, "\n- - - TRANSCRIPT caption - - -\n");
for (int i=0;i<15;i++)
{
@@ -203,7 +220,7 @@ int write_cc_buffer_as_transcript2(struct eia608_screen *data, struct encoder_ct
}
wrote_something=1;
}
dbg_print(CCX_DMT_608, "- - - - - - - - - - - -\r\n");
dbg_print(CCX_DMT_DECODER_608, "- - - - - - - - - - - -\r\n");
return wrote_something;
}
int write_cc_bitmap_as_transcript(struct cc_subtitle *sub, struct encoder_ctx *context)
@@ -212,18 +229,20 @@ int write_cc_bitmap_as_transcript(struct cc_subtitle *sub, struct encoder_ctx *c
int x_pos, y_pos, width, height, i;
int x, y, y_off, x_off, ret;
uint8_t *pbuf;
char *filename;
//char *filename;
struct cc_bitmap* rect;
png_color *palette = NULL;
png_byte *alpha = NULL;
#ifdef ENABLE_OCR
char*str = NULL;
#endif
int used;
//int used;
#ifdef ENABLE_OCR
unsigned h1,m1,s1,ms1;
unsigned h2,m2,s2,ms2;
#endif
LLONG start_time, end_time;
char timeline[128];
//char timeline[128];
int len = 0;
x_pos = -1;
@@ -505,14 +524,17 @@ int encode_sub(struct encoder_ctx *context, struct cc_subtitle *sub)
{
int wrote_something = 0 ;
if (ccx_options.extract!=1)
context++;
if (sub->type == CC_608)
{
struct eia608_screen *data = NULL;
for(data = sub->data; sub->nb_data ; sub->nb_data--,data++)
{
// Determine context based on channel. This replaces the code that was above, as this was incomplete (for cases where -12 was used for example)
//if (ccx_options.extract!=1)
//context++;
if (data->my_field == 2)
context++;
new_sentence=1;
if(data->format == SFORMAT_XDS)
@@ -592,3 +614,52 @@ int encode_sub(struct encoder_ctx *context, struct cc_subtitle *sub)
freep(&sub->data);
return wrote_something;
}
void write_cc_buffer_to_gui(struct eia608_screen *data, struct encoder_ctx *context)
{
unsigned h1, m1, s1, ms1;
unsigned h2, m2, s2, ms2;
LLONG ms_start;
int with_data = 0;
for (int i = 0; i<15; i++)
{
if (data->row_used[i])
with_data = 1;
}
if (!with_data)
return;
ms_start = data->start_time;
ms_start += subs_delay;
if (ms_start<0) // Drop screens that because of subs_delay start too early
return;
int time_reported = 0;
for (int i = 0; i<15; i++)
{
if (data->row_used[i])
{
fprintf(stderr, "###SUBTITLE#");
if (!time_reported)
{
LLONG 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.
// Note, only MM:SS here as we need to save space in the preview window
fprintf(stderr, "%02u:%02u#%02u:%02u#",
h1 * 60 + m1, s1, h2 * 60 + m2, s2);
time_reported = 1;
}
else
fprintf(stderr, "##");
// We don't capitalize here because whatever function that was used
// before to write to file already took care of it.
int length = get_decoder_line_encoded_for_gui(subline, i, data);
fwrite(subline, 1, length, stderr);
fwrite("\n", 1, 1, stderr);
}
}
fflush(stderr);
}

View File

@@ -1,21 +1,33 @@
#ifndef _CC_ENCODER_COMMON_H
#define _CC_ENCODER_COMMON_H
#include "ccx_common_structs.h"
#include "ccx_decoders_structs.h"
#include "ccx_encoders_structs.h"
#include "ccx_encoders_helpers.h"
#define REQUEST_BUFFER_CAPACITY(ctx,length) if (length>ctx->capacity) \
{ctx->capacity = length * 2; ctx->buffer = (unsigned char*)realloc(ctx->buffer, ctx->capacity); \
if (ctx->buffer == NULL) { fatal(EXIT_NOT_ENOUGH_MEMORY, "Not enough memory, bailing out\n"); } \
}
extern ccx_encoders_transcript_format ccx_encoders_default_transcript_settings;
/**
* Context of encoder, This structure gives single interface
* to all encoder
*/
struct encoder_ctx
{
/** common buffer used by all encoder */
/* common buffer used by all encoder */
unsigned char *buffer;
/** capacity of buffer */
/* capacity of buffer */
unsigned int capacity;
/* keep count of srt subtitle*/
unsigned int srt_counter;
/** output contet */
/* output context */
struct ccx_s_write *out;
/** start time of previous sub */
/* start time of previous sub */
LLONG prev_start;
};
@@ -64,4 +76,6 @@ int write_cc_bitmap_as_spupng(struct cc_subtitle *sub, struct encoder_ctx *conte
int write_cc_bitmap_as_srt(struct cc_subtitle *sub, struct encoder_ctx *context);
int write_cc_bitmap_as_sami(struct cc_subtitle *sub, struct encoder_ctx *context);
int write_cc_bitmap_as_smptett(struct cc_subtitle *sub, struct encoder_ctx *context);
#endif

391
src/ccx_encoders_helpers.c Normal file
View File

@@ -0,0 +1,391 @@
#include "ccx_encoders_helpers.h"
#include "ccx_common_char_encoding.h"
#include "ccx_common_constants.h"
#include "ccx_common_structs.h"
#include "ccx_decoders_common.h"
#ifdef _MSC_VER
#define strcasecmp stricmp
#endif
// userdefined rgb color
unsigned char usercolor_rgb[8] = "";
static int spell_builtin_added = 0; // so we don't do it twice
// Case arrays
char **spell_lower = NULL;
char **spell_correct = NULL;
int spell_words = 0;
int spell_capacity = 0;
// Some basic English words, so user-defined doesn't have to
// include the common stuff
static const char *spell_builtin[] =
{
"I", "I'd", "I've", "I'd", "I'll",
"January", "February", "March", "April", // May skipped intentionally
"June", "July", "August", "September", "October", "November",
"December", "Monday", "Tuesday", "Wednesday", "Thursday",
"Friday", "Saturday", "Sunday", "Halloween", "United States",
"Spain", "France", "Italy", "England",
NULL
};
int string_cmp2(const void *p1, const void *p2, void *arg)
{
return strcasecmp(*(char**)p1, *(char**)p2);
}
int string_cmp(const void *p1, const void *p2)
{
return string_cmp2(p1, p2, NULL);
}
void correct_case(int line_num, struct eia608_screen *data)
{
char delim[64] = {
' ', '\n', '\r', 0x89, 0x99,
'!', '"', '#', '%', '&',
'\'', '(', ')', ';', '<',
'=', '>', '?', '[', '\\',
']', '*', '+', ',', '-',
'.', '/', ':', '^', '_',
'{', '|', '}', '~', '\0' };
char *line = strdup(((char*)data->characters[line_num]));
char *oline = (char*)data->characters[line_num];
char *c = strtok(line, delim);
do
{
char **index = bsearch(&c, spell_lower, spell_words, sizeof(*spell_lower), string_cmp);
if (index)
{
char *correct_c = *(spell_correct + (index - spell_lower));
size_t len = strlen(correct_c);
memcpy(oline + (c - line), correct_c, len);
}
} while ((c = strtok(NULL, delim)) != NULL);
free(line);
}
void capitalize(int line_num, struct eia608_screen *data)
{
for (int i = 0; i<CCX_DECODER_608_SCREEN_WIDTH; i++)
{
switch (data->characters[line_num][i])
{
case ' ':
case 0x89: // This is a transparent space
case '-':
break;
case '.': // Fallthrough
case '?': // Fallthrough
case '!':
case ':':
new_sentence = 1;
break;
default:
if (new_sentence)
data->characters[line_num][i] = cctoupper(data->characters[line_num][i]);
else
data->characters[line_num][i] = cctolower(data->characters[line_num][i]);
new_sentence = 0;
break;
}
}
}
// Encodes a generic string. Note that since we use the encoders for closed caption
// data, text would have to be encoded as CCs... so using special characters here
// it's a bad idea.
unsigned encode_line(unsigned char *buffer, unsigned char *text)
{
unsigned bytes = 0;
while (*text)
{
switch (ccx_encoders_helpers_settings.encoding)
{
case CCX_ENC_UTF_8:
case CCX_ENC_LATIN_1:
*buffer = *text;
bytes++;
buffer++;
break;
case CCX_ENC_UNICODE:
*buffer = *text;
*(buffer + 1) = 0;
bytes += 2;
buffer += 2;
break;
}
text++;
}
return bytes;
}
unsigned get_decoder_line_encoded_for_gui(unsigned char *buffer, int line_num, struct eia608_screen *data)
{
unsigned char *line = data->characters[line_num];
unsigned char *orig = buffer; // Keep for debugging
int first = 0, last = 31;
find_limit_characters(line, &first, &last);
for (int i = first; i <= last; i++)
{
get_char_in_latin_1(buffer, line[i]);
buffer++;
}
*buffer = 0;
return (unsigned)(buffer - orig); // Return length
}
unsigned char *close_tag(unsigned char *buffer, char *tagstack, char tagtype, int *punderlined, int *pitalics, int *pchanged_font)
{
for (int l = strlen(tagstack) - 1; l >= 0; l--)
{
char cur = tagstack[l];
switch (cur)
{
case 'F':
buffer += encode_line(buffer, (unsigned char *) "</font>");
(*pchanged_font)--;
break;
case 'U':
buffer += encode_line(buffer, (unsigned char *) "</u>");
(*punderlined)--;
break;
case 'I':
buffer += encode_line(buffer, (unsigned char *) "</i>");
(*pitalics)--;
break;
}
tagstack[l] = 0; // Remove from stack
if (cur == tagtype) // We closed up to the required tag, done
return buffer;
}
if (tagtype != 'A') // All
ccx_common_logging.fatal_ftn(CCX_COMMON_EXIT_BUG_BUG, "Mismatched tags in encoding, this is a bug, please report");
return buffer;
}
unsigned get_decoder_line_encoded(unsigned char *buffer, int line_num, struct eia608_screen *data)
{
int col = COL_WHITE;
int underlined = 0;
int italics = 0;
int changed_font = 0;
char tagstack[128] = ""; // Keep track of opening/closing tags
unsigned char *line = data->characters[line_num];
unsigned char *orig = buffer; // Keep for debugging
int first = 0, last = 31;
if (ccx_encoders_helpers_settings.trim_subs)
find_limit_characters(line, &first, &last);
for (int i = first; i <= last; i++)
{
// Handle color
int its_col = data->colors[line_num][i];
if (its_col != col && !ccx_encoders_helpers_settings.no_font_color &&
!(col == COL_USERDEFINED && its_col == COL_WHITE)) // Don't replace user defined with white
{
if (changed_font)
buffer = close_tag(buffer, tagstack, 'F', &underlined, &italics, &changed_font);
// Add new font tag
buffer += encode_line(buffer, (unsigned char*)color_text[its_col][1]);
if (its_col == COL_USERDEFINED)
{
// The previous sentence doesn't copy the whole
// <font> tag, just up to the quote before the color
buffer += encode_line(buffer, (unsigned char*)usercolor_rgb);
buffer += encode_line(buffer, (unsigned char*) "\">");
}
if (color_text[its_col][1][0]) // That means a <font> was added to the buffer
{
strcat(tagstack, "F");
changed_font++;
}
col = its_col;
}
// Handle underlined
int is_underlined = data->fonts[line_num][i] & FONT_UNDERLINED;
if (is_underlined && underlined == 0 && !ccx_encoders_helpers_settings.no_type_setting) // Open underline
{
buffer += encode_line(buffer, (unsigned char *) "<u>");
strcat(tagstack, "U");
underlined++;
}
if (is_underlined == 0 && underlined && !ccx_encoders_helpers_settings.no_type_setting) // Close underline
{
buffer = close_tag(buffer, tagstack, 'U', &underlined, &italics, &changed_font);
}
// Handle italics
int has_ita = data->fonts[line_num][i] & FONT_ITALICS;
if (has_ita && italics == 0 && !ccx_encoders_helpers_settings.no_type_setting) // Open italics
{
buffer += encode_line(buffer, (unsigned char *) "<i>");
strcat(tagstack, "I");
italics++;
}
if (has_ita == 0 && italics && !ccx_encoders_helpers_settings.no_type_setting) // Close italics
{
buffer = close_tag(buffer, tagstack, 'I', &underlined, &italics, &changed_font);
}
int bytes = 0;
switch (ccx_encoders_helpers_settings.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;
break;
}
buffer += bytes;
}
buffer = close_tag(buffer, tagstack, 'A', &underlined, &italics, &changed_font);
if (underlined || italics || changed_font)
ccx_common_logging.fatal_ftn(CCX_COMMON_EXIT_BUG_BUG, "Not all tags closed in encoding, this is a bug, please report.\n");
*buffer = 0;
return (unsigned)(buffer - orig); // Return length
}
/*void delete_all_lines_but_current(ccx_decoder_608_context *context, struct eia608_screen *data, int row)
{
for (int i=0;i<15;i++)
{
if (i!=row)
{
memset(data->characters[i], ' ', CCX_DECODER_608_SCREEN_WIDTH);
data->characters[i][CCX_DECODER_608_SCREEN_WIDTH] = 0;
memset(data->colors[i], context->settings.default_color, CCX_DECODER_608_SCREEN_WIDTH + 1);
memset(data->fonts[i], FONT_REGULAR, CCX_DECODER_608_SCREEN_WIDTH + 1);
data->row_used[i]=0;
}
}
}*/
/*void fprintf_encoded (struct encoder_ctx *ctx,FILE *fh, const char *string)
{
int used;
REQUEST_BUFFER_CAPACITY(ctx,strlen (string)*3);
used=encode_line (ctx->buffer,(unsigned char *) string);
fwrite (ctx->buffer,used,1,fh);
}*/
int add_word(const char *word)
{
char *new_lower;
char *new_correct;
char **ptr_lower;
char **ptr_correct;
int i;
if (spell_words == spell_capacity)
{
// Time to grow
spell_capacity += 50;
ptr_lower = (char **)realloc(spell_lower, sizeof (char *)*
spell_capacity);
ptr_correct = (char **)realloc(spell_correct, sizeof (char *)*
spell_capacity);
}
size_t len = strlen(word);
new_lower = (char *)malloc(len + 1);
new_correct = (char *)malloc(len + 1);
if (ptr_lower == NULL || ptr_correct == NULL ||
new_lower == NULL || new_correct == NULL)
{
spell_capacity = 0;
for (i = 0; i < spell_words; i++)
{
freep(&spell_lower[spell_words]);
freep(&spell_correct[spell_words]);
}
freep(&spell_lower);
freep(&spell_correct);
freep(&ptr_lower);
freep(&ptr_correct);
freep(&new_lower);
freep(&new_correct);
spell_words = 0;
return -1;
}
else
{
spell_lower = ptr_lower;
spell_correct = ptr_correct;
}
strcpy(new_correct, word);
for (size_t i = 0; i<len; i++)
{
char c = new_correct[i];
c = tolower(c); // TO-DO: Add Spanish characters
new_lower[i] = c;
}
new_lower[len] = 0;
spell_lower[spell_words] = new_lower;
spell_correct[spell_words] = new_correct;
spell_words++;
return 0;
}
int add_built_in_words()
{
if (!spell_builtin_added)
{
int i = 0;
while (spell_builtin[i] != NULL)
{
if (add_word(spell_builtin[i]))
return -1;
i++;
}
spell_builtin_added = 1;
}
return 0;
}
/**
* @param base points to the start of the array
* @param nb number of element in array
* @param size size of each element
* @param compar Comparison function, which is called with three argument
* that point to the objects being compared and arg.
* @param arg argument passed as it is to compare function
*/
void shell_sort(void *base, int nb, size_t size, int(*compar)(const void*p1, const void *p2, void*arg), void *arg)
{
unsigned char *lbase = (unsigned char*)base;
unsigned char *tmp = (unsigned char*)malloc(size);
for (int gap = nb / 2; gap > 0; gap = gap / 2)
{
int p, j;
for (p = gap; p < nb; p++)
{
memcpy(tmp, lbase + (p *size), size);
for (j = p; j >= gap && (compar(tmp, lbase + ((j - gap) * size), arg) < 0); j -= gap)
{
memcpy(lbase + (j*size), lbase + ((j - gap) * size), size);
}
memcpy(lbase + (j *size), tmp, size);
}
}
free(tmp);
}
void ccx_encoders_helpers_perform_shellsort_words(){
shell_sort(spell_lower, spell_words, sizeof(*spell_lower), string_cmp2, NULL);
shell_sort(spell_correct, spell_words, sizeof(*spell_correct), string_cmp2, NULL);
}
void ccx_encoders_helpers_setup(enum ccx_encoding_type encoding,int no_font_color,int no_type_setting,int trim_subs){
ccx_encoders_helpers_settings.encoding = encoding;
ccx_encoders_helpers_settings.no_font_color = no_font_color;
ccx_encoders_helpers_settings.no_type_setting = no_type_setting;
ccx_encoders_helpers_settings.trim_subs = trim_subs;
}

View File

@@ -0,0 +1,38 @@
#ifndef _CCX_ENCODERS_HELPERS_H
#define _CCX_ENCODERS_HELPERS_H
#include "ccx_common_common.h"
#include "ccx_common_constants.h"
#include "ccx_decoders_structs.h"
#include "ccx_decoders_608.h"
extern char **spell_lower;
extern char **spell_correct;
extern int spell_words;
extern int spell_capacity;
extern unsigned char usercolor_rgb[8];
struct ccx_encoders_helpers_settings_t {
int trim_subs;
int no_font_color;
int no_type_setting;
enum ccx_encoding_type encoding;
} ccx_encoders_helpers_settings;
// Helper functions
void correct_case(int line_num, struct eia608_screen *data);
void capitalize(int line_num, struct eia608_screen *data);
unsigned get_decoder_line_encoded_for_gui(unsigned char *buffer, int line_num, struct eia608_screen *data);
unsigned get_decoder_line_encoded(unsigned char *buffer, int line_num, struct eia608_screen *data);
int string_cmp(const void *p1, const void *p2);
int string_cmp2(const void *p1, const void *p2, void *arg);
int add_built_in_words();
int add_word(const char *word);
void shell_sort(void *base, int nb, size_t size, int(*compar)(const void*p1, const void *p2, void*arg), void *arg);
void ccx_encoders_helpers_perform_shellsort_words();
void ccx_encoders_helpers_setup(enum ccx_encoding_type encoding, int no_font_color, int no_type_setting, int trim_subs);
#endif

View File

@@ -0,0 +1,25 @@
#ifndef CCX_ENCODERS_STRUCTS_H
typedef struct {
// TODO: add more options, and (perhaps) reduce other ccextractor options?
int showStartTime, showEndTime; // Show start and/or end time.
int showMode; // Show which mode if available (E.G.: POP, RU1, ...)
int showCC; // Show which CC channel has been captured.
int relativeTimestamp; // Timestamps relative to start of sample or in UTC?
int xds; // Show XDS or not
int useColors; // Add colors or no colors
int isFinal; // Used to determine if these parameters should be changed afterwards.
} ccx_encoders_transcript_format;
struct ccx_s_write
{
int multiple_files;
char *first_input_file;
int fh;
char *filename;
void* spupng_data;
};
#define CCX_ENCODERS_STRUCTS_H
#endif

View File

@@ -43,8 +43,7 @@ static int set_int(void *var, char*val)
struct conf_map configuration_map[] = {
{"INPUT_SOURCE",offsetof(struct ccx_s_options,input_source),set_int},
{"BUFFER_INPUT",offsetof(struct ccx_s_options,buffer_input),set_int},
{"DIRECT_ROLLUP",offsetof(struct ccx_s_options,direct_rollup),set_int},
{"BUFFER_INPUT",offsetof(struct ccx_s_options,buffer_input),set_int},
{"NOFONT_COLOR",offsetof(struct ccx_s_options,nofontcolor),set_int},
{"NOTYPE_SETTING",offsetof(struct ccx_s_options,notypesetting),set_int},
{"CODEC",offsetof(struct ccx_s_options,codec),set_int},
@@ -60,9 +59,7 @@ struct conf_map configuration_map[] = {
{"END_CREDITS_FOR_ATMOST",offsetof(struct ccx_s_options,endcreditsforatmost),set_time},
{"VIDEO_EDITED",offsetof(struct ccx_s_options,binary_concat),set_int},
{"GOP_TIME",offsetof(struct ccx_s_options,use_gop_as_pts),set_int},
{"FIX_PADDINDG",offsetof(struct ccx_s_options,fix_padding),set_int},
{"NO_ROLL_UP",offsetof(struct ccx_s_options,norollup),set_int},
{"FORCED_RU",offsetof(struct ccx_s_options,forced_ru),set_int},
{"FIX_PADDINDG",offsetof(struct ccx_s_options,fix_padding),set_int},
{"TRIM",offsetof(struct ccx_s_options,trim_subs),set_int},
{"GUI_MODE_REPORTS",offsetof(struct ccx_s_options,gui_mode_reports),set_int},
{"NO_PROGRESS_BAR",offsetof(struct ccx_s_options,no_progress_bar),set_int},
@@ -70,8 +67,7 @@ struct conf_map configuration_map[] = {
{"CAP_FILE",offsetof(struct ccx_s_options,sentence_cap_file),set_string},
{"PROGRAM_NUMBER",offsetof(struct ccx_s_options,ts_forced_program),set_int},
{"AUTO_PROGRAM",offsetof(struct ccx_s_options,ts_autoprogram),set_int},
{"STREAM",offsetof(struct ccx_s_options,live_stream),set_int},
{"SCREEN_TO_PROCESS",offsetof(struct ccx_s_options,screens_to_process),set_int},
{"STREAM",offsetof(struct ccx_s_options,live_stream),set_int},
{"START_AT",offsetof(struct ccx_s_options,extraction_start),set_time},
{"END_AT",offsetof(struct ccx_s_options,extraction_end),set_time},
{"INVASTIGATE_PACKET",offsetof(struct ccx_s_options,investigate_packets),set_int},
@@ -89,6 +85,12 @@ struct conf_map configuration_map[] = {
{"STREAM_TYPE",offsetof(struct ccx_s_options,ts_datastreamtype),set_int},
{"TS_FORCED_STREAM_TYPE",offsetof(struct ccx_s_options,ts_forced_streamtype),set_int},
{"DATE_FORMAT",offsetof(struct ccx_s_options,date_format),set_int},
// Settings for 608 decoder
{ "NO_ROLL_UP", offsetof(struct ccx_s_options, settings_608.no_rollup), set_int },
{ "FORCED_RU", offsetof(struct ccx_s_options, settings_608.force_rollup), set_int },
{ "DIRECT_ROLLUP", offsetof(struct ccx_s_options, settings_608.direct_rollup), set_int },
{ "SCREEN_TO_PROCESS", offsetof(struct ccx_s_options, settings_608.screens_to_process), set_int },
{NULL}
};
static int parse_opts(char *str, struct ccx_s_options *opt)

View File

@@ -24,7 +24,7 @@
#include "dvb_subtitle_decoder.h"
#include "utility.h"
#include "cc_decoders_common.h"
#include "ccx_decoders_common.h"
#define DVBSUB_PAGE_SEGMENT 0x10
#define DVBSUB_REGION_SEGMENT 0x11
@@ -1535,6 +1535,7 @@ int dvbsub_decode(void *dvb_ctx, const unsigned char *buf, int buf_size, struct
p = buf;
p_end = buf + buf_size;
set_fts();
while (p_end - p >= 6 && *p == 0x0f)
{
p += 1;

View File

@@ -350,7 +350,7 @@ static int read_seq_info(struct bitstream *esstream)
// We only get here after seeing that start code
if (next_u32(esstream) != 0xB3010000) // LSB first (0x000001B3)
fatal(EXIT_BUG_BUG, "read_seq_info: Impossible!");
fatal(CCX_COMMON_EXIT_BUG_BUG, "read_seq_info: Impossible!");
// If we get here esstream points to the start of a sequence_header_code
// should we run out of data in esstream this is where we want to restart
@@ -390,7 +390,7 @@ static int sequence_header(struct bitstream *esstream)
// We only get here after seeing that start code
if (read_u32(esstream) != 0xB3010000) // LSB first (0x000001B3)
fatal(EXIT_BUG_BUG, "Impossible!");
fatal(CCX_COMMON_EXIT_BUG_BUG, "Impossible!");
unsigned hor_size = (unsigned) read_bits(esstream,12);
unsigned vert_size = (unsigned) read_bits(esstream,12);
@@ -532,7 +532,7 @@ static int read_gop_info(struct bitstream *esstream, struct cc_subtitle *sub)
// We only get here after seeing that start code
if (next_u32(esstream) != 0xB8010000) // LSB first (0x000001B8)
fatal(EXIT_BUG_BUG, "Impossible!");
fatal(CCX_COMMON_EXIT_BUG_BUG, "Impossible!");
// If we get here esstream points to the start of a group_start_code
// should we run out of data in esstream this is where we want to restart
@@ -569,7 +569,7 @@ static int gop_header(struct bitstream *esstream, struct cc_subtitle *sub)
// We only get here after seeing that start code
if (read_u32(esstream) != 0xB8010000) // LSB first (0x000001B8)
fatal(EXIT_BUG_BUG, "Impossible!");
fatal(CCX_COMMON_EXIT_BUG_BUG, "Impossible!");
unsigned drop_frame_flag = (unsigned) read_bits(esstream,1);
struct gop_time_code gtc;
@@ -703,7 +703,7 @@ static int read_pic_info(struct bitstream *esstream, struct cc_subtitle *sub)
// We only get here after seeing that start code
if (next_u32(esstream) != 0x00010000) // LSB first (0x00000100)
fatal(EXIT_BUG_BUG, "Impossible!");
fatal(CCX_COMMON_EXIT_BUG_BUG, "Impossible!");
// If we get here esstream points to the start of a group_start_code
// should we run out of data in esstream this is where we want to restart
@@ -848,7 +848,7 @@ static int pic_header(struct bitstream *esstream)
// We only get here after seeing that start code
if (read_u32(esstream) != 0x00010000) // LSB first (0x00000100)
fatal(EXIT_BUG_BUG, "Impossible!");
fatal(CCX_COMMON_EXIT_BUG_BUG, "Impossible!");
temporal_reference = (int) read_bits(esstream,10);
picture_coding_type = (enum ccx_frame_type) read_bits(esstream,3);
@@ -952,7 +952,7 @@ static int read_eau_info(struct bitstream *esstream, int udtype, struct cc_subti
unsigned char *tst = next_bytes(esstream, 4);
if (!tst || tst[0]!=0x00 || tst[1]!=0x00 || tst[2]!=0x01
|| (tst[3]!=0xB2 && tst[3]!=0xB5) ) // (0x000001 B2||B5)
fatal(EXIT_BUG_BUG, "Impossible!");
fatal(CCX_COMMON_EXIT_BUG_BUG, "Impossible!");
// The following extension_and_user_data() function makes sure that
// user data is not evaluated twice. Should the function run out of

View File

@@ -19,7 +19,7 @@ int user_data(struct bitstream *ustream, int udtype, struct cc_subtitle *sub)
// ustream->error=1;
return 0; // Actually discarded on call.
// CFS: Seen in a Wobble edited file.
// fatal(EXIT_BUG_BUG, "user_data: Impossible!");
// fatal(CCX_COMMON_EXIT_BUG_BUG, "user_data: Impossible!");
}
// Do something
@@ -31,7 +31,7 @@ int user_data(struct bitstream *ustream, int udtype, struct cc_subtitle *sub)
{
return 0; // Actually discarded on call.
// CFS: Seen in Stick_VHS.mpg.
// fatal(EXIT_BUG_BUG, "user_data: Impossible!");
// fatal(CCX_COMMON_EXIT_BUG_BUG, "user_data: Impossible!");
}
// DVD CC header, see
@@ -164,7 +164,7 @@ int user_data(struct bitstream *ustream, int udtype, struct cc_subtitle *sub)
/* marker = (unsigned int)read_bits(ustream,1); // TODO: Add syntax check */
if (ustream->bitsleft < 0)
fatal(EXIT_BUG_BUG, "Oops!");
fatal(CCX_COMMON_EXIT_BUG_BUG, "Oops!");
// Field_number is either
// 0 .. forbiden
@@ -243,7 +243,7 @@ int user_data(struct bitstream *ustream, int udtype, struct cc_subtitle *sub)
int proceed = 1;
unsigned char *cc_data = read_bytes(ustream, cc_count*3);
if (ustream->bitsleft < 0)
fatal(EXIT_BUG_BUG, "Not enough for CC captions!");
fatal(CCX_COMMON_EXIT_BUG_BUG, "Not enough for CC captions!");
// Check for proper marker - This read makes sure that
// cc_count*3+1 bytes are read and available in cc_data.

187
src/ffmpeg_intgr.c Normal file
View File

@@ -0,0 +1,187 @@
#include "ffmpeg_intgr.h"
#ifdef ENABLE_FFMPEG
#include <libavformat/avformat.h>
#include <libavfilter/avfiltergraph.h>
#include <libavfilter/avcodec.h>
#include <libavfilter/buffersink.h>
#include <libavfilter/buffersrc.h>
#include <libavutil/avstring.h>
#include <libswresample/swresample.h>
#include <libavutil/opt.h>
#include <libavutil/audio_fifo.h>
#include <libavutil/log.h>
#include <libavutil/error.h>
#include "ccextractor.h"
struct ffmpeg_ctx
{
AVFormatContext *ifmt;
AVCodecContext *dec_ctx;
AVFrame *frame;
int stream_index;
};
/**
* call back function to be registered for avlog
*/
static void log_cb(void* ptr, int level, const char* fmt, va_list vl)
{
if (level > av_log_get_level())
return;
const char*name = NULL;
FILE *flog;
if (ccx_options.messages_target==CCX_MESSAGES_STDOUT)
flog = stdout;
else
flog = stderr;
if (level == AV_LOG_PANIC)
fprintf(flog, "[panic][%s] ", name);
else if (level == AV_LOG_FATAL)
fprintf(flog, "[fatal][%s] ", name);
else if (level == AV_LOG_ERROR)
fprintf(flog, "[error][%s] ", name);
else if (level == AV_LOG_WARNING)
fprintf(flog, "[warning][%s] ", name);
else if (level == AV_LOG_INFO)
fprintf(flog, "[info][%s] ", name);
else if (level == AV_LOG_DEBUG)
fprintf(flog, "[debug][%s] ", name);
vfprintf(flog, fmt, vl);
}
/**
* @path this path could be relative or absolute path of static file
* this path could be path of device
*
* @return ctx Context of ffmpeg
*/
void *init_ffmpeg(char *path)
{
int ret = 0;
int stream_index = 0;
struct ffmpeg_ctx *ctx;
AVCodec *dec = NULL;
avcodec_register_all();
av_register_all();
if(ccx_options.debug_mask & CCX_DMT_VERBOSE)
av_log_set_level(AV_LOG_INFO);
else if (ccx_options.messages_target == 0)
av_log_set_level(AV_LOG_FATAL);
av_log_set_callback(log_cb);
ctx = av_malloc(sizeof(*ctx));
if(!ctx)
{
av_log(NULL,AV_LOG_ERROR,"Not enough memory\n");
return NULL;
}
/**
* Initialize decoder according to the name of input
*/
ret = avformat_open_input(&ctx->ifmt, path, NULL, NULL);
if(ret < 0)
{
av_log(NULL,AV_LOG_ERROR,"could not open input(%s) format\n",path);
goto fail;
}
ret = avformat_find_stream_info(ctx->ifmt,NULL);
if(ret < 0)
{
av_log(NULL,AV_LOG_ERROR,"could not find any stream\n");
goto fail;
}
/* first search in strean if not found search the video stream */
ret = av_find_best_stream(ctx->ifmt, AVMEDIA_TYPE_VIDEO, -1, -1, &dec, 0);
if (ret < 0)
{
av_log(NULL, AV_LOG_ERROR, "no suitable subtitle or caption\n");
goto fail;
}
stream_index = ret;
ctx->dec_ctx = ctx->ifmt->streams[stream_index]->codec;
ctx->stream_index = stream_index;
ret = avcodec_open2(ctx->dec_ctx, dec, NULL);
if(ret < 0)
{
av_log(NULL,AV_LOG_ERROR,"unable to open codec\n");
goto fail;
}
//Initialize frame where input frame will be stored
ctx->frame = av_frame_alloc();
fail:
return ctx;
}
/**
* @param ctx context of ffmpeg
* @param data preallocated buffer where data will be recieved
* @param maxlen length of buffer, where data will be copied
* @return number of bytes recieved as data
*/
int ff_get_ccframe(void *arg,char*data,int maxlen)
{
struct ffmpeg_ctx *ctx = arg;
int len = 0;
int ret = 0;
int got_frame;
AVPacket packet;
ret = av_read_frame(ctx->ifmt, &packet);
if(ret == AVERROR_EOF)
{
return ret;
}
else if(ret < 0)
{
av_log(NULL, AV_LOG_ERROR, "not able to read the packet\n");
return ret;
}
else if(packet.stream_index != ctx->stream_index)
{
return AVERROR(EAGAIN);
}
ret = avcodec_decode_video2(ctx->dec_ctx,ctx->frame, &got_frame,&packet);
if(ret < 0)
{
av_log(NULL,AV_LOG_ERROR,"unable to decode packet\n");
}
else if (!got_frame)
{
return AVERROR(EAGAIN);
}
current_pts = av_frame_get_best_effort_timestamp(ctx->frame);
if(!pts_set)
pts_set = 1;
set_fts();
for(int i = 0;i< ctx->frame->nb_side_data;i++)
{
if(ctx->frame->side_data[i]->type == AV_FRAME_DATA_A53_CC)
{
ctx->frame->pts = av_frame_get_best_effort_timestamp(ctx->frame);
if(ctx->frame->side_data[i]->size > maxlen)
av_log(NULL,AV_LOG_ERROR,"Please consider increasing length of data\n");
else
{
memcpy(data,ctx->frame->side_data[i]->data,ctx->frame->side_data[i]->size);
len = ctx->frame->side_data[i]->size;
}
}
}
if(ret < 0)
return ret;
return len;
}
#endif

23
src/ffmpeg_intgr.h Normal file
View File

@@ -0,0 +1,23 @@
#ifndef _FFMPEG_INTIGRATION
#define _FFMPEG_INTIGRATION
#ifdef ENABLE_FFMPEG
#include "libavutil/common.h"
#include "libavutil/error.h"
#endif
/**
* @path this path could be relative or absolute path of static file
* this path could be path of device
*
* @return ctx Context of ffmpeg
*/
void *init_ffmpeg(char *path);
/**
* @param ctx context of ffmpeg
* @param data preallocated buffer where data will be recieved
* @param maxlen length of buffer, where data will be copied
* @return number of bytes recieved as data
*/
int ff_get_ccframe(void *arg,char*data,int maxlen);
#endif

View File

@@ -134,7 +134,7 @@ int switch_to_next_file (LLONG bytesinbuffer)
infd = start_upd_srv(ccx_options.udpaddr, ccx_options.udpport);
return 1;
if(infd < 0)
fatal (EXIT_BUG_BUG, "socket() failed.");
fatal (CCX_COMMON_EXIT_BUG_BUG, "socket() failed.");
}
@@ -209,7 +209,7 @@ void position_sanity_check ()
LLONG realpos=LSEEK (in,0,SEEK_CUR);
if (realpos!=past-filebuffer_pos+bytesinbuffer)
{
fatal (EXIT_BUG_BUG, "Position desync, THIS IS A BUG. Real pos =%lld, past=%lld.\n",realpos,past);
fatal (CCX_COMMON_EXIT_BUG_BUG, "Position desync, THIS IS A BUG. Real pos =%lld, past=%lld.\n",realpos,past);
}
}
#endif
@@ -243,7 +243,7 @@ void buffered_seek (int offset)
// We got into the start buffer (hopefully)
if (startbytes_pos+filebuffer_pos < 0)
{
fatal (EXIT_BUG_BUG, "PANIC: Attempt to seek before buffer start, this is a bug!");
fatal (CCX_COMMON_EXIT_BUG_BUG, "PANIC: Attempt to seek before buffer start, this is a bug!");
}
startbytes_pos+=filebuffer_pos;
filebuffer_pos=0;
@@ -300,7 +300,7 @@ void return_to_buffer (unsigned char *buffer, unsigned int bytes)
}
if (bytesinbuffer + bytes > FILEBUFFERSIZE)
fatal (EXIT_BUG_BUG, "Invalid return_to_buffer() - please submit a bug report.");
fatal (CCX_COMMON_EXIT_BUG_BUG, "Invalid return_to_buffer() - please submit a bug report.");
memmove (filebuffer+bytes,filebuffer,bytesinbuffer);
memcpy (filebuffer,buffer,bytes);
bytesinbuffer+=bytes;

View File

@@ -5,9 +5,8 @@
#include <unistd.h>
#endif
#include "708.h"
#include "dvb_subtitle_decoder.h"
#include "cc_encoders_common.h"
#include "ccx_encoders_common.h"
// IMPORTED TRASH INFO, REMOVE
extern long num_nal_unit_type_7;
extern long num_vcl_hrd;
@@ -20,8 +19,6 @@ extern long num_unexpected_sei_length;
unsigned current_vert_size = 0;
unsigned current_aspect_ratio = 0;
unsigned current_frame_rate = 4; // Assume standard fps, 29.97
double current_fps = (double) 30000.0 / 1001; /* 29.97 */ // TODO: Get from framerates_values[] instead
LLONG current_pts = 0;
unsigned rollover_bits = 0; // The PTS rolls over every 26 hours and that can happen in the middle of a stream.
LLONG result; // Number of bytes read/skipped in last read operation
int end_of_file=0; // End of file?
@@ -31,9 +28,6 @@ const static unsigned char DO_NOTHING[] = {0x80, 0x80};
LLONG inbuf = 0; // Number of bytes loaded in buffer
int ccx_bufferdatatype = CCX_PES; // Can be RAW, PES, H264 or Hauppage
int current_tref = 0; // Store temporal reference of current frame
enum ccx_frame_type current_picture_coding_type = CCX_FRAME_TYPE_RESET_OR_UNKNOWN;
// Remember if the last header was valid. Used to suppress too much output
// and the expected unrecognized first header for TiVo files.
int strangeheader=0;
@@ -577,7 +571,7 @@ void general_loop(void *enc_ctx)
i = wtv_getmoredata();
break;
default:
fatal(EXIT_BUG_BUG, "Impossible stream_mode");
fatal(CCX_COMMON_EXIT_BUG_BUG, "Impossible stream_mode");
}
position_sanity_check();
@@ -667,9 +661,9 @@ void general_loop(void *enc_ctx)
else if (ccx_bufferdatatype == CCX_H264) // H.264 data from TS file
{
got = process_avc(buffer, inbuf,&dec_sub);
}
}
else
fatal(EXIT_BUG_BUG, "Unknown data type!");
fatal(CCX_COMMON_EXIT_BUG_BUG, "Unknown data type!");
if (got>inbuf)
{
@@ -737,7 +731,7 @@ void rcwt_loop(void *enc_ctx)
memset(&dec_sub, 0,sizeof(dec_sub));
// As BUFSIZE is a macro this is just a reminder
if (BUFSIZE < (3*0xFFFF + 10))
fatal (EXIT_BUG_BUG, "BUFSIZE too small for RCWT caption block.\n");
fatal (CCX_COMMON_EXIT_BUG_BUG, "BUFSIZE too small for RCWT caption block.\n");
// Generic buffer to hold some data
parsebuf = (unsigned char*)malloc(1024);
@@ -772,6 +766,12 @@ void rcwt_loop(void *enc_ctx)
fatal(EXIT_MISSING_RCWT_HEADER, "Missing RCWT header. Abort.\n");
}
if (parsebuf[6] == 0 && parsebuf[7] == 2)
{
tlt_read_rcwt();
return;
}
// Initialize first time. As RCWT files come with the correct FTS the
// initial (minimal) time needs to be set to 0.
current_pts = 0;

View File

@@ -5,7 +5,7 @@
#include <gpac/isomedia.h>
#include "../ccextractor.h"
#include "../utility.h"
#include "../cc_encoders_common.h"
#include "../ccx_encoders_common.h"
void do_NAL (unsigned char *NALstart, LLONG NAL_length, struct cc_subtitle *sub); // From avc_functions.c
void set_fts(void); // From timing.c

View File

@@ -2,7 +2,7 @@
For now, integration with ccextractor is a quick hack. It could get better with time. */
#include "ccextractor.h"
#include "608.h"
#include "ccx_decoders_608.h"
#ifdef _WIN32
#include <io.h>
#else
@@ -12,7 +12,7 @@ For now, integration with ccextractor is a quick hack. It could get better with
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include "cc_encoders_common.h"
#include "ccx_encoders_common.h"
static unsigned int header_state;
static unsigned char psm_es_type[256];

View File

@@ -15,6 +15,8 @@
#define OK 1
#define PASSWORD 2
#define BIN_MODE 3
#define CC_DESC 4
#pragma warning( suppress : 4005)
#define ERROR 51
#define UNKNOWN_COMMAND 52
#define WRONG_PASSWORD 53
@@ -66,7 +68,7 @@ void init_sockets (void);
void pr_command(char c);
#endif
void connect_to_srv(const char *addr, const char *port)
void connect_to_srv(const char *addr, const char *port, const char *cc_desc)
{
if (NULL == addr)
{
@@ -86,6 +88,12 @@ void connect_to_srv(const char *addr, const char *port)
if (ask_passwd(srv_sd) < 0)
fatal(EXIT_FAILURE, "Unable to connect\n");
if (cc_desc != NULL &&
write_block(srv_sd, CC_DESC, cc_desc, strlen(cc_desc)) < 0)
{
fatal(EXIT_FAILURE, "Unable to connect\n");
}
mprint("Connected to %s:%s\n", addr, port);
}
@@ -188,16 +196,19 @@ ssize_t write_block(int fd, char command, const char *buf, size_t buf_len)
fprintf(stderr, " ");
#endif
if ((rc = writen(fd, buf, buf_len)) < 0)
return -1;
else if (rc != (int) buf_len)
return 0;
nwritten += rc;
if (buf_len > 0)
{
if ((rc = writen(fd, buf, buf_len)) < 0)
return -1;
else if (rc != (int) buf_len)
return 0;
nwritten += rc;
}
#if DEBUG_OUT
if (buf != NULL)
{
fwrite(buf, sizeof(char), buf_len - 2, stderr);
fwrite(buf, sizeof(char), buf_len, stderr);
fprintf(stderr, " ");
}
#endif
@@ -335,9 +346,6 @@ int ask_passwd(int sd)
p++;
len = p - pw; /* without \n */
printf("\n");
fflush(stdout);
if (write_block(sd, PASSWORD, pw, len) < 0)
return -1;
@@ -478,11 +486,12 @@ int check_password(int fd, const char *pwd)
char c;
int rc;
size_t len = BUFFER_SIZE;
size_t len;
char buf[BUFFER_SIZE];
while(1)
{
len = BUFFER_SIZE;
#if DEBUG_OUT
fprintf(stderr, "[S] PASSWORD\n");
#endif
@@ -495,7 +504,7 @@ int check_password(int fd, const char *pwd)
if (c != PASSWORD)
return -1;
if (0 != strcmp(pwd, buf))
if (strlen(pwd) != len || strncmp(pwd, buf, len) != 0)
{
sleep(WRONG_PASSWORD_DELAY);
@@ -569,21 +578,25 @@ int tcp_bind(const char *port, int *family)
}
}
if (0 == bind(sockfd, p->ai_addr, p->ai_addrlen))
break;
if (bind(sockfd, p->ai_addr, p->ai_addrlen) < 0)
{
#if _WIN32
wprintf(L"bind() eror: %ld\n", WSAGetLastError());
closesocket(sockfd);
wprintf(L"bind() error: %ld\n", WSAGetLastError());
closesocket(sockfd);
#else
mprint("bind() error: %s\n", strerror(errno));
close(sockfd);
mprint("bind() error: %s\n", strerror(errno));
close(sockfd);
#endif
if (p->ai_next != NULL)
mprint("trying next addres ...\n");
}
if (p->ai_next != NULL)
mprint("trying next addres ...\n");
*family = p->ai_family;
continue;
}
*family = p->ai_family;
break;
}
freeaddrinfo(ai);
@@ -883,12 +896,11 @@ int start_upd_srv(const char *addr_str, unsigned port)
struct sockaddr_in servaddr;
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = addr;
servaddr.sin_port = htons(port);
if (IN_MULTICAST(addr))
servaddr.sin_addr.s_addr = addr;
servaddr.sin_addr.s_addr = htonl(addr);
else
servaddr.sin_addr.s_addr = INADDR_ANY;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
if (bind(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) != 0)
{
@@ -896,7 +908,7 @@ int start_upd_srv(const char *addr_str, unsigned port)
wprintf(L"bind() eror: %ld\n", WSAGetLastError());
exit(EXIT_FAILURE);
#else
fatal(EXIT_BUG_BUG, "bind() error: %s\n", strerror(errno));
fatal(CCX_COMMON_EXIT_BUG_BUG, "bind() error: %s\n", strerror(errno));
#endif
}
@@ -904,14 +916,14 @@ int start_upd_srv(const char *addr_str, unsigned port)
struct ip_mreq group;
group.imr_multiaddr.s_addr = htonl(addr);
group.imr_interface.s_addr = htonl(INADDR_ANY);
if (setsockopt(infd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&group, sizeof(group)) < 0)
if (setsockopt(sockfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&group, sizeof(group)) < 0)
{
#if _WIN32
wprintf(L"setsockopt() error: %ld\n", WSAGetLastError());
#else
mprint("setsockopt() error: %s\n", strerror(errno));
#endif
fatal(EXIT_BUG_BUG, "Cannot join multicast group.");
fatal(CCX_COMMON_EXIT_BUG_BUG, "Cannot join multicast group.");
}
}

View File

@@ -3,7 +3,7 @@
#include <sys/types.h>
void connect_to_srv(const char *addr, const char *port);
void connect_to_srv(const char *addr, const char *port, const char *cc_desc);
void net_send_header(const unsigned char *data, size_t len);
void net_send_cc(const unsigned char *data, size_t len);

View File

@@ -18,7 +18,7 @@ void writeraw (const unsigned char *data, int length, struct ccx_s_write *wb)
write (wb->fh,data,length);
}
void writedata(const unsigned char *data, int length, struct s_context_cc608 *context, struct cc_subtitle *sub)
void writedata(const unsigned char *data, int length, ccx_decoder_608_context *context, struct cc_subtitle *sub)
{
// Don't do anything for empty data
if (data==NULL)
@@ -37,7 +37,7 @@ void writedata(const unsigned char *data, int length, struct s_context_cc608 *co
ccx_options.write_format==CCX_OF_NULL)
process608 (data,length,context, sub);
else
fatal(EXIT_BUG_BUG, "Should not be reached!");
fatal(CCX_COMMON_EXIT_BUG_BUG, "Should not be reached!");
}
void flushbuffer (struct ccx_s_write *wb, int closefile)
@@ -178,14 +178,16 @@ void writercwtdata (const unsigned char *data)
if (cbcount > 0)
{
writeraw(cbheader,10,&wbout1);
writeraw(cbbuffer,3*cbcount, &wbout1);
if (ccx_options.send_to_srv)
{
net_send_cc(cbheader, 10);
net_send_cc(cbbuffer, 3*cbcount);
}
else
{
writeraw(cbheader,10,&wbout1);
writeraw(cbbuffer,3*cbcount, &wbout1);
}
}
cbcount = 0;
cbempty = 0;
@@ -228,14 +230,16 @@ void writercwtdata (const unsigned char *data)
memcpy(cbbuffer, "\x04\x80\x80", 3); // Field 1 padding
memcpy(cbbuffer+3, "\x05\x80\x80", 3); // Field 2 padding
writeraw(cbheader,10,&wbout1);
writeraw(cbbuffer,3*cbcount, &wbout1);
if (ccx_options.send_to_srv)
{
net_send_cc(cbheader, 10);
net_send_cc(cbbuffer, 3*cbcount);
}
else
{
writeraw(cbheader,10,&wbout1);
writeraw(cbbuffer,3*cbcount, &wbout1);
}
cbcount = 0;
cbempty = 0;

View File

@@ -2,7 +2,6 @@
#include "utility.h"
static int inputfile_capacity=0;
static int spell_builtin_added=0; // so we don't do it twice
static const char *DEF_VAL_STARTCREDITSNOTBEFORE="0";
static const char *DEF_VAL_STARTCREDITSNOTAFTER="5:00"; // To catch the theme after the teaser in TV shows
@@ -11,19 +10,6 @@ static const char *DEF_VAL_STARTCREDITSFORATMOST="5";
static const char *DEF_VAL_ENDCREDITSFORATLEAST="2";
static const char *DEF_VAL_ENDCREDITSFORATMOST="5";
// Some basic English words, so user-defined doesn't have to
// include the common stuff
static const char *spell_builtin[]=
{
"I", "I'd", "I've", "I'd", "I'll",
"January","February","March","April", // May skipped intentionally
"June","July","August","September","October","November",
"December","Monday","Tuesday","Wednesday","Thursday",
"Friday","Saturday","Sunday","Halloween","United States",
"Spain","France","Italy","England",
NULL
};
int stringztoms (const char *s, struct ccx_boundary_time *bt)
{
unsigned ss=0, mm=0, hh=0;
@@ -69,81 +55,6 @@ int stringztoms (const char *s, struct ccx_boundary_time *bt)
return 0;
}
int add_word (const char *word)
{
char *new_lower;
char *new_correct;
char **ptr_lower;
char **ptr_correct;
int i;
if (spell_words==spell_capacity)
{
// Time to grow
spell_capacity+=50;
ptr_lower=(char **) realloc (spell_lower, sizeof (char *) *
spell_capacity);
ptr_correct=(char **) realloc (spell_correct, sizeof (char *) *
spell_capacity);
}
size_t len=strlen (word);
new_lower = (char *) malloc (len+1);
new_correct = (char *) malloc (len+1);
if (ptr_lower==NULL || ptr_correct==NULL ||
new_lower==NULL || new_correct==NULL)
{
spell_capacity = 0;
for ( i = 0; i < spell_words ; i++)
{
freep(&spell_lower[spell_words]);
freep(&spell_correct[spell_words]);
}
freep(&spell_lower);
freep(&spell_correct);
freep(&ptr_lower);
freep(&ptr_correct);
freep(&new_lower);
freep(&new_correct);
spell_words = 0;
return -1;
}
else
{
spell_lower = ptr_lower;
spell_correct = ptr_correct;
}
strcpy (new_correct, word);
for (size_t i=0; i<len; i++)
{
char c=new_correct[i];
c=tolower (c); // TO-DO: Add Spanish characters
new_lower[i]=c;
}
new_lower[len]=0;
spell_lower[spell_words]=new_lower;
spell_correct[spell_words]=new_correct;
spell_words++;
return 0;
}
int add_built_in_words()
{
if (!spell_builtin_added)
{
int i=0;
while (spell_builtin[i]!=NULL)
{
if (add_word(spell_builtin[i]))
return -1;
i++;
}
spell_builtin_added=1;
}
return 0;
}
int process_cap_file (char *filename)
{
int ret = 0;
@@ -319,10 +230,12 @@ void set_output_format (const char *format)
if (ccx_options.date_format==ODF_NONE)
ccx_options.date_format=ODF_HHMMSSMS;
// Sets the right things so that timestamps and the mode are printed.
ccx_options.transcript_settings.showStartTime = 1;
ccx_options.transcript_settings.showEndTime = 1;
ccx_options.transcript_settings.showCC = 0;
ccx_options.transcript_settings.showMode = 1;
if (!ccx_options.transcript_settings.isFinal){
ccx_options.transcript_settings.showStartTime = 1;
ccx_options.transcript_settings.showEndTime = 1;
ccx_options.transcript_settings.showCC = 0;
ccx_options.transcript_settings.showMode = 1;
}
}
else if (strcmp (format,"report")==0)
{
@@ -429,11 +342,13 @@ void usage (void)
mprint (" -tcp port: Reads the input data in BIN format according to CCExtractor's\n");
mprint (" protocol, listening specified port on the local host\n");
mprint (" -tcppassword password: Sets server password for new connections to tcp server\n");
mprint (" -tcpdesc description: Sends to the server short description about captions e.g.\n");
mprint (" channel name or file name\n");
mprint ("Options that affect what will be processed:\n");
mprint (" -1, -2, -12: Output Field 1 data, Field 2 data, or both\n");
mprint (" (DEFAULT is -1)\n");
mprint (" -cc2: When in srt/sami mode, process captions in channel 2\n");
mprint (" instead channel 1.\n");
mprint (" instead of channel 1.\n");
mprint ("-svc --service N,N...: Enabled CEA-708 captions processing for the listed\n");
mprint (" services. The parameter is a command delimited list\n");
mprint (" of services numbers, such as \"1,2\" to process the\n");
@@ -562,6 +477,8 @@ void usage (void)
mprint (" affects Teletext in timed transcript with -datets.\n");
mprint ("\n");
mprint ("Options that affect what kind of output will be produced:\n");
mprint(" -nobom: Do not append a BOM (Byte Order Mark) to output files.");
mprint(" Note that this may break files when using Windows.");
mprint (" -unicode: Encode subtitles in Unicode instead of Latin-1.\n");
mprint (" -utf8: Encode subtitles in UTF-8 (no longer needed.\n");
mprint (" because UTF-8 is now the default).\n");
@@ -825,8 +742,8 @@ void parse_708services (char *s)
e++;
*e=0;
svc=atoi (c);
if (svc<1 || svc>63)
fatal (EXIT_MALFORMED_PARAMETER, "Invalid service number (%d), valid range is 1-63.");
if (svc<1 || svc>CCX_DECODERS_708_MAX_SERVICES)
fatal (EXIT_MALFORMED_PARAMETER, "Invalid service number (%d), valid range is 1-%d.",svc,CCX_DECODERS_708_MAX_SERVICES);
cea708services[svc-1]=1;
do_cea708=1;
c=e+1;
@@ -871,8 +788,7 @@ void init_option (struct ccx_s_options *option)
if(option->sentence_cap_file && process_cap_file (option->sentence_cap_file))
fatal (EXIT_ERROR_IN_CAPITALIZATION_FILE, "There was an error processing the capitalization file.\n");
shell_sort(spell_lower,spell_words,sizeof(*spell_lower),string_cmp2,NULL);
shell_sort(spell_correct,spell_words,sizeof(*spell_correct),string_cmp2,NULL);
ccx_encoders_helpers_perform_shellsort_words();
}
if(option->ts_forced_program != -1)
option->ts_forced_program_selected = 1;
@@ -940,7 +856,7 @@ void parse_parameters (int argc, char *argv[])
}
if (strcmp (argv[i],"-dru")==0)
{
ccx_options.direct_rollup = 1;
ccx_options.settings_608.direct_rollup = 1;
continue;
}
if (strcmp (argv[i],"-nofc")==0 ||
@@ -949,6 +865,9 @@ void parse_parameters (int argc, char *argv[])
ccx_options.nofontcolor=1;
continue;
}
if (strcmp(argv[i], "-nobom") == 0){
ccx_options.no_bom = 1;
}
if (strcmp (argv[i],"-nots")==0 ||
strcmp (argv[i],"--notypesetting")==0)
{
@@ -1145,22 +1064,22 @@ void parse_parameters (int argc, char *argv[])
if (strcmp (argv[i],"-noru")==0 ||
strcmp (argv[i],"--norollup")==0)
{
ccx_options.norollup = 1;
ccx_options.settings_608.no_rollup = 1;
continue;
}
if (strcmp (argv[i],"-ru1")==0)
{
ccx_options.forced_ru=1;
ccx_options.settings_608.force_rollup = 1;
continue;
}
if (strcmp (argv[i],"-ru2")==0)
{
ccx_options.forced_ru=2;
ccx_options.settings_608.force_rollup = 2;
continue;
}
if (strcmp (argv[i],"-ru3")==0)
{
ccx_options.forced_ru=3;
ccx_options.settings_608 .force_rollup = 3;
continue;
}
if (strcmp (argv[i],"-trim")==0)
@@ -1234,7 +1153,7 @@ void parse_parameters (int argc, char *argv[])
fatal (EXIT_MALFORMED_PARAMETER, "--defaultcolor expects a 7 character parameter that starts with #\n");
}
strcpy ((char *) usercolor_rgb,argv[i+1]);
ccx_options.cc608_default_color=COL_USERDEFINED;
ccx_options.settings_608.default_color = COL_USERDEFINED;
i++;
continue;
}
@@ -1250,8 +1169,8 @@ void parse_parameters (int argc, char *argv[])
if ((strcmp (argv[i],"-scr")==0 ||
strcmp (argv[i],"--screenfuls")==0) && i<argc-1)
{
ccx_options.screens_to_process=atoi_hex (argv[i+1]);
if (ccx_options.screens_to_process<0)
ccx_options.settings_608.screens_to_process = atoi_hex(argv[i + 1]);
if (ccx_options.settings_608.screens_to_process<0)
{
fatal (EXIT_MALFORMED_PARAMETER, "--screenfuls only accepts positive integers.\n");
}
@@ -1310,7 +1229,7 @@ void parse_parameters (int argc, char *argv[])
}
if (strcmp (argv[i],"-608")==0)
{
ccx_options.debug_mask |= CCX_DMT_608;
ccx_options.debug_mask |= CCX_DMT_DECODER_608;
continue;
}
if (strcmp (argv[i],"-deblev")==0)
@@ -1347,12 +1266,14 @@ void parse_parameters (int argc, char *argv[])
}
if (strcmp (argv[i],"-xds")==0)
{
ccx_options.transcript_settings.xds = 1;
if (!ccx_options.transcript_settings.isFinal){
ccx_options.transcript_settings.xds = 1;
}
continue;
}
if (strcmp (argv[i],"-xdsdebug")==0)
{
ccx_options.debug_mask |= CCX_DMT_XDS;
ccx_options.debug_mask |= CCX_DMT_DECODER_XDS;
continue;
}
if (strcmp (argv[i],"-parsedebug")==0)
@@ -1509,11 +1430,15 @@ void parse_parameters (int argc, char *argv[])
if (strcmp (argv[i],"-UCLA")==0 || strcmp (argv[i],"-ucla")==0)
{
ccx_options.millis_separator='.';
ccx_options.transcript_settings.showStartTime = 1;
ccx_options.transcript_settings.showEndTime = 1;
ccx_options.transcript_settings.showCC = 1;
ccx_options.transcript_settings.showMode = 1;
ccx_options.transcript_settings.relativeTimestamp = 0;
ccx_options.no_bom = 1;
if (!ccx_options.transcript_settings.isFinal){
ccx_options.transcript_settings.showStartTime = 1;
ccx_options.transcript_settings.showEndTime = 1;
ccx_options.transcript_settings.showCC = 1;
ccx_options.transcript_settings.showMode = 1;
ccx_options.transcript_settings.relativeTimestamp = 0;
ccx_options.transcript_settings.isFinal = 1;
}
continue;
}
if (strcmp (argv[i],"-lf")==0 || strcmp (argv[i],"-LF")==0)
@@ -1573,13 +1498,15 @@ void parse_parameters (int argc, char *argv[])
if (strlen(format) == 7){
if (ccx_options.date_format == ODF_NONE)
ccx_options.date_format = ODF_HHMMSSMS; // Necessary for displaying times, if any would be used.
ccx_options.transcript_settings.showStartTime = format[0]-'0';
ccx_options.transcript_settings.showEndTime = format[1] - '0';
ccx_options.transcript_settings.showMode = format[2] - '0';
ccx_options.transcript_settings.showCC = format[3] - '0';
ccx_options.transcript_settings.relativeTimestamp = format[4] - '0';
ccx_options.transcript_settings.xds = format[5] - '0';
ccx_options.transcript_settings.useColors = format[6] - '0';
if (!ccx_options.transcript_settings.isFinal){
ccx_options.transcript_settings.showStartTime = format[0] - '0';
ccx_options.transcript_settings.showEndTime = format[1] - '0';
ccx_options.transcript_settings.showMode = format[2] - '0';
ccx_options.transcript_settings.showCC = format[3] - '0';
ccx_options.transcript_settings.relativeTimestamp = format[4] - '0';
ccx_options.transcript_settings.xds = format[5] - '0';
ccx_options.transcript_settings.useColors = format[6] - '0';
}
i++;
}
else {
@@ -1667,6 +1594,14 @@ void parse_parameters (int argc, char *argv[])
continue;
}
if (strcmp (argv[i],"-tcpdesc")==0 && i<argc-1)
{
ccx_options.tcp_desc = argv[i + 1];
i++;
continue;
}
fatal (EXIT_INCOMPATIBLE_PARAMETERS, "Error: Parameter %s not understood.\n", argv[i]);
// Unrecognized switches are silently ignored
}

View File

@@ -18,7 +18,7 @@ void params_dump(void)
mprint ("Network, UDP/%u",ccx_options.udpport);
else
{
mprint ("Network, %s:%d",ccx_options.udpport, ccx_options.udpport);
mprint ("Network, %s:%d",ccx_options.udpaddr, ccx_options.udpport);
}
break;
case CCX_DS_TCP:
@@ -63,7 +63,7 @@ void params_dump(void)
break;
#endif
default:
fatal (EXIT_BUG_BUG, "BUG: Unknown stream mode.\n");
fatal(CCX_COMMON_EXIT_BUG_BUG, "BUG: Unknown stream mode.\n");
break;
}
mprint ("]\n");
@@ -117,7 +117,7 @@ void params_dump(void)
mprint ("[Debug: %s] ", (ccx_options.debug_mask & CCX_DMT_VERBOSE) ? "Yes": "No");
mprint ("[Buffer input: %s]\n", ccx_options.buffer_input ? "Yes": "No");
mprint ("[Use pic_order_cnt_lsb for H.264: %s] ", ccx_options.usepicorder ? "Yes": "No");
mprint ("[Print CC decoder traces: %s]\n", (ccx_options.debug_mask & CCX_DMT_608) ? "Yes": "No");
mprint("[Print CC decoder traces: %s]\n", (ccx_options.debug_mask & CCX_DMT_DECODER_608) ? "Yes" : "No");
mprint ("[Target format: %s] ",extension);
mprint ("[Encoding: ");
switch (ccx_options.encoding)
@@ -204,7 +204,7 @@ void params_dump(void)
}
void print_file_report(void)
void print_file_report(void)
{
#define Y_N(cond) ((cond) ? "Yes" : "No")
@@ -212,6 +212,12 @@ void print_file_report(void)
switch (ccx_options.input_source)
{
case CCX_DS_FILE:
if (current_file < 0)
{
printf("file is not openened yet\n");
return;
}
printf("%s\n", inputfile[current_file]);
break;
case CCX_DS_STDIN:
@@ -356,12 +362,12 @@ void print_file_report(void)
if (cc_stats[0] > 0 || cc_stats[1] > 0)
{
printf("XDS: %s\n", Y_N(file_report.xds));
printf("XDS: %s\n", Y_N(file_report.data_from_608->xds));
printf("CC1: %s\n", Y_N(file_report.cc_channels_608[0]));
printf("CC2: %s\n", Y_N(file_report.cc_channels_608[1]));
printf("CC3: %s\n", Y_N(file_report.cc_channels_608[2]));
printf("CC4: %s\n", Y_N(file_report.cc_channels_608[3]));
printf("CC1: %s\n", Y_N(file_report.data_from_608->cc_channels[0]));
printf("CC2: %s\n", Y_N(file_report.data_from_608->cc_channels[1]));
printf("CC3: %s\n", Y_N(file_report.data_from_608->cc_channels[2]));
printf("CC4: %s\n", Y_N(file_report.data_from_608->cc_channels[3]));
}
printf("CEA-708: %s\n", Y_N(cc_stats[2] > 0 || cc_stats[3] > 0));
@@ -369,17 +375,17 @@ void print_file_report(void)
if (cc_stats[2] > 0 || cc_stats[3] > 0)
{
printf("Services: ");
for (int i = 0; i < 63; i++)
for (int i = 0; i < CCX_DECODERS_708_MAX_SERVICES; i++)
{
if (file_report.services708[i] == 0)
if (file_report.data_from_708->services[i] == 0)
continue;
printf("%d ", i);
}
printf("\n");
printf("Primary Language Present: %s\n", Y_N(file_report.services708[1]));
printf("Primary Language Present: %s\n", Y_N(file_report.data_from_708->services[1]));
printf("Secondary Language Present: %s\n", Y_N(file_report.services708[2]));
printf("Secondary Language Present: %s\n", Y_N(file_report.data_from_708->services[2]));
}
printf("MPEG-4 Timed Text: %s\n", Y_N(file_report.mp4_cc_track_cnt));

View File

@@ -1,104 +0,0 @@
#ifndef CCX_PLATFORM_H
#define CCX_PLATFORM_H
#define __STDC_FORMAT_MACROS
#ifdef _WIN32
#include <io.h>
#include <ws2tcpip.h>
#include <windows.h>
#define STDIN_FILENO 0
#define STDOUT_FILENO 1
#define STDERR_FILENO 2
#include "inttypes.h"
#define UINT64_MAX _UI64_MAX
typedef int socklen_t;
typedef int ssize_t;
typedef uint32_t in_addr_t;
#define IN_CLASSD(i) (((INT32)(i) & 0xf0000000) == 0xe0000000)
#define IN_MULTICAST(i) IN_CLASSD(i)
#include <direct.h>
#define mkdir(path, mode) _mkdir(path)
#define snprintf(buf, len, fmt, ...) _snprintf(buf, len, fmt, __VA_ARGS__)
#define sleep(sec) Sleep((sec) * 1000)
#else // _WIN32
#include <unistd.h>
#define __STDC_LIMIT_MACROS
#include <inttypes.h>
#include <stdint.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <sys/stat.h>
#include <sys/types.h>
#endif // _WIN32
#include "disable_warnings.h"
#ifdef _MSC_VER
#include "stdintmsc.h"
// Don't bug me with strcpy() deprecation warnings
#pragma warning(disable : 4996)
#else
#include <stdint.h>
#endif
#ifdef __OpenBSD__
#define FOPEN64 fopen
#define OPEN open
#define FSEEK fseek
#define FTELL ftell
#define LSEEK lseek
#define FSTAT fstat
#else
#ifdef _WIN32
#define OPEN _open
// 64 bit file functions
#if defined(MSC_VER)
extern "C" int __cdecl _fseeki64(FILE *, __int64, int);
extern "C" __int64 __cdecl _ftelli64(FILE *);
#define FSEEK _fseeki64
#define FTELL _ftelli64
#else
// For MinGW
#define FSEEK fseeko64
#define FTELL ftello64
#endif
#define TELL _telli64
#define LSEEK _lseeki64
typedef struct _stati64 FSTATSTRUCT;
#else
// Linux internally maps these functions to 64bit usage,
// if _FILE_OFFSET_BITS macro is set to 64
#define FOPEN64 fopen
#define OPEN open
#define LSEEK lseek
#define FSEEK fseek
#define FTELL ftell
#define FSTAT fstat
#define TELL tell
#include <stdint.h>
#endif
#endif
#ifndef int64_t_C
#define int64_t_C(c) (c ## LL)
#define uint64_t_C(c) (c ## ULL)
#endif
#ifndef O_BINARY
#define O_BINARY 0 // Not present in Linux because it's always binary
#endif
typedef int64_t LLONG;
#endif // CCX_PLATFORM_H

View File

@@ -1,5 +1,4 @@
#include "ccextractor.h"
#include "708.h"
// Defined by the maximum number of B-Frames per anchor frame.
//#define MAXBFRAMES 50 - from ccextractor.h
@@ -19,8 +18,6 @@ int has_ccdata_buffered = 0;
// B-Frames belong to this I- or P-frame.
static int anchor_seq_number = -1;
// Remember the current field for 608 decoding
int current_field=1; // 1 = field 1, 2 = field 2, 3 = 708
static int in_xds_mode ; // Stolen from 608.c We need this for debug
@@ -204,8 +201,8 @@ int do_cb (unsigned char *cc_block, struct cc_subtitle *sub)
return 1;
// Print raw data with FTS.
dbg_print(CCX_DMT_CBRAW, "%s %d %02X:%02X:%02X", print_mstime(fts_now + fts_global),in_xds_mode,
cc_block[0], cc_block[1], cc_block[2]);
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
@@ -302,7 +299,7 @@ int do_cb (unsigned char *cc_block, struct cc_subtitle *sub)
// printf ("Warning: Losing EIA-708 data!\n");
break;
default:
fatal(EXIT_BUG_BUG, "Cannot be reached!");
fatal(CCX_COMMON_EXIT_BUG_BUG, "Cannot be reached!");
} // switch (cc_type)
} // cc_valid
else

View File

@@ -1,9 +1,8 @@
#include "ccfont2.xbm" // CC font from libzvbi
#include "platform.h"
#include "spupng_encoder.h"
#include "ccx_common_common.h"
#include "ccx_encoders_common.h"
#include <assert.h>
#include "cc_encoders_common.h"
#include "utility.h"
#ifdef ENABLE_OCR
#include "ocr.h"
#endif
@@ -20,7 +19,7 @@ spupng_init_font()
/* de-interleave font image (puts all chars in row 0) */
if (!(t = (uint8_t*)malloc(ccfont2_width * ccfont2_height / 8)))
fatal(EXIT_NOT_ENOUGH_MEMORY, "Memory allocation failed");
ccx_common_logging.fatal_ftn(EXIT_NOT_ENOUGH_MEMORY, "Memory allocation failed");
for (p = t, i = 0; i < CCH; i++)
for (j = 0; j < ccfont2_height; p += ccfont2_width / 8, j += CCH)
@@ -35,7 +34,7 @@ struct spupng_t *spunpg_init(struct ccx_s_write *out)
{
struct spupng_t *sp = (struct spupng_t *) malloc(sizeof(struct spupng_t));
if (NULL == sp)
fatal(EXIT_NOT_ENOUGH_MEMORY, "Memory allocation failed");
ccx_common_logging.fatal_ftn(EXIT_NOT_ENOUGH_MEMORY, "Memory allocation failed");
if (!initialized)
{
@@ -45,13 +44,13 @@ struct spupng_t *spunpg_init(struct ccx_s_write *out)
if ((sp->fpxml = fdopen(out->fh, "w")) == NULL)
{
fatal(EXIT_FILE_CREATION_FAILED, "Cannot open %s: %s\n",
ccx_common_logging.fatal_ftn(CCX_COMMON_EXIT_FILE_CREATION_FAILED, "Cannot open %s: %s\n",
out->filename, strerror(errno));
}
sp->dirname = (char *) malloc(
sizeof(char) * (strlen(out->filename) + 3));
if (NULL == sp->dirname)
fatal(EXIT_NOT_ENOUGH_MEMORY, "Memory allocation failed");
ccx_common_logging.fatal_ftn(EXIT_NOT_ENOUGH_MEMORY, "Memory allocation failed");
strcpy(sp->dirname, out->filename);
char* p = strrchr(sp->dirname, '.');
@@ -63,7 +62,7 @@ struct spupng_t *spunpg_init(struct ccx_s_write *out)
{
if (errno != EEXIST)
{
fatal(EXIT_FILE_CREATION_FAILED, "Cannot create %s: %s\n",
ccx_common_logging.fatal_ftn(CCX_COMMON_EXIT_FILE_CREATION_FAILED, "Cannot create %s: %s\n",
sp->dirname, strerror(errno));
}
// If dirname isn't a directory or if we don't have write permission,
@@ -73,7 +72,7 @@ struct spupng_t *spunpg_init(struct ccx_s_write *out)
// enough to append /subNNNN.png
sp->pngfile = (char *) malloc(sizeof(char) * (strlen(sp->dirname) + 13));
if (NULL == sp->pngfile)
fatal(EXIT_NOT_ENOUGH_MEMORY, "Memory allocation failed");
ccx_common_logging.fatal_ftn(EXIT_NOT_ENOUGH_MEMORY, "Memory allocation failed");
sp->fileIndex = 0;
sprintf(sp->pngfile, "%s/sub%04d.png", sp->dirname, sp->fileIndex);
@@ -98,11 +97,11 @@ spunpg_free(struct spupng_t *sp)
}
void
spupng_write_header(struct spupng_t *sp)
spupng_write_header(struct spupng_t *sp,int multiple_files,char *first_input_file)
{
fprintf(sp->fpxml, "<subpictures>\n<stream>\n");
if (num_input_files > 0)
fprintf(sp->fpxml, "<!-- %s -->\n", inputfile[0]);
if (multiple_files)
fprintf(sp->fpxml, "<!-- %s -->\n", first_input_file);
}
void
@@ -118,7 +117,7 @@ void write_spumux_header(struct ccx_s_write *out)
if (0 == out->spupng_data)
out->spupng_data = spunpg_init(out);
spupng_write_header((struct spupng_t*)out->spupng_data);
spupng_write_header((struct spupng_t*)out->spupng_data,out->multiple_files,out->first_input_file);
}
void write_spumux_footer(struct ccx_s_write *out)
@@ -352,7 +351,7 @@ static int save_spupng(const char *filename, uint8_t *bitmap, int w, int h,
f = fopen(filename, "wb");
if (!f)
{
mprint("DVB:unable to open %s in write mode \n", filename);
ccx_common_logging.log_ftn("DVB:unable to open %s in write mode \n", filename);
ret = -1;
goto end;
}
@@ -360,12 +359,12 @@ static int save_spupng(const char *filename, uint8_t *bitmap, int w, int h,
png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL,NULL);
if (!png_ptr)
{
mprint("DVB:unable to create png write struct\n");
ccx_common_logging.log_ftn("DVB:unable to create png write struct\n");
goto end;
}
if (!(info_ptr = png_create_info_struct(png_ptr)))
{
mprint("DVB:unable to create png info struct\n");
ccx_common_logging.log_ftn("DVB:unable to create png info struct\n");
ret = -1;
goto end;
}
@@ -373,7 +372,7 @@ static int save_spupng(const char *filename, uint8_t *bitmap, int w, int h,
row_pointer = (png_bytep*) malloc(sizeof(png_bytep) * h);
if (!row_pointer)
{
mprint("DVB: unable to allocate row_pointer\n");
ccx_common_logging.log_ftn("DVB: unable to allocate row_pointer\n");
ret = -1;
goto end;
}
@@ -399,7 +398,7 @@ static int save_spupng(const char *filename, uint8_t *bitmap, int w, int h,
}
if (i != h)
{
mprint("DVB: unable to allocate row_pointer internals\n");
ccx_common_logging.log_ftn("DVB: unable to allocate row_pointer internals\n");
ret = -1;
goto end;
}
@@ -614,8 +613,11 @@ int write_cc_bitmap_as_spupng(struct cc_subtitle *sub, struct encoder_ctx *conte
else if ( !(sub->flags & SUB_EOD_MARKER))
write_sputag(sp, sub->start_time, sub->end_time);
if(sub->nb_data == 0 )
if(sub->nb_data == 0 && (sub->flags & SUB_EOD_MARKER))
{
context->prev_start = -1;
return 0;
}
rect = sub->data;
for(i = 0;i < sub->nb_data;i++)
{

View File

@@ -1,9 +1,9 @@
#ifndef _SPUPNG_ENCODER_H
#define _SPUPNG_ENCODER_H
#include <stdio.h>
#include "ccx_common_platform.h"
#include "ccx_encoders_structs.h"
#include "png.h"
#include "ccextractor.h"
// CC page dimensions
#define ROWS 15

View File

@@ -366,16 +366,16 @@ void telxcc_dump_prev_page (void)
fdprintf(wbout1.fh, "%s|", c_temp1);
}
if (ccx_options.transcript_settings.showEndTime)
{
{
millis_to_date (prev_hide_timestamp, c_temp2);
fdprintf(wbout1.fh,"%s|",c_temp2);
}
if (ccx_options.transcript_settings.showMode){
fdprintf(wbout1.fh, "TLT|");
fdprintf(wbout1.fh,"%s|",c_temp2);
}
if (ccx_options.transcript_settings.showCC){
fdprintf(wbout1.fh, "%.3u|", bcd_page_to_int(tlt_config.page));
}
if (ccx_options.transcript_settings.showMode){
fdprintf(wbout1.fh, "TLT|");
}
if (wbout1.fh!=-1) fdprintf(wbout1.fh, "%s",page_buffer_prev);
fdprintf(wbout1.fh,"%s",encoded_crlf);
@@ -588,7 +588,7 @@ void process_page(teletext_page_t *page) {
}
}
time_reported=0;
switch (ccx_options.write_format)
{
case CCX_OF_TRANSCRIPT:
@@ -712,6 +712,7 @@ void process_telx_packet(data_unit_t data_unit_id, teletext_packet_payload_t *pa
// it would be nice, if subtitle hides on previous video frame, so we contract 40 ms (1 frame @25 fps)
page_buffer.hide_timestamp = timestamp - 40;
process_page(&page_buffer);
}
page_buffer.show_timestamp = timestamp;
@@ -898,6 +899,45 @@ void process_telx_packet(data_unit_t data_unit_id, teletext_packet_payload_t *pa
}
}
void tlt_write_rcwt(uint8_t data_unit_id, uint8_t *packet, uint64_t timestamp) {
if (ccx_options.send_to_srv) {
net_send_cc((unsigned char *) &data_unit_id, sizeof(uint8_t));
net_send_cc((unsigned char *) &timestamp, sizeof(uint64_t));
net_send_cc((unsigned char *) packet, 44);
} else {
writeraw((unsigned char *) &data_unit_id, sizeof(uint8_t), &wbout1);
writeraw((unsigned char *) &timestamp, sizeof(uint64_t), &wbout1);
writeraw((unsigned char *) packet, 44, &wbout1);
}
}
void tlt_read_rcwt() {
int len = 1 + 8 + 44;
char *buf = (char *) malloc(len);
if (buf == NULL)
fatal(EXIT_NOT_ENOUGH_MEMORY, "Not enough memory");
while(1) {
buffered_read(buf, len);
past += result;
if (result != len) {
end_of_file = 1;
free(buf);
return;
}
data_unit_t id = buf[0];
uint64_t t;
memcpy(&t, &buf[1], sizeof(uint64_t));
teletext_packet_payload_t *pl = (teletext_packet_payload_t *)&buf[9];
last_timestamp = t;
process_telx_packet(id, pl, t);
}
}
void tlt_process_pes_packet(uint8_t *buffer, uint16_t size) {
uint64_t pes_prefix;
uint8_t pes_stream_id;
@@ -1000,8 +1040,11 @@ void tlt_process_pes_packet(uint8_t *buffer, uint16_t size) {
// reverse endianess (via lookup table), ETS 300 706, chapter 7.1
for (uint8_t j = 0; j < data_unit_len; j++) buffer[i + j] = REVERSE_8[buffer[i + j]];
// FIXME: This explicit type conversion could be a problem some day -- do not need to be platform independant
process_telx_packet((data_unit_t) data_unit_id, (teletext_packet_payload_t *)&buffer[i], last_timestamp);
if (ccx_options.write_format == CCX_OF_RCWT)
tlt_write_rcwt(data_unit_id, &buffer[i], last_timestamp);
else
// FIXME: This explicit type conversion could be a problem some day -- do not need to be platform independant
process_telx_packet((data_unit_t) data_unit_id, (teletext_packet_payload_t *)&buffer[i], last_timestamp);
}
}
@@ -1016,7 +1059,7 @@ void analyze_pat(uint8_t *buffer, uint8_t size) {
//!
if (pat.pointer_field > 0) {
fatal (EXIT_UNSUPPORTED, "! pat.pointer_field > 0 (0x%02x)\n\n", pat.pointer_field);
fatal(CCX_COMMON_EXIT_UNSUPPORTED, "! pat.pointer_field > 0 (0x%02x)\n\n", pat.pointer_field);
}
pat.table_id = buffer[1];
@@ -1054,7 +1097,7 @@ void analyze_pmt(uint8_t *buffer, uint8_t size) {
//!
if (pmt.pointer_field > 0) {
fatal (EXIT_UNSUPPORTED, "! pmt.pointer_field > 0 (0x%02x)\n\n", pmt.pointer_field);
fatal(CCX_COMMON_EXIT_UNSUPPORTED, "! pmt.pointer_field > 0 (0x%02x)\n\n", pmt.pointer_field);
}
pmt.table_id = buffer[1];
@@ -1110,14 +1153,15 @@ void telxcc_init(void)
// Close output
void telxcc_close(void)
{
if (telxcc_inited)
{
if (telxcc_inited && ccx_options.write_format != CCX_OF_RCWT)
{
// output any pending close caption
if (page_buffer.tainted == YES) {
// this time we do not subtract any frames, there will be no more frames
page_buffer.hide_timestamp = last_timestamp;
process_page(&page_buffer);
}
}
telxcc_dump_prev_page();
if ((tlt_frames_produced == 0) && (tlt_config.nonempty == YES)) {
@@ -1208,7 +1252,7 @@ int main_telxcc (int argc, char *argv[]) {
// not TS packet?
if (header.sync != 0x47)
fatal (EXIT_UNSUPPORTED, "- Invalid TS packet header\n- telxcc does not work with unaligned TS.\n\n");
fatal (CCX_COMMON_EXIT_UNSUPPORTED, "- Invalid TS packet header\n- telxcc does not work with unaligned TS.\n\n");
// uncorrectable error?
if (header.transport_error > 0) {

View File

@@ -503,9 +503,9 @@ LLONG ts_getmoredata(void)
else
{
if (ccx_options.ts_forced_cappid)
fatal (EXIT_UNSUPPORTED, "Unable to determine stream type of selected PID.");
fatal(CCX_COMMON_EXIT_UNSUPPORTED, "Unable to determine stream type of selected PID.");
else
fatal(EXIT_BUG_BUG, "Not reachable!");
fatal(CCX_COMMON_EXIT_BUG_BUG, "Not reachable!");
}
// We read a video PES
@@ -562,7 +562,7 @@ LLONG ts_getmoredata(void)
// 12 bytes total length, stream id = 0xbd (Private non-video and non-audio), etc
if (2 > BUFSIZE - inbuf)
{
fatal(EXIT_BUG_BUG,
fatal(CCX_COMMON_EXIT_BUG_BUG,
"Remaining buffer (%lld) not enough to hold the 3 Hauppage bytes.\n"
"Please send bug report!",
BUFSIZE - inbuf);
@@ -614,7 +614,7 @@ LLONG ts_getmoredata(void)
if (databuflen > BUFSIZE - inbuf)
{
fatal(EXIT_BUG_BUG,
fatal(CCX_COMMON_EXIT_BUG_BUG,
"PES data packet (%ld) larger than remaining buffer (%lld).\n"
"Please send bug report!",
databuflen, BUFSIZE - inbuf);

View File

@@ -286,7 +286,7 @@ int parse_PMT (unsigned char *buf,int len, int pos)
break;
ccx_options.ts_cappid = newcappid = elementary_PID;
cap_stream_type = newcap_stream_type = ccx_stream_type;
max_dif = 10;
max_dif = 30;
}
}
}
@@ -455,7 +455,7 @@ int parse_PAT (void)
dbg_print(CCX_DMT_PAT, "Long PAT packet (%u / %u), skipping.\n",
section_number, last_section_number);
return gotpes;
/* fatal(EXIT_BUG_BUG,
/* fatal(CCX_COMMON_EXIT_BUG_BUG,
"Sorry, long PATs not yet supported!\n"); */
}
@@ -519,7 +519,7 @@ int parse_PAT (void)
if ( programm_data+4 > payload_length )
{
fatal(EXIT_BUG_BUG,
fatal(CCX_COMMON_EXIT_BUG_BUG,
"Sorry, PAT too long!\n");
}
@@ -599,7 +599,7 @@ int parse_PAT (void)
if (!ccx_options.ts_forced_program_selected)
{
if (!ccx_options.ts_autoprogram)
fatal(EXIT_BUG_BUG, "Run ccextractor again with --program-number specifying which program\nto process.");
fatal(CCX_COMMON_EXIT_BUG_BUG, "Run ccextractor again with --program-number specifying which program\nto process.");
else
mprint ("\nThe first program with a suitable CC stream will be selected.\n");
}

View File

@@ -1,9 +1,6 @@
#include <signal.h>
#include "ccextractor.h"
#ifdef _MSC_VER
#define strcasecmp stricmp
#endif
static char *text;
static int text_size=0;
@@ -71,23 +68,10 @@ void millis_to_date (uint64_t timestamp, char *buffer)
break;
default:
fatal (EXIT_BUG_BUG, "Invalid value for date_format in millis_to_date()\n");
fatal(CCX_COMMON_EXIT_BUG_BUG, "Invalid value for date_format in millis_to_date()\n");
}
}
void mstotime (LLONG milli, unsigned *hours, unsigned *minutes,
unsigned *seconds, unsigned *ms)
{
// LLONG milli = (LLONG) ((ccblock*1000)/29.97);
*ms=(unsigned) (milli%1000); // milliseconds
milli=(milli-*ms)/1000; // Remainder, in seconds
*seconds = (int) (milli%60);
milli=(milli-*seconds)/60; // Remainder, in minutes
*minutes = (int) (milli%60);
milli=(milli-*minutes)/60; // Remainder, in hours
*hours=(int) milli;
}
bool_t in_array(uint16_t *array, uint16_t length, uint16_t element) {
bool_t r = NO;
for (uint16_t i = 0; i < length; i++)
@@ -125,47 +109,6 @@ void fatal(int exit_code, const char *fmt, ...)
exit(exit_code);
}
/* printf() for fd instead of FILE*, since dprintf is not portable */
void fdprintf (int fd, const char *fmt, ...)
{
/* Guess we need no more than 100 bytes. */
int n, size = 100;
char *p, *np;
va_list ap;
if( fd < 0)
return;
if ((p = (char *) malloc (size)) == NULL)
return;
while (1)
{
/* Try to print in the allocated space. */
va_start(ap, fmt);
n = vsnprintf (p, size, fmt, ap);
va_end(ap);
/* If that worked, return the string. */
if (n > -1 && n < size)
{
write (fd, p, n);
free (p);
return;
}
/* Else try again with more space. */
if (n > -1) /* glibc 2.1 */
size = n+1; /* precisely what is needed */
else /* glibc 2.0 */
size *= 2; /* twice the old size */
if ((np = (char *) realloc (p, size)) == NULL)
{
free(p);
return ;
} else {
p = np;
}
}
}
/* General output, replacement for printf so we can control globally where messages go.
mprint => Message print */
void mprint (const char *fmt, ...)
@@ -302,48 +245,18 @@ int hex2int (char high, char low)
return -1;
return h*16+l;
}
/**
* @param base points to the start of the array
* @param nb number of element in array
* @param size size of each element
* @param compar Comparison function, which is called with three argument
* that point to the objects being compared and arg.
* @param arg argument passed as it is to compare function
*/
void shell_sort(void *base, int nb,size_t size,int (*compar)(const void*p1,const void *p2,void*arg),void *arg)
{
unsigned char *lbase = (unsigned char*)base;
unsigned char *tmp = (unsigned char*)malloc(size);
for (int gap = nb / 2; gap > 0; gap = gap / 2)
{
int p, j;
for (p = gap; p < nb; p++)
{
memcpy(tmp, lbase + (p *size), size);
for (j = p; j >= gap && ( compar(tmp,lbase + ( (j - gap) * size),arg) < 0); j -= gap)
{
memcpy(lbase + (j*size),lbase + ( (j - gap) * size),size);
}
memcpy(lbase + (j *size),tmp, size);
}
}
free(tmp);
}
int string_cmp2(const void *p1,const void *p2,void *arg)
#ifndef _WIN32
void m_signal(int sig, void (*func)(int))
{
return strcasecmp(*(char**)p1,*(char**)p2);
}
int string_cmp(const void *p1,const void *p2)
{
return string_cmp2(p1, p2, NULL);
}
struct sigaction act;
act.sa_handler = func;
sigemptyset(&act.sa_mask);
act.sa_flags = 0;
void freep(void *arg)
{
void **ptr = (void **) arg;
if (*ptr)
free(*ptr);
*ptr = NULL;
if (sigaction(sig, &act, NULL))
perror("sigaction() error");
return;
}
#endif

View File

@@ -2,7 +2,7 @@
#define CC_UTILITY_H
#ifndef _WIN32
#include <arpa/inet.h>
#include <arpa/inet.h>
#endif
#define RL32(x) (*(unsigned int *)(x))
@@ -10,9 +10,4 @@
#define RL16(x) (*(unsigned short int*)(x))
#define RB16(x) (ntohs(*(unsigned short int*)(x)))
void shell_sort(void *base, int nb,size_t size,int (*compar)(const void*p1,const void *p2,void*arg),void *arg);
int string_cmp(const void *p1,const void *p2);
int string_cmp2(const void *p1,const void *p2,void *arg);
void freep(void *arg);
#endif
#endif

View File

@@ -4,6 +4,7 @@
#define WTV_STREAM2 "\xA2\xC3\xD2\xC2\x7E\x9A\xDA\x11\x8B\xF7\x00\x07\xE9\x5E\xAD\x8D"
#define WTV_DATA "\x95\xC3\xD2\xC2\x7E\x9A\xDA\x11\x8B\xF7\x00\x07\xE9\x5E\xAD\x8D"
#define WTV_STREAM_VIDEO "\x76\x69\x64\x73\x00\x00\x10\x00\x80\x00\x00\xAA\x00\x38\x9B\x71"
#define WTV_STREAM_AUDIO "\x61\x75\x64\x73\x00\x00\x10\x00\x80\x00\x00\xAA\x00\x38\x9B\x71"
#define WTV_STREAM_MSTVCAPTION "\x89\x8A\x8B\xB8\x49\xB0\x80\x4C\xAD\xCF\x58\x98\x98\x5E\x22\xC1"
#define WTV_EOF "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
#define WTV_TIMING "\x5B\x05\xE6\x1B\x97\xA9\x49\x43\x88\x17\x1A\x65\x5A\x29\x8A\x97"
@@ -18,6 +19,9 @@
//Maximum size we will try and malloc for chunked_buffer. 100MB
#define WTV_MAX_ALLOC 1024*1024*100
#define WTV_CC_TIMESTAMP_MAGIC 1668330
#define WTV_CC_TIMESTAMP_MAGIC_THRESH 2 //Only switch to alt stream after THRESH magic numbers
struct wtv_chunked_buffer
{
uint64_t skip_chunks[256];

View File

@@ -297,6 +297,8 @@ int read_header(struct wtv_chunked_buffer *cb) {
LLONG get_data(struct wtv_chunked_buffer *cb) {
static int video_streams[32];
static int alt_stream; //Stream to use for timestamps if the cc stream has broken timestamps
static int use_alt_stream = 0;
static int num_streams=0;
while(1)
{
@@ -368,9 +370,12 @@ LLONG get_data(struct wtv_chunked_buffer *cb) {
video_streams[num_streams]=stream_id; // We keep a list of stream ids
num_streams++; // Even though there should only be 1
}
if (memcmp(stream_type, WTV_STREAM_AUDIO, 16))
alt_stream = stream_id;
len-=28;
}
if( !memcmp(guid, WTV_TIMING, 16 ) && check_stream_id(stream_id, video_streams, num_streams))
if (!memcmp(guid, WTV_TIMING, 16) && ((use_alt_stream < WTV_CC_TIMESTAMP_MAGIC_THRESH && check_stream_id(stream_id, video_streams, num_streams))
|| (use_alt_stream == WTV_CC_TIMESTAMP_MAGIC_THRESH && stream_id == alt_stream)))
{
// The WTV_TIMING GUID contains a timestamp for the given stream_id
dbg_print(CCX_DMT_PARSE, "WTV TIMING\n");
@@ -379,12 +384,18 @@ LLONG get_data(struct wtv_chunked_buffer *cb) {
int64_t time;
memcpy(&time, cb->buffer+0x8, 8); // Read the timestamp
dbg_print(CCX_DMT_PARSE, "TIME: %ld\n", time);
if(time!=-1) { // Ignore -1 timestamps
if (time != -1 && time != WTV_CC_TIMESTAMP_MAGIC) { // Ignore -1 timestamps
current_pts = time_to_pes_time(time); // Convert from WTV to PES time
pts_set = 1;
frames_since_ref_time = 0;
set_fts();
}
}
else if (time == WTV_CC_TIMESTAMP_MAGIC && stream_id != alt_stream) {
use_alt_stream++;
mprint("WARNING: %i WTV_CC_TIMESTAMP_MAGIC detected in cc timestamps. \n", use_alt_stream);
if (use_alt_stream == WTV_CC_TIMESTAMP_MAGIC_THRESH)
mprint("WARNING: WTV_CC_TIMESTAMP_MAGIC_THRESH reached. Switching to alt timestamps!\n");
}
len-=16;
}
if( !memcmp(guid, WTV_DATA, 16 )

View File

@@ -1,8 +0,0 @@
#ifndef _XDS_H
#define _XDS_H
void xds_write_transcript_line_suffix (struct ccx_s_write *wb);
void xds_write_transcript_line_prefix (struct ccx_s_write *wb, LLONG start_time, LLONG end_time, int cur_xds_packet_class);
#endif

Binary file not shown.

View File

@@ -11,15 +11,21 @@
</ProjectConfiguration>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\src\608.h" />
<ClInclude Include="..\src\ccx_common_char_encoding.h" />
<ClInclude Include="..\src\ccx_common_common.h" />
<ClInclude Include="..\src\ccx_decoders_608.h" />
<ClInclude Include="..\src\608_spupng.h" />
<ClInclude Include="..\src\708.h" />
<ClInclude Include="..\src\asf_constants.h" />
<ClInclude Include="..\src\bitstream.h" />
<ClInclude Include="..\src\ccextractor.h" />
<ClInclude Include="..\src\cc_encoders_common.h" />
<ClInclude Include="..\src\ccx_decoders_708.h" />
<ClInclude Include="..\src\ccx_decoders_structs.h" />
<ClInclude Include="..\src\ccx_encoders_helpers.h" />
<ClInclude Include="..\src\ccx_encoders_structs.h" />
<ClInclude Include="..\src\ccx_decoders_common.h" />
<ClInclude Include="..\src\ccx_encoders_common.h" />
<ClInclude Include="..\src\configuration.h" />
<ClInclude Include="..\src\constants.h" />
<ClInclude Include="..\src\ccx_common_constants.h" />
<ClInclude Include="..\src\disable_warnings.h" />
<ClInclude Include="..\src\dvb_subtitle_decoder.h" />
<ClInclude Include="..\src\gpacmp4\gpac\avparse.h" />
@@ -47,6 +53,7 @@
<ClInclude Include="..\src\gpacmp4\gpac\version.h" />
<ClInclude Include="..\src\gpacmp4\targetver.h" />
<ClInclude Include="..\src\hamming.h" />
<ClInclude Include="..\src\ccx_common_structs.h" />
<ClInclude Include="..\src\inttypes.h" />
<ClInclude Include="..\src\libpng\png.h" />
<ClInclude Include="..\src\libpng\pngconf.h" />
@@ -56,13 +63,16 @@
<ClInclude Include="..\src\libpng\pngpriv.h" />
<ClInclude Include="..\src\libpng\pngstruct.h" />
<ClInclude Include="..\src\networking.h" />
<ClInclude Include="..\src\platform.h" />
<ClInclude Include="..\src\ccx_common_platform.h" />
<ClInclude Include="..\src\ocr.h" />
<ClInclude Include="..\src\spupng_encoder.h" />
<ClInclude Include="..\src\stdint.h" />
<ClInclude Include="..\src\stdintmsc.h" />
<ClInclude Include="..\src\teletext.h" />
<ClInclude Include="..\src\ccx_common_timing.h" />
<ClInclude Include="..\src\utility.h" />
<ClInclude Include="..\src\wtv_constants.h" />
<ClInclude Include="..\src\ccx_decoders_xds.h" />
<ClInclude Include="..\src\zlib\crc32.h" />
<ClInclude Include="..\src\zlib\deflate.h" />
<ClInclude Include="..\src\zlib\gzguts.h" />
@@ -76,25 +86,26 @@
<ClInclude Include="..\src\zlib\zutil.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\src\608.c" />
<ClCompile Include="..\src\608_helpers.c" />
<ClCompile Include="..\src\ccx_common_common.c" />
<ClCompile Include="..\src\ccx_decoders_608.c" />
<ClCompile Include="..\src\608_sami.c" />
<ClCompile Include="..\src\608_smptett.c" />
<ClCompile Include="..\src\608_spupng.c" />
<ClCompile Include="..\src\608_srt.c" />
<ClCompile Include="..\src\708.c" />
<ClCompile Include="..\src\708_encoding.c" />
<ClCompile Include="..\src\activity.c" />
<ClCompile Include="..\src\asf_functions.c" />
<ClCompile Include="..\src\avc_functions.c" />
<ClCompile Include="..\src\ccextractor.c" />
<ClCompile Include="..\src\ccx_decoders_708.c" />
<ClCompile Include="..\src\ccx_encoders_helpers.c" />
<ClCompile Include="..\src\cc_bitstream.c" />
<ClCompile Include="..\src\cc_decoders_common.c" />
<ClCompile Include="..\src\cc_encoders_common.c" />
<ClCompile Include="..\src\ccx_decoders_common.c" />
<ClCompile Include="..\src\ccx_encoders_common.c" />
<ClCompile Include="..\src\configuration.c" />
<ClCompile Include="..\src\constants.c" />
<ClCompile Include="..\src\ccx_common_constants.c" />
<ClCompile Include="..\src\dvb_subtitle_decoder.c" />
<ClCompile Include="..\src\encoding.c" />
<ClCompile Include="..\src\ccx_common_char_encoding.c" />
<ClCompile Include="..\src\es_functions.c" />
<ClCompile Include="..\src\es_userdata.c" />
<ClCompile Include="..\src\file_functions.c" />
@@ -158,6 +169,7 @@
<ClCompile Include="..\src\libpng\pngwutil.c" />
<ClCompile Include="..\src\myth.c" />
<ClCompile Include="..\src\networking.c" />
<ClCompile Include="..\src\ocr.c" />
<ClCompile Include="..\src\output.c" />
<ClCompile Include="..\src\params.c" />
<ClCompile Include="..\src\params_dump.c" />
@@ -165,12 +177,12 @@
<ClCompile Include="..\src\spupng_encoder.c" />
<ClCompile Include="..\src\stream_functions.c" />
<ClCompile Include="..\src\telxcc.c" />
<ClCompile Include="..\src\timing.c" />
<ClCompile Include="..\src\ccx_common_timing.c" />
<ClCompile Include="..\src\ts_functions.c" />
<ClCompile Include="..\src\ts_tables.c" />
<ClCompile Include="..\src\utility.c" />
<ClCompile Include="..\src\wtv_functions.c" />
<ClCompile Include="..\src\xds.c" />
<ClCompile Include="..\src\ccx_decoders_xds.c" />
<ClCompile Include="..\src\zlib\adler32.c" />
<ClCompile Include="..\src\zlib\crc32.c" />
<ClCompile Include="..\src\zlib\deflate.c" />

View File

@@ -31,17 +31,26 @@
<Filter Include="Header Files\zlib">
<UniqueIdentifier>{e76a99a9-8a06-4ffb-afa1-f87c057f8448}</UniqueIdentifier>
</Filter>
<Filter Include="Header Files\ccx_decoders">
<UniqueIdentifier>{5af060a0-c719-4d1b-913f-71c4452fbe10}</UniqueIdentifier>
</Filter>
<Filter Include="Header Files\ccx_common">
<UniqueIdentifier>{955fdac2-43c6-4968-8fce-7d40bad9c712}</UniqueIdentifier>
</Filter>
<Filter Include="Header Files\ccx_encoders">
<UniqueIdentifier>{489d2c0b-43e8-4d51-8304-f4e59ee8d253}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\ccx_decoders">
<UniqueIdentifier>{0e9c939f-a37c-4d06-a611-4c262b620763}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\ccx_encoders">
<UniqueIdentifier>{720b7c91-968e-4dd8-a8df-6d99f9c9b52d}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\ccx_common">
<UniqueIdentifier>{2b841054-ad06-429d-9b44-fabd29fbeef0}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\src\608.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\src\608_spupng.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\src\708.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\src\asf_constants.h">
<Filter>Header Files</Filter>
</ClInclude>
@@ -51,36 +60,21 @@
<ClInclude Include="..\src\ccextractor.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\src\constants.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\src\disable_warnings.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\src\dvb_subtitle_decoder.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\src\hamming.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\src\inttypes.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\src\platform.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\src\spupng_encoder.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\src\stdint.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\src\stdintmsc.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\src\teletext.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\src\wtv_constants.h">
<Filter>Header Files</Filter>
</ClInclude>
@@ -216,44 +210,68 @@
<ClInclude Include="..\src\configuration.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\src\cc_encoders_common.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\src\networking.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\src\ccx_decoders_structs.h">
<Filter>Header Files\ccx_decoders</Filter>
</ClInclude>
<ClInclude Include="..\src\ccx_encoders_structs.h">
<Filter>Header Files\ccx_encoders</Filter>
</ClInclude>
<ClInclude Include="..\src\ccx_decoders_608.h">
<Filter>Header Files\ccx_decoders</Filter>
</ClInclude>
<ClInclude Include="..\src\ccx_decoders_common.h">
<Filter>Header Files\ccx_decoders</Filter>
</ClInclude>
<ClInclude Include="..\src\ccx_decoders_xds.h">
<Filter>Header Files\ccx_decoders</Filter>
</ClInclude>
<ClInclude Include="..\src\ccx_encoders_common.h">
<Filter>Header Files\ccx_encoders</Filter>
</ClInclude>
<ClInclude Include="..\src\ccx_common_common.h">
<Filter>Header Files\ccx_common</Filter>
</ClInclude>
<ClInclude Include="..\src\ccx_common_structs.h">
<Filter>Header Files\ccx_common</Filter>
</ClInclude>
<ClInclude Include="..\src\ccx_common_platform.h">
<Filter>Header Files\ccx_common</Filter>
</ClInclude>
<ClInclude Include="..\src\ccx_common_constants.h">
<Filter>Header Files\ccx_common</Filter>
</ClInclude>
<ClInclude Include="..\src\ccx_common_timing.h">
<Filter>Header Files\ccx_common</Filter>
</ClInclude>
<ClInclude Include="..\src\ccx_decoders_708.h">
<Filter>Header Files\ccx_decoders</Filter>
</ClInclude>
<ClInclude Include="..\src\ccx_encoders_helpers.h">
<Filter>Header Files\ccx_encoders</Filter>
</ClInclude>
<ClInclude Include="..\src\ocr.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\src\spupng_encoder.h">
<Filter>Header Files\ccx_encoders</Filter>
</ClInclude>
<ClInclude Include="..\src\ccx_common_char_encoding.h">
<Filter>Header Files\ccx_common</Filter>
</ClInclude>
<ClInclude Include="..\src\dvb_subtitle_decoder.h">
<Filter>Header Files\ccx_decoders</Filter>
</ClInclude>
<ClInclude Include="..\src\teletext.h">
<Filter>Header Files\ccx_decoders</Filter>
</ClInclude>
<ClInclude Include="..\src\608_spupng.h">
<Filter>Header Files\ccx_encoders</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\src\gpacmp4\stbl_read.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\gpacmp4\stbl_write.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\608.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\608_helpers.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\608_sami.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\608_smptett.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\608_spupng.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\608_srt.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\708.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\708_encoding.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\activity.c">
<Filter>Source Files</Filter>
</ClCompile>
@@ -266,21 +284,9 @@
<ClCompile Include="..\src\cc_bitstream.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\cc_decoders_common.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\ccextractor.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\constants.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\dvb_subtitle_decoder.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\encoding.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\es_functions.c">
<Filter>Source Files</Filter>
</ClCompile>
@@ -308,18 +314,9 @@
<ClCompile Include="..\src\sequencing.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\spupng_encoder.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\stream_functions.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\telxcc.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\timing.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\ts_functions.c">
<Filter>Source Files</Filter>
</ClCompile>
@@ -332,9 +329,6 @@
<ClCompile Include="..\src\wtv_functions.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\xds.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\gpacmp4\av_parsers.c">
<Filter>Source Files\gpacmp4</Filter>
</ClCompile>
@@ -527,11 +521,71 @@
<ClCompile Include="..\src\configuration.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\cc_encoders_common.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\networking.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\ccx_decoders_608.c">
<Filter>Source Files\ccx_decoders</Filter>
</ClCompile>
<ClCompile Include="..\src\ccx_decoders_common.c">
<Filter>Source Files\ccx_decoders</Filter>
</ClCompile>
<ClCompile Include="..\src\ccx_decoders_xds.c">
<Filter>Source Files\ccx_decoders</Filter>
</ClCompile>
<ClCompile Include="..\src\ccx_encoders_common.c">
<Filter>Source Files\ccx_encoders</Filter>
</ClCompile>
<ClCompile Include="..\src\ccx_common_constants.c">
<Filter>Source Files\ccx_common</Filter>
</ClCompile>
<ClCompile Include="..\src\ccx_common_common.c">
<Filter>Source Files\ccx_common</Filter>
</ClCompile>
<ClCompile Include="..\src\ccx_common_timing.c">
<Filter>Source Files\ccx_common</Filter>
</ClCompile>
<ClCompile Include="..\src\ccx_decoders_708.c">
<Filter>Source Files\ccx_decoders</Filter>
</ClCompile>
<ClCompile Include="..\src\ccx_encoders_helpers.c">
<Filter>Source Files\ccx_encoders</Filter>
</ClCompile>
<ClCompile Include="..\src\ocr.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\spupng_encoder.c">
<Filter>Source Files\ccx_encoders</Filter>
</ClCompile>
<ClCompile Include="..\src\ccx_common_char_encoding.c">
<Filter>Source Files\ccx_common</Filter>
</ClCompile>
<ClCompile Include="..\src\dvb_subtitle_decoder.c">
<Filter>Source Files\ccx_decoders</Filter>
</ClCompile>
<ClCompile Include="..\src\telxcc.c">
<Filter>Source Files\ccx_decoders</Filter>
</ClCompile>
<ClCompile Include="..\src\608_sami.c">
<Filter>Source Files\ccx_encoders</Filter>
</ClCompile>
<ClCompile Include="..\src\608_smptett.c">
<Filter>Source Files\ccx_encoders</Filter>
</ClCompile>
<ClCompile Include="..\src\608_spupng.c">
<Filter>Source Files\ccx_encoders</Filter>
</ClCompile>
<ClCompile Include="..\src\608_srt.c">
<Filter>Source Files\ccx_encoders</Filter>
</ClCompile>
<ClCompile Include="..\src\708_encoding.c">
<Filter>Source Files\ccx_encoders</Filter>
</ClCompile>
<ClCompile Include="..\src\gpacmp4\stbl_write.c">
<Filter>Source Files\gpacmp4</Filter>
</ClCompile>
<ClCompile Include="..\src\gpacmp4\stbl_read.c">
<Filter>Source Files\gpacmp4</Filter>
</ClCompile>
</ItemGroup>
</Project>