mirror of
https://github.com/CCExtractor/ccextractor.git
synced 2026-02-12 05:25:06 +00:00
Compare commits
78 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
18f781d099 | ||
|
|
84db812769 | ||
|
|
7763f8aeab | ||
|
|
faa879801e | ||
|
|
4635329a5b | ||
|
|
b89cc3b6df | ||
|
|
e9f8313f7c | ||
|
|
324cd84ffe | ||
|
|
9d7518c9ec | ||
|
|
32e0d6023d | ||
|
|
c9465e476b | ||
|
|
45d237da40 | ||
|
|
631ae2e02f | ||
|
|
695aa14cd7 | ||
|
|
b638bb1d3a | ||
|
|
28950bf90e | ||
|
|
77f8289ca6 | ||
|
|
cece92a828 | ||
|
|
bd08454d66 | ||
|
|
c6e5dd5cf7 | ||
|
|
bd8e3ad137 | ||
|
|
8a2e71fcfb | ||
|
|
301c2a7138 | ||
|
|
5368d7292f | ||
|
|
29689b10aa | ||
|
|
4d8883d0f1 | ||
|
|
efe6fceb3a | ||
|
|
d9a998b95f | ||
|
|
bf94c2997d | ||
|
|
6405a3973d | ||
|
|
9270e22a65 | ||
|
|
02e19cf617 | ||
|
|
1493b6c4f5 | ||
|
|
74ab732999 | ||
|
|
5961d1b56e | ||
|
|
87d6a6bf91 | ||
|
|
456d23f547 | ||
|
|
02da93d0e4 | ||
|
|
597304e932 | ||
|
|
918889c890 | ||
|
|
47bfe6bffc | ||
|
|
5789a0a224 | ||
|
|
b15f54c7f9 | ||
|
|
bc3794eb14 | ||
|
|
4e66d290a6 | ||
|
|
7b48b01fd1 | ||
|
|
883dfaae4a | ||
|
|
884a25a7cd | ||
|
|
8cc8767634 | ||
|
|
90a6902ad4 | ||
|
|
b334acb426 | ||
|
|
9c847aa4f1 | ||
|
|
c3397d1949 | ||
|
|
41ad0b4006 | ||
|
|
7fa59a14f7 | ||
|
|
170a57b9c6 | ||
|
|
0a15c2d16e | ||
|
|
c52283676a | ||
|
|
ce3c2b5ae2 | ||
|
|
48e030d94c | ||
|
|
afaa7c8b76 | ||
|
|
4e6c0352b0 | ||
|
|
f84b69aca7 | ||
|
|
cc7ebbc4d7 | ||
|
|
7a74b815fa | ||
|
|
331038634d | ||
|
|
aa2c316093 | ||
|
|
3347f5d345 | ||
|
|
141792a299 | ||
|
|
183e613981 | ||
|
|
19e2912a71 | ||
|
|
dc82154a03 | ||
|
|
2029dab3bf | ||
|
|
405d808d0b | ||
|
|
ecc0714f48 | ||
|
|
26410b991d | ||
|
|
19b1bff7f4 | ||
|
|
b765198d53 |
@@ -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
|
||||
|
||||
19
README.md
19
README.md
@@ -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
|
||||
|
||||
@@ -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
58
docs/FFMPEG.TXT
Normal 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
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
166
src/608.h
@@ -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
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
10
src/ccx_common_char_encoding.h
Normal file
10
src/ccx_common_char_encoding.h
Normal 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
65
src/ccx_common_common.c
Normal 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
17
src/ccx_common_common.h
Normal 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
|
||||
@@ -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};
|
||||
@@ -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
113
src/ccx_common_platform.h
Normal 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
52
src/ccx_common_structs.h
Normal 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
|
||||
@@ -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
64
src/ccx_common_timing.h
Normal 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
|
||||
@@ -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
149
src/ccx_decoders_608.h
Normal 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
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
100
src/ccx_decoders_common.c
Normal 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
25
src/ccx_decoders_common.h
Normal 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
|
||||
79
src/ccx_decoders_structs.h
Normal file
79
src/ccx_decoders_structs.h
Normal 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
|
||||
@@ -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
15
src/ccx_decoders_xds.h
Normal 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
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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
391
src/ccx_encoders_helpers.c
Normal 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;
|
||||
}
|
||||
38
src/ccx_encoders_helpers.h
Normal file
38
src/ccx_encoders_helpers.h
Normal 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
|
||||
25
src/ccx_encoders_structs.h
Normal file
25
src/ccx_encoders_structs.h
Normal 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
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
187
src/ffmpeg_intgr.c
Normal 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
23
src/ffmpeg_intgr.h
Normal 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
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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];
|
||||
|
||||
@@ -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.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
20
src/output.c
20
src/output.c
@@ -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;
|
||||
|
||||
177
src/params.c
177
src/params.c
@@ -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
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
|
||||
104
src/platform.h
104
src/platform.h
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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++)
|
||||
{
|
||||
|
||||
@@ -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
|
||||
|
||||
72
src/telxcc.c
72
src/telxcc.c
@@ -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 *) ×tamp, sizeof(uint64_t));
|
||||
net_send_cc((unsigned char *) packet, 44);
|
||||
} else {
|
||||
writeraw((unsigned char *) &data_unit_id, sizeof(uint8_t), &wbout1);
|
||||
writeraw((unsigned char *) ×tamp, 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) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
111
src/utility.c
111
src/utility.c
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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];
|
||||
|
||||
@@ -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 )
|
||||
|
||||
@@ -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.
@@ -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" />
|
||||
|
||||
@@ -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>
|
||||
Reference in New Issue
Block a user