Compare commits

...

670 Commits
v0.72 ... v0.78

Author SHA1 Message Date
cfsmp3
509ed756fd 0.78 2015-12-14 21:29:45 +01:00
cfsmp3
152b69ddba Changed version number to 0.78 2015-12-12 18:53:48 +01:00
Anshul Maheshwari
c2eedab33d Adding simple xml support
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-12-12 17:49:54 +05:30
Carlos Fernandez
677fee4145 Start segments at 1 2015-10-28 06:58:26 -07:00
Anshul Maheshwari
72dad743dc remove white space
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-10-27 19:14:52 +05:30
Anshul Maheshwari
e262b0699a Memory Cleanup
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-10-27 19:05:52 +05:30
Anshul Maheshwari
6942089a32 Remove Dead Code
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-10-27 17:59:10 +05:30
Anshul Maheshwari
993adc3dec Indenting psi function
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-10-27 17:58:09 +05:30
Anshul Maheshwari
fe7a39c0cb initialized end of string
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-10-27 17:53:20 +05:30
Anshul Maheshwari
3bd704e495 working explicit no roll up in ISDB
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-10-27 13:59:13 +05:30
Anshul Maheshwari
6992e54f8e Correct indentation
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-10-26 10:15:15 +05:30
Anshul Maheshwari
4d5ab77fed improve isdb
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-10-25 15:29:18 +05:30
Anshul Maheshwari
1b2328d728 Adding No Rollup in ISDB
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-10-23 19:34:47 +05:30
Anshul Maheshwari
2944e12541 remove unnecessary space
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-10-23 15:33:13 +05:30
Anshul Maheshwari
763972ca4b Added latin-1 support for teletext transcript
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-10-23 04:22:11 +05:30
Anshul Maheshwari
01fe0c1fc9 consider last character
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-10-23 01:56:39 +05:30
Anshul Maheshwari
8d160a70ff Correcting broken encoding of telexcc
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-10-23 01:15:40 +05:30
Anshul Maheshwari
fc90b9c9f5 Added caption server details in logs
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-10-21 20:52:50 +05:30
Anshul Maheshwari
0a803df23f Adding parsing logic for private user data
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-10-21 18:24:36 +05:30
Anshul Maheshwari
d3a1ed4b06 Adding Caption descriptor
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>

This description has been added with refrence to descripton defined
in ATSC Standard

Standard Name:   Digital Video Service Multiplex and
              Transport System Standard for Cable Television

Standard Number: ANSI/SCTE 54 2009
Table 5.5 Descriptors
Section 5.8.3.6 Caption service descriptor

This was implemented for broken video in Willem testSuite with number 6
2015-10-21 17:21:39 +05:30
Anshul Maheshwari
ad89e0074b revert back max bframe
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-10-21 14:05:59 +05:30
Anshul Maheshwari
169a39eb3e correct Garbeled cc in multiple slice header
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-10-21 13:19:46 +05:30
Anshul Maheshwari
a6145af7f3 newline after showing all payload
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-10-19 16:47:28 +05:30
Anshul Maheshwari
03b60ef140 use common logger
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-10-19 13:37:51 +05:30
Anshul Maheshwari
1b7ef1e198 remove dead code
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-10-19 13:37:01 +05:30
Anshul Maheshwari
72de68a575 Specify es paresr specific function
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>

They should be moved in structure instead of writing them openly in
common decoder
2015-10-19 13:34:07 +05:30
Anshul Maheshwari
24e7b94599 regards for local count while allocatinf buffer
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-10-19 13:33:19 +05:30
Anshul Maheshwari
c5dc4531ae use CCX_TRUE instead of 1
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-10-19 13:31:22 +05:30
Anshul Maheshwari
a3e07b4a63 putting back logic of skiping packet when empty
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-10-17 18:16:43 +05:30
Anshul Maheshwari
d48555b849 clear buffer after copid to cc_sub
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-10-06 13:48:04 +05:30
Anshul Maheshwari
a1f05caddf same name buf instead buf1 buf2
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-10-06 13:17:05 +05:30
Anshul Maheshwari
669eb36603 remove redundant logs
Signed-off-by: Anshul Maheshwari <anshul.ffmpeg@gmail.com>
2015-10-06 08:54:09 +02:00
Anshul Maheshwari
ce379bcfda nb of data not decreased properly
Signed-off-by: Anshul Maheshwari <anshul.ffmpeg@gmail.com>
2015-10-06 08:51:43 +02:00
Anshul Maheshwari
00657ffdcd reset payload
Signed-off-by: Anshul Maheshwari <anshul.ffmpeg@gmail.com>
2015-10-05 15:59:56 +02:00
Anshul Maheshwari
d9e0ba027f memset payload
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-10-05 19:26:38 +05:30
Anshul Maheshwari
a7279e3d8a initialize min glb time stamp
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-10-05 19:07:19 +05:30
Anshul Maheshwari
61ae7e9f10 Merge branch 'master' of github.com:anshul1912/ccextractor 2015-10-05 19:03:20 +05:30
Anshul Maheshwari
548d323ca1 Initialize maxtref
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-10-05 19:03:01 +05:30
Anshul Maheshwari
d2d7a17f3b strtok_r for windows
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-10-05 12:58:09 +05:30
cfsmp3
65b0ed0038 Merge branch 'pr/n232_kisselef' 2015-10-04 09:56:20 +02:00
cfsmp3
2b0523d34c Merge branch 'pr/n233_anshul1912' 2015-10-04 09:55:28 +02:00
Anshul Maheshwari
5bef6bd5a4 ISDB tag in transcript mode
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-10-03 20:25:36 +05:30
Anshul Maheshwari
5ca3965c7b care newline in isdb to transcript
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-10-03 19:18:37 +05:30
Oleg Kisselef
e855665c87 cea-708 fixed unhandled predefined window styles 2015-10-02 13:25:14 +03:00
cfsmp3
e9bf8dad9f Merge branch 'pr/n231_anshul1912' 2015-09-30 13:54:15 +02:00
Anshul Maheshwari
54c2b21a4c Update isdb changes
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-09-30 17:21:53 +05:30
cfsmp3
afe5cba480 Merge branch 'pr/n230_anshul1912' 2015-09-30 13:45:15 +02:00
Anshul Maheshwari
8c34f4cbb2 make pcr program wise
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-09-30 16:34:27 +05:30
Anshul Maheshwari
e422e7075a correct buffered_read_opt declaration
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-09-30 14:06:35 +05:30
Anshul Maheshwari
cc0ee507dd remove some vs warning
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-09-30 13:37:27 +05:30
cfsmp3
540850f0b9 Merge branch 'pr/n230_anshul1912' 2015-09-29 17:05:54 +02:00
Anshul Maheshwari
a973c0a9c3 Merge remote-tracking branch 'upstream/master' into isdb 2015-09-29 20:34:42 +05:30
Anshul Maheshwari
ae27b3411b changed some variable name in isdb
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-09-29 20:34:20 +05:30
cfsmp3
89c4ac091a Merge branch 'pr/n230_anshul1912' 2015-09-29 16:56:34 +02:00
Anshul Maheshwari
843ca9b60a add ISDB source files
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-09-29 20:22:53 +05:30
cfsmp3
d135362d40 Add leading 0s in segment names 2015-09-29 16:51:59 +02:00
Anshul Maheshwari
2f1b9df6e9 ISDB support
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-09-29 20:18:50 +05:30
cfsmp3
5ef2519bf5 Merge branch 'pr/n228_anshul1912' 2015-09-24 12:22:45 +02:00
Anshul Maheshwari
f258d317cc remove uninitialized memory
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-09-24 15:51:35 +05:30
cfsmp3
4d3fcd6779 Merge branch 'pr/n228_anshul1912' 2015-09-24 11:54:23 +02:00
Anshul Maheshwari
f1b0aff789 Adding system segmentation logic
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-09-24 15:18:46 +05:30
wforums
6e9a30b354 fix solution
-
2015-09-24 00:08:19 +02:00
wforums
37091708b7 Merge remote-tracking branch 'CCExtractor/master'
Conflicts:
	windows/ccextractor.vcxproj.filters
2015-09-24 00:05:46 +02:00
wforums
0885aae79c Updating project files
-
2015-09-24 00:03:54 +02:00
Anshul Maheshwari
5e5d30d154 Merge branch 'master' of github.com:anshul1912/ccextractor 2015-09-23 23:25:40 +05:30
Anshul Maheshwari
a614db1e20 Add option to segment file
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-09-23 23:25:18 +05:30
Anshul Maheshwari
f7f29e558b removed uninitialized use of result
Signed-off-by: Anshul Maheshwari <anshul.ffmpeg@gmail.com>
2015-09-18 11:59:00 +02:00
Anshul Maheshwari
ddc1bfe74f removed global variable result
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-09-18 12:39:27 +05:30
Anshul Maheshwari
18b95d9564 renamed headerfile
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-09-17 15:51:20 +05:30
Anshul Maheshwari
b012f87d87 move buffered read to file_buffer
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-09-17 15:45:16 +05:30
Anshul Maheshwari
73f277fe95 rename to keep consistency with other file
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-09-17 00:52:38 +05:30
Anshul Maheshwari
bd3df850a5 renamed 608 encoder to generic cc_encoders
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-09-17 00:36:12 +05:30
Anshul Maheshwari
73b52462c0 rename encoders from 608 to generic
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-09-17 00:28:15 +05:30
Anshul Maheshwari
267d7b4a2e moved buffer_read to file_buffer
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-09-17 00:00:22 +05:30
Anshul Maheshwari
35cdeda56c Adding error checking for memory in epg
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-09-16 17:59:44 +05:30
Anshul Maheshwari
0f90eebdf6 uninitialized section length
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-09-16 17:59:40 +05:30
Anshul Maheshwari
962357ed0f Adding comments
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-09-15 19:56:46 +05:30
Anshul Maheshwari
69d077df9e Adding space and reindenting
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-09-15 18:07:54 +05:30
Anshul Maheshwari
e2b0534374 remove dead code
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-09-15 17:57:39 +05:30
Anshul Maheshwari
4204b7878d remove dangling declaration
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-09-15 17:55:39 +05:30
Anshul Maheshwari
1e2237f7ec saving missing result
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-09-15 17:41:00 +05:30
Anshul Maheshwari
6bfe3b3f86 Merge branch 'master' of github.com:anshul1912/ccextractor 2015-09-15 17:12:06 +05:30
Anshul Maheshwari
940bee33a4 Merge remote-tracking branch 'upstream/master' 2015-09-15 17:10:54 +05:30
cfsmp3
7c787157d8 Added -dumpdef (dump defective TS packet) as a debug option 2015-09-15 12:40:45 +02:00
Anshul Maheshwari
7514886199 change from int to LLONG
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-09-15 15:15:37 +05:30
Anshul Maheshwari
ad5b917f3b Compile code in vs2013
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-09-15 15:04:59 +05:30
Anshul Maheshwari
66408fc950 moved buffered_read to inline function
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-09-15 13:51:34 +05:30
cfsmp3
94ec02eea9 Merge branch 'pr/n226_anshul1912' 2015-09-14 13:08:31 +02:00
Anshul Maheshwari
5e33e2e2ac Avoid derefrence of NULL
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-09-12 21:13:07 +05:30
cfsmp3
34613037fc bugfix in webvtt 2015-09-08 17:17:38 +02:00
Anshul Maheshwari
f2b24f13af refactor Webvtt
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>

1) remove srt counter from webvtt
2) add include files so that compiler gives error at incorrect arguments in function call
3) WEBVTT Header do not use srt counter but declared as static const str wriiteen while writing any header
4) Removed srt counter from output file from webvtt refrence taken from http://dev.w3.org/html5/webvtt/
2015-09-08 16:10:37 +05:30
cfsmp3
c718d21d0f Changes to other files 2015-09-08 11:17:28 +02:00
cfsmp3
a2828f0060 -Merge branch 'pr/n216_anshul1912'
-Added WebVTT support (manual merge of the previous PR)
2015-09-07 11:29:07 +02:00
rkuchumov
4b3b846a2c updated changes.txt 2015-09-03 20:49:29 +03:00
Anshul Maheshwari
b232945c71 refactoring headers includes
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-09-02 12:32:22 +05:30
Anshul Maheshwari
f91d1cb9b7 remove errors due to incorrect merge
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-09-01 15:26:50 +05:30
Anshul Maheshwari
fadd8aad8b merge multiprogram changes to main
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-09-01 12:53:05 +05:30
cfsmp3
b0479b247a Merge branch 'pr/n219_kisselef' 2015-08-28 10:12:19 +02:00
cfsmp3
a659544bd2 Merge branch 'pr/n217_brooss' 2015-08-28 10:09:29 +02:00
Oleg Kisselef
9ce4c99180 cea-708 usage help updated 2015-08-28 09:58:50 +03:00
Oleg Kisselef
52f51147b8 cea-708 predefined window styles 2015-08-28 09:49:10 +03:00
Oleg Kisselef
34836b50a1 cea-708 structures renamed according to POSIX. enums names updated. 2015-08-27 22:04:13 +03:00
Oleg Kisselef
7179796365 fixed linux build scripts 2015-08-27 13:50:55 +03:00
Oleg Kisselef
966c90eece win-build: strndup function implementation added 2015-08-27 11:19:03 +03:00
Oleg Kisselef
3281bf929a win-build: iconv updated and executable code removed from header 2015-08-27 11:14:34 +03:00
Oleg Kisselef
906a0704bc -awin-build: networking.c endl 2015-08-27 11:08:17 +03:00
Oleg Kisselef
20785c095c -awin-build: fixed ioctl on windows 2015-08-27 11:07:54 +03:00
Oleg Kisselef
dee2280d06 cea-708 fixed txt,ttxt crlf output 2015-08-26 21:46:40 +03:00
Oleg Kisselef
f6b69b64c3 cea-708 norollup parameter passing. removed ccx_options dependency 2015-08-26 21:42:57 +03:00
Oleg Kisselef
2f09b37f7c cea-708 fixed default pen color 2015-08-26 21:29:32 +03:00
Oleg Kisselef
20cf0f5151 cea-708 detecting malformed services parameter 2015-08-26 19:55:05 +03:00
Oleg Kisselef
860e926b5a cea-708 fixed mem usage bugs 2015-08-26 17:53:12 +03:00
Oleg Kisselef
9f81a4b5c1 cea-708 charset support 2015-08-26 17:26:19 +03:00
Oleg Kisselef
5d85220121 cea-708 cleaning up writers 2015-08-26 16:16:36 +03:00
Oleg Kisselef
6423efa2d7 cea-708 multiprogram support done 2015-08-26 15:54:52 +03:00
Oleg Kisselef
932cb77265 encoding cea-708 2015-08-26 13:54:09 +03:00
Anshul Maheshwari
691244a00e initilaize min_pts to 0 in rcwt
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-08-25 17:52:07 +05:30
Anshul Maheshwari
440c59a5fd Adding space to rcwt_loop
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-08-25 17:33:07 +05:30
Anshul Maheshwari
8a3e2b5efc remove derefrencing global variable
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-08-25 16:37:11 +05:30
Anshul Maheshwari
119a4361df remove if condition
Signed-off-by: Anshul Maheshwari <anshul.ffmpeg@gmail.com>
2015-08-25 12:35:17 +02:00
Anshul Maheshwari
6c93b6dcf4 initialized variables
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-08-25 15:56:07 +05:30
Oleg Kisselef
4d76cd30c0 cea-708 removed unnecessary data from dtvcc decoder 2015-08-25 12:41:30 +03:00
Anshul Maheshwari
96fd051e01 pass dec_ctx instead of its channel
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-08-25 14:12:30 +05:30
Anshul Maheshwari
2fe0da30be ignore xds if not selected in transcript
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-08-25 11:51:09 +05:30
Brooss
890e045a88 SDT: Remove code adding extra null to channel name string end. 2015-08-25 12:34:36 +10:00
Oleg Kisselef
b333df4317 cea-708 keeping symbols in 16-bit variables 2015-08-25 00:05:34 +03:00
Oleg Kisselef
33d91a979c fixed charset handling for cea-708 2015-08-24 23:59:43 +03:00
Anshul Maheshwari
b3614f592f dont derefrence global variables
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-08-24 20:36:24 +05:30
Anshul Maheshwari
3bdb5f3863 remove xds global init
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-08-24 20:21:58 +05:30
Anshul Maheshwari
ad6346f802 making xds_context and moving global vars
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-08-24 20:11:14 +05:30
Anshul Maheshwari
66f41438be moving global variable of sequence to ctx
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-08-24 16:55:06 +05:30
Anshul Maheshwari
647a91eafa shifting global variable in context
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-08-24 13:41:35 +05:30
Brooss
ecf200e290 Add support for parsing the Service Description Table in MPEGTS and using it to provide real channel names in EPG output. 2015-08-24 14:35:10 +10:00
Anshul Maheshwari
da576bff2b Pass timing in get_fts function
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-08-22 17:45:09 +05:30
Anshul Maheshwari
fcbf113526 Merge remote-tracking branch 'upstream/master' 2015-08-22 14:46:06 +05:30
cfsmp3
b90d144ff6 Merge branch 'pr/n213_anshul1912' 2015-08-22 10:48:45 +02:00
cfsmp3
2ac0ed2032 Merge branch 'pr/n214_rkuchumov' 2015-08-22 10:47:49 +02:00
cfsmp3
0afefc0392 Merge branch 'pr/n215_brooss' 2015-08-22 10:46:29 +02:00
Oleg Kisselef
9efe2b4b22 cea-708 debug message on decoder creation added 2015-08-22 09:51:02 +03:00
Oleg Kisselef
d54d881390 cea-708 color-per-row support 2015-08-22 00:03:13 +03:00
Oleg Kisselef
58b496a434 log text updated 2015-08-21 23:14:31 +03:00
Oleg Kisselef
41a8803860 checking if current window is set 2015-08-21 23:13:35 +03:00
Oleg Kisselef
4146423878 cea-708 code flow almost same as for 608 captions 2015-08-21 23:07:10 +03:00
Oleg Kisselef
1c35dcae03 fixed creating of file if output=null 2015-08-22 10:30:25 +03:00
Oleg Kisselef
3bcdbce709 dependencies updated 2015-08-22 08:56:52 +03:00
Brooss
250ee1f29b Parse after buffer fill, not on next packet 2015-08-22 04:04:46 +10:00
Brooss
fd1a86b2f5 Add support for multi-packet PATs and PMTs in MPEGTS 2015-08-22 02:25:10 +10:00
Anshul Maheshwari
3433ed2e5c removed somestatic variable from avc
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-08-21 15:22:30 +05:30
rkuchumov
c7606beae1 segfault when closing socket input fixed (forgot about this file) 2015-08-20 19:58:38 +03:00
rkuchumov
d639323e4c segfault when closing socket input fixed 2015-08-20 19:48:34 +03:00
rkuchumov
72e780f175 ccextractor-ccextractor connection fix 2015-08-20 17:16:47 +03:00
Anshul Maheshwari
651dc67a5d update linux related chages in ocr
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-08-20 18:24:37 +05:30
Oleg Kisselef
6cfd7710a7 Merge branch 'master' into feature-cea-708 2015-08-19 23:47:59 +03:00
Oleg Kisselef
adc1d4662d changes 2015-08-19 20:25:07 +03:00
Oleg Kisselef
5c51b582bf cea-708 yet another big refactoring. rollup captions added. 2015-08-19 19:16:19 +03:00
Oleg Kisselef
16e794163c cea-708 added show/hide time for screens and windows 2015-08-19 18:58:43 +03:00
Oleg Kisselef
4e25d80b48 checking if have 708 captions when updating fts_global 2015-08-19 18:57:37 +03:00
Oleg Kisselef
2949918ed1 some timing debug info added 2015-08-19 18:55:47 +03:00
Oleg Kisselef
46ea522ecb cea-708 output style fix 2015-08-19 08:19:13 +03:00
Oleg Kisselef
f571a04ffc cea-708 doc updated 2015-08-18 23:28:32 +03:00
Oleg Kisselef
610b811d53 cea-708 encoding->charset 2015-08-18 17:09:57 +03:00
Oleg Kisselef
e5c4053c05 cea-708 decoder ff and hcr handling 2015-08-18 14:28:34 +03:00
Anshul Maheshwari
0b9bf16850 updated ocr doc file
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-08-18 16:14:54 +05:30
Oleg Kisselef
8489edf966 cea-708 params help updated 2015-08-18 13:34:41 +03:00
Oleg Kisselef
22127cccb0 added extra space because unicode symbols can be 6-byte long. cleaning windows where needed. 2015-08-18 11:57:35 +03:00
Anshul Maheshwari
57eb42c7bb Compile code using Visual studio
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-08-18 12:19:33 +05:30
Oleg Kisselef
0a6630f7ab specifying an encoding for non-latin languages for CEA-708 captions 2015-08-18 09:26:01 +03:00
Oleg Kisselef
b89dd8d401 cea-708 Korean encoder anchor position issue workarounded 2015-08-17 21:40:32 +03:00
Oleg Kisselef
778e66f951 cea-708 sami output merged 2015-08-17 17:55:18 +03:00
Oleg Kisselef
7a06d99443 cea-708 transcript output merged 2015-08-17 17:25:40 +03:00
Oleg Kisselef
3fff94a555 cea-708 srt and debug output refactored and improved 2015-08-17 17:09:53 +03:00
Oleg Kisselef
b65cc8ad8e dont handling 16-bit chars for cea-708 2015-08-17 09:53:24 +03:00
rkuchumov
28ddfef2b1 sending header when reconnecting 2015-08-16 19:15:15 +03:00
rkuchumov
f23cc1f41e reconnecting when no ping arrived 2015-08-16 12:25:01 +03:00
rkuchumov
1ca63ba125 mandatory desc and passw blocks 2015-08-16 11:14:00 +03:00
Oleg Kisselef
af66ace345 cea-708 defined utf8 symbol max size in bytes 2015-08-14 23:33:06 +03:00
Oleg Kisselef
c0079aee6f cea-708 handling 16-bit characters (utf16) 2015-08-14 23:29:32 +03:00
Oleg Kisselef
21a88f9cc1 added utf16 to utf8 conversion function 2015-08-14 23:28:39 +03:00
Oleg Kisselef
9923ef98ee added "all" value for cea-708 services 2015-08-14 20:52:28 +03:00
Oleg Kisselef
abce1dd873 moved cea-708 global variables into single context variable 2015-08-14 13:28:59 +03:00
Oleg Kisselef
308d500308 more cea-708 refactoring 2015-08-14 09:49:22 +03:00
Oleg Kisselef
ae6cf97bce more cea-708 refactorings 2015-08-14 00:30:53 +03:00
rkuchumov
53bedd30c1 sending ping to server 2015-08-13 22:59:45 +03:00
Oleg Kisselef
764d251986 cea-708 code refactoring 2015-08-13 20:59:28 +03:00
Anshul Maheshwari
1bfb96151f support 3.04 tesseract
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-08-13 21:11:52 +05:30
rkuchumov
741e87e00e empty description support 2015-08-11 09:59:04 +03:00
rkuchumov
098bff1230 Merge branch 'master' into networking_epg_support 2015-08-10 10:09:55 +03:00
rkuchumov
0374c5ec78 small fix & closing connection when server doesnt responce 2015-08-10 10:07:29 +03:00
Anshul Maheshwari
e7bec67c93 remove static timestamps from teletext
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-08-08 17:23:45 +05:30
Anshul Maheshwari
b9e0f67dec Correcting redundant check
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-08-08 16:20:30 +05:30
Anshul Maheshwari
acd96d44d2 Initialize stream mode before using it
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-08-08 14:01:19 +05:30
Anshul Maheshwari
4e4da44c39 Add 0x for hex represntation
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-08-06 18:05:16 +05:30
Anshul Maheshwari
bb0f836e84 removing redundant code
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-08-06 15:55:02 +05:30
Anshul Maheshwari
5f6a8c7f54 Using EOF instead global variable
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-08-06 15:48:42 +05:30
Anshul Maheshwari
0c6bf5d8b1 make some space
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-08-06 14:41:40 +05:30
Anshul Maheshwari
f8210f94f2 Passing only demuxer ctx to wtv getdata
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-08-06 14:33:22 +05:30
rkuchumov
243674ed96 adding ping support from the server 2015-08-06 11:58:19 +03:00
Anshul Maheshwari
322d352ca0 selecting multiprogram for ts stream in report mode
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-08-04 18:59:48 +05:30
Anshul Maheshwari
c8c71085e1 Adding return from set_fts
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-08-04 18:54:17 +05:30
Anshul Maheshwari
4969e6a8fd Initialize Teletext when data not present
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-08-04 15:10:20 +05:30
Anshul Maheshwari
ece4a5fa8a Memory Leakage in Teletext
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-08-04 13:59:01 +05:30
cfsmp3
7d034f44e4 Merge branch 'pr/n202_anshul1912' 2015-08-02 16:39:55 +02:00
cfsmp3
c12d3856f2 Merge branch 'pr/n201_december-soul'
Conflicts:
	src/ccextractor.c
	src/lib_ccx/ccx_encoders_common.c
	src/lib_ccx/lib_ccx.c
2015-08-02 16:38:43 +02:00
Anshul Maheshwari
24f9106cde Merge remote-tracking branch 'carlos/master' 2015-08-01 12:21:44 +05:30
Anshul Maheshwari
58503141c3 Ignore empty string Srt encoder
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-07-31 22:44:08 +05:30
Anshul Maheshwari
3b214f491b correcting sub delay for end time
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-07-31 22:23:14 +05:30
Anshul Maheshwari
f83ca18c7d Merge branch 'master' of https://github.com/anshul1912/ccextractor 2015-07-31 21:36:01 +05:30
Anshul Maheshwari
1261cee8dc incorrect update of stream
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-07-31 21:33:18 +05:30
Anshul Maheshwari
92ecaa9434 dont check program number in single stream mode
Signed-off-by: Anshul Maheshwari <anshul.ffmpeg@gmail.com>
2015-07-31 11:03:10 +02:00
Anshul Maheshwari
fd66228b26 Cleaning stream data when PAT changes
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-07-31 12:30:41 +05:30
Anshul Maheshwari
bfd7556b50 free memory for ignored stream
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-07-31 11:15:44 +05:30
Anshul Maheshwari
3174e3dc9e remove multi addition of data_node len
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-07-30 13:40:44 +05:30
Anshul Maheshwari
ec26080bd2 if last crc is equal to present crc dont update pmt
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-07-30 12:22:12 +05:30
Anshul Maheshwari
5ea83ccf9d corrected len and buf for crc
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-07-30 11:37:16 +05:30
Anshul Maheshwari
5af65d941a need capinfo only true when any good crc already found
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-07-29 19:21:12 +05:30
Anshul Maheshwari
0d79ad3cb6 crc used while checking packet second time
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-07-29 19:18:42 +05:30
Anshul Maheshwari
8499a6b426 Init bufferdatatype
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-07-29 18:02:52 +05:30
Anshul Maheshwari
577a79de47 initialized gop
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-07-29 15:18:21 +05:30
Anshul Maheshwari
6133b9c26d print fps message once
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-07-29 12:52:06 +05:30
Anshul Maheshwari
c4e91f8ccc Remove memory leakage
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-07-29 11:58:42 +05:30
cfsmp3
589fd91d8e Merge branch 'pr/n202_anshul1912' 2015-07-28 22:33:15 +02:00
Anshul Maheshwari
03eba6114b remove invalid access of memory
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-07-28 20:23:32 +05:30
Anshul Maheshwari
56f0786cc3 correct broken Freport
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-07-28 11:30:09 +05:30
cfsmp3
aff591fd9b Merge branch 'pr/n202_anshul1912' 2015-07-28 07:05:22 +02:00
Anshul Maheshwari
bdaa3a1352 Completed Freport for teletext and DVB
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-07-27 22:02:47 +05:30
Anshul Maheshwari
f3b104584d update multiprogram changes in doc
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-07-27 16:04:28 +05:30
Anshul Maheshwari
e47315e423 not to unset remaining buffer
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-07-27 15:36:36 +05:30
Anshul Maheshwari
43335e30a9 move strange header to demux_ctx
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-07-27 13:43:58 +05:30
Anshul Maheshwari
79c4a48d60 ES code in Context
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-07-27 13:33:00 +05:30
Anshul Maheshwari
a5538902ec moving telxcc related globals to telxcc Ctx
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-07-27 11:51:20 +05:30
Anshul Maheshwari
1b9d905b28 move global vars from es to decode ctx
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-07-27 10:43:45 +05:30
Anshul Maheshwari
89c8b018c8 move parity code to ccx_common_common.c
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-07-27 10:42:16 +05:30
Anshul Maheshwari
cde69fdd88 remove segfault in epg
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-07-27 10:05:00 +05:30
rkuchumov
a798fdf57e merge conflicts 2015-07-26 13:09:55 +03:00
Anshul Maheshwari
8b89ad0c5a refactor enc demux cfg
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-07-25 16:52:13 +05:30
Anshul Maheshwari
309f4130e0 Clean ts code
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-07-25 16:29:55 +05:30
Anshul Maheshwari
0f2ccdbe4f added newline in warning
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-07-25 16:17:22 +05:30
Anshul Maheshwari
eeb33de590 Verified checksum and save section in pinfo
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-07-25 16:15:13 +05:30
rkuchumov
91a8997826 Merge branch 'networking_epg_support' of https://github.com/rkuchumov/ccextractor into networking_epg_support 2015-07-24 22:48:04 +03:00
rkuchumov
5fb7bc434c changed net protocol (passw check) 2015-07-24 22:24:51 +03:00
rkuchumov
77540355ed epg lang and category fields support 2015-07-24 22:24:51 +03:00
rkuchumov
c5362b682e indentation fix 2015-07-24 22:24:51 +03:00
rkuchumov
e0f3751fe8 sending epg 2015-07-24 22:23:51 +03:00
rkuchumov
54583f95a3 wrapping bin data with headers 2015-07-24 22:23:51 +03:00
rkuchumov
990e653e91 Merge branch 'networking_epg_support' of https://github.com/rkuchumov/ccextractor into networking_epg_support 2015-07-24 18:44:49 +03:00
rkuchumov
9d2fb48d3d changed net protocol (passw check) 2015-07-24 18:39:42 +03:00
rkuchumov
e5e51c4389 epg lang and category fields support 2015-07-24 18:39:42 +03:00
rkuchumov
74dbd4d7e5 indentation fix 2015-07-24 18:39:42 +03:00
rkuchumov
784a46d165 sending epg 2015-07-24 18:37:12 +03:00
rkuchumov
83e1959db8 wrapping bin data with headers 2015-07-24 18:37:12 +03:00
cfsmp3
e0bf79f28b Merge branch 'pr/n200_anshul1912' 2015-07-24 16:28:50 +02:00
cfsmp3
5c1f4772c7 typo fix 2015-07-24 16:28:37 +02:00
Anshul Maheshwari
deca14c2c2 refresh dvb codec
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-07-24 16:38:04 +05:30
Anshul Maheshwari
8023ebe8e2 revert current pts flag
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-07-24 15:54:25 +05:30
Anshul Maheshwari
0e98604267 made telexcc working in bin format
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-07-24 12:49:42 +05:30
Anshul Maheshwari
7e68c8e823 cross check for cinfo
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-07-24 11:15:59 +05:30
Anshul Maheshwari
601dbfd062 use encoder with pn
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-07-23 21:43:30 +05:30
Anshul Maheshwari
35983534f1 remove seg fault
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-07-23 20:06:58 +05:30
Anshul Maheshwari
f88330c7c9 close telexcc
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-07-23 20:01:29 +05:30
Anshul Maheshwari
a0bf7dadf8 move init_hdcc to dec_ctx
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-07-23 19:48:48 +05:30
Anshul Maheshwari
f2added8d1 revert hdcc flush
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-07-23 19:45:30 +05:30
Anshul Maheshwari
9f78a843ee Add global hdcc flag to decode context
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-07-23 18:47:04 +05:30
Anshul Maheshwari
3e78fdd675 wait till stream stream type is know
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-07-23 18:21:35 +05:30
Anshul Maheshwari
c5dfd52eb9 Initialize cinfo with codec
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-07-23 17:45:26 +05:30
Anshul Maheshwari
08df39c3d4 initialize max_gop
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-07-23 17:08:19 +05:30
Anshul Maheshwari
9fad88fee3 cleaning ts tables
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-07-23 17:04:58 +05:30
rkuchumov
6ae94fdbab changed net protocol (passw check) 2015-07-23 13:59:18 +03:00
rkuchumov
8d5f0e5505 epg lang and category fields support 2015-07-23 12:55:37 +03:00
Anshul Maheshwari
11b614cedf Initialize codec in dec update
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-07-23 12:43:13 +05:30
Anshul Maheshwari
fc79649c9c initialize file buffer in stdin
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-07-23 12:35:21 +05:30
Anshul Maheshwari
b85e93a2cb opening raw type condition
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-07-23 12:21:34 +05:30
Anshul Maheshwari
dd8923b2e4 error checking in init decoder 2015-07-23 12:13:31 +05:30
Anshul Maheshwari
1437aea328 multiple decode context
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-07-22 15:33:09 +05:30
Anshul Maheshwari
1fdad2314f remove segfault at free of filename
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-07-21 18:07:24 +05:30
Anshul Maheshwari
6aac9dad43 not working multiprogram
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-07-21 13:13:25 +05:30
Anshul Maheshwari
fc248dd41f not to use data_node before recieved
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-07-14 21:22:11 +05:30
Anshul Maheshwari
a2394df838 remove derefrence NULL pointer
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-07-14 21:07:20 +05:30
Anshul Maheshwari
306d60ccf9 encoder ctx initilaziation only when required
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-07-14 21:01:08 +05:30
Anshul Maheshwari
d78a722260 moved encoder related code in each loop
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-07-14 15:39:35 +05:30
Anshul Maheshwari
4a34799e09 Adding flush logic in function
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-07-14 15:22:07 +05:30
Anshul Maheshwari
489622fb0b Merge branch 'master' of https://github.com/anshul1912/ccextractor 2015-07-14 12:02:41 +05:30
Anshul Maheshwari
9689dd8c19 remove VS Compiler error from list.h
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-07-13 09:31:35 -07:00
Anshul Maheshwari
d29f6817c6 error checking in encoder
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-07-13 18:49:06 +05:30
Anshul Maheshwari
f9ea7009fe removed segfault from 708
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-07-13 18:46:33 +05:30
Anshul Maheshwari
ddd8381440 Correcting out context selection on basis of field
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-07-13 18:08:15 +05:30
Anshul Maheshwari
964b8c1165 refactored encoder
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-07-13 03:32:26 +05:30
Anshul Maheshwari
0541a2fb62 move output context in encoder from global context
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-07-13 00:16:26 +05:30
Anshul Maheshwari
f3654174fc moving file_function to demux ctx
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-07-10 23:33:52 +05:30
rkuchumov
0fc1055da6 indentation fix 2015-07-10 17:26:26 +03:00
rkuchumov
a654b133e5 sending epg 2015-07-10 17:21:46 +03:00
Anshul Maheshwari
3a886c6a5b proper initialization of cc_data
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-07-10 19:42:48 +05:30
Anshul Maheshwari
4a8d51aed1 including avc header
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-07-10 19:24:37 +05:30
Anshul Maheshwari
70f5723c89 making context of avc
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-07-10 19:22:51 +05:30
rkuchumov
b85702a706 wrapping bin data with headers 2015-07-10 15:45:06 +03:00
Anshul Maheshwari
0bf1e83fa1 free pat payload
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-07-10 17:51:36 +05:30
Anshul Maheshwari
67d62631aa remove ignore param from demux_data
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-07-10 17:24:03 +05:30
Anshul Maheshwari
43f276abca correctcondition to ignore stream
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-07-10 17:13:23 +05:30
Anshul Maheshwari
7cea808f46 ignore unused stream in cap info
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-07-10 17:10:29 +05:30
Anshul Maheshwari
adbe8ed934 eof handle in rawloop
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-07-10 15:59:22 +05:30
Anshul Maheshwari
a3eba7cf45 error checking in copy capbuf
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-07-10 13:13:29 +05:30
Anshul Maheshwari
3f26290614 Check pid before needs
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-07-10 12:14:30 +05:30
Anshul Maheshwari
d63660468a init datastream with sane value
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-07-10 02:34:05 +05:30
Anshul Maheshwari
3daecf66a3 replced stream info array from list
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-07-10 02:06:49 +05:30
Anshul Maheshwari
16db90a630 Free mem allocated for input file name
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-07-09 23:41:35 +05:30
Anshul Maheshwari
c1d7f82819 handling wrong pes header
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-07-09 22:07:08 +05:30
Anshul Maheshwari
f8ee9504a8 handling wrong pes header
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-07-09 21:26:58 +05:30
Anshul Maheshwari
c75d056b76 Handling boundary condition
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-07-09 13:16:23 +05:30
Anshul Maheshwari
6c38f1b73b rename windex to len
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-07-09 12:59:07 +05:30
Anshul Maheshwari
00b61a291d Initialize demux node in general loop
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-07-09 12:36:06 +05:30
Anshul Maheshwari
fcdc5f852b Passing demux ctx instead of lib ctx
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-07-09 12:08:38 +05:30
Anshul Maheshwari
0424b0f119 remove memory leakage in teletext 2015-07-08 23:10:39 +05:30
Anshul Maheshwari
82559fd572 Initialize demuxer data
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-07-08 22:40:20 +05:30
Anshul Maheshwari
3837ffae59 Correct asf and wtv
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-07-08 22:25:53 +05:30
Anshul Maheshwari
2e4cda0383 working telxcc code with srt
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-07-08 22:02:33 +05:30
Anshul Maheshwari
dc6ef18c21 Free tree of streams and program 2015-07-08 16:51:58 +05:30
Anshul Maheshwari
bf3790183a woorking telxcc code
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-07-08 16:41:52 +05:30
Anshul Maheshwari
bfa8b593ab teletext to srt working
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-07-08 11:20:49 +05:30
Anshul Maheshwari
401d679f80 reversed priority 2015-07-07 19:27:43 +05:30
Anshul Maheshwari
157faaf0b5 Add multistream support in databuffer 2015-07-07 19:11:45 +05:30
Anshul Maheshwari
cb49812d17 broken teletext
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-07-07 12:10:05 +05:30
Anshul Maheshwari
d88fa2a3ce remove context dependency from write_section 2015-07-06 22:13:17 +05:30
Anshul Maheshwari
5716ab7cfc Add back haupage support in ts 2015-07-06 21:14:25 +05:30
Anshul Maheshwari
04b9e40cc5 Add reset hack back again 2015-07-06 21:08:47 +05:30
Anshul Maheshwari
2f92036557 Initialize databuffertype 2015-07-06 18:24:41 +05:30
Anshul Maheshwari
6aaa4fe2d4 Add windex instead len 2015-07-06 17:01:15 +05:30
Anshul Maheshwari
ab0f54bb57 correct handling for eof
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-07-06 15:43:44 +05:30
Anshul Maheshwari
6642084132 Open up more buffer type 2015-07-06 02:12:50 +05:30
Anshul Maheshwari
c5ca7c7e1a working with srt output and single program input
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-07-06 01:48:08 +05:30
Anshul Maheshwari
5b24334b43 move pmt code related comments near parsePMT
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-07-03 14:59:44 +05:30
Anshul Maheshwari
df93801021 Initilaize param
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-07-03 12:43:25 +05:30
Anshul Maheshwari
64285879db encoding flushed bytes 2015-07-03 11:51:03 +05:30
Anshul Maheshwari
0523f0bcd5 check array boundary before acess
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-07-02 18:49:14 +05:30
Anshul Maheshwari
c6721ebc3e making array of cap pid
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-07-02 16:40:44 +05:30
Anshul Maheshwari
9d22f9a466 Adding error Message at boundary
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-07-02 16:39:41 +05:30
Anshul Maheshwari
d58fb00970 Correcting boundary condtions
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-07-02 14:43:56 +05:30
Anshul Maheshwari
62e189a9cb correctin loss of last frame 2015-07-01 17:06:55 +05:30
Anshul Maheshwari
dc17946a55 Remove infinite loops
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-07-01 11:21:50 +05:30
Anshul Maheshwari
78d8d858d2 Adding header file
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-06-30 21:56:36 +05:30
Anshul Maheshwari
30e7f95f38 move pmt from global to demuxer ctx 2015-06-30 21:32:46 +05:30
Anshul Maheshwari
8026d2e671 Remove unused loop
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-06-30 20:34:01 +05:30
Anshul Maheshwari
c98e00201a remove seg fault while overwrite detection
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-06-30 19:09:49 +05:30
Anshul Maheshwari
9b0ba130f1 Corrected broken position_sanity_check 2015-06-30 19:00:33 +05:30
Anshul Maheshwari
83aa9709f4 moving subline bufffer to encoder context
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-06-30 11:39:32 +05:30
Anshul Maheshwari
340549e916 coreected broken detect stream 2015-06-29 21:34:15 +05:30
Anshul Maheshwari
6d41964bba Addin decoded subtitle in decoder context
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-06-29 21:31:37 +05:30
Anshul Maheshwari
71f030f4ee move parameter checking to parameter ctx 2015-06-29 12:10:50 +05:30
Anshul Maheshwari
67653d06d3 Restore default when no -o param provided 2015-06-29 11:38:36 +05:30
Anshul Maheshwari
ab9f3a4b4a give memory for '\0' character in output file 2015-06-29 11:37:19 +05:30
Anshul Maheshwari
d9e9305e2c Seprate wbout context 2015-06-28 15:41:34 +05:30
Anshul Maheshwari
2bcc0c5561 corrected elementry to elementary 2015-06-27 15:21:00 +05:30
Anshul Maheshwari
cd03d8a658 moved filename part in lib_ccx 2015-06-27 15:18:42 +05:30
Anshul Maheshwari
589074886b removing multiple file in encoder ctx 2015-06-27 14:55:02 +05:30
Anshul Maheshwari
c6ca493752 Removed redundant wbout struct 2015-06-27 14:34:40 +05:30
Anshul Maheshwari
aef649d23a Initialize past value in open 2015-06-26 21:05:06 +05:30
Anshul Maheshwari
610b7323f4 time depend on demuxer init 2015-06-26 20:26:09 +05:30
Anshul Maheshwari
eb6f6a9000 Added Demuxer data to seprate out context 2015-06-26 20:18:49 +05:30
Anshul Maheshwari
f3fe829d48 remove false warning about premature file completion 2015-06-25 20:06:54 +05:30
Anshul Maheshwari
cb39d12615 Making demuxer context
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-06-25 19:09:54 +05:30
Anshul Maheshwari
5d52026736 remove wbout dependency 2015-06-23 22:21:07 +05:30
Anshul Maheshwari
48dce9c7ce correct header guard 2015-06-22 17:12:41 +05:30
Anshul Maheshwari
2032a754e6 moved credits initializations 2015-06-22 14:30:38 +05:30
Anshul Maheshwari
aa353140ef remove wbout dependency from decoder 2015-06-21 23:55:19 +05:30
Anshul Maheshwari
ee47e8458f Use cc_sub in raw dvd 2015-06-21 23:49:08 +05:30
Anshul Maheshwari
081f127c85 remove compiler warnings
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-06-20 21:26:01 +05:30
cfsmp3
7169c71360 Merge branch 'pr/n187_anshul1912' 2015-06-20 13:54:47 +02:00
cfsmp3
5c3a757e5b Updated CHANGES.TXT with release date 2015-06-20 13:54:21 +02:00
Anshul Maheshwari
673cadc6bf Version 0.77 2015-06-20 17:00:19 +05:30
cfsmp3
2318e714db Merge branch 'pr/n186_anshul1912' 2015-06-20 11:06:41 +02:00
Anshul Maheshwari
a6d27a2de5 compile on windows
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-06-19 23:31:37 -07:00
Anshul Maheshwari
dc842b0312 removed segfault with cap file 2015-06-19 22:59:22 +05:30
cfsmp3
3879f5c7ef Merge branch 'pr/n156_kisselef'
Conflicts:
	src/lib_ccx/CMakeLists.txt

Changed 0.76 to 0.77
2015-06-19 13:14:55 +02:00
Anshul Maheshwari
e01d93afa8 Corrected typos in help info
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-06-18 17:24:47 +05:30
Anshul Maheshwari
6ec8086b0a remove invalid warn at srt 2015-06-18 11:39:20 +05:30
Anshul Maheshwari
b80572c3b6 Corrected help display for BOM 2015-06-17 19:38:53 +05:30
Anshul Maheshwari
3f6fd51f45 removed segfault at ccextractor.c 2015-06-17 19:09:52 +05:30
Anshul Maheshwari
87af82f022 corrected broken raw output 2015-06-17 18:42:08 +05:30
Anshul Maheshwari
020ca9a1cf Merge remote-tracking branch 'carlos/master' 2015-06-17 16:26:00 +05:30
Anshul Maheshwari
beccc3d5b7 Correct broken rcwt
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-06-17 16:23:33 +05:30
Anshul Maheshwari
1d03bd7d13 pass cc_sub structure to rcwt 2015-06-17 11:59:04 +05:30
cfsmp3
13290294a6 Merge branch 'pr/n182_anshul1912' 2015-06-16 20:10:26 +02:00
Anshul Maheshwari
1eef500c73 Indent decoder 2015-06-16 23:34:22 +05:30
Anshul Maheshwari
ca5135c8aa passing decoder sub structure in teletext 2015-06-16 20:15:47 +05:30
Anshul Maheshwari
740a1d798e add space in code 2015-06-13 19:22:24 +05:30
Anshul Maheshwari
b68a086698 remove dead code 2015-06-13 19:09:31 +05:30
Anshul Maheshwari
0e60ceb4d0 moving option check in param context 2015-06-13 19:08:40 +05:30
Anshul Maheshwari
2030c16b22 Display usage when no input file 2015-06-13 10:58:17 +02:00
cfsmp3
79b1bca8f7 Merge branch 'pr/n179_anshul1912' 2015-06-12 08:02:56 +02:00
cfsmp3
76b3d3e4d1 Merge branch 'pr/n180_rkuchumov' 2015-06-12 08:02:09 +02:00
rkuchumov
90d8731a03 dep target is fixed 2015-06-10 21:50:01 +03:00
rkuchumov
85270c7047 optimization is removed for ccextractor.c 2015-06-10 21:39:53 +03:00
rkuchumov
c9e596e60a flushing cc buffer every I, P slice for both fields 2015-06-10 08:25:20 +03:00
Anshul Maheshwari
24d83e130a Remove Segmentation Fault at opt service
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-06-05 12:11:05 +05:30
cfsmp3
4fc19d4289 Merge branch 'pr/n175_wforums' 2015-06-04 22:09:40 +02:00
wforums
74ad11b44f Release project build fix
Fixed release project for VS. New subfolders weren't included.
2015-06-04 00:34:08 +02:00
wforums
051a6f1f67 git ignore update
Updated gitignore with some more VS project files.
2015-06-04 00:31:29 +02:00
Oleg Kisselef
3f7eb981e6 Fixed millis_to_date usage with ocr enabled build 2015-06-04 03:02:39 +06:00
Carlos Fernandez
8ca152262e Merge branch 'pr/n171_kisselef' 2015-05-28 06:53:39 -07:00
Anshul Maheshwari
f17501f0e5 linux build using Cmake 2015-05-28 12:05:10 +05:30
Oleg Kisselef
6cc8d7de05 ts/ps detection fall through removed 2015-05-27 17:10:01 +06:00
Carlos Fernandez
d4f6db8479 Merge branch 'pr/n168_codeman38' 2015-05-26 18:35:39 -07:00
Anshul Maheshwari
7b22a8d966 Segmentation Fault supression 2015-05-26 11:42:18 +05:30
Anshul Maheshwari
c5cebeaa4f Adding some space 2015-05-25 18:49:00 +05:30
Anshul Maheshwari
f1cf6c7be8 Added check on boundary condition 2015-05-25 18:48:20 +05:30
Cody Boisclair
80303ddde5 Add iconv to EXTRA_LIBS in CMakeLists.
Compilation via cmake fails on OS X if libiconv is not
specified as a required library.
2015-05-24 00:40:16 -04:00
Anshul Maheshwari
89ee62ea14 EPG help at new line 2015-05-22 17:35:46 +05:30
Anshul Maheshwari
a1959d20f3 remove make clean hangsup problem 2015-05-19 19:56:33 +05:30
Anshul Maheshwari
810cb73203 Indenting code 2015-05-19 15:50:01 +05:30
Anshul Maheshwari
38b9ed7fcd Indenting code 2015-05-19 15:28:14 +05:30
Anshul Maheshwari
35b8f2375f Indenting Code 2015-05-19 14:17:09 +05:30
Anshul Maheshwari
aa619b5f93 Indenting Code 2015-05-19 14:11:10 +05:30
Anshul Maheshwari
c03d3032aa Merge remote-tracking branch 'carlos/master' 2015-05-19 12:41:18 +05:30
Anshul Maheshwari
191cdd2bdc Indentation of 708 decoder 2015-05-19 12:40:15 +05:30
Anshul Maheshwari
9d5c8759e5 Indenting code 2015-05-19 12:28:20 +05:30
Anshul Maheshwari
a4b5c6e028 Indent code
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-05-19 12:24:22 +05:30
Anshul Maheshwari
113b606091 Indentation of cc_bitstream 2015-05-19 12:11:18 +05:30
Anshul Maheshwari
a69e031835 Indentation of avc_function
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-05-19 12:07:51 +05:30
Anshul Maheshwari
ba38055bed lib_ccx/asf_functions.c
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-05-19 11:59:27 +05:30
Anshul Maheshwari
3c086e8ff0 Indent asf constants
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-05-19 11:54:29 +05:30
Anshul Maheshwari
f9c26d8684 Indent activity.c 2015-05-19 11:37:41 +05:30
Anshul Maheshwari
2ed9789f9c Indenting 708_encoding 2015-05-19 11:14:57 +05:30
Anshul Maheshwari
282108942b Correcting Header guard for spupng
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-05-19 11:12:41 +05:30
Anshul Maheshwari
6c107a0d4e Indent spupng code 2015-05-19 11:08:45 +05:30
Anshul Maheshwari
6e4ab6faae Fails earlier if not enough memory
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-05-19 10:57:01 +05:30
Anshul Maheshwari
e8016edfc1 Move copyright notice to top
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-05-19 10:52:48 +05:30
Anshul Maheshwari
30839f7c2c Indent smptett code
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-05-19 10:50:27 +05:30
Anshul Maheshwari
89459a6c2e Indenting sami code
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-05-19 10:45:04 +05:30
Anshul Maheshwari
c49db8c083 Removing runtime warnings 2015-05-19 10:40:40 +05:30
Anshul Maheshwari
fa6588fa80 Remove redundant print code
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2015-05-19 10:38:05 +05:30
Carlos Fernandez
7d74256664 Merge branch 'pr/n166_anshul1912' 2015-05-18 09:28:39 -07:00
Anshul Maheshwari
2210660ae4 Indentation no change in logic 2015-05-18 19:46:57 +05:30
Anshul Maheshwari
f2fc93b7f8 removed dead code 2015-05-18 19:36:22 +05:30
Anshul Maheshwari
d54a2d9486 Indentation of utility.c 2015-05-18 19:10:48 +05:30
Anshul Maheshwari
88015d6d4b Adding milliseprator in tlt_config init 2015-05-18 12:22:35 +05:30
Anshul Maheshwari
f1ff75b846 Remove ccxoptions fromm encoder 2015-05-16 15:04:22 +05:30
Anshul Maheshwari
1123755dc7 Remove options from decoder 2015-05-16 13:16:25 +05:30
Carlos Fernandez
6a4f379ab7 Merge branch 'pr/n165_wforums' 2015-05-15 08:21:39 -07:00
Anshul Maheshwari
9369cde9a3 partially removing global options from utility 2015-05-15 19:56:01 +05:30
Anshul Maheshwari
a1d985b4ca Remove use of global options in sami 2015-05-15 18:07:31 +05:30
Anshul Maheshwari
b26854d3d7 Removing ccx_options from output ctx 2015-05-15 17:57:10 +05:30
Anshul Maheshwari
cbb4b4c7bb remove use of global var in telexcc 2015-05-15 13:37:15 +05:30
wforums
1a1aa746d5 Possible MP4 detection fix
Expanded detection for mp4. Needs to be checked with test suite and then
discussed :)
2015-05-14 23:52:23 +02:00
Anshul Maheshwari
b4f5b5b98e Removing global options from Mp4 2015-05-15 00:31:18 +05:30
Anshul Maheshwari
fa3b651ee1 Remove use glb bar ccx_options in param ctx 2015-05-14 23:54:26 +05:30
Carlos Fernandez
91d079be1e Merge branch 'pr/n164_anshul1912' 2015-05-14 19:54:17 +02:00
Anshul Maheshwari
d16ea0a7ea Decleare Xds related func in Xds header 2015-05-14 23:14:55 +05:30
wforums
6133bf6297 Revert of changes in stream format detection
Regression testing points out that at least 12 files no longer produce
correct results due to this change. Reverting is necessary until a
better solution for #69 can be found that does not break current other
files.
2015-05-13 18:44:58 +02:00
Oleg Kisselef
14e1420b7e Merge branch 'master' into feature-with-ocr-cmake-parameter 2015-05-05 13:30:16 +06:00
Oleg Kisselef
10568a0270 Merge branch 'master' into feature-mp4-c708-support 2015-05-05 12:56:23 +06:00
cfsmp3
53da058fe1 Merge branch 'pr/n155_kisselef' 2015-05-04 13:40:49 +02:00
cfsmp3
4d199fb03b Merge branch 'pr/n159_kisselef' 2015-05-04 13:39:47 +02:00
cfsmp3
f04cbbd99c Experiments with 708 in MP4. 2015-05-04 13:39:06 +02:00
Oleg Kisselef
e572ba8b6e better naming 2015-04-26 21:47:02 +06:00
Oleg Kisselef
45974e88be debug constant typo fix 2015-04-26 21:40:36 +06:00
Oleg Kisselef
8140bf3e52 mp4 708: fixed *cc_count value obtaining 2015-04-24 18:27:28 +06:00
Oleg Kisselef
4570965af2 removed ide auto-added header include 2015-04-24 15:51:07 +06:00
Oleg Kisselef
fcd250a557 basic c708 support for mp4 2015-04-24 15:43:59 +06:00
Oleg Kisselef
b92e42e685 yet another gpac fix applied 2015-04-24 15:42:08 +06:00
Oleg Kisselef
5daccf4268 gpac size calculation fix merged from gpac repo 2015-04-24 15:40:15 +06:00
Oleg Kisselef
e0903a0789 cdp sections enum added 2015-04-24 15:39:20 +06:00
Oleg Kisselef
bcf1546fc2 added c708 media subtype 2015-04-24 15:38:15 +06:00
Oleg Kisselef
92f53be666 fixed cmake to add gpac platform dependent defines 2015-04-23 17:30:22 +06:00
Oleg Kisselef
8ae0bd7f16 cmake build doc updated 2015-04-17 22:50:57 +06:00
Oleg Kisselef
754159e2bc cmakelists codestyle 2015-04-17 22:35:29 +06:00
Oleg Kisselef
3f817d655c added WITH_OCR parameter to cmake and libs dependencies 2015-04-17 22:16:42 +06:00
Oleg Kisselef
572837d7ba if ENABLE_OCR replaced everywhere with ifdef to have one style 2015-04-17 22:15:56 +06:00
Oleg Kisselef
fb8dcf4025 handling 7-byte PES packets for dvb-subs stream 2015-04-17 22:10:42 +06:00
cfsmp3
c7b77b5555 Fix crash on broken PMT section
Moved order of file format (MP4 now higher priority than PS)
2015-04-12 23:30:26 +02:00
cfsmp3
fe1ac8564a Merge branch 'pr/n148_kisselef' 2015-04-08 11:20:07 +02:00
cfsmp3
9230390937 Merge branch 'pr/n149_kisselef' 2015-04-08 11:17:20 +02:00
cfsmp3
14f926124d Merge branch 'pr/n150_anshul1912' 2015-04-08 11:15:31 +02:00
cfsmp3
76e8489304 XDS: Support for Canadian French content advisory
XDS: Support for the (obsolete) aspect ratio packet type
2015-04-08 11:14:50 +02:00
Anshul Maheshwari
0e0b1973f0 removing redundant init_options 2015-04-08 01:12:27 +05:30
Oleg Kisselef
a6666a4fbd detecting when output filename is same as one of input filenames to avoid overwrite 2015-04-07 12:02:52 +06:00
Oleg Kisselef
3a66db200d typo in mp4 detection algorithm fixed: 'feee'->'free'
added 'wide' box to mp4 detection algorithm
2015-04-06 22:22:00 +06:00
cfsmp3
4f3e5fe677 0.76 2015-03-28 13:32:09 +01:00
cfsmp3
ad99ccdfec Merge branch 'pr/n143_hardikchoudhary12' 2015-03-23 13:06:32 +01:00
cfsmp3
1bc174efa2 Merge branch 'pr/n144_ivladak' 2015-03-23 13:05:50 +01:00
cfsmp3
983db8c92d Allow processing EPG only 2015-03-23 13:05:10 +01:00
Vladislav Ivanishin
b4ce115f7c Fixed mac build 2015-03-21 04:26:49 +03:00
hardikchoudhary12
cb7f31ef8c Update README.md
Updated grammar.
2015-03-17 04:00:55 +05:30
cfsmp3
1a5d78b1b4 Merge branch 'pr/n138_brooss' 2015-03-04 09:38:22 +01:00
Brooss
c873ff6a06 add -xmltvonlycurrent option 2015-03-04 15:53:16 +11:00
Brooss
454024808d escape XML strings 2015-03-03 15:56:24 +11:00
Brooss
0a22e1e429 fix crash with -out=null 2015-03-03 14:38:19 +11:00
Brooss
3fb288357d change parse_EPG_packet to void 2015-03-03 12:27:28 +11:00
Brooss
966d88fc10 fix gcc warnings 2015-03-03 12:12:40 +11:00
Brooss
c91aa79852 rename win_iconv.c -> win_iconv.h, fixes build script 2015-03-03 12:06:07 +11:00
cfsmp3
04ccb477f1 -stdin was broken, fixed. 2015-03-02 09:48:55 +01:00
cfsmp3
10ea570229 Merge branch 'pr/n137_brooss' 2015-03-02 07:14:45 +01:00
Brooss
551c3d0e2f Fix referencing outdated offset in EPG_decode_extended_event_descriptor 2015-03-02 13:00:28 +11:00
cfsmp3
49530b079b Merge branch 'pr/n137_brooss' 2015-03-01 18:40:15 +01:00
Brooss
02986fe7a8 fix buffer overrun in EPG_decode_extended_event_descriptor 2015-03-02 04:18:36 +11:00
cfsmp3
a230ec5f6f Merge branch 'pr/n135_brooss' 2015-03-01 17:03:24 +01:00
Brooss
7902b85d1b Fix codepage symbol getting letf in the middle of certain dvb extented_event_descriptor strings 2015-03-02 02:24:18 +11:00
Brooss
77d275d6a5 fix ratings closings tag 2015-03-02 01:48:54 +11:00
Brooss
4c2a4a59a2 Add fallback workaround for streams with no PMT but EPG 2015-03-02 00:49:13 +11:00
cfsmp3
d80455a408 Merge branch 'pr/n134_mailumangjain' 2015-03-01 09:12:33 +01:00
cfsmp3
27e2bb9017 fix for broken stdout 2015-03-01 09:12:12 +01:00
Umang Jain
9358978a61 Fixes output for field_2 2015-02-27 20:47:50 +05:30
Brooss
cffd02c106 string formatting in EPG_print_event fix 2015-02-26 14:25:57 +11:00
cfsmp3
b45370cbb4 Minor typo correction 2015-02-25 08:43:06 +01:00
Brooss
56e15a3be0 Call iconv_close. Fix warning 2015-02-25 16:48:40 +11:00
Brooss
7b4d93988f Fixes for compiling on MSVC2013 2015-02-25 16:37:57 +11:00
Umang Jain
0e803eba95 Fix for SegFault error in -out=raw/bin output format
Issue Link:https://github.com/CCExtractor/ccextractor/issues/102
2015-02-24 18:58:54 +05:30
Brooss
8c9bfa17dd fix fprintf formatting in EPG_print_event() 2015-02-16 11:46:55 +11:00
Brooss
413173f5e5 add public domain win_iconv for win32 2015-02-16 11:28:49 +11:00
Brooss
1a050c76a5 Inital DVB and ATSC EPG support 2015-02-16 11:06:51 +11:00
cfsmp3
c3d00d80f5 Added support for M2TS 2015-02-10 17:27:17 +01:00
cfsmp3
c989c941df Added dates to CHANGES.TXT 2015-01-22 13:50:04 +01:00
cfsmp3
dc9f6d250a Fix annoying warning in OSX build 2015-01-18 22:56:26 +01:00
cfsmp3
9f00cec9c0 Uncomment a condition in es_functions that was causing garbled output (unknown why we commeted it out in the first place) 2015-01-10 17:57:16 +01:00
cfsmp3
b7d2754518 Merge branch 'pr/n130_anshul1912' 2015-01-09 13:29:33 +01:00
Anshul Maheshwari
94675b2dac handle no language found 2015-01-09 13:14:32 +01:00
Anshul Maheshwari
2c9faa70ea give error message with ENABLE_OCR 2015-01-07 19:57:57 +01:00
cfsmp3
b7616fcb17 Merge branch 'pr/n130_anshul1912' 2015-01-07 16:32:30 +01:00
Anshul Maheshwari
eb93345544 added dirent.h 2015-01-07 20:44:47 +05:30
cfsmp3
e6024c1cb1 Merge branch 'pr/n129_anshul1912' 2015-01-07 15:16:23 +01:00
Anshul Maheshwari
ecc4c2520e assigning prev_start to start_time 2015-01-07 19:38:55 +05:30
Anshul Maheshwari
a83c686f6a Remove multi warning when traindata not present 2015-01-07 18:49:53 +05:30
Anshul Maheshwari
c4a8135b4d using language while opening traindata
Signed-off-by: Anshul Maheshwari <anshul.ffmpeg@gmail.com>
2015-01-07 14:45:47 +05:30
cfsmp3
004f9d512a Typos 2015-01-07 10:01:39 +01:00
cfsmp3
53df68b4c3 Merge branch 'pr/n128_anshul1912' 2015-01-06 21:40:30 +01:00
Anshul Maheshwari
74bb91aa5b fixing minor bugs 2015-01-06 21:19:39 +05:30
rkuchumov
453bb56520 stdout output fix 2015-01-01 10:55:26 +03:00
cfsmp3
db50730a00 Fixed typos in docs 2014-12-25 12:17:34 +01:00
Anshul Maheshwari
36a266e43c Merge branch 'master' of https://github.com/anshul1912/ccextractor 2014-12-24 11:58:32 +05:30
Anshul Maheshwari
354c52ec61 updated teletext changes 2014-12-24 11:53:00 +05:30
Anshul Maheshwari
2b65419bfb Merge remote-tracking branch 'carlos/master' 2014-12-24 11:47:07 +05:30
cfsmp3
740365db7e Merge branch 'pr/n125_MikaYuoadas' 2014-12-23 12:44:45 +01:00
cfsmp3
03dc0498ea Init 'ret' variables 2014-12-23 12:43:47 +01:00
Akim Sadaoui
e9a7474f3d Fixed potential timestamp overflow with negative delay
When delay was a large enough negative number, some show_timestamp would
overflow and be set to ridiculously large value.
2014-12-19 17:00:12 +01:00
Akim Sadaoui
1ecb2abd62 Added support for -startat and -endat for teletext input 2014-12-19 16:59:23 +01:00
Akim Sadaoui
d3b4b8ff03 Fixed smptett timeExpression format
Now all timeExperssion in smptett file comply to:
http://www.w3.org/TR/2013/REC-ttml1-20130924/#timing-value-timeExpression
2014-12-19 16:55:47 +01:00
Akim Sadaoui
29aa63c23c Fixed a typo in smptett header 2014-12-19 16:50:21 +01:00
Anshul Maheshwari
7083a36ecb Merge remote-tracking branch 'carlos/master' 2014-11-30 21:09:40 +05:30
Anshul Maheshwari
38421e886e Merge remote-tracking branch 'carlos/master' 2014-11-28 19:42:19 +01:00
Akim Sadaoui
b0de53c351 Added default style to smptett header 2014-11-28 15:57:50 +01:00
Akim Sadaoui
09dcb8b7c0 Fixed a rare bug with some teletext input
In rare cases, the output had the last line written after the footer (i.e. for
smptett the last </div></tt> was after the last <p>).
2014-11-28 15:56:28 +01:00
Akim Sadaoui
13ab9e6a4e Fixed line break in output for teletext input 2014-11-28 15:56:06 +01:00
Akim Sadaoui
08ae34bc24 Added smptett support for teletext input 2014-11-28 15:54:40 +01:00
Akim Sadaoui
f5f1a70eb8 fixed a typo in generated smptett 2014-11-28 15:54:35 +01:00
Anshul Maheshwari
471c130928 updated version to 0.75 2014-11-26 18:31:01 +05:30
cfsmp3
4db37e7ac3 Merge branch 'pr/n121_anshul1912' 2014-11-26 13:57:53 +01:00
Anshul Maheshwari
3953f806b0 corrected sign of argument 2014-11-26 18:02:25 +05:30
Anshul Maheshwari
cf0ebd27f7 corrected initial value of ret 2014-11-26 18:00:53 +05:30
Anshul Maheshwari
559d05c478 added flag in CCExtractor Cmake to build with FFMpeg 2014-11-26 17:58:49 +05:30
Anshul Maheshwari
4d7e629ba5 in ffmpeg intigration logic, removed unneeded malloc and free 2014-11-26 17:57:41 +05:30
Anshul Maheshwari
866c4ea159 added flag in CCExtractor Cmake to build with FFMpeg 2014-11-26 17:55:20 +05:30
Anshul Maheshwari
cf508653f2 documented how to compile ccextractor with FFmpeg using cmake 2014-11-26 17:53:12 +05:30
Anshul Maheshwari
b3b683aa83 Instruction on how to build ccextractor with CMake 2014-11-25 15:00:39 +05:30
Anshul Maheshwari
9f6309ef14 More elaborate warning for DVB subtitle's 2014-11-14 18:12:48 +05:30
cfsmp3
b95e06c21c Merge branch 'pr/n118_anshul1912' 2014-11-11 13:35:37 +01:00
Anshul Maheshwari
7ed99097ba removed libpng15 requirement in cmake 2014-10-31 04:44:38 +05:30
Anshul Maheshwari
3f4bbbde25 addd some platform specific library path 2014-10-31 04:38:06 +05:30
Anshul Maheshwari
5828f50210 init timing while initilaizing library 2014-10-31 04:19:53 +05:30
Anshul Maheshwari
b5931e8749 added dinit function to remove some memory leaks 2014-10-29 21:23:41 +05:30
Anshul Maheshwari
c588b42e0a remove redundant write format 2014-10-20 04:06:51 +05:30
Anshul Maheshwari
f9ee9570a4 remove internal use of ccx_decoders_common_settings_t 2014-10-20 03:16:57 +05:30
Anshul Maheshwari
55e408bbb7 made seprate decoder context 2014-10-19 22:36:02 +05:30
Anshul Maheshwari
93a5ae9728 cmake:generate pkg-config pc file on make install 2014-10-17 22:02:08 +05:30
cfsmp3
5c7430cff5 Merge branch 'pr/n116_anshul1912' 2014-10-12 09:56:02 +02:00
cfsmp3
fecf14bc15 Merge branch 'pr/n117_wforums' 2014-10-12 09:55:18 +02:00
wforums
a4275eba62 MAC build command fix
Fixed.
2014-10-12 00:47:47 +02:00
wforums
3873e8fd30 Bugfix for output filename fix
Getting tired :( Forgot to change header.
2014-10-12 00:45:08 +02:00
Anshul Maheshwari
5e22be2576 reverted back the changes of adding exra byte 2014-10-12 03:56:00 +05:30
cfsmp3
0b568cb168 Merge branch 'pr/n115_wforums' 2014-10-11 22:53:25 +02:00
cfsmp3
017d539710 Merge branch 'pr/n114_anshul1912' 2014-10-11 22:52:40 +02:00
wforums
06c8f69056 Output filename fix
The provided names in -o1 and -o2 were not passed on between argument
passing and initialisation of write structures, resulting in default
names.
2014-10-11 22:47:16 +02:00
Anshul Maheshwari
b06654b760 increased 1 byte of cc_data according to spec
According to CEA-708-D August 2008
cc_data() {
    reserved                   1 bit
    proccess_cc_data_flag      1 bit
    zero bit                   1 bit
    cc_count                   5 bit
    reserved                   8 bit
    for( i = 0; i < cc_count; i++) {
        one_bit_4_compatibility      1 bit
        reserved                     4 bit
        cc_valid                     1 bit
        cc_type                      2 bit
        cc_data_1                    8 bit
        cc_data_2                    8 bit
    }
}
2014-10-12 00:55:08 +05:30
cfsmp3
4ff49c2010 Merge branch 'pr/n113_anshul1912' 2014-10-11 13:02:11 +02:00
Anshul Maheshwari
0c650711cf corrected ffmpeg enabled build 2014-10-11 14:54:02 +05:30
cfsmp3
3128f10fb5 In srt, use -lf to change CRLF for LF. 2014-10-11 11:23:18 +02:00
cfsmp3
63b209929e Version push (to 0.75) 2014-10-11 10:48:12 +02:00
cfsmp3
5f68a9166f -Added -bom 2014-10-11 10:39:56 +02:00
Anshul Maheshwari
15616edea8 updated changes 2014-10-11 12:26:54 +05:30
cfsmp3
cce4ec5e1a Merge branch 'pr/n111_wforums' 2014-10-11 08:05:02 +02:00
Anshul Maheshwari
72ecd279cf passing ctx to store_hdcc 2014-10-11 10:47:06 +05:30
Anshul Maheshwari
87f1a3845c remove more global variables from header files 2014-10-11 02:25:58 +05:30
Anshul Maheshwari
4ae5f3483c removed global variable from header files 2014-10-11 01:48:57 +05:30
Anshul Maheshwari
38876690f8 Merge branch 'master' of https://github.com/anshul1912/ccextractor 2014-10-10 23:57:55 +05:30
Anshul Maheshwari
7bb4e842dd corrected function declaration 2014-10-10 23:56:53 +05:30
wforums
26d9584a93 Windows projext fix 2014-10-10 18:49:46 +02:00
wforums
9d5ce9aaae UCLA bug fix?
-
2014-10-10 18:49:39 +02:00
wforums
47264425df Fix of build script + moving ccfont2 2014-10-10 16:47:30 +02:00
wforums
e8f8d04369 possible fix for ucla timing issue 2014-10-10 16:37:41 +02:00
Anshul Maheshwari
78cb26c9cb moved windows specific include 2014-10-09 20:20:23 -07:00
Anshul Maheshwari
2f5d45df01 added library file in windows build script 2014-10-09 18:49:02 -07:00
wforums
53be44dfdb Merge branch 'master' of https://github.com/CCExtractor/ccextractor 2014-10-09 23:12:13 +02:00
wforums
48b5a0b384 Small UCLA fix
-
2014-10-09 23:12:07 +02:00
Anshul Maheshwari
a08c7b1871 corrected do_NAL declaration 2014-10-09 16:15:13 +05:30
Anshul Maheshwari
0a2a00f883 corrected pointer 2014-10-09 15:36:46 +05:30
Anshul Maheshwari
2125e58e1f minor refactoring to correctly set options 2014-10-09 15:04:17 +05:30
Anshul Maheshwari
5bdd6971f7 moved option parsing in library 2014-10-08 18:48:16 +05:30
Anshul Maheshwari
051bc7138d moved global variable in library context 2014-10-08 18:44:07 +05:30
Anshul Maheshwari
e6dca329ee removed option parameter from ccextractor 2014-10-07 21:43:00 +05:30
Anshul Maheshwari
6cfddb12a6 corrected typo cxx to ccx 2014-10-07 19:56:35 +05:30
Anshul Maheshwari
c9c063b8d8 Merge -xds willem changes 2014-10-07 19:50:02 +05:30
Anshul Maheshwari
e0cd8b2e56 builds on windows 2014-10-07 19:25:09 -07:00
Anshul Maheshwari
38d2088db5 include lib_ccx.h instead of ccextractor.h 2014-10-07 16:35:30 +05:30
Anshul Maheshwari
8e940b050a rename ccextractor.h to lib_ccx.h 2014-10-07 16:25:14 +05:30
cfsmp3
5733b40ca6 Merge branch 'pr/n107_anshul1912' 2014-10-07 12:03:51 +02:00
cfsmp3
22c40675a6 Merge branch 'pr/n108_wforums' 2014-10-07 12:00:36 +02:00
wforums
a3ef46c21d XDS fix + exception when parameters not compatible
See title :)
2014-10-07 11:34:09 +02:00
Anshul Maheshwari
93a546bab4 compiled on windows 2014-10-07 00:24:45 -07:00
Anshul Maheshwari
ec427fd82c remove use of relative path 2014-10-07 00:21:28 -07:00
Anshul Maheshwari
70cc3c2046 Added Cmake support 2014-10-07 02:39:41 +05:30
Anshul Maheshwari
5634960813 add ccx library path in Makefile 2014-10-07 02:39:36 +05:30
Anshul Maheshwari
c7a49e80e3 relative paths while including header file 2014-10-07 02:39:31 +05:30
Anshul Maheshwari
617d2d30dc move all code except ccextractor in folder lib_ccx 2014-10-07 02:38:54 +05:30
cfsmp3
18f781d099 0.74 2014-09-24 13:04:26 +02:00
Ruslan Kuchumov
84db812769 windows support 2014-09-08 18:49:37 +00:00
Ruslan Kuchumov
7763f8aeab pointer bugfix 2014-09-08 18:02:49 +00:00
Ruslan Kuchumov
faa879801e printing output on SIGINT 2014-09-08 09:02:10 +00:00
wforums
4635329a5b Changes.txt updated
-
2014-09-06 13:17:04 +02:00
wforums
b89cc3b6df UCLA TT format change
Switched around TEL & TT page number in ttxt format.
2014-09-06 13:16:51 +02:00
wforums
e9f8313f7c BOM parameter
BOM can be not written now if -nobom is passed as parameter.
2014-09-06 13:16:25 +02:00
wforums
324cd84ffe UCLA parameter fix
Added a new option to ensure that UCLA parameter doesn't get overriden
anymore.
2014-09-06 12:13:50 +02:00
wforums
9d7518c9ec -o1 -o2 -12 fix
Fixes the issue where when using multiple output files, everyting is
written to the -o2 output file.
2014-09-06 00:07:28 +02:00
Ruslan Kuchumov
32e0d6023d sending teletext to the server 2014-09-04 16:07:06 +00:00
Ruslan Kuchumov
c9465e476b segfault when no input files bugfix 2014-09-04 16:02:51 +00:00
Ruslan Kuchumov
45d237da40 removed bin output when sending to server 2014-09-04 15:33:02 +00:00
cfsmp3
631ae2e02f Version bump (0.72 to 0.73) 2014-08-19 07:45:00 +02:00
Anshul Maheshwari
695aa14cd7 Merge remote-tracking branch 'carlos/master' 2014-08-18 23:47:03 +05:30
Anshul Maheshwari
b638bb1d3a updated some grammer in Readme.md 2014-08-18 23:37:03 +05:30
Anshul Maheshwari
28950bf90e changes should not be in Readme.md 2014-08-18 23:22:43 +05:30
wforums
77f8289ca6 Version change
- Added description
2014-08-18 14:26:52 +02:00
wforums
cece92a828 Merge conflict resolve
Fixed merge conflicts
2014-08-18 13:50:30 +02:00
wforums
bd08454d66 Merge from upstream 2014-08-18 13:45:44 +02:00
wforums
c6e5dd5cf7 GPACMP4 filter
moved 2 files to filter
2014-08-18 13:43:12 +02:00
cfsmp3
bd8e3ad137 Merge branch 'pr/n98_rkuchumov' 2014-08-18 13:34:31 +02:00
cfsmp3
8a2e71fcfb Merge branch 'pr/n99_rkuchumov' 2014-08-18 13:33:06 +02:00
wforums
301c2a7138 Library - step one and half
- moved around some functions
- 608_helpers is gone now (moved last function)
2014-08-18 10:35:43 +02:00
Anshul Maheshwari
5368d7292f update version 2014-08-18 13:13:54 +05:30
Anshul Maheshwari
29689b10aa Merge branch 'master' of https://github.com/anshul1912/ccextractor 2014-08-18 13:11:03 +05:30
Anshul Maheshwari
4d8883d0f1 Documented FFmpeg Intigration 2014-08-18 13:10:06 +05:30
Anshul Maheshwari
efe6fceb3a add cflags for gpacmp4 on linux 2014-08-17 10:19:54 +02:00
Ruslan Kuchumov
d9a998b95f memory leak 2014-08-16 23:53:34 +00:00
Ruslan Kuchumov
bf94c2997d unusable variable 2014-08-16 23:41:14 +00:00
Ruslan Kuchumov
6405a3973d tlt support 2014-08-16 21:53:00 +00:00
Anshul Maheshwari
9270e22a65 Merge branch 'master' of https://github.com/anshul1912/ccextractor 2014-08-16 09:49:32 +02:00
Anshul Maheshwari
02e19cf617 corrected CFLAGS to be include in ffmpeg enable 2014-08-16 09:48:29 +02:00
Ruslan Kuchumov
1493b6c4f5 renaming 2014-08-15 21:29:28 +00:00
wforums
74ab732999 Library - fixes
-
2014-08-15 18:37:15 +02:00
wforums
5961d1b56e Library - fixes
-
2014-08-15 18:24:17 +02:00
wforums
87d6a6bf91 Library - fixes
Include fixes
2014-08-15 18:19:48 +02:00
wforums
456d23f547 Library - step one and half
- Cleaned out header files + adjusted accordingly
- Decoupled spupng_encoder from ccextractor.h
- Decoupled ccx_encoders_common from ccextractor.h
2014-08-15 17:47:58 +02:00
wforums
02da93d0e4 Merge conflict fix
-
2014-08-15 14:09:33 +02:00
wforums
597304e932 Merge from upstream
-
2014-08-15 12:34:18 +02:00
Anshul Maheshwari
918889c890 corrected timing in spupng xml file 2014-08-15 12:28:30 +02:00
Anshul Maheshwari
47bfe6bffc corrected timing for tudor using ffmpeg 2014-08-15 12:28:29 +02:00
cfsmp3
5789a0a224 Updated MD 2014-08-15 12:28:29 +02:00
Anshul Maheshwari
b15f54c7f9 Intigration of ffmpeg in ccextractor 2014-08-15 12:28:28 +02:00
wforums
bc3794eb14 Library - step one and hafl
-
2014-08-15 11:59:53 +02:00
wforums
4e66d290a6 Library - step one and half
Moved most of 608_helper functions to ccx_encoders_helpers, as they seem
more logical. No idea yet where the last one has to go (used in both
encoder/decoder 608 right now)
2014-08-15 11:44:14 +02:00
wforums
7b48b01fd1 Library - intermediate
This one has errors!
2014-08-15 09:00:16 +02:00
Anshul Maheshwari
883dfaae4a corrected timing in spupng xml file 2014-08-14 20:45:38 +05:30
wforums
884a25a7cd Commented unused vars
Added a ; too much.
2014-08-13 15:54:27 +02:00
wforums
8cc8767634 Commented unused variables
-
2014-08-13 15:48:08 +02:00
wforums
90a6902ad4 Library - step one and half
More removal of links.
2014-08-13 15:47:53 +02:00
wforums
b334acb426 Library - step one and half
Decoupled 708 from ccextractor.h (finally), reworked some things as
well.
2014-08-13 15:33:51 +02:00
Anshul Maheshwari
9c847aa4f1 Merge remote-tracking branch 'carlos/master' 2014-08-13 17:48:50 +05:30
Anshul Maheshwari
c3397d1949 corrected timing for tudor using ffmpeg 2014-08-13 17:48:00 +05:30
Ruslan Kuchumov
41ad0b4006 cc_name 2014-08-12 22:32:11 +00:00
wforums
170a57b9c6 Library - fix
-
2014-08-12 14:34:34 +02:00
wforums
0a15c2d16e Library - fix
Fix of includes
2014-08-12 14:32:28 +02:00
wforums
c52283676a Library - step one and half
- Moved enum & struct to more appropriate place (also fixes error with
compiling under linux)
2014-08-12 14:26:48 +02:00
wforums
ce3c2b5ae2 Merge fix 2
-
2014-08-12 12:25:35 +02:00
wforums
48e030d94c Merge fix
Fixing errors that popped up after trying to merge.
2014-08-12 12:14:36 +02:00
wforums
afaa7c8b76 Merge try
Trying to merge
2014-08-12 11:41:22 +02:00
Anshul Maheshwari
f84b69aca7 Intigration of ffmpeg in ccextractor 2014-08-12 10:43:07 +05:30
181 changed files with 33027 additions and 20600 deletions

5
.gitignore vendored
View File

@@ -9,10 +9,13 @@ CVS
*.o
linux/ccextractor
linux/depend
windows/debug/*
windows/debug/**
windows/release/**
####
# Visual Studio project Ignored files
*.suo
*.sdf
*.opensdf
*.user

View File

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

View File

@@ -1,20 +1,12 @@
ccextractor
===========
CCExtractor - Carlos' version (mainstream).
Carlos' version (mainstream) is the most stable branch.
GSOC - 0.72
-----------
- Fix for WTV files with incorrect timing
- Added support for fps change using data from AVC video track in a H264 TS file.
Extracting subtitles has never been so easy. Just type the following command:
ccextrator "name of input"
GSOC - 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
Gui lovers should download the Sorceforge version of CCExtractor, the Git Version is not your cup of tea.
http://ccextractor.sourceforge.net/download-ccextractor.html
For News about release, please find CHANGES.TXT

View File

@@ -28,4 +28,17 @@ To do:
CCExtractor fully support Asian languages. I do need samples
though. No samples, no support.
- A few commands are not yet supported, specifically those related
to delay.
to delay.
- Detect and extract captions from MP4 (MOV) files, handled by gpacmp4
Done (18.08.2015):
- Major refactoring
- Librarized as much as possible (global vars moved to dtvcc context)
- Added some control commands support
- 16 bit charset support added (not "moved everything to 16-bit", but they could be successfully exported)
- SAMI output added
- Transcript output added
- Timed transcript output added
- Added colour support (only one colour/style can be applied for the whole screen at the moment)
- Roll up captions handling

View File

@@ -1,10 +1,63 @@
0.72 - GSOC
-----------
0.78 (2015-12-12)
-----------------
- Support to extract Closed Caption from MultiProgram at once.
- CEA-708: exporting to SAMI (.smi), Transcript (.txt), Timed Transcript (ttxt) and SubRip (.srt).
- CEA-708: 16 bit charset support (tested on Korean).
- CEA-708: Roll Up captions handling.
- Changed TCP connection protocol (BIN data is now wrapped in packets, added EPG support and keep-alive packets).
- TCP connection password prompt is removed. To set connection password use -tcppassword argument instead.
- Support ISDB Closed Caption.
- Added a new output format, simplexml (used internally by a CCExtractor user, may or may not be useful for
anyone else).
0.77 (2015-06-20)
-----------------
- Fixed bug in capitalization code ('I' was not being capitalized).
- GUI should now run in Windows 8 (using the include .Net runtime, since
3.5 cannot be installed in Windows 8 apparently).
- Fixed Mac build script, binary is now compiled with support for
files over 2 GB.
- Fixed bug in PMT code, damaged PMT sections could make CCExtractor
crash.
0.76 (2015-03-28)
-----------------
- Added basic M2TS support
- Added EPG support - you can now export the Program Guide to XML
- Some bugfixes
0.75 (2015-01-15)
-----------------
- Fixed issue with teletext to other then srt.
- CCExtractor can be used as library if compiled using cmake
- By default the Windows version adds BOM to generated UTF files (this is
because it's needed to open the files correctly) while all other
builds don't add it (because it messes with text processing tools).
You can use -bom and -nobom to change the behaviour.
0.74 (2014-09-24)
-----------------
- 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 (2014-08-19)
------------------------
- 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 (2014-08-12)
------------------------
- 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
-----------
0.71 - GSOC (2014-07-31)
------------------------
- 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
@@ -14,8 +67,8 @@
- Fix for .bin files when not using latin1 charset
- Correction of mp4 timing, when one timestamp points timing of two atom
0.70 - GSOC
-----------
0.70 - GSOC (2014-07-06)
------------------------
This is the first release that is part of Google's Summer of Code.
Anshul, Ruslan and Willem joined CCExtractor to work on a number of things
over the summer, and their work is already reaching the mainstream
@@ -55,8 +108,8 @@ version of CCExtractor.
settings (-out, -ucla, -xds, -txt, -ttxt, ...)
- Fixed Negative timing Bug
0.69
----
0.69 (2014-04-05)
-----------------
- A few patches from Christopher Small, including proper support
for multiple multicast clients listening on the same port.
- GUI: Fixed teletext preview.
@@ -75,8 +128,8 @@ version of CCExtractor.
- Windows GUI: Some code refactoring, since the HDHomeRun support makes
the code larger enough to require more than one source file :-)
0.68
----
0.68 (2013-12-24)
-----------------
- A couple of shared variables between 608 decoders were causing
problems when both fields were processed at the same time with
-12, fixed.
@@ -90,8 +143,8 @@ version of CCExtractor.
(Heleen Buus).
- Some fixes (Chris Small).
0.67
----
0.67 (2013-10-09)
-----------------
- Padding bytes were being discarded early in the process in 0.66,
which is convenient for debugging, but it messes with timing in
.raw, which depends on padding. Fixed.
@@ -111,8 +164,8 @@ version of CCExtractor.
roll-up mode.
0.66
----
0.66 (2013-07-01)
-----------------
- Fixed bug in auto detection code that triggered a message
about file being auto of sync.
- Added -investigate_packets
@@ -190,8 +243,8 @@ version of CCExtractor.
- Added -noautotimeref: Prevent UTC reference from being auto set from
the stream data.
0.65
----
0.65 (2013-03-14)
-----------------
- Minor GUI changes for teletext
- Added end timestamps in timed transcripts
- Added support for SMPTE (patch by John Kemp)
@@ -209,8 +262,8 @@ version of CCExtractor.
display their contents (-parsePAT and -parsePMT) which makes
troubleshooting easier.
0.64
----
0.64 (2012-10-29)
-----------------
- Changed Window GUI size (larger).
- Added Teletext options to GUI.
- Added -teletext to force teletext mode even if not detected
@@ -230,8 +283,8 @@ version of CCExtractor.
- Added --nogoptime to force PTS timing even when CCExtractor would
use GOP timing otherwise.
0.63
----
0.63 (2012-08-17)
-----------------
- Telext support added, by integrating Petr Kutalek's telxcc. Integration is
still quite basic (there's equivalent code from both CCExtractor and
telxcc) and some clean up is needed, but it works. Petr has announced that
@@ -239,8 +292,8 @@ version of CCExtractor.
CCExtractor.
- Some bug fixes, as usual.
0.62
----
0.62 (2012-05-23)
-----------------
- Corrected Mac build "script" (needed to add GPAC includes). Thanks to the
Mac users that sent this.
- Hauppauge mode now uses PES timing, needed for files that don't have
@@ -262,8 +315,8 @@ version of CCExtractor.
or certain samples (we had none like this in our test collection). Thanks,
Rajesh.
0.61
----
0.61 (2012-03-08)
-----------------
- Fix: GCC 3.4.4 can now build CCExtractor.
- Fix: Damaged TS packets (those that come with 'error in transport' bit
on) are now skipped.
@@ -273,8 +326,8 @@ version of CCExtractor.
anything but please report).
- Some non-interesting cleanup.
0.60
----
0.60 (unreleased)
-----------------
- Add: MP4 support, using GPAC (a media library). Integration is currently
"enough so it works", but needs some more work. There's some duplicate
code, the stream must be a file (no streaming), etc.
@@ -284,8 +337,8 @@ version of CCExtractor.
roll-up) was broken, with complete lines being missing.
- Fix: bin format not working as input.
0.59
----
0.59 (2011-10-07)
-----------------
- More AVC/H.264 work. pic_order_cnt_type != 0 will be processed now.
- Fix: Roll-up captions with interruptions for Text (with ResumeTextDisplay
in the middle of the caption data) were missing complete lines.
@@ -313,8 +366,8 @@ version of CCExtractor.
- Some code clean up, minor refactoring.
- Teletext detection (not yet processing).
0.58
----
0.58 (2011-08-21)
-----------------
- Implemented new PTS based mode to order the caption information
of AVC/H.264 data streams. The old pic_order_cnt_lsb based method
is still available via the -poc or --usepicorder command switches.
@@ -338,18 +391,18 @@ version of CCExtractor.
output are processed OK.
- Updated Windows GUI.
0.57
----
0.57 (2010-12-16)
-----------------
- Bugfixes in the Windows version. Some debug code was unintentionally
left in the released version.
0.56
----
0.56 (2010-12-09)
-----------------
- H264 support
- Other minor changes a lot less important
0.55
----
0.55 (2009-08-09)
-----------------
- Replace pattern matching code with improved parser for MPEG-2 elementary
streams.
- Fix parsing of ReplayTV 5000 captions.
@@ -364,8 +417,8 @@ version of CCExtractor.
because of the odd number of fields. I used top_field_first to tell when the channels
are reversed. See Table 6-1 of the SCTE 20 [Paul Fernquist]
0.54
----
0.54 (2009-04-16)
-----------------
- Add -nosync and -fullbin switches for debugging purposes.
- Remove -lg (--largegops) switch.
- Improve syncronization of captions for source files with
@@ -378,8 +431,8 @@ version of CCExtractor.
- Added a feature to add start and end messages (for credits).
See help screen for details.
0.53
----
0.53 (2009-02-24)
-----------------
- Force generated RCWT files to have the same length as source file.
- Fix documentation for -startat / -endat switches.
- Make -startat / -endat work with all output formats.
@@ -405,8 +458,8 @@ version of CCExtractor.
it (there's not .NET 3.5 for Windows 2000), as
requested by a couple of key users.
0.51
----
0.51 (unreleased)
-----------------
- Removed -autopad and -goppad, no longer needed.
- In preparation to a new binary format we have
renamed the current .bin to .raw. Raw files
@@ -431,14 +484,14 @@ version of CCExtractor.
too.
- [Volker] Dish Network clean-up
0.50
----
0.50 (2008-12-12)
-----------------
- [Volker] Fix in DVR-MS NTSC timing
- [Volker] More clean-up
- Minor fixes
0.49
----
0.49 (2008-12-10)
-----------------
- [Volker] Major MPEG parser rework. Code much
cleaner now.
- Some stations transmit broken roll-up captions,
@@ -455,8 +508,8 @@ version of CCExtractor.
- [Volker] Added support for DVR-MS NTSC files.
- Other minor bugfixes and changes.
0.46
----
0.46 (2008-11-24)
-----------------
- Added support for live streaming, ccextractor
can now process files that are being recorded
at the same time.
@@ -469,9 +522,8 @@ version of CCExtractor.
Note: For now, it's only ATSC recordings, not
NTSC (analog) recordings.
0.45
----
0.45 (2008-11-14)
-----------------
- Added autodetection of DVR-MS files.
- Added -asf to force DVR-MS mode.
- Added some specific support for DVR-MS
@@ -491,8 +543,8 @@ version of CCExtractor.
need ccextractor to use GOP timing in large
GOPs.
0.44
----
0.44 (2008-09-10)
-----------------
- Added an option to the GUI to process
individual files in batch, i.e. call
ccextractor once per file. Use it if you
@@ -503,8 +555,8 @@ version of CCExtractor.
- Several minor bugfixes.
- Updated the GUI to add the new options.
0.43
----
0.43 (2008-06-20)
-----------------
- Fixed a bug in the read loop (no less)
that caused some files to fail when
reading without buffering (which is
@@ -512,16 +564,16 @@ version of CCExtractor.
- Several improvements in the GUI, such as
saving current options as default.
0.42
----
0.42 (2008-06-17)
-----------------
- The option switch "-transcript" has been
changed to "--transcript". Also, "-txt"
has been added as the short alias.
- Windows GUI
- Updated help screen
0.41
----
0.41 (2008-06-15)
-----------------
- Default output is now .srt instead of .bin,
use -raw if you need the data dump instead of
.srt.
@@ -533,15 +585,15 @@ version of CCExtractor.
there aren't useless. But if they annoy
you go ahead...
0.40
----
0.40 (2008-05-20)
-----------------
- Fixed a bug in the sanity check function
that caused the Myth branch to abort.
- Fixed the OSX build script, it needed a
new #define to work.
0.39
----
0.39 (2008-05-11)
-----------------
- Added a -transcript. If used, the output will
have no time information. Also, if in roll-up
mode there will be no repeated lines.
@@ -574,8 +626,8 @@ version of CCExtractor.
join the subs), use -ve.
0.36
----
0.36 (unreleased)
-----------------
- Fixed bug in SMI, nbsp was missing a ;.
- Footer for SAMI files was incorrect (<body> and
<sami> tags were being opened again instead of
@@ -605,8 +657,8 @@ version of CCExtractor.
as usual.
0.35
----
0.35 (unreleased)
-----------------
- Added --defaultcolor to the help screen. Code
was already in 0.34 but the documentation wasn't
updated.
@@ -615,8 +667,8 @@ version of CCExtractor.
- At the end of the process, a ratio between
video length and time to process is displayed.
0.34
----
0.34 (2007-06-03)
-----------------
- Added some basic letter case and capitalization
support. For captions that broadcast in ALL
UPPERCASE (most of them), ccextractor can now
@@ -667,8 +719,8 @@ version of CCExtractor.
Number (0.0.0.34 in this version) in case
you want to check for version info.
0.33
----
0.33 (unreleased)
-----------------
- Added -scr or --screenfuls, to select the
number of screenfuls ccextractor should
write before exiting. A screenful is
@@ -687,8 +739,8 @@ version of CCExtractor.
Use -nofc or --nofontcolor if you don't
want these tags.
0.32
----
0.32 (unreleased)
-----------------
- Added -delay ms, which adds (or substracts)
a number of milliseconds to all times in
.srt/.sami files. For example,
@@ -707,8 +759,8 @@ version of CCExtractor.
such as from minute 3 to minute 5. Check
help screen for exact syntax.
0.31
----
0.31 (unreleased)
-----------------
- Added -dru (direct rollup), which causes
roll-up captions to be written as
they would on TV instead of line by line.
@@ -716,20 +768,20 @@ version of CCExtractor.
and ugly too (each line is written many
times, two characters at time).
0.30
----
0.30 (2007-05-24)
-----------------
- Fix in extended char decoding, I wasn't
replacing the previous char.
- When a sequence code was found before
having a PTS, reported time was
undefined.
0.29
----
0.29 (unreleased)
-----------------
- Minor bugfix.
0.28
----
0.28 (unreleased)
-----------------
- Fixed a buffering related issue. Short version,
the first 2 Mb in non-TS mode were being
discarded.
@@ -738,20 +790,20 @@ version of CCExtractor.
they are not part of the .srt "standard"
even if McPoodle add them.
0.27
----
0.27 (unreleased)
-----------------
- Modified sanitizing code, it's less aggresive
now. Ideally it should mean that characters
won't be missed anymore. We'll see.
0.26
----
0.26 (unreleased)
-----------------
- Added -gp (or -goppad) to make ccextractor use
GOP timing. Try it for non TS files where
subs start OK but desync as the video advances.
0.25
----
0.25 (unreleased)
-----------------
- Format detection is not perfect yet. I've added
-nomyth to prevent the MytvTV code path to be
called. I've seen apparently correct files that
@@ -761,8 +813,8 @@ version of CCExtractor.
options will work.
0.24
----
0.24 (unreleased)
-----------------
- Fixed a bug that caused dvr-ms (Windows Media Center)
files to be incorrectly processed (letters out of
order all the time).
@@ -776,8 +828,8 @@ version of CCExtractor.
still can).
0.22
----
0.22 (2007-05-15)
-----------------
- Added text mode handling into decoder, which gets rids
of junk when text mode data is present.
- Added support for certain (possibly non standard
@@ -788,8 +840,8 @@ version of CCExtractor.
- Other Minor bug fixes.
0.20
----
0.20 (2007-05-07)
-----------------
- Unicode should be decent now.
- Added support for Hauppauge PVR 250 cards, and (possibly)
many others (bttv) with the same closed caption recording
@@ -806,8 +858,8 @@ version of CCExtractor.
though. If you have a good CSS for .SAMI files let me
know.
0.19
----
0.19 (2007-05-03)
-----------------
- Work on Dish Network streams, timing was completely broken.
It's fixed now at least for the samples I have, if it's not
completely fixed let me know. Credit for this goes to
@@ -818,8 +870,8 @@ version of CCExtractor.
- Added Unicode and Latin-1 encoding.
0.17
----
0.17 (2007-04-29)
-----------------
- Extraction to .srt is almost complete - works correctly for
pop-up and roll-up captions, possibly not yet for paint-on
(mostly because I don't have any sample with paint-on captions
@@ -827,8 +879,8 @@ version of CCExtractor.
- Minor bug fixes.
- Automatic TS/non-TS mode detection.
0.14
----
0.14 (2007-04-25)
-----------------
- Work on handling special cases related to the MPEG reference
clock: Roll over, jumps, etc.
- Modified padding code a bit: In particular, padding occurs
@@ -841,8 +893,8 @@ version of CCExtractor.
needs to start with a TS header).
- Minor bug fixes.
0.07
----
0.07 (2007-04-19)
-----------------
- Added MPEG reference clock parsing.
- Added autopadding in TS. Does miracles with timing.
- Added video information (as extracted from sequence header).

58
docs/FFMPEG.TXT Normal file
View File

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

View File

@@ -6,8 +6,8 @@ extract text from images. In the World of Subtile, subtitle stored
in bitmap format are common and even neccassary. for converting subtile
in bitmap format to subtilte in text format ocr is used.
Dependecy
=========
Dependency
==========
Tesseract (OCR library by google)
Leptonica (image processing library)
@@ -43,9 +43,10 @@ sudo make install
sudo ldconfig
Note:
1) CCExtractor is tested with Tesseract 3.02.02 version.
1) CCExtractor is tested with Tesseract 3.04 version but it works with older versions.
you can download tesseract from https://drive.google.com/folderview?id=0B7l10Bj_LprhQnpSRkpGMGV2eE0&usp=sharing
you can download tesseract from https://github.com/tesseract-ocr/tesseract/archive/3.04.00.tar.gz
you can download tesseract training data from https://github.com/tesseract-ocr/tessdata/archive/3.04.00.tar.gz
@@ -55,13 +56,10 @@ make ENABLE_OCR=yes
How to compile ccextractor on Windows with OCR
=============================================
===============================================
Download prebuild library of leptonica from following link
http://www.leptonica.com/source/leptonica-1.68-win32-lib-include-dirs.zip
Download prebuild library of tesseract from following tesseract official link
https://code.google.com/p/tesseract-ocr/downloads/detail?name=tesseract-3.02.02-win32-lib-include-dirs.zip
Download prebuild library of leptonica and tesseract from following link
https://drive.google.com/file/d/0B2ou7ZfB-2nZOTRtc3hJMHBtUFk/view?usp=sharing
put the path of libs/include of leptonica and tesseract in library paths.
step 1) In visual studio 2013 right click <Project> and select property.
@@ -85,12 +83,12 @@ 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 libtesseract302.lib in new line
Step 7)Add liblept168.lib in new line
Step 6)Add libtesseract304d.lib in new line
Step 7)Add liblept172.lib in new line
Download language data from following link
https://code.google.com/p/tesseract-ocr/downloads/list
after downloading the tesseract-ocr-3.02.eng.tar extract the tar file and put
after downloading the tesseract-ocr-3.02.eng.tar.gz extract the tar file and put
tessdata folder where you have kept ccextractor executable
Copy the tesseract and leptonica dll in the folder of executable or in system32.
Copy the tesseract and leptonica dll from lib folder downloaded from above link to folder of executable or in system32.

View File

@@ -1,4 +1,4 @@
ccextractor, 0.71
ccextractor, 0.78
-----------------
Authors: Carlos Fernández (cfsmp3), Volker Quetschke.
Maintainer: cfsmp3
@@ -18,6 +18,15 @@ Google Summer of Code 2014 students
- Ruslan KuchumoV
- Anshul Maheshwari
Google Summer of Code 2015 students
- Willem van iseghem
- Ruslan Kuchumov
- Anshul Maheshwari
- Nurendra Choudhary
- Oleg Kiselev
- Vasanth Kalingeri
License
-------
GPL 2.0.

View File

@@ -0,0 +1,31 @@
For building ccextractor using cmake folllow below steps..
Step 1) Check you have right version of cmake installed. ( version >= 3.0.2 )
We are using CMP0037 policy of cmake which was introduced in 3.0.0
since we have tested our system only with cmake version 3.0.2, I would
suggest to use 3.0.2 or higher version.
Step 2) create a seprate directory where you want to build the target.
In Unix you can do it using follwing commands.
~> cd ccextractor
~> mkdir build
Step 3) make the build sytem using cmake
~> cmake ../src/
Step 4) Compile the code.
~> make
~> make install
Step 5) Use CCextractor as you would like
If you want to build CCExtractor with FFMpeg you need to pass
cmake -DWITH_FFMPEG=ON ../src/
If you want to build CCExtractor with OCR you need to pass
cmake -DWITH_OCR=ON ../src/
Hint for looking all the things you want to set from outside
cmake -LAH ../src/

View File

@@ -1,21 +1,28 @@
SHELL = /bin/sh
CC = gcc
SYS := $(shell gcc -dumpmachine)
CFLAGS = -O3 -std=gnu99
INCLUDE = -I../src/gpacmp4/ -I../src/libpng -I../src/zlib
INCLUDE = -I../src/gpacmp4/ -I../src/libpng -I../src/zlib -I../src/lib_ccx -I../src/.
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
VPATH = ../src:../src/gpacmp4:../src/libpng:../src/zlib
VPATH = ../src:../src/gpacmp4:../src/libpng:../src/zlib:../src/lib_ccx
SRCS_DIR = ../src
SRCS_C = $(wildcard $(SRCS_DIR)/*.c)
OBJS = $(SRCS_C:$(SRCS_DIR)/%.c=$(OBJS_DIR)/%.o)
SRCS_CCX_DIR = $(SRCS_DIR)/lib_ccx
SRCS_CCX = $(wildcard $(SRCS_CCX_DIR)/*.c)
OBJS_CCX = $(SRCS_CCX:$(SRCS_CCX_DIR)/%.c=$(OBJS_DIR)/%.o)
SRCS_PNG_DIR = $(SRCS_DIR)/libpng
SRCS_PNG = $(wildcard $(SRCS_PNG_DIR)/*.c)
OBJS_PNG = $(SRCS_PNG:$(SRCS_PNG_DIR)/%.c=$(OBJS_DIR)/%.o)
@@ -35,9 +42,39 @@ INSTLALL_PROGRAM = $(INSTLALL)
DESTDIR = /usr/bin
ifeq ($(ENABLE_OCR),yes)
CFLAGS+=-I/usr/local/include/tesseract -I/usr/local/include/leptonica
CFLAGS+=-DENABLE_OCR
LDFLAGS+= $(shell pkg-config --libs tesseract)
CFLAGS+=-DENABLE_OCR -DPNG_NO_CONFIG_H
TESS_LDFLAGS+= $(shell pkg-config --libs tesseract)
LEPT_LDFLAGS+= $(shell pkg-config --libs lept)
#error checking of library are there or not
ifeq ($(TESS_LDFLAGS),$(EMPTY))
$(error **ERROR** "tesseract not found")
else
#TODO print the version of library found
$(info "tesseract found")
endif
ifeq ($(LEPT_LDFLAGS),$(EMPTY))
$(error **ERROR** "leptonica not found")
else
#TODO print the version of library found
$(info "Leptonica found")
endif
CFLAGS += $(shell pkg-config --cflags tesseract)
CFLAGS += $(shell pkg-config --cflags lept)
LDFLAGS += $(TESS_LDFLAGS)
LDFLAGS += $(LEPT_LDFLAGS)
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
@@ -47,8 +84,8 @@ all: objs_dir $(TARGET)
objs_dir:
mkdir -p $(OBJS_DIR)
$(TARGET): $(OBJS) $(OBJS_PNG) $(OBJS_GPACMP4) $(OBJS_ZLIB)
$(CC) $(ALL_FLAGS) $(CFLAGS) $(OBJS) $(OBJS_PNG) $(OBJS_GPACMP4) $(OBJS_ZLIB) $(LDFLAGS) -o $@
$(TARGET): $(OBJS) $(OBJS_PNG) $(OBJS_GPACMP4) $(OBJS_ZLIB) $(OBJS_CCX)
$(CC) $(ALL_FLAGS) $(CFLAGS) $(OBJS) $(OBJS_CCX) $(OBJS_PNG) $(OBJS_GPACMP4) $(OBJS_ZLIB) $(LDFLAGS) -o $@
$(OBJS_DIR)/%.o: %.c
$(CC) -c $(ALL_FLAGS) $(INCLUDE) $(CFLAGS) $< -o $@
@@ -56,12 +93,15 @@ $(OBJS_DIR)/%.o: %.c
$(OBJS_DIR)/%.o: %.cpp
$(CC) -c $(ALL_FLAGS) $(INCLUDE) $(CFLAGS) $< -o $@ -I../src/gpacmp4
$(OBJS_DIR)/ccextractor.o: ccextractor.c
$(CC) -c $(ALL_FLAGS) $(INCLUDE) $(CFLAGS) -O0 $< -o $@
.PHONY: clean
clean:
rm $(TARGET) 2>/dev/null || true
rm $(OBJS_PNG) $(OBJS_ZLIB) $(OBJS_GPACMP4) $(OBJS) 2>/dev/null || true
rm -rd $(OBJS_DIR) 2>/dev/null || true
rm .depend 2>/dev/null || true
rm -rf $(TARGET) 2>/dev/null || true
rm -rf $(OBJS_CCX) $(OBJS_PNG) $(OBJS_ZLIB) $(OBJS_GPACMP4) $(OBJS) 2>/dev/null || true
rm -rdf $(OBJS_DIR) 2>/dev/null || true
rm -rf .depend 2>/dev/null || true
.PHONY: install
install: $(TARGET)
@@ -73,7 +113,7 @@ uninstall:
.PHONY: depend dep
depend dep:
$(CC) $(CFLAGS) -E -MM $(SRCS_C) $(SRCS_PNG) $(SRCS_ZLIB) \
$(CC) $(CFLAGS) $(INCLUDE) -E -MM $(SRCS_C) $(SRCS_PNG) $(SRCS_ZLIB) $(SRCS_CCX) \
$(SRCS_GPACMP4_C) $(SRCS_GPACMP4_CPP) |\
sed 's/^[a-zA-Z_0-9]*.o/$(OBJS_DIR)\/&/' > .depend

View File

@@ -1,2 +1,11 @@
#!/bin/bash
gcc -std=gnu99 -Wno-write-strings -DGPAC_CONFIG_LINUX -D_FILE_OFFSET_BITS=64 -I../src/gpacmp4/ -I../src/libpng/ -I../src/zlib/ -o ccextractor $(find ../src/ -name '*.cpp') $(find ../src/ -name '*.c') -lm -zmuldefs
BLD_FLAGS="-std=gnu99 -Wno-write-strings -DGPAC_CONFIG_LINUX -D_FILE_OFFSET_BITS=64"
BLD_INCLUDE="-I../src/lib_ccx/ -I../src/gpacmp4/ -I../src/libpng/ -I../src/zlib/"
SRC_LIBPNG="$(find ../src/libpng/ -name '*.c')"
SRC_ZLIB="$(find ../src/zlib/ -name '*.c')"
SRC_CCX="$(find ../src/lib_ccx/ -name '*.c')"
SRC_GPAC="$(find ../src/gpacmp4/ -name '*.c')"
BLD_SOURCES="../src/ccextractor.c $SRC_CCX $SRC_GPAC $SRC_ZLIB $SRC_LIBPNG"
BLD_LINKER="-lm -zmuldefs"
gcc $BLD_FLAGS $BLD_INCLUDE -o ccextractor $BLD_SOURCES $BLD_LINKER

View File

@@ -1,2 +1,11 @@
#!/bin/bash
gcc -g -std=gnu99 -Wno-write-strings -DGPAC_CONFIG_LINUX -D_FILE_OFFSET_BITS=64 -I../src/gpacmp4/ -I../src/libpng/ -I../src/zlib/ -o ccextractor $(find ../src/ -name '*.cpp') $(find ../src/ -name '*.c') -lm -zmuldefs
BLD_FLAGS="-g -std=gnu99 -Wno-write-strings -DGPAC_CONFIG_LINUX -D_FILE_OFFSET_BITS=64"
BLD_INCLUDE="-I../src/lib_ccx/ -I../src/gpacmp4/ -I../src/libpng/ -I../src/zlib/"
SRC_LIBPNG="$(find ../src/libpng/ -name '*.c')"
SRC_ZLIB="$(find ../src/zlib/ -name '*.c')"
SRC_CCX="$(find ../src/lib_ccx/ -name '*.c')"
SRC_GPAC="$(find ../src/gpacmp4/ -name '*.c')"
BLD_SOURCES="../src/ccextractor.c $SRC_CCX $SRC_GPAC $SRC_ZLIB $SRC_LIBPNG"
BLD_LINKER="-lm -zmuldefs"
gcc $BLD_FLAGS $BLD_INCLUDE -o ccextractor $BLD_SOURCES $BLD_LINKER

3
mac/build.command Normal file → Executable file
View File

@@ -1 +1,2 @@
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')
gcc -std=gnu99 -Wno-write-strings -DGPAC_CONFIG_DARWIN -D_FILE_OFFSET_BITS=64 -Dfopen64=fopen -Dopen64=open -Dlseek64=lseek -I ../src/gpacmp4 -I ../src/lib_ccx -I ../src/libpng -I ../src/zlib -o ccextractor $(find ../src/ -name '*.cpp' \! -name 'win_*') $(find ../src/ -name '*.c' \! -name 'win_*') -liconv

166
src/608.h
View File

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

View File

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

View File

@@ -1,282 +0,0 @@
#include "ccextractor.h"
#include "cc_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;
sprintf ((char *) str,
"<SYNC start=%llu><P class=\"UNKNOWNCC\">\r\n",
(unsigned long long)ms_start);
if (ccx_options.encoding!=CCX_ENC_UNICODE)
{
dbg_print(CCX_DMT_608, "\r%s\n", str);
}
used = encode_line(context->buffer,(unsigned char *) str);
write (context->out->fh, context->buffer, used);
int len=strlen (string);
unsigned char *unescaped= (unsigned char *) malloc (len+1);
unsigned char *el = (unsigned char *) malloc (len*3+1); // Be generous
if (el==NULL || unescaped==NULL)
fatal (EXIT_NOT_ENOUGH_MEMORY, "In write_stringz_as_sami() - not enough memory.\n");
int pos_r=0;
int pos_w=0;
// Scan for \n in the string and replace it with a 0
while (pos_r<len)
{
if (string[pos_r]=='\\' && string[pos_r+1]=='n')
{
unescaped[pos_w]=0;
pos_r+=2;
}
else
{
unescaped[pos_w]=string[pos_r];
pos_r++;
}
pos_w++;
}
unescaped[pos_w]=0;
// Now read the unescaped string (now several string'z and write them)
unsigned char *begin=unescaped;
while (begin<unescaped+len)
{
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);
}
write(context->out->fh, el, u);
write(context->out->fh, encoded_br, encoded_br_length);
write(context->out->fh, encoded_crlf, encoded_crlf_length);
begin+= strlen ((const char *) begin)+1;
}
sprintf ((char *) str,"</P></SYNC>\r\n");
if (ccx_options.encoding!=CCX_ENC_UNICODE)
{
dbg_print(CCX_DMT_608, "\r%s\n", str);
}
used=encode_line (context->buffer,(unsigned char *) str);
write(context->out->fh, context->buffer, used);
sprintf ((char *) str,
"<SYNC start=%llu><P class=\"UNKNOWNCC\">&nbsp;</P></SYNC>\r\n\r\n",
(unsigned long long)ms_end);
if (ccx_options.encoding!=CCX_ENC_UNICODE)
{
dbg_print(CCX_DMT_608, "\r%s\n", str);
}
write(context->out->fh, context->buffer, used);
free(el);
free(unescaped);
}
int write_cc_bitmap_as_sami(struct cc_subtitle *sub, struct encoder_ctx *context)
{
struct spupng_t *sp = (struct spupng_t *)context->out->spupng_data;
int x_pos, y_pos, width, height, i;
int x, y, y_off, x_off, ret;
uint8_t *pbuf;
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;
LLONG ms_start, ms_end;
char timeline[128];
int len = 0;
x_pos = -1;
y_pos = -1;
width = 0;
height = 0;
if (context->prev_start != -1 && (sub->flags & SUB_EOD_MARKER))
{
ms_start = context->prev_start + subs_delay;
ms_end = sub->start_time - 1;
}
else if ( !(sub->flags & SUB_EOD_MARKER))
{
ms_start = sub->start_time + subs_delay;
ms_end = sub->end_time - 1;
}
if(sub->nb_data == 0 )
return 0;
rect = sub->data;
for(i = 0;i < sub->nb_data;i++)
{
if(x_pos == -1)
{
x_pos = rect[i].x;
y_pos = rect[i].y;
width = rect[i].w;
height = rect[i].h;
}
else
{
if(x_pos > rect[i].x)
{
width += (x_pos - rect[i].x);
x_pos = rect[i].x;
}
if (rect[i].y < y_pos)
{
height += (y_pos - rect[i].y);
y_pos = rect[i].y;
}
if (rect[i].x + rect[i].w > x_pos + width)
{
width = rect[i].x + rect[i].w - x_pos;
}
if (rect[i].y + rect[i].h > y_pos + height)
{
height = rect[i].y + rect[i].h - y_pos;
}
}
}
if ( sub->flags & SUB_EOD_MARKER )
context->prev_start = sub->start_time;
pbuf = (uint8_t*) malloc(width * height);
memset(pbuf, 0x0, width * height);
for(i = 0;i < sub->nb_data;i++)
{
x_off = rect[i].x - x_pos;
y_off = rect[i].y - y_pos;
for (y = 0; y < rect[i].h; y++)
{
for (x = 0; x < rect[i].w; x++)
pbuf[((y + y_off) * width) + x_off + x] = rect[i].data[0][y * rect[i].w + x];
}
}
palette = (png_color*) malloc(rect[0].nb_colors * sizeof(png_color));
if(!palette)
{
ret = -1;
goto end;
}
alpha = (png_byte*) malloc(rect[0].nb_colors * sizeof(png_byte));
if(!alpha)
{
ret = -1;
goto end;
}
/* TODO do rectangle, wise one color table should not be used for all rectangle */
mapclut_paletee(palette, alpha, (uint32_t *)rect[0].data[1],rect[0].nb_colors);
quantize_map(alpha, palette, pbuf, width*height, 3, rect[0].nb_colors);
#ifdef ENABLE_OCR
str = ocr_bitmap(palette,alpha,pbuf,width,height);
if(str && str[0])
{
if (context->prev_start != -1 || !(sub->flags & SUB_EOD_MARKER))
{
char *token = NULL;
sprintf(context->buffer,
"<SYNC start=%llu><P class=\"UNKNOWNCC\">\r\n"
,(unsigned long long)ms_start);
write(context->out->fh,context->buffer,strlen(context->buffer));
token = strtok(str,"\r\n");
while (token)
{
sprintf(context->buffer,"%s",token);
token = strtok(NULL,"\r\n");
if(token)
strcat(context->buffer,"<br>\n");
else
strcat(context->buffer,"\n");
write(context->out->fh,context->buffer,strlen(context->buffer));
}
sprintf(context->buffer,
"<SYNC start=%llu><P class=\"UNKNOWNCC\">&nbsp;</P></SYNC>\r\n\r\n"
,(unsigned long long)ms_end);
write(context->out->fh,context->buffer,strlen(context->buffer));
}
}
#endif
end:
sub->nb_data = 0;
freep(&sub->data);
freep(&palette);
freep(&alpha);
return ret;
}
int write_cc_buffer_as_sami(struct eia608_screen *data, struct encoder_ctx *context)
{
int used;
LLONG startms, endms;
int wrote_something=0;
startms = data->start_time;
startms+=subs_delay;
if (startms<0) // Drop screens that because of subs_delay start too early
return 0;
endms = data->end_time;
endms--; // To prevent overlapping with next line.
sprintf ((char *) str,
"<SYNC start=%llu><P class=\"UNKNOWNCC\">\r\n",
(unsigned long long)startms);
if (ccx_options.encoding!=CCX_ENC_UNICODE)
{
dbg_print(CCX_DMT_608, "\r%s\n", str);
}
used = encode_line(context->buffer,(unsigned char *) str);
write (context->out->fh, context->buffer, used);
for (int i=0;i<15;i++)
{
if (data->row_used[i])
{
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);
}
write (context->out->fh, subline, length);
wrote_something=1;
if (i!=14)
write (context->out->fh, encoded_br, encoded_br_length);
write (context->out->fh,encoded_crlf, encoded_crlf_length);
}
}
sprintf ((char *) str,"</P></SYNC>\r\n");
if (ccx_options.encoding!=CCX_ENC_UNICODE)
{
dbg_print(CCX_DMT_608, "\r%s\n", str);
}
used = encode_line(context->buffer,(unsigned char *) str);
write (context->out->fh, context->buffer, used);
sprintf ((char *) str,
"<SYNC start=%llu><P class=\"UNKNOWNCC\">&nbsp;</P></SYNC>\r\n\r\n",
(unsigned long long)endms);
if (ccx_options.encoding!=CCX_ENC_UNICODE)
{
dbg_print(CCX_DMT_608, "\r%s\n", str);
}
used = encode_line(context->buffer,(unsigned char *) str);
write (context->out->fh, context->buffer, used);
return wrote_something;
}

View File

@@ -1,297 +0,0 @@
#include "ccextractor.h"
#include "cc_encoders_common.h"
#include "png.h"
#include "spupng_encoder.h"
#include "ocr.h"
#include "utility.h"
// Produces minimally-compliant SMPTE Timed Text (W3C TTML)
// format-compatible output
// See http://www.w3.org/TR/ttaf1-dfxp/ and
// https://www.smpte.org/sites/default/files/st2052-1-2010.pdf
// Copyright (C) 2012 John Kemp
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
void write_stringz_as_smptett(char *string, struct encoder_ctx *context, LLONG ms_start, LLONG ms_end)
{
int used;
unsigned h1,m1,s1,ms1;
unsigned h2,m2,s2,ms2;
mstotime (ms_start,&h1,&m1,&s1,&ms1);
mstotime (ms_end-1,&h2,&m2,&s2,&ms2);
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);
}
used = encode_line(context->buffer,(unsigned char *) str);
write (context->out->fh, context->buffer, used);
int len=strlen (string);
unsigned char *unescaped= (unsigned char *) malloc (len+1);
unsigned char *el = (unsigned char *) malloc (len*3+1); // Be generous
if (el==NULL || unescaped==NULL)
fatal (EXIT_NOT_ENOUGH_MEMORY, "In write_stringz_as_sami() - not enough memory.\n");
int pos_r=0;
int pos_w=0;
// Scan for \n in the string and replace it with a 0
while (pos_r<len)
{
if (string[pos_r]=='\\' && string[pos_r+1]=='n')
{
unescaped[pos_w]=0;
pos_r+=2;
}
else
{
unescaped[pos_w]=string[pos_r];
pos_r++;
}
pos_w++;
}
unescaped[pos_w]=0;
// Now read the unescaped string (now several string'z and write them)
unsigned char *begin=unescaped;
while (begin<unescaped+len)
{
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);
}
write(context->out->fh, el, u);
//write (wb->fh, encoded_br, encoded_br_length);
write(context->out->fh, encoded_crlf, encoded_crlf_length);
begin+= strlen ((const char *) begin)+1;
}
sprintf ((char *) str,"</p>\n");
if (ccx_options.encoding!=CCX_ENC_UNICODE)
{
dbg_print(CCX_DMT_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);
}
used = encode_line(context->buffer,(unsigned char *) str);
write (context->out->fh, context->buffer, used);
sprintf ((char *) str,"</p>\n");
free(el);
free(unescaped);
}
int write_cc_bitmap_as_smptett(struct cc_subtitle *sub, struct encoder_ctx *context)
{
struct spupng_t *sp = (struct spupng_t *)context->out->spupng_data;
int x_pos, y_pos, width, height, i;
int x, y, y_off, x_off, ret;
uint8_t *pbuf;
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;
LLONG ms_start, ms_end;
char timeline[128];
int len = 0;
x_pos = -1;
y_pos = -1;
width = 0;
height = 0;
if (context->prev_start != -1 && (sub->flags & SUB_EOD_MARKER))
{
ms_start = context->prev_start + subs_delay;
ms_end = sub->start_time - 1;
}
else if ( !(sub->flags & SUB_EOD_MARKER))
{
ms_start = sub->start_time + subs_delay;
ms_end = sub->end_time - 1;
}
if(sub->nb_data == 0 )
return 0;
rect = sub->data;
for(i = 0;i < sub->nb_data;i++)
{
if(x_pos == -1)
{
x_pos = rect[i].x;
y_pos = rect[i].y;
width = rect[i].w;
height = rect[i].h;
}
else
{
if(x_pos > rect[i].x)
{
width += (x_pos - rect[i].x);
x_pos = rect[i].x;
}
if (rect[i].y < y_pos)
{
height += (y_pos - rect[i].y);
y_pos = rect[i].y;
}
if (rect[i].x + rect[i].w > x_pos + width)
{
width = rect[i].x + rect[i].w - x_pos;
}
if (rect[i].y + rect[i].h > y_pos + height)
{
height = rect[i].y + rect[i].h - y_pos;
}
}
}
if ( sub->flags & SUB_EOD_MARKER )
context->prev_start = sub->start_time;
pbuf = (uint8_t*) malloc(width * height);
memset(pbuf, 0x0, width * height);
for(i = 0;i < sub->nb_data;i++)
{
x_off = rect[i].x - x_pos;
y_off = rect[i].y - y_pos;
for (y = 0; y < rect[i].h; y++)
{
for (x = 0; x < rect[i].w; x++)
pbuf[((y + y_off) * width) + x_off + x] = rect[i].data[0][y * rect[i].w + x];
}
}
palette = (png_color*) malloc(rect[0].nb_colors * sizeof(png_color));
if(!palette)
{
ret = -1;
goto end;
}
alpha = (png_byte*) malloc(rect[0].nb_colors * sizeof(png_byte));
if(!alpha)
{
ret = -1;
goto end;
}
/* TODO do rectangle, wise one color table should not be used for all rectangle */
mapclut_paletee(palette, alpha, (uint32_t *)rect[0].data[1],rect[0].nb_colors);
quantize_map(alpha, palette, pbuf, width*height, 3, rect[0].nb_colors);
#ifdef ENABLE_OCR
str = ocr_bitmap(palette,alpha,pbuf,width,height);
if(str && str[0])
{
if (context->prev_start != -1 || !(sub->flags & SUB_EOD_MARKER))
{
mstotime (ms_start,&h1,&m1,&s1,&ms1);
mstotime (ms_end-1,&h2,&m2,&s2,&ms2); // -1 To prevent overlapping with next line.
sprintf ((char *) context->buffer,"<p begin=\"%02u:%02u:%02u,%03u\" end=\"%02u:%02u:%02u,%03u\">\n",h1,m1,s1,ms1, h2,m2,s2,ms2);
write (context->out->fh, context->buffer,strlen(context->buffer) );
len = strlen(str);
write (context->out->fh, str, len);
write (context->out->fh, encoded_crlf, encoded_crlf_length);
sprintf ((char *) str,"</p>\n");
}
}
#endif
end:
sub->nb_data = 0;
freep(&sub->data);
freep(&palette);
freep(&alpha);
return ret;
}
int write_cc_buffer_as_smptett(struct eia608_screen *data, struct encoder_ctx *context)
{
int used;
unsigned h1,m1,s1,ms1;
unsigned h2,m2,s2,ms2;
LLONG endms;
int wrote_something=0;
LLONG startms = data->start_time;
startms+=subs_delay;
if (startms<0) // Drop screens that because of subs_delay start too early
return 0;
endms = data->end_time;
endms--; // To prevent overlapping with next line.
mstotime (startms,&h1,&m1,&s1,&ms1);
mstotime (endms-1,&h2,&m2,&s2,&ms2);
sprintf ((char *) str,"<p begin=\"%02u:%02u:%02u,%03u\" end=\"%02u:%02u:%02u,%03u\">\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);
}
used = encode_line(context->buffer,(unsigned char *) str);
write (context->out->fh, context->buffer, used);
for (int i=0;i<15;i++)
{
if (data->row_used[i])
{
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);
}
write(context->out->fh, subline, length);
wrote_something=1;
write(context->out->fh, encoded_crlf, encoded_crlf_length);
}
}
sprintf ((char *) str,"</p>\n");
if (ccx_options.encoding!=CCX_ENC_UNICODE)
{
dbg_print(CCX_DMT_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);
}
used = encode_line(context->buffer,(unsigned char *) str);
//write (wb->fh, enc_buffer,enc_buffer_used);
return wrote_something;
}

View File

@@ -1,279 +0,0 @@
#include <assert.h>
#include <sys/stat.h>
#include "608_spupng.h"
void
draw_row(struct eia608_screen* data, int row, uint8_t * canvas, int rowstride)
{
int column;
int unicode = 0;
uint8_t pen[2];
uint8_t* cell;
int first = -1;
int last = 0;
pen[0] = COL_BLACK;
for (column = 0; column < COLUMNS ; column++) {
if (COL_TRANSPARENT != data->colors[row][column])
{
cell = canvas + ((column+1) * CCW);
get_char_in_unicode((unsigned char*)&unicode, data->characters[row][column]);
pen[1] = data->colors[row][column];
int attr = data->fonts[row][column];
draw_char_indexed(cell, rowstride, pen, unicode, (attr & FONT_ITALICS) != 0, (attr & FONT_UNDERLINED) != 0);
if (first < 0)
{
// draw a printable space before the first non-space char
first = column;
if (unicode != 0x20)
{
cell = canvas + ((first) * CCW);
draw_char_indexed(cell, rowstride, pen, 0x20, 0, 0);
}
}
last = column;
}
}
// draw a printable space after the last non-space char
// unicode should still contain the last character
// check whether it is a space
if (unicode != 0x20)
{
cell = canvas + ((last+2) * CCW);
draw_char_indexed(cell, rowstride, pen, 0x20, 0, 0);
}
}
static png_color palette[10] =
{
{ 0xff, 0xff, 0xff }, // COL_WHITE = 0,
{ 0x00, 0xff, 0x00 }, // COL_GREEN = 1,
{ 0x00, 0x00, 0xff }, // COL_BLUE = 2,
{ 0x00, 0xff, 0xff }, // COL_CYAN = 3,
{ 0xff, 0x00, 0x00 }, // COL_RED = 4,
{ 0xff, 0xff, 0x00 }, // COL_YELLOW = 5,
{ 0xff, 0x00, 0xff }, // COL_MAGENTA = 6,
{ 0xff, 0xff, 0xff }, // COL_USERDEFINED = 7,
{ 0x00, 0x00, 0x00 }, // COL_BLACK = 8
{ 0x00, 0x00, 0x00 } // COL_TRANSPARENT = 9
};
static png_byte alpha[10] =
{
255,
255,
255,
255,
255,
255,
255,
255,
255,
0
};
int
spupng_write_png(struct spupng_t *sp, struct eia608_screen* data,
png_structp png_ptr, png_infop info_ptr,
png_bytep image,
png_bytep* row_pointer,
unsigned int ww, unsigned int wh)
{
unsigned int i;
if (setjmp(png_jmpbuf(png_ptr)))
return 0;
png_init_io (png_ptr, sp->fppng);
png_set_IHDR (png_ptr,
info_ptr,
ww,
wh,
/* bit_depth */ 8,
PNG_COLOR_TYPE_PALETTE,
PNG_INTERLACE_NONE,
PNG_COMPRESSION_TYPE_DEFAULT,
PNG_FILTER_TYPE_DEFAULT);
png_set_PLTE (png_ptr, info_ptr, palette, sizeof(palette) / sizeof(palette[0]));
png_set_tRNS (png_ptr, info_ptr, alpha, sizeof(alpha) / sizeof(alpha[0]), NULL);
png_set_gAMA (png_ptr, info_ptr, 1.0 / 2.2);
png_write_info (png_ptr, info_ptr);
for (i = 0; i < wh; i++)
row_pointer[i] = image + i * ww;
png_write_image (png_ptr, row_pointer);
png_write_end (png_ptr, info_ptr);
return 1;
}
int
spupng_export_png(struct spupng_t *sp, struct eia608_screen* data)
{
png_structp png_ptr;
png_infop info_ptr;
png_bytep *row_pointer;
png_bytep image;
int ww, wh, rowstride, row_adv;
int row;
assert ((sizeof(png_byte) == sizeof(uint8_t))
&& (sizeof(*image) == sizeof(uint8_t)));
// Allow space at beginning and end of each row for a padding space
ww = CCW * (COLUMNS+2);
wh = CCH * ROWS;
row_adv = (COLUMNS+2) * CCW * CCH;
rowstride = ww * sizeof(*image);
if (!(row_pointer = (png_bytep*)malloc(sizeof(*row_pointer) * wh))) {
mprint("Unable to allocate %d byte buffer.\n",
sizeof(*row_pointer) * wh);
return 0;
}
if (!(image = (png_bytep)malloc(wh * ww * sizeof(*image)))) {
mprint("Unable to allocate %d KB image buffer.",
wh * ww * sizeof(*image) / 1024);
free(row_pointer);
return 0;
}
// Initialize image to transparent
memset(image, COL_TRANSPARENT, wh * ww * sizeof(*image));
/* draw the image */
for (row = 0; row < ROWS; row++) {
if (data->row_used[row])
draw_row(data, row, image + row * row_adv, rowstride);
}
/* Now save the image */
if (!(png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,
NULL, NULL, NULL)))
goto unknown_error;
if (!(info_ptr = png_create_info_struct(png_ptr))) {
png_destroy_write_struct(&png_ptr, (png_infopp) NULL);
goto unknown_error;
}
if (!spupng_write_png (sp, data, png_ptr, info_ptr, image, row_pointer, ww, wh)) {
png_destroy_write_struct (&png_ptr, &info_ptr);
goto write_error;
}
png_destroy_write_struct (&png_ptr, &info_ptr);
free (row_pointer);
free (image);
return 1;
write_error:
unknown_error:
free (row_pointer);
free (image);
return 0;
}
int
spupng_write_ccbuffer(struct spupng_t *sp, struct eia608_screen* data,
struct encoder_ctx *context)
{
LLONG ms_start = data->start_time + subs_delay;
if (ms_start < 0)
{
dbg_print(CCX_DMT_VERBOSE, "Negative start\n");
return 0;
}
int row;
int empty_buf = 1;
char str[256] = "";
for (row = 0; row < 15; row++)
{
if (data->row_used[row])
{
empty_buf = 0;
break;
}
}
if (empty_buf)
{
dbg_print(CCX_DMT_VERBOSE, "Blank page\n");
return 0;
}
LLONG ms_end = data->end_time;
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",
sp->pngfile, strerror(errno));
}
if (!spupng_export_png(sp, data))
{
fatal(EXIT_FILE_CREATION_FAILED, "Cannot write %s: %s\n",
sp->pngfile, strerror(errno));
}
fclose(sp->fppng);
write_sputag(sp,ms_start,ms_end);
for (row = 0; row < ROWS; row++)
{
if (data->row_used[row])
{
int len = get_decoder_line_encoded(subline, row, data);
// Check for characters that spumux won't parse
// null chars will be changed to space
// pairs of dashes will be changed to underscores
for (unsigned char* ptr = subline; ptr < subline+len; ptr++)
{
switch (*ptr)
{
case 0:
*ptr = ' ';
break;
case '-':
if (*(ptr+1) == '-')
{
*ptr++ = '_';
*ptr = '_';
}
break;
}
}
strncat(str,(const char*)subline,256);
strncat(str,"\n",256);
}
}
write_spucomment(sp,str);
return 1;
}
int write_cc_buffer_as_spupng(struct eia608_screen *data,struct encoder_ctx *context)
{
if (0 != context->out->spupng_data)
{
struct spupng_t *sp = (struct spupng_t *) context->out->spupng_data;
return spupng_write_ccbuffer(sp, data, context);
}
return 0;
}

1242
src/708.c

File diff suppressed because it is too large Load Diff

292
src/708.h
View File

@@ -1,292 +0,0 @@
#ifndef _INCLUDE_708_
#define _INCLUDE_708_
#define MAX_708_PACKET_LENGTH 128
#define I708_MAX_ROWS 15
#define I708_MAX_COLUMNS 42
#define I708_SCREENGRID_ROWS 75
#define I708_SCREENGRID_COLUMNS 210
#define I708_MAX_WINDOWS 8
enum COMMANDS_C0_CODES
{
NUL=0,
ETX=3,
BS=8,
FF=0xC,
CR=0xD,
HCR=0xE,
EXT1=0x10,
P16=0x18
};
enum COMMANDS_C1_CODES
{
CW0=0x80,
CW1=0x81,
CW2=0x82,
CW3=0x83,
CW4=0x84,
CW5=0x85,
CW6=0x86,
CW7=0x87,
CLW=0x88,
DSW=0x89,
HDW=0x8A,
TGW=0x8B,
DLW=0x8C,
DLY=0x8D,
DLC=0x8E,
RST=0x8F,
SPA=0x90,
SPC=0x91,
SPL=0x92,
RSV93=0x93,
RSV94=0x94,
RSV95=0x95,
RSV96=0x96,
SWA=0x97,
DF0=0x98,
DF1=0x99,
DF2=0x9A,
DF3=0x9B,
DF4=0x9C,
DF5=0x9D,
DF6=0x9E,
DF7=0x9F
};
struct S_COMMANDS_C1
{
int code;
const char *name;
const char *description;
int length;
};
enum eWindowsAttribJustify
{
left=0,
right=1,
center=2,
full=3
};
enum eWindowsAttribPrintDirection
{
pd_left_to_right=0,
pd_right_to_left=1,
pd_top_to_bottom=2,
pd_bottom_to_top=3
};
enum eWindowsAttribScrollDirection
{
sd_left_to_right=0,
sd_right_to_left=1,
sd_top_to_bottom=2,
sd_bottom_to_top=3
};
enum eWindowsAttribScrollDisplayEffect
{
snap=0,
fade=1,
wipe=2
};
enum eWindowsAttribEffectDirection
{
left_to_right=0,
right_to_left=1,
top_to_bottom=2,
bottom_to_top=3
};
enum eWindowsAttribFillOpacity
{
solid=0,
flash=1,
traslucent=2,
transparent=3
};
enum eWindowsAttribBorderType
{
none=0,
raised=1,
depressed=2,
uniform=3,
shadow_left=4,
shadow_right=5
};
enum ePenAttribSize
{
pensize_small=0,
pensize_standard=1,
pensize_large=2
};
enum ePenAttribFontStyle
{
fontstyle_default_or_undefined=0,
monospaced_with_serifs=1,
proportionally_spaced_with_serifs=2,
monospaced_without_serifs=3,
proportionally_spaced_without_serifs=4,
casual_font_type=5,
cursive_font_type=6,
small_capitals=7
};
enum ePanAttribTextTag
{
texttag_dialog=0,
texttag_source_or_speaker_id=1,
texttag_electronic_voice=2,
texttag_foreign_language=3,
texttag_voiceover=4,
texttag_audible_translation=5,
texttag_subtitle_translation=6,
texttag_voice_quality_description=7,
texttag_song_lyrics=8,
texttag_sound_effect_description=9,
texttag_musical_score_description=10,
texttag_expletitive=11,
texttag_undefined_12=12,
texttag_undefined_13=13,
texttag_undefined_14=14,
texttag_not_to_be_displayed=15
};
enum ePanAttribOffset
{
offset_subscript=0,
offset_normal=1,
offset_superscript=2
};
enum ePanAttribEdgeType
{
edgetype_none=0,
edgetype_raised=1,
edgetype_depressed=2,
edgetype_uniform=3,
edgetype_left_drop_shadow=4,
edgetype_right_drop_shadow=5
};
enum eAnchorPoints
{
anchorpoint_top_left = 0,
anchorpoint_top_center = 1,
anchorpoint_top_right =2,
anchorpoint_middle_left = 3,
anchorpoint_middle_center = 4,
anchorpoint_middle_right = 5,
anchorpoint_bottom_left = 6,
anchorpoint_bottom_center = 7,
anchorpoint_bottom_right = 8
};
typedef struct e708Pen_color
{
int fg_color;
int fg_opacity;
int bg_color;
int bg_opacity;
int edge_color;
} e708Pen_color;
typedef struct e708Pen_attribs
{
int pen_size;
int offset;
int text_tag;
int font_tag;
int edge_type;
int underline;
int italic;
} e708Pen_attribs;
typedef struct e708Window_attribs
{
int fill_color;
int fill_opacity;
int border_color;
int border_type01;
int justify;
int scroll_dir;
int print_dir;
int word_wrap;
int border_type;
int display_eff;
int effect_dir;
int effect_speed;
} e708Window_attribs;
typedef struct e708Window
{
int is_defined;
int number; // Handy, in case we only have a pointer to the window
int priority;
int col_lock;
int row_lock;
int visible;
int anchor_vertical;
int relative_pos;
int anchor_horizontal;
int row_count;
int anchor_point;
int col_count;
int pen_style;
int win_style;
unsigned char commands[6]; // Commands used to create this window
e708Window_attribs attribs;
e708Pen_attribs pen;
e708Pen_color pen_color;
int pen_row;
int pen_column;
unsigned char *rows[I708_MAX_ROWS+1]; // Max is 15, but we define an extra one for convenience
int memory_reserved;
int is_empty;
} e708Window;
typedef struct tvscreen
{
unsigned char chars[I708_SCREENGRID_ROWS][I708_SCREENGRID_COLUMNS+1];
}
tvscreen;
typedef struct cc708_service_decoder
{
e708Window windows[I708_MAX_WINDOWS];
int current_window;
int inited;
LLONG current_visible_start_ms;
tvscreen tv1, tv2; // Current and previous "screenfuls", note that we switch between them
int is_empty_tv1, is_empty_tv2;
int cur_tv; // 1 or 2 rather than 0 or 1, to at least be consistent with the decoder
tvscreen *tv; // Pointer to the current TV buffer
char *filename; // Where we are going to write our output
int fh; // Handle to output file. -1 if not yet open
int srt_counter;
}
cc708_service_decoder;
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);
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

View File

@@ -1,45 +0,0 @@
/********************************************************
256 BYTES IS ENOUGH FOR ALL THE SUPPORTED CHARACTERS IN
EIA-708, SO INTERNALLY WE USE THIS TABLE (FOR CONVENIENCE)
00-1F -> Characters that are in the G2 group in 20-3F,
except for 06, which is used for the closed captions
sign "CC" which is defined in group G3 as 00. (this
is by the article 33).
20-7F -> Group G0 as is - corresponds to the ASCII code
80-9F -> Characters that are in the G2 group in 60-7F
(there are several blank characters here, that's OK)
A0-FF -> Group G1 as is - non-English characters and symbols
*/
unsigned char get_internal_from_G0 (unsigned char g0_char)
{
return g0_char;
}
unsigned char get_internal_from_G1 (unsigned char g1_char)
{
return g1_char;
}
// TODO: Probably not right
// G2: Extended Control Code Set 1
unsigned char get_internal_from_G2 (unsigned char g2_char)
{
if (g2_char>=0x20 && g2_char<=0x3F)
return g2_char-0x20;
if (g2_char>=0x60 && g2_char<=0x7F)
return g2_char+0x20;
// Rest unmapped, so we return a blank space
return 0x20;
}
// TODO: Probably not right
// G3: Future Characters and Icon Expansion
unsigned char get_internal_from_G3 (unsigned char g3_char)
{
if (g3_char==0xa0) // The "CC" (closed captions) sign
return 0x06;
// Rest unmapped, so we return a blank space
return 0x20;
}

View File

@@ -0,0 +1,6 @@
/**
* the configured options and settings for CCExtractor
*/
#define CCExtractor_VERSION_MAJOR @CCEXTRACTOR_VERSION_MAJOR@
#define CCExtractor_VERSION_MINOR @CCEXTRACTOR_VERSION_MINOR@

88
src/CMakeLists.txt Normal file
View File

@@ -0,0 +1,88 @@
cmake_minimum_required (VERSION 3.0.2)
project (CCExtractor)
option (WITH_FFMPEG "Build using FFmpeg demuxer and decoder" OFF)
option (WITH_OCR "Build with OCR (Optical Character Recognition) feature" OFF)
#Version number
set (CCEXTRACTOR_VERSION_MAJOR 0)
set (CCEXTRACTOR_VERSION_MINOR 77)
# configure a header file to pass some of the CMake settings
# to the source code
configure_file (
"${PROJECT_SOURCE_DIR}/CCExtractorConfig.h.in"
"${PROJECT_BINARY_DIR}/CCExtractorConfig.h"
)
include_directories ("${PROJECT_SOURCE_DIR}")
include_directories ("${PROJECT_SOURCE_DIR}/lib_ccx")
include_directories ("${PROJECT_SOURCE_DIR}/gpacmp4/")
#Adding some platform specific library path
link_directories (/opt/local/lib)
link_directories (/usr/local/lib)
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O0 -Wall -g -std=gnu99 -Wno-write-strings -D_FILE_OFFSET_BITS=64")
add_subdirectory (lib_ccx)
aux_source_directory (${PROJECT_SOURCE_DIR} SOURCEFILE)
set (EXTRA_LIBS ${EXTRA_LIBS} ccx)
set (EXTRA_LIBS ${EXTRA_LIBS} m)
IF(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
set (EXTRA_LIBS ${EXTRA_LIBS} iconv)
ENDIF(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
find_package (PkgConfig)
if(PKG_CONFIG_FOUND)
pkg_check_modules(PNG libpng )
if(PNG_FOUND)
set (EXTRA_LIBS ${EXTRA_LIBS} png)
else (PNG_FOUND)
include_directories ("${PROJECT_SOURCE_DIR}/libpng/")
aux_source_directory ("${PROJECT_SOURCE_DIR}/libpng/" SOURCEFILE)
aux_source_directory ("${PROJECT_SOURCE_DIR}/zlib/" SOURCEFILE)
endif(PNG_FOUND)
endif (PKG_CONFIG_FOUND)
########################################################
# Build using FFmpeg libraries
########################################################
if (PKG_CONFIG_FOUND AND WITH_FFMPEG)
pkg_check_modules (AVFORMAT REQUIRED libavformat)
pkg_check_modules (AVUTIL REQUIRED libavutil)
pkg_check_modules (AVCODEC REQUIRED libavcodec)
set (EXTRA_LIBS ${EXTRA_LIBS} ${AVFORMAT_STATIC_LIBRARIES})
set (EXTRA_LIBS ${EXTRA_LIBS} ${AVUTIL_STATIC_LIBRARIES})
set (EXTRA_LIBS ${EXTRA_LIBS} ${AVCODEC_STATIC_LIBRARIES})
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DENABLE_FFMPEG")
endif (PKG_CONFIG_FOUND AND WITH_FFMPEG)
########################################################
# Build with OCR using leptonica and tesseract libraries
########################################################
if (WITH_OCR)
find_package(PkgConfig)
pkg_check_modules (TESSERACT REQUIRED tesseract)
pkg_check_modules (LEPTONICA REQUIRED lept)
set (EXTRA_LIBS ${EXTRA_LIBS} ${TESSERACT_STATIC_LIBRARIES})
set (EXTRA_LIBS ${EXTRA_LIBS} ${LEPTONICA_STATIC_LIBRARIES})
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DENABLE_OCR ${TESSERACT_CFLAGS} ${LEPTONICA_CFLAGS}")
endif (WITH_OCR)
add_executable (ccextractor ${SOURCEFILE})
target_link_libraries (ccextractor ${EXTRA_LIBS})
install (TARGETS ccextractor DESTINATION bin)

View File

@@ -1,147 +0,0 @@
/* This file contains functions that report the user of the GUI of
relevant events. */
#include "ccextractor.h"
static int credits_shown=0;
unsigned long net_activity_gui=0;
/* Print current progress. For percentaje, -1 -> streaming mode */
void activity_progress (int percentaje, int cur_min, int cur_sec)
{
if (!ccx_options.no_progress_bar)
{
if (percentaje==-1)
mprint ("\rStreaming | %02d:%02d", cur_min, cur_sec);
else
mprint ("\r%3d%% | %02d:%02d",percentaje, cur_min, cur_sec);
}
fflush (stdout);
if (ccx_options.gui_mode_reports)
{
fprintf (stderr, "###PROGRESS#%d#%d#%d\n", percentaje, cur_min, cur_sec);
fflush (stderr);
}
}
void activity_input_file_open (const char *filename)
{
if (ccx_options.gui_mode_reports)
{
fprintf (stderr, "###INPUTFILEOPEN#%s\n", filename);
fflush (stderr);
}
}
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_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)
{
if (ccx_options.gui_mode_reports)
{
fprintf (stderr, "###VIDEOINFO#%u#%u#%s#%s\n",
hor_size,vert_size, aspect_ratio, framerate);
fflush (stderr);
}
}
void activity_message (const char *fmt, ...)
{
if (ccx_options.gui_mode_reports)
{
va_list args;
fprintf (stderr, "###MESSAGE#");
va_start(args, fmt);
fprintf(stderr, fmt, args);
fprintf(stderr, "\n");
va_end(args);
fflush (stderr);
}
}
void activity_input_file_closed (void)
{
if (ccx_options.gui_mode_reports)
{
fprintf (stderr, "###INPUTFILECLOSED\n");
fflush (stderr);
}
}
void activity_program_number (unsigned program_number)
{
if (ccx_options.gui_mode_reports)
{
fprintf (stderr, "###TSPROGRAMNUMBER#%u\n",program_number);
fflush (stderr);
}
}
void activity_report_version (void)
{
if (ccx_options.gui_mode_reports)
{
fprintf (stderr, "###VERSION#CCExtractor#%s\n",VERSION);
fflush (stderr);
}
}
void activity_report_data_read (void)
{
if (ccx_options.gui_mode_reports)
{
fprintf (stderr, "###DATAREAD#%lu\n",net_activity_gui/1000);
fflush (stderr);
}
}
void activity_header (void)
{
if (!credits_shown)
{
credits_shown=1;
mprint ("CCExtractor %s, Carlos Fernandez Sanz, Volker Quetschke.\n", VERSION);
mprint ("Teletext portions taken from Petr Kutalek's telxcc\n");
mprint ("--------------------------------------------------------------------------\n");
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,375 +0,0 @@
#include "ccextractor.h"
// Hold functions to read streams on a bit or byte oriented basis
// plus some data related helper functions.
// Guidelines for all bitsream functions:
// * No function shall advance the pointer past the end marker
// * If bitstream.bitsleft < 0 do not attempt any read access,
// but decrease bitsleft by the number of bits that were
// attempted to read.
// Initialize bitstream
int init_bitstream(struct bitstream *bstr, unsigned char *start, unsigned char *end)
{
bstr->pos = start;
bstr->bpos = 8;
bstr->end = end;
bstr->bitsleft = (bstr->end - bstr->pos)*8;
bstr->error = 0;
bstr->_i_pos = NULL;
bstr->_i_bpos = 0;
if(bstr->bitsleft < 0)
{
// See if we can somehow recover of this disaster by reporting the problem instead of terminating.
mprint ( "init_bitstream: bitstream has negative length!");
return 1;
}
return 0;
}
// Read bnum bits from bitstream bstr with the most significant
// bit read first without advancing the bitstream pointer.
// A 64 bit unsigned integer is returned. 0 is returned when
// there are not enough bits left in the bitstream.
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);
// Sanity check
if(bstr->end - bstr->pos < 0)
fatal(EXIT_BUG_BUG, "next_bits: bitstream has negative length!");
// Keep a negative bitstream.bitsleft, but correct it.
if (bstr->bitsleft <= 0)
{
bstr->bitsleft -= bnum;
return 0;
}
// Calculate the remaining number of bits in bitstream after reading.
bstr->bitsleft = 0LL + (bstr->end - bstr->pos - 1)*8 + bstr->bpos - bnum;
if (bstr->bitsleft < 0)
return 0;
// Special case for reading zero bits. Return zero
if(bnum == 0)
return 0;
int vbit = bstr->bpos;
unsigned char *vpos = bstr->pos;
if(vbit < 1 || vbit > 8)
{
fatal(EXIT_BUG_BUG, "next_bits: Illegal bit position value %d!", vbit);
}
while( 1 )
{
if(vpos >= bstr->end)
{
// We should not get here ...
fatal(EXIT_BUG_BUG, "next_bits: Reading after end of data ...");
}
res |= (*vpos & (0x01 << (vbit-1)) ? 1 : 0);
vbit--;
bnum--;
if(vbit == 0)
{
vpos++;
vbit = 8;
}
if(bnum)
{
res <<= 1;
}
else
break;
}
// Remember the bitstream position
bstr->_i_bpos = vbit;
bstr->_i_pos = vpos;
return res;
}
// Read bnum bits from bitstream bstr with the most significant
// bit read first. A 64 bit unsigned integer is returned.
uint64_t read_bits(struct bitstream *bstr, unsigned bnum)
{
uint64_t res = next_bits(bstr, bnum);
// Special case for reading zero bits. Also abort when not enough
// bits are left. Return zero
if(bnum == 0 || bstr->bitsleft < 0)
return 0;
// Advance the bitstream
bstr->bpos = bstr->_i_bpos;
bstr->pos = bstr->_i_pos;
return res;
}
// This function will advance the bitstream by bnum bits, if possible.
// Advancing of more than 64 bits is possible.
// Return TRUE when successfull, otherwise FALSE
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!");
// Keep a negative bstr->bitsleft, but correct it.
if (bstr->bitsleft < 0)
{
bstr->bitsleft -= bnum;
return 0;
}
// Calculate the remaining number of bits in bitstream after reading.
bstr->bitsleft = 0LL + (bstr->end - bstr->pos - 1)*8 + bstr->bpos - bnum;
if (bstr->bitsleft < 0)
return 0;
// Special case for reading zero bits. Return zero
if(bnum == 0)
return 1;
bstr->bpos -= bnum%8;
bstr->pos += bnum/8;
if (bstr->bpos < 1)
{
bstr->bpos += 8;
bstr->pos += 1;
}
return 1;
}
// Return TRUE if the current position in the bitstream is on a byte
// boundary, i.e., the next bit in the bitstream is the first bit in
// a byte, otherwise return FALSE
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!");
int vbit = bstr->bpos;
if(vbit == 0 || vbit > 8)
{
fatal(EXIT_BUG_BUG, "is_byte_aligned: Illegal bit position value %d!\n", vbit);
}
if (vbit == 8)
return 1;
else
return 0;
}
// Move bitstream to next byte border. Adjust bitsleft.
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!");
int vbit = bstr->bpos;
if(vbit == 0 || vbit > 8)
{
fatal(EXIT_BUG_BUG, "make_byte_aligned: Illegal bit position value %d!\n", vbit);
}
// Keep a negative bstr->bitsleft, but correct it.
if (bstr->bitsleft < 0)
{
// Pay attention to the bit alignment
bstr->bitsleft = (bstr->bitsleft-7)/8 *8;
return;
}
if(bstr->bpos != 8)
{
bstr->bpos = 8;
bstr->pos += 1;
}
// Reset, in case a next_???() function was used before
bstr->bitsleft = 0LL + 8*(bstr->end-bstr->pos-1)+bstr->bpos;
return;
}
// Return pointer to first of bynum bytes from the bitstream if the
// following conditions are TRUE:
// The bitstream is byte aligned and there are enough bytes left in
// it to read bynum bytes. Otherwise return NULL.
// This function does not advance the bitstream pointer.
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!");
// Keep a negative bstr->bitsleft, but correct it.
if (bstr->bitsleft < 0)
{
bstr->bitsleft -= bynum*8;
return NULL;
}
bstr->bitsleft = 0LL + (bstr->end - bstr->pos - 1)*8 + bstr->bpos - bynum*8;
if (!is_byte_aligned(bstr) || bstr->bitsleft < 0 || bynum < 1)
return NULL;
// Remember the bitstream position
bstr->_i_bpos = 8;
bstr->_i_pos = bstr->pos + bynum;
return bstr->pos;
}
// Return pointer to first of bynum bytes from the bitstream if the
// following conditions are TRUE:
// The bitstream is byte aligned and there are enough bytes left in
// it to read bynum bytes. Otherwise return NULL.
// This function does advance the bitstream pointer.
unsigned char *read_bytes(struct bitstream *bstr, unsigned bynum)
{
unsigned char *res = next_bytes(bstr, bynum);
// Advance the bitstream when a read was possible
if(res)
{
bstr->bpos = bstr->_i_bpos;
bstr->pos = bstr->_i_pos;
}
return res;
}
// Return an integer number with "bytes" precision from the current
// bitstream position. Allowed "bytes" values are 1,2,4,8.
// This function does advance the bitstream pointer when "advance" is
// set to TRUE.
// Numbers come MSB (most significant first), and we need to account for
// little-endian and big-endian CPUs.
uint64_t bitstream_get_num(struct bitstream *bstr, unsigned bytes, int advance)
{
void *bpos;
uint64_t rval=0;
if (advance)
bpos = read_bytes(bstr, bytes);
else
bpos = next_bytes(bstr, bytes);
if (!bpos)
return 0;
switch (bytes)
{
case 1:
case 2:
case 4:
case 8:
break;
default:
fatal (EXIT_BUG_BUG, "bitstream_get_num: Illegal precision value [%u]!",
bytes);
break;
}
for (unsigned i=0;i<bytes;i++)
{
unsigned char *ucpos=((unsigned char *)bpos) +bytes-i-1; // Read backwards
unsigned char uc=*ucpos;
rval=(rval<<8) + uc;
}
return rval;
}
// Read unsigned Exp-Golomb code from bitstream
uint64_t ue(struct bitstream *bstr)
{
uint64_t res = 0;
int zeros=0;
while(!read_bits(bstr,1))
zeros++;
res = (0x01 << zeros) - 1 + read_bits(bstr,zeros);
return res;
}
// Read signed Exp-Golomb code from bitstream
int64_t se(struct bitstream *bstr)
{
int64_t res = 0;
res = ue(bstr);
// The following function might truncate when res+1 overflows
//res = (res+1)/2 * (res % 2 ? 1 : -1);
// Use this:
res = (res/2+(res%2 ? 1 : 0)) * (res % 2 ? 1 : -1);
return res;
}
// Read unsigned integer with bnum bits length. Basically an
// alias for read_bits().
uint64_t u(struct bitstream *bstr, unsigned bnum)
{
return read_bits(bstr, bnum);
}
// Read signed integer with bnum bits length.
int64_t i(struct bitstream *bstr, unsigned bnum)
{
uint64_t res = read_bits(bstr, bnum);
// Special case for reading zero bits. Return zero
if(bnum == 0)
return 0;
return (0xFFFFFFFFFFFFFFFFULL << bnum) | res;
}
// Return the value with the bit order reversed.
uint8_t reverse8(uint8_t data)
{
uint8_t res = 0;
for (int k=0;k<8;k++)
{
res <<= 1;
res |= (data & (0x01 << k) ? 1 : 0);
}
return res;
}

View File

@@ -1,25 +0,0 @@
/* Functions used by both the 608 and 708 decoders. An effort should be
made to reuse, not duplicate, as many functions as possible */
#include "ccextractor.h"
/* This function returns a FTS that is guaranteed to be at least 1 ms later than the end of the previous screen. It shouldn't be needed
obviously but it guarantees there's no timing overlap */
LLONG get_visible_start (void)
{
LLONG fts = get_fts();
if (fts <= minimum_fts)
fts = minimum_fts+1;
dbg_print(CCX_DMT_608, "Visible Start time=%s\n", print_mstime(fts));
return fts;
}
/* This function returns the current FTS and saves it so it can be used by get_visible_start */
LLONG get_visible_end (void)
{
LLONG fts = get_fts();
if (fts>minimum_fts)
minimum_fts=fts;
dbg_print(CCX_DMT_608, "Visible End time=%s\n", print_mstime(fts));
return fts;
}

View File

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

View File

@@ -1,594 +0,0 @@
#include "ccextractor.h"
#include "cc_decoders_common.h"
#include "cc_encoders_common.h"
#include "spupng_encoder.h"
#include "608_spupng.h"
#include "utility.h"
#include "xds.h"
#include "ocr.h"
static const char *sami_header= // TODO: Revise the <!-- comments
"<SAMI>\n\
<HEAD>\n\
<STYLE TYPE=\"text/css\">\n\
<!--\n\
P {margin-left: 16pt; margin-right: 16pt; margin-bottom: 16pt; margin-top: 16pt;\n\
text-align: center; font-size: 18pt; font-family: arial; font-weight: bold; color: #f0f0f0;}\n\
.UNKNOWNCC {Name:Unknown; lang:en-US; SAMIType:CC;}\n\
-->\n\
</STYLE>\n\
</HEAD>\n\n\
<BODY>\n";
static const char *smptett_header =
"<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n\
<tt xmlns=\"http://www.w3.org/ns/ttml\" xml:lang=\"en\">\n\
<body>\n<div>\n" ;
void write_subtitle_file_footer(struct encoder_ctx *ctx,struct ccx_s_write *out)
{
int used;
switch (ccx_options.write_format)
{
case CCX_OF_SAMI:
sprintf ((char *) str,"</BODY></SAMI>\n");
if (ccx_options.encoding!=CCX_ENC_UNICODE)
{
dbg_print(CCX_DMT_608, "\r%s\n", str);
}
used=encode_line (ctx->buffer,(unsigned char *) str);
write(out->fh, ctx->buffer, used);
break;
case CCX_OF_SMPTETT:
sprintf ((char *) str,"</div></body></tt>\n");
if (ccx_options.encoding!=CCX_ENC_UNICODE)
{
dbg_print(CCX_DMT_608, "\r%s\n", str);
}
used=encode_line (ctx->buffer,(unsigned char *) str);
write (out->fh, ctx->buffer,used);
break;
case CCX_OF_SPUPNG:
write_spumux_footer(out);
break;
default: // Nothing to do, no footer on this format
break;
}
}
void write_subtitle_file_header(struct encoder_ctx *ctx,struct ccx_s_write *out)
{
int used;
switch (ccx_options.write_format)
{
case CCX_OF_SRT: // Subrip subtitles have no header
break;
case CCX_OF_SAMI: // This header brought to you by McPoodle's CCASDI
//fprintf_encoded (wb->fh, sami_header);
REQUEST_BUFFER_CAPACITY(ctx,strlen (sami_header)*3);
used=encode_line (ctx->buffer,(unsigned char *) sami_header);
write (out->fh, ctx->buffer,used);
break;
case CCX_OF_SMPTETT: // This header brought to you by McPoodle's CCASDI
//fprintf_encoded (wb->fh, sami_header);
REQUEST_BUFFER_CAPACITY(ctx,strlen (smptett_header)*3);
used=encode_line (ctx->buffer,(unsigned char *) smptett_header);
write(out->fh, ctx->buffer, used);
break;
case CCX_OF_RCWT: // Write header
write(out->fh, rcwt_header, sizeof(rcwt_header));
if (ccx_options.send_to_srv)
net_send_header(rcwt_header, sizeof(rcwt_header));
break;
case CCX_OF_SPUPNG:
write_spumux_header(out);
break;
case CCX_OF_TRANSCRIPT: // No header. Fall thru
default:
break;
}
}
void write_cc_line_as_transcript2(struct eia608_screen *data, struct encoder_ctx *context, int line_number)
{
unsigned h1,m1,s1,ms1;
unsigned h2,m2,s2,ms2;
LLONG start_time = data->start_time;
LLONG end_time = data->end_time;
if (ccx_options.sentence_cap)
{
capitalize (line_number,data);
correct_case(line_number,data);
}
int length = get_decoder_line_basic (subline, line_number, data);
if (ccx_options.encoding!=CCX_ENC_UNICODE)
{
dbg_print(CCX_DMT_608, "\r");
dbg_print(CCX_DMT_608, "%s\n",subline);
}
if (length>0)
{
if (data->start_time == -1)
{
// CFS: Means that the line has characters but we don't have a timestamp for the first one. Since the timestamp
// is set for example by the write_char function, it possible that we don't have one in empty lines (unclear)
// For now, let's not consider this a bug as before and just return.
// fatal (EXIT_BUG_BUG, "Bug in timedtranscript (ts_start_of_current_line==-1). Please report.");
return;
}
if (ccx_options.transcript_settings.showStartTime){
char buf1[80];
if (ccx_options.transcript_settings.relativeTimestamp){
millis_to_date(start_time + subs_delay, buf1);
fdprintf(context->out->fh, "%s|", buf1);
}
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;
struct tm *start_time_struct = gmtime(&start_time_int);
strftime(buf1, sizeof(buf1), "%Y%m%d%H%M%S", start_time_struct);
fdprintf(context->out->fh, "%s%c%03d|", buf1,ccx_options.millis_separator,start_time_dec);
}
}
if (ccx_options.transcript_settings.showEndTime){
char buf2[80];
if (ccx_options.transcript_settings.relativeTimestamp){
millis_to_date(end_time, buf2);
fdprintf(context->out->fh, "%s|", buf2);
}
else {
mstotime(get_fts() + subs_delay, &h2, &m2, &s2, &ms2);
time_t end_time_int = end_time / 1000;
int end_time_dec = end_time % 1000;
struct tm *end_time_struct = gmtime(&end_time_int);
strftime(buf2, sizeof(buf2), "%Y%m%d%H%M%S", end_time_struct);
fdprintf(context->out->fh, "%s%c%03d|", buf2,ccx_options.millis_separator,end_time_dec);
}
}
if (ccx_options.transcript_settings.showCC){
fdprintf(context->out->fh, "CC%d|", data->my_field == 1 ? data->channel : data->channel + 2); // Data from field 2 is CC3 or 4
}
if (ccx_options.transcript_settings.showMode){
const char *mode = "???";
switch (data->mode)
{
case MODE_POPON:
mode = "POP";
break;
case MODE_FAKE_ROLLUP_1:
mode = "RU1";
break;
case MODE_ROLLUP_2:
mode = "RU2";
break;
case MODE_ROLLUP_3:
mode = "RU3";
break;
case MODE_ROLLUP_4:
mode = "RU4";
break;
case MODE_TEXT:
mode = "TXT";
break;
case MODE_PAINTON:
mode = "PAI";
break;
}
fdprintf(context->out->fh, "%s|", mode);
}
write(context->out->fh, subline, length);
write(context->out->fh, encoded_crlf, encoded_crlf_length);
}
// fprintf (wb->fh,encoded_crlf);
}
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");
for (int i=0;i<15;i++)
{
if (data->row_used[i])
{
write_cc_line_as_transcript2 (data, context, i);
}
wrote_something=1;
}
dbg_print(CCX_DMT_608, "- - - - - - - - - - - -\r\n");
return wrote_something;
}
int write_cc_bitmap_as_transcript(struct cc_subtitle *sub, struct encoder_ctx *context)
{
struct spupng_t *sp = (struct spupng_t *)context->out->spupng_data;
int x_pos, y_pos, width, height, i;
int x, y, y_off, x_off, ret;
uint8_t *pbuf;
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;
LLONG start_time, end_time;
char timeline[128];
int len = 0;
x_pos = -1;
y_pos = -1;
width = 0;
height = 0;
if (context->prev_start != -1 && (sub->flags & SUB_EOD_MARKER))
{
start_time = context->prev_start + subs_delay;
end_time = sub->start_time - 1;
}
else if ( !(sub->flags & SUB_EOD_MARKER))
{
start_time = sub->start_time + subs_delay;
end_time = sub->end_time - 1;
}
if(sub->nb_data == 0 )
return 0;
rect = sub->data;
for(i = 0;i < sub->nb_data;i++)
{
if(x_pos == -1)
{
x_pos = rect[i].x;
y_pos = rect[i].y;
width = rect[i].w;
height = rect[i].h;
}
else
{
if(x_pos > rect[i].x)
{
width += (x_pos - rect[i].x);
x_pos = rect[i].x;
}
if (rect[i].y < y_pos)
{
height += (y_pos - rect[i].y);
y_pos = rect[i].y;
}
if (rect[i].x + rect[i].w > x_pos + width)
{
width = rect[i].x + rect[i].w - x_pos;
}
if (rect[i].y + rect[i].h > y_pos + height)
{
height = rect[i].y + rect[i].h - y_pos;
}
}
}
if ( sub->flags & SUB_EOD_MARKER )
context->prev_start = sub->start_time;
pbuf = (uint8_t*) malloc(width * height);
memset(pbuf, 0x0, width * height);
for(i = 0;i < sub->nb_data;i++)
{
x_off = rect[i].x - x_pos;
y_off = rect[i].y - y_pos;
for (y = 0; y < rect[i].h; y++)
{
for (x = 0; x < rect[i].w; x++)
pbuf[((y + y_off) * width) + x_off + x] = rect[i].data[0][y * rect[i].w + x];
}
}
palette = (png_color*) malloc(rect[0].nb_colors * sizeof(png_color));
if(!palette)
{
ret = -1;
goto end;
}
alpha = (png_byte*) malloc(rect[0].nb_colors * sizeof(png_byte));
if(!alpha)
{
ret = -1;
goto end;
}
/* TODO do rectangle, wise one color table should not be used for all rectangle */
mapclut_paletee(palette, alpha, (uint32_t *)rect[0].data[1],rect[0].nb_colors);
quantize_map(alpha, palette, pbuf, width*height, 3, rect[0].nb_colors);
#ifdef ENABLE_OCR
str = ocr_bitmap(palette,alpha,pbuf,width,height);
if(str && str[0])
{
if (context->prev_start != -1 || !(sub->flags & SUB_EOD_MARKER))
{
char *token = NULL;
token = strtok(str,"\r\n");
while (token)
{
if (ccx_options.transcript_settings.showStartTime)
{
char buf1[80];
if (ccx_options.transcript_settings.relativeTimestamp)
{
millis_to_date(start_time + subs_delay, buf1);
fdprintf(context->out->fh, "%s|", buf1);
}
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;
struct tm *start_time_struct = gmtime(&start_time_int);
strftime(buf1, sizeof(buf1), "%Y%m%d%H%M%S", start_time_struct);
fdprintf(context->out->fh, "%s%c%03d|", buf1,ccx_options.millis_separator,start_time_dec);
}
}
if (ccx_options.transcript_settings.showEndTime)
{
char buf2[80];
if (ccx_options.transcript_settings.relativeTimestamp)
{
millis_to_date(end_time, buf2);
fdprintf(context->out->fh, "%s|", buf2);
}
else
{
mstotime(get_fts() + subs_delay, &h2, &m2, &s2, &ms2);
time_t end_time_int = end_time / 1000;
int end_time_dec = end_time % 1000;
struct tm *end_time_struct = gmtime(&end_time_int);
strftime(buf2, sizeof(buf2), "%Y%m%d%H%M%S", end_time_struct);
fdprintf(context->out->fh, "%s%c%03d|", buf2,ccx_options.millis_separator,end_time_dec);
}
}
if (ccx_options.transcript_settings.showCC)
{
fdprintf(context->out->fh,"%s|",language[sub->lang_index]);
}
if (ccx_options.transcript_settings.showMode)
{
fdprintf(context->out->fh,"DVB|");
}
fdprintf(context->out->fh,"%s\n",token);
token = strtok(NULL,"\r\n");
}
}
}
#endif
end:
sub->nb_data = 0;
freep(&sub->data);
freep(&palette);
freep(&alpha);
return ret;
}
void try_to_add_end_credits(struct encoder_ctx *context, struct ccx_s_write *out)
{
LLONG window, length, st, end;
if (out->fh == -1)
return;
window=get_fts()-last_displayed_subs_ms-1;
if (window<ccx_options.endcreditsforatleast.time_in_ms) // Won't happen, window is too short
return;
length=ccx_options.endcreditsforatmost.time_in_ms > window ?
window : ccx_options.endcreditsforatmost.time_in_ms;
st=get_fts()-length-1;
end=get_fts();
switch (ccx_options.write_format)
{
case CCX_OF_SRT:
write_stringz_as_srt(ccx_options.end_credits_text, context, st, end);
break;
case CCX_OF_SAMI:
write_stringz_as_sami(ccx_options.end_credits_text, context, st, end);
break;
case CCX_OF_SMPTETT:
write_stringz_as_smptett(ccx_options.end_credits_text, context, st, end);
break ;
default:
// Do nothing for the rest
break;
}
}
void try_to_add_start_credits(struct encoder_ctx *context,LLONG start_ms)
{
LLONG st, end, window, length;
LLONG l = start_ms + subs_delay;
// We have a windows from last_displayed_subs_ms to l - we need to see if it fits
if (l<ccx_options.startcreditsnotbefore.time_in_ms) // Too early
return;
if (last_displayed_subs_ms+1 > ccx_options.startcreditsnotafter.time_in_ms) // Too late
return;
st = ccx_options.startcreditsnotbefore.time_in_ms>(last_displayed_subs_ms+1) ?
ccx_options.startcreditsnotbefore.time_in_ms : (last_displayed_subs_ms+1); // When would credits actually start
end = ccx_options.startcreditsnotafter.time_in_ms<(l-1) ?
ccx_options.startcreditsnotafter.time_in_ms : (l-1);
window = end-st; // Allowable time in MS
if (ccx_options.startcreditsforatleast.time_in_ms>window) // Window is too short
return;
length=ccx_options.startcreditsforatmost.time_in_ms > window ?
window : ccx_options.startcreditsforatmost.time_in_ms;
dbg_print(CCX_DMT_VERBOSE, "Last subs: %lld Current position: %lld\n",
last_displayed_subs_ms, l);
dbg_print(CCX_DMT_VERBOSE, "Not before: %lld Not after: %lld\n",
ccx_options.startcreditsnotbefore.time_in_ms,
ccx_options.startcreditsnotafter.time_in_ms);
dbg_print(CCX_DMT_VERBOSE, "Start of window: %lld End of window: %lld\n",st,end);
if (window>length+2)
{
// Center in time window
LLONG pad=window-length;
st+=(pad/2);
}
end=st+length;
switch (ccx_options.write_format)
{
case CCX_OF_SRT:
write_stringz_as_srt(ccx_options.start_credits_text,context,st,end);
break;
case CCX_OF_SAMI:
write_stringz_as_sami(ccx_options.start_credits_text, context, st, end);
break;
case CCX_OF_SMPTETT:
write_stringz_as_smptett(ccx_options.start_credits_text, context, st, end);
break;
default:
// Do nothing for the rest
break;
}
startcredits_displayed=1;
return;
}
int init_encoder(struct encoder_ctx *ctx,struct ccx_s_write *out)
{
ctx->buffer = (unsigned char *) malloc (INITIAL_ENC_BUFFER_CAPACITY);
if (ctx->buffer==NULL)
return -1;
ctx->capacity=INITIAL_ENC_BUFFER_CAPACITY;
ctx->srt_counter = 0;
ctx->out = out;
/** used in case of SUB_EOD_MARKER */
ctx->prev_start = -1;
write_subtitle_file_header(ctx,out);
return 0;
}
void dinit_encoder(struct encoder_ctx *ctx)
{
if (ccx_options.end_credits_text!=NULL)
try_to_add_end_credits(ctx,ctx->out);
write_subtitle_file_footer(ctx,ctx->out);
freep(&ctx->buffer);
ctx->capacity = 0;
}
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++)
{
new_sentence=1;
if(data->format == SFORMAT_XDS)
{
xds_write_transcript_line_prefix (context->out, data->start_time, data->end_time,data->cur_xds_packet_class);
if(data->xds_len > 0)
write (context->out->fh, data->xds_str,data->xds_len);
freep (&data->xds_str);
xds_write_transcript_line_suffix (context->out);
continue;
}
if(!data->start_time)
break;
switch (ccx_options.write_format)
{
case CCX_OF_SRT:
if (!startcredits_displayed && ccx_options.start_credits_text!=NULL)
try_to_add_start_credits(context, data->start_time);
wrote_something = write_cc_buffer_as_srt(data, context);
break;
case CCX_OF_SAMI:
if (!startcredits_displayed && ccx_options.start_credits_text!=NULL)
try_to_add_start_credits(context, data->start_time);
wrote_something = write_cc_buffer_as_sami(data, context);
break;
case CCX_OF_SMPTETT:
if (!startcredits_displayed && ccx_options.start_credits_text!=NULL)
try_to_add_start_credits(context, data->start_time);
wrote_something = write_cc_buffer_as_smptett(data, context);
break;
case CCX_OF_TRANSCRIPT:
wrote_something = write_cc_buffer_as_transcript2(data, context);
break;
case CCX_OF_SPUPNG:
wrote_something = write_cc_buffer_as_spupng(data, context);
break;
default:
break;
}
if (wrote_something)
last_displayed_subs_ms=get_fts()+subs_delay;
if (ccx_options.gui_mode_reports)
write_cc_buffer_to_gui(sub->data, context);
}
freep(&sub->data);
}
if(sub->type == CC_BITMAP)
{
switch (ccx_options.write_format)
{
case CCX_OF_SRT:
if (!startcredits_displayed && ccx_options.start_credits_text!=NULL)
try_to_add_start_credits(context, sub->start_time);
wrote_something = write_cc_bitmap_as_srt(sub, context);
case CCX_OF_SAMI:
if (!startcredits_displayed && ccx_options.start_credits_text!=NULL)
try_to_add_start_credits(context, sub->start_time);
wrote_something = write_cc_bitmap_as_sami(sub, context);
case CCX_OF_SMPTETT:
if (!startcredits_displayed && ccx_options.start_credits_text!=NULL)
try_to_add_start_credits(context, sub->start_time);
wrote_something = write_cc_bitmap_as_smptett(sub, context);
case CCX_OF_TRANSCRIPT:
wrote_something = write_cc_bitmap_as_transcript(sub, context);
break;
case CCX_OF_SPUPNG:
wrote_something = write_cc_bitmap_as_spupng(sub, context);
break;
default:
break;
}
}
if (!sub->nb_data)
freep(&sub->data);
return wrote_something;
}

View File

@@ -1,67 +0,0 @@
#ifndef _CC_ENCODER_COMMON_H
#define _CC_ENCODER_COMMON_H
/**
* Context of encoder, This structure gives single interface
* to all encoder
*/
struct encoder_ctx
{
/** common buffer used by all encoder */
unsigned char *buffer;
/** capacity of buffer */
unsigned int capacity;
/* keep count of srt subtitle*/
unsigned int srt_counter;
/** output contet */
struct ccx_s_write *out;
/** start time of previous sub */
LLONG prev_start;
};
#define INITIAL_ENC_BUFFER_CAPACITY 2048
/**
* Inialize encoder context with output context
* allocate initial memory to buffer of context
* write subtitle header to file refrenced by
* output context
*
* @param ctx preallocated encoder ctx
* @param out output context
*
* @return 0 on SUCESS, -1 on failure
*/
int init_encoder(struct encoder_ctx *ctx,struct ccx_s_write *out);
/**
* try to add end credits in subtitle file and then write subtitle
* footer
*
* deallocate encoder ctx, so before using encoder_ctx again
* after deallocating user need to allocate encoder ctx again
*
* @oaram ctx Initialized encoder ctx using init_encoder
*/
void dinit_encoder(struct encoder_ctx *ctx);
/**
* @param ctx encoder context
* @param sub subtitle context returned by decoder
*/
int encode_sub(struct encoder_ctx *ctx,struct cc_subtitle *sub);
int write_cc_buffer_as_srt(struct eia608_screen *data, struct encoder_ctx *context);
void write_stringz_as_srt(char *string, struct encoder_ctx *context, LLONG ms_start, LLONG ms_end);
int write_cc_buffer_as_sami(struct eia608_screen *data, struct encoder_ctx *context);
void write_stringz_as_sami(char *string, struct encoder_ctx *context, LLONG ms_start, LLONG ms_end);
int write_cc_buffer_as_smptett(struct eia608_screen *data, struct encoder_ctx *context);
void write_stringz_as_smptett(char *string, struct encoder_ctx *context, LLONG ms_start, LLONG ms_end);
void write_cc_buffer_to_gui(struct eia608_screen *data, struct encoder_ctx *context);
int write_cc_bitmap_as_spupng(struct cc_subtitle *sub, struct encoder_ctx *context);
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

File diff suppressed because it is too large Load Diff

View File

@@ -1,595 +0,0 @@
#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>
// compatibility across platforms
#include "platform.h"
#define VERSION "0.72"
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
{
int hh,mm,ss;
LLONG time_in_ms;
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 nofontcolor;
int notypesetting;
struct ccx_boundary_time extraction_start, extraction_end; // Segment we actually process
int print_file_reports;
/* subtitle codec type */
enum cxx_code_type codec;
enum cxx_code_type nocodec;
/* Credit stuff */
char *start_credits_text;
char *end_credits_text;
struct ccx_boundary_time startcreditsnotbefore, startcreditsnotafter; // Where to insert start credits, if possible
struct ccx_boundary_time startcreditsforatleast, startcreditsforatmost; // How long to display them?
struct ccx_boundary_time endcreditsforatleast, endcreditsforatmost;
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
int sentence_cap ; // FIX CASE? = Fix case?
char *sentence_cap_file; // Extra words file?
int live_stream; /* -1 -> Not a complete file but a live stream, without timeout
0 -> A regular file
>0 -> Live stream with a timeout of this value in seconds */
int messages_target; // 0 = nowhere (quiet), 1=stdout, 2=stderr
/* Levenshtein's parameters, for string comparison */
int levdistmincnt, levdistmaxpct; // Means 2 fails or less is "the same", 10% or less is also "the same"
int investigate_packets; // Look for captions in all packets when everything else fails
int fullbin; // Disable pruning of padding cc blocks
int nosync; // Disable syncing
unsigned hauppauge_mode; // If 1, use PID=1003, process specially and so on
int wtvconvertfix; // Fix broken Windows 7 conversion
int wtvmpeg2;
int auto_myth; // Use myth-tv mpeg code? 0=no, 1=yes, 2=auto
/* MP4 related stuff */
unsigned mp4vidtrack; // Process the video track even if a CC dedicated track exists.
/* General settings */
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.
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
LLONG debug_mask_on_debug; // If we're using temp_debug to enable/disable debug "live", this is the mask when temp_debug=1
unsigned ts_autoprogram ; // Try to find a stream with captions automatically (no -pn needed)
unsigned ts_cappid ; // PID for stream that holds caption information
unsigned ts_forced_cappid ; // If 1, never mess with the selected PID
unsigned ts_forced_program; // Specific program to process in TS files, if ts_forced_program_selected==1
unsigned ts_forced_program_selected;
int ts_datastreamtype ; // User WANTED stream type (i.e. use the stream that has this type)
unsigned ts_forced_streamtype; // User selected (forced) stream type
/* Networking */
char *udpaddr;
unsigned udpport; // Non-zero => Listen for UDP packets on this port, no files.
unsigned send_to_srv;
char *tcpport;
char *tcp_password;
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
};
struct ts_payload
{
unsigned char *start; // Payload start
unsigned length; // Payload length
unsigned pesstart; // PES or PSI start
unsigned pid; // Stream PID
int counter; // continuity counter
int transport_error; // 0 = packet OK, non-zero damaged
unsigned char section_buf[1024];
int section_index;
int section_size;
};
struct PAT_entry
{
unsigned program_number;
unsigned PMT_PID;
unsigned char *last_pmt_payload;
unsigned last_pmt_length;
};
struct PMT_entry
{
unsigned program_number;
unsigned PMT_PID;
unsigned elementary_PID;
unsigned ccx_stream_type;
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
{
unsigned program_cnt;
unsigned width;
unsigned height;
unsigned aspect_ratio;
unsigned frame_rate;
unsigned xds : 1;
unsigned cc_channels_608[4];
unsigned services708[63];
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?
uint16_t page; // teletext page containing cc we want to filter
uint16_t tid; // 13-bit packet ID for teletext stream
double offset; // time offset in seconds
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
uint16_t user_page; // Page selected by user, which MIGHT be different to 'page' depending on autodetection stuff
};
#define buffered_skip(bytes) if (bytes<=bytesinbuffer-filebuffer_pos) { \
filebuffer_pos+=bytes; \
result=bytes; \
} else result=buffered_read_opt (NULL,bytes);
#define buffered_read(buffer,bytes) if (bytes<=bytesinbuffer-filebuffer_pos) { \
if (buffer!=NULL) memcpy (buffer,filebuffer+filebuffer_pos,bytes); \
filebuffer_pos+=bytes; \
result=bytes; \
} else { result=buffered_read_opt (buffer,bytes); if (ccx_options.gui_mode_reports && ccx_options.input_source==CCX_DS_NETWORK) {net_activity_gui++; if (!(net_activity_gui%1000))activity_report_data_read();}}
#define buffered_read_4(buffer) if (4<=bytesinbuffer-filebuffer_pos) { \
if (buffer) { buffer[0]=filebuffer[filebuffer_pos]; \
buffer[1]=filebuffer[filebuffer_pos+1]; \
buffer[2]=filebuffer[filebuffer_pos+2]; \
buffer[3]=filebuffer[filebuffer_pos+3]; \
filebuffer_pos+=4; \
result=4; } \
} else result=buffered_read_opt (buffer,4);
#define buffered_read_byte(buffer) if (bytesinbuffer-filebuffer_pos) { \
if (buffer) { *buffer=filebuffer[filebuffer_pos]; \
filebuffer_pos++; \
result=1; } \
} else result=buffered_read_opt (buffer,1);
extern LLONG buffered_read_opt (unsigned char *buffer, unsigned int bytes);
//params.c
void parse_parameters (int argc, char *argv[]);
void usage (void);
int atoi_hex (char *s);
int stringztoms (const char *s, struct ccx_boundary_time *bt);
// general_loop.c
void position_sanity_check ();
int init_file_buffer( void );
LLONG ps_getmoredata( void );
LLONG general_getmoredata( void );
void raw_loop (void *enc_ctx);
LLONG process_raw (struct cc_subtitle *sub);
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);
void activity_report_version (void);
void activity_input_file_closed (void);
void activity_input_file_open (const char *filename);
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_report_data_read (void);
extern LLONG result;
extern int end_of_file;
extern LLONG inbuf;
extern int ccx_bufferdatatype; // Can be RAW or PES
// asf_functions.c
LLONG asf_getmoredata( void );
// wtv_functions.c
LLONG wtv_getmoredata( void );
// avc_functions.c
LLONG process_avc (unsigned char *avcbuf, LLONG avcbuflen, struct cc_subtitle *sub);
void init_avc(void);
// es_functions.c
LLONG process_m2v (unsigned char *data, LLONG length, struct cc_subtitle *sub);
extern unsigned top_field_first;
// es_userdata.c
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);
void prepare_for_new_file (void);
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);
void anchor_hdcc(int seq);
void process_hdcc (struct cc_subtitle *sub);
int do_cb (unsigned char *cc_block, struct cc_subtitle *sub);
// mp4.c
int processmp4 (char *file,void *enc_ctx);
// params_dump.c
void params_dump(void);
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 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);
// stream_functions.c
void detect_stream_type (void);
int detect_myth( void );
int read_video_pes_header (unsigned char *header, int *headerlength, int sbuflen);
int read_pts_pes(unsigned char*header, int len);
// ts_functions.c
void init_ts( void );
int ts_readpacket(void);
long ts_readstream(void);
LLONG ts_getmoredata( void );
int write_section(struct ts_payload *payload, unsigned char*buf, int size, int pos);
int parse_PMT (unsigned char *buf,int len, int pos);
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);
bool_t in_array(uint16_t *array, uint16_t length, uint16_t element) ;
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);
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);
void tlt_process_pes_packet(uint8_t *buffer, uint16_t size) ;
void telxcc_init(void);
void telxcc_close(void);
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;
extern unsigned char *buffer;
extern LLONG past;
extern LLONG total_inputsize, total_past; // Only in binary concat mode
extern char **inputfile;
extern int current_file;
extern LLONG result; // Number of bytes read/skipped in last read operation
extern int strangeheader;
extern unsigned char startbytes[STARTBYTESLENGTH];
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 const char *desc[256];
extern FILE *fh_out_elementarystream;
extern int infd;
extern int false_pict_header;
extern int stat_numuserheaders;
extern int stat_dvdccheaders;
extern int stat_scte20ccheaders;
extern int stat_replay5000headers;
extern int stat_replay4000headers;
extern int stat_dishheaders;
extern int stat_hdtv;
extern int stat_divicom;
extern enum ccx_stream_mode_enum stream_mode;
extern int cc_stats[4];
extern LLONG inputsize;
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
extern struct ccx_s_options ccx_options;
extern int temp_debug;
extern unsigned long net_activity_gui;
/* General (ES stream) video information */
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;
extern enum ccx_bufferdata_type bufferdatatype; // Can be CCX_BUFFERDATA_TYPE_RAW or CCX_BUFFERDATA_TYPE_PES
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;
extern unsigned hauppauge_warning_shown;
extern unsigned char *subline;
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
extern unsigned cap_stream_type;
extern struct ts_payload payload;
extern unsigned char tspacket[188];
extern struct PAT_entry pmt_array[TS_PMT_MAP_SIZE];
extern uint16_t pmt_array_length;
extern unsigned pmtpid;
extern unsigned TS_program_number;
extern unsigned char *last_pat_payload;
extern unsigned last_pat_length;
extern long capbuflen;
#define HAUPPAGE_CCPID 1003 // PID for CC's in some Hauppauge recordings
/* Exit codes. Take this seriously as the GUI depends on them.
0 means OK as usual,
<100 means display whatever was output to stderr as a warning
>=100 means display whatever was output to stdout as an error
*/
#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 int timestamps_on_transcript;
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;
#endif

View File

@@ -1,133 +0,0 @@
#include "ccextractor.h"
// RCWT header (11 bytes):
//byte(s) value description (All values below are hex numbers, not
// actual numbers or values
//0-2 CCCCED magic number, for Closed Caption CC Extractor Data
//3 CC Creating program. Legal values: CC = CC Extractor
//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};
const unsigned char BROADCAST_HEADER[]={0xff, 0xff, 0xff, 0xff};
const unsigned char LITTLE_ENDIAN_BOM[]={0xff, 0xfe};
const unsigned char UTF8_BOM[]={0xef, 0xbb,0xbf};
const unsigned char DVD_HEADER[8]={0x00,0x00,0x01,0xb2,0x43,0x43,0x01,0xf8};
const unsigned char lc1[1]={0x8a};
const unsigned char lc2[1]={0x8f};
const unsigned char lc3[2]={0x16,0xfe};
const unsigned char lc4[2]={0x1e,0xfe};
const unsigned char lc5[1]={0xff};
const unsigned char lc6[1]={0xfe};
const double framerates_values[16]=
{
0,
24000.0/1001, /* 23.976 */
24.0,
25.0,
30000.0/1001, /* 29.97 */
30.0,
50.0,
60000.0/1001, /* 59.94 */
60.0,
0,
0,
0,
0,
0
};
const char *framerates_types[16]=
{
"00 - forbidden",
"01 - 23.976",
"02 - 24",
"03 - 25",
"04 - 29.97",
"05 - 30",
"06 - 50",
"07 - 59.94",
"08 - 60",
"09 - reserved",
"10 - reserved",
"11 - reserved",
"12 - reserved",
"13 - reserved",
"14 - reserved",
"15 - reserved"
};
const char *aspect_ratio_types[16]=
{
"00 - forbidden",
"01 - 1:1",
"02 - 4:3",
"03 - 16:9",
"04 - 2.21:1",
"05 - reserved",
"06 - reserved",
"07 - reserved",
"08 - reserved",
"09 - reserved",
"10 - reserved",
"11 - reserved",
"12 - reserved",
"13 - reserved",
"14 - reserved",
"15 - reserved"
};
const char *pict_types[8]=
{
"00 - ilegal (0)",
"01 - I",
"02 - P",
"03 - B",
"04 - ilegal (D)",
"05 - ilegal (5)",
"06 - ilegal (6)",
"07 - ilegal (7)"
};
const char *slice_types[10]=
{
"0 - P",
"1 - B",
"2 - I",
"3 - SP",
"4 - SI",
"5 - P",
"6 - B",
"7 - I",
"8 - SP",
"9 - SI"
};
const char *cc_types[4] =
{
"NTSC line 21 field 1 closed captions",
"NTSC line 21 field 2 closed captions",
"DTVCC Channel Packet Data",
"DTVCC Channel Packet Start"
};
enum
{
NTSC_CC_f1 = 0,
NTSC_CC_f2 = 1,
DTVCC_PACKET_DATA = 2,
DTVCC_PACKET_START = 3,
};
const char *language[4] =
{
"und",
"eng",
"fin",
NULL
};

View File

@@ -1,840 +0,0 @@
#include <ctype.h>
void get_char_in_latin_1 (unsigned char *buffer, unsigned char c)
{
unsigned char c1='?';
if (c<0x80)
{
// Regular line-21 character set, mostly ASCII except these exceptions
switch (c)
{
case 0x2a: // lowercase a, acute accent
c1=0xe1;
break;
case 0x5c: // lowercase e, acute accent
c1=0xe9;
break;
case 0x5e: // lowercase i, acute accent
c1=0xed;
break;
case 0x5f: // lowercase o, acute accent
c1=0xf3;
break;
case 0x60: // lowercase u, acute accent
c1=0xfa;
break;
case 0x7b: // lowercase c with cedilla
c1=0xe7;
break;
case 0x7c: // division symbol
c1=0xf7;
break;
case 0x7d: // uppercase N tilde
c1=0xd1;
break;
case 0x7e: // lowercase n tilde
c1=0xf1;
break;
default:
c1=c;
break;
}
*buffer=c1;
return;
}
switch (c)
{
// THIS BLOCK INCLUDES THE 16 EXTENDED (TWO-BYTE) LINE 21 CHARACTERS
// THAT COME FROM HI BYTE=0x11 AND LOW BETWEEN 0x30 AND 0x3F
case 0x80: // Registered symbol (R)
c1=0xae;
break;
case 0x81: // degree sign
c1=0xb0;
break;
case 0x82: // 1/2 symbol
c1=0xbd;
break;
case 0x83: // Inverted (open) question mark
c1=0xbf;
break;
case 0x84: // Trademark symbol (TM) - Does not exist in Latin 1
break;
case 0x85: // Cents symbol
c1=0xa2;
break;
case 0x86: // Pounds sterling
c1=0xa3;
break;
case 0x87: // Music note - Not in latin 1, so we use 'pilcrow'
c1=0xb6;
break;
case 0x88: // lowercase a, grave accent
c1=0xe0;
break;
case 0x89: // transparent space, we make it regular
c1=0x20;
break;
case 0x8a: // lowercase e, grave accent
c1=0xe8;
break;
case 0x8b: // lowercase a, circumflex accent
c1=0xe2;
break;
case 0x8c: // lowercase e, circumflex accent
c1=0xea;
break;
case 0x8d: // lowercase i, circumflex accent
c1=0xee;
break;
case 0x8e: // lowercase o, circumflex accent
c1=0xf4;
break;
case 0x8f: // lowercase u, circumflex accent
c1=0xfb;
break;
// THIS BLOCK INCLUDES THE 32 EXTENDED (TWO-BYTE) LINE 21 CHARACTERS
// THAT COME FROM HI BYTE=0x12 AND LOW BETWEEN 0x20 AND 0x3F
case 0x90: // capital letter A with acute
c1=0xc1;
break;
case 0x91: // capital letter E with acute
c1=0xc9;
break;
case 0x92: // capital letter O with acute
c1=0xd3;
break;
case 0x93: // capital letter U with acute
c1=0xda;
break;
case 0x94: // capital letter U with diaresis
c1=0xdc;
break;
case 0x95: // lowercase letter U with diaeresis
c1=0xfc;
break;
case 0x96: // apostrophe
c1=0x27;
break;
case 0x97: // inverted exclamation mark
c1=0xa1;
break;
case 0x98: // asterisk
c1=0x2a;
break;
case 0x99: // apostrophe (yes, duped). See CCADI source code.
c1=0x27;
break;
case 0x9a: // em dash
c1=0x2d;
break;
case 0x9b: // copyright sign
c1=0xa9;
break;
case 0x9c: // Service Mark - not available in latin 1
break;
case 0x9d: // Full stop (.)
c1=0x2e;
break;
case 0x9e: // Quoatation mark
c1=0x22;
break;
case 0x9f: // Quoatation mark
c1=0x22;
break;
case 0xa0: // uppercase A, grave accent
c1=0xc0;
break;
case 0xa1: // uppercase A, circumflex
c1=0xc2;
break;
case 0xa2: // uppercase C with cedilla
c1=0xc7;
break;
case 0xa3: // uppercase E, grave accent
c1=0xc8;
break;
case 0xa4: // uppercase E, circumflex
c1=0xca;
break;
case 0xa5: // capital letter E with diaresis
c1=0xcb;
break;
case 0xa6: // lowercase letter e with diaresis
c1=0xeb;
break;
case 0xa7: // uppercase I, circumflex
c1=0xce;
break;
case 0xa8: // uppercase I, with diaresis
c1=0xcf;
break;
case 0xa9: // lowercase i, with diaresis
c1=0xef;
break;
case 0xaa: // uppercase O, circumflex
c1=0xd4;
break;
case 0xab: // uppercase U, grave accent
c1=0xd9;
break;
case 0xac: // lowercase u, grave accent
c1=0xf9;
break;
case 0xad: // uppercase U, circumflex
c1=0xdb;
break;
case 0xae: // LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
c1=0xab;
break;
case 0xaf: // RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
c1=0xbb;
break;
// THIS BLOCK INCLUDES THE 32 EXTENDED (TWO-BYTE) LINE 21 CHARACTERS
// THAT COME FROM HI BYTE=0x13 AND LOW BETWEEN 0x20 AND 0x3F
case 0xb0: // Uppercase A, tilde
c1=0xc3;
break;
case 0xb1: // Lowercase a, tilde
c1=0xe3;
break;
case 0xb2: // Uppercase I, acute accent
c1=0xcd;
break;
case 0xb3: // Uppercase I, grave accent
c1=0xcc;
break;
case 0xb4: // Lowercase i, grave accent
c1=0xec;
break;
case 0xb5: // Uppercase O, grave accent
c1=0xd2;
break;
case 0xb6: // Lowercase o, grave accent
c1=0xf2;
break;
case 0xb7: // Uppercase O, tilde
c1=0xd5;
break;
case 0xb8: // Lowercase o, tilde
c1=0xf5;
break;
case 0xb9: // Open curly brace
c1=0x7b;
break;
case 0xba: // Closing curly brace
c1=0x7d;
break;
case 0xbb: // Backslash
c1=0x5c;
break;
case 0xbc: // Caret
c1=0x5e;
break;
case 0xbd: // Underscore
c1=0x5f;
break;
case 0xbe: // Pipe (broken bar)
c1=0xa6;
break;
case 0xbf: // Tilde
c1=0x7e;
break;
case 0xc0: // Uppercase A, umlaut
c1=0xc4;
break;
case 0xc1: // Lowercase A, umlaut
c1=0xe3;
break;
case 0xc2: // Uppercase O, umlaut
c1=0xd6;
break;
case 0xc3: // Lowercase o, umlaut
c1=0xf6;
break;
case 0xc4: // Esszett (sharp S)
c1=0xdf;
break;
case 0xc5: // Yen symbol
c1=0xa5;
break;
case 0xc6: // Currency symbol
c1=0xa4;
break;
case 0xc7: // Vertical bar
c1=0x7c;
break;
case 0xc8: // Uppercase A, ring
c1=0xc5;
break;
case 0xc9: // Lowercase A, ring
c1=0xe5;
break;
case 0xca: // Uppercase O, slash
c1=0xd8;
break;
case 0xcb: // Lowercase o, slash
c1=0xf8;
break;
case 0xcc: // Upper left corner
case 0xcd: // Upper right corner
case 0xce: // Lower left corner
case 0xcf: // Lower right corner
default: // For those that don't have representation
*buffer='?'; // I'll do it eventually, I promise
break; // This are weird chars anyway
}
*buffer=c1;
}
void get_char_in_unicode (unsigned char *buffer, unsigned char c)
{
unsigned char c1,c2;
switch (c)
{
case 0x84: // Trademark symbol (TM)
c2=0x21;
c1=0x22;
break;
case 0x87: // Music note
c2=0x26;
c1=0x6a;
break;
case 0x9c: // Service Mark
c2=0x21;
c1=0x20;
break;
case 0xcc: // Upper left corner
c2=0x23;
c1=0x1c;
break;
case 0xcd: // Upper right corner
c2=0x23;
c1=0x1d;
break;
case 0xce: // Lower left corner
c2=0x23;
c1=0x1e;
break;
case 0xcf: // Lower right corner
c2=0x23;
c1=0x1f;
break;
default: // Everything else, same as latin-1 followed by 00
get_char_in_latin_1 (&c1,c);
c2=0;
break;
}
*buffer=c1;
*(buffer+1)=c2;
}
int get_char_in_utf_8 (unsigned char *buffer, unsigned char c) // Returns number of bytes used
{
if (c<0x80) // Regular line-21 character set, mostly ASCII except these exceptions
{
switch (c)
{
case 0x2a: // lowercase a, acute accent
*buffer=0xc3;
*(buffer+1)=0xa1;
return 2;
case 0x5c: // lowercase e, acute accent
*buffer=0xc3;
*(buffer+1)=0xa9;
return 2;
case 0x5e: // lowercase i, acute accent
*buffer=0xc3;
*(buffer+1)=0xad;
return 2;
case 0x5f: // lowercase o, acute accent
*buffer=0xc3;
*(buffer+1)=0xb3;
return 2;
case 0x60: // lowercase u, acute accent
*buffer=0xc3;
*(buffer+1)=0xba;
return 2;
case 0x7b: // lowercase c with cedilla
*buffer=0xc3;
*(buffer+1)=0xa7;
return 2;
case 0x7c: // division symbol
*buffer=0xc3;
*(buffer+1)=0xb7;
return 2;
case 0x7d: // uppercase N tilde
*buffer=0xc3;
*(buffer+1)=0x91;
return 2;
case 0x7e: // lowercase n tilde
*buffer=0xc3;
*(buffer+1)=0xb1;
return 2;
case 0x7f: // Solid block
*buffer=0xe2;
*(buffer+1)=0x96;
*(buffer+2)=0xa0;
return 3;
default:
*buffer=c;
return 1;
}
}
switch (c)
{
// THIS BLOCK INCLUDES THE 16 EXTENDED (TWO-BYTE) LINE 21 CHARACTERS
// THAT COME FROM HI BYTE=0x11 AND LOW BETWEEN 0x30 AND 0x3F
case 0x80: // Registered symbol (R)
*buffer=0xc2;
*(buffer+1)=0xae;
return 2;
case 0x81: // degree sign
*buffer=0xc2;
*(buffer+1)=0xb0;
return 2;
case 0x82: // 1/2 symbol
*buffer=0xc2;
*(buffer+1)=0xbd;
return 2;
case 0x83: // Inverted (open) question mark
*buffer=0xc2;
*(buffer+1)=0xbf;
return 2;
case 0x84: // Trademark symbol (TM)
*buffer=0xe2;
*(buffer+1)=0x84;
*(buffer+2)=0xa2;
return 3;
case 0x85: // Cents symbol
*buffer=0xc2;
*(buffer+1)=0xa2;
return 2;
case 0x86: // Pounds sterling
*buffer=0xc2;
*(buffer+1)=0xa3;
return 2;
case 0x87: // Music note
*buffer=0xe2;
*(buffer+1)=0x99;
*(buffer+2)=0xaa;
return 3;
case 0x88: // lowercase a, grave accent
*buffer=0xc3;
*(buffer+1)=0xa0;
return 2;
case 0x89: // transparent space, we make it regular
*buffer=0x20;
return 1;
case 0x8a: // lowercase e, grave accent
*buffer=0xc3;
*(buffer+1)=0xa8;
return 2;
case 0x8b: // lowercase a, circumflex accent
*buffer=0xc3;
*(buffer+1)=0xa2;
return 2;
case 0x8c: // lowercase e, circumflex accent
*buffer=0xc3;
*(buffer+1)=0xaa;
return 2;
case 0x8d: // lowercase i, circumflex accent
*buffer=0xc3;
*(buffer+1)=0xae;
return 2;
case 0x8e: // lowercase o, circumflex accent
*buffer=0xc3;
*(buffer+1)=0xb4;
return 2;
case 0x8f: // lowercase u, circumflex accent
*buffer=0xc3;
*(buffer+1)=0xbb;
return 2;
// THIS BLOCK INCLUDES THE 32 EXTENDED (TWO-BYTE) LINE 21 CHARACTERS
// THAT COME FROM HI BYTE=0x12 AND LOW BETWEEN 0x20 AND 0x3F
case 0x90: // capital letter A with acute
*buffer=0xc3;
*(buffer+1)=0x81;
return 2;
case 0x91: // capital letter E with acute
*buffer=0xc3;
*(buffer+1)=0x89;
return 2;
case 0x92: // capital letter O with acute
*buffer=0xc3;
*(buffer+1)=0x93;
return 2;
case 0x93: // capital letter U with acute
*buffer=0xc3;
*(buffer+1)=0x9a;
return 2;
case 0x94: // capital letter U with diaresis
*buffer=0xc3;
*(buffer+1)=0x9c;
return 2;
case 0x95: // lowercase letter U with diaeresis
*buffer=0xc3;
*(buffer+1)=0xbc;
return 2;
case 0x96: // apostrophe
*buffer=0x27;
return 1;
case 0x97: // inverted exclamation mark
*buffer=0xc2;
*(buffer+1)=0xa1;
return 2;
case 0x98: // asterisk
*buffer=0x2a;
return 1;
case 0x99: // Plain single quote
*buffer=0x27;
return 1;
case 0x9a: // em dash
*buffer=0xe2;
*(buffer+1)=0x80;
*(buffer+2)=0x94;
return 3;
case 0x9b: // copyright sign
*buffer=0xc2;
*(buffer+1)=0xa9;
return 2;
case 0x9c: // Service mark
*buffer=0xe2;
*(buffer+1)=0x84;
*(buffer+2)=0xa0;
return 3;
case 0x9d: // Round bullet
*buffer=0xe2;
*(buffer+1)=0x80;
*(buffer+2)=0xa2;
return 3;
case 0x9e: // Opening double quotes
*buffer=0xe2;
*(buffer+1)=0x80;
*(buffer+2)=0x9c;
return 3;
case 0x9f: // Closing double quotes
*buffer=0xe2;
*(buffer+1)=0x80;
*(buffer+2)=0x9d;
return 3;
case 0xa0: // uppercase A, grave accent
*buffer=0xc3;
*(buffer+1)=0x80;
return 2;
case 0xa1: // uppercase A, circumflex
*buffer=0xc3;
*(buffer+1)=0x82;
return 2;
case 0xa2: // uppercase C with cedilla
*buffer=0xc3;
*(buffer+1)=0x87;
return 2;
case 0xa3: // uppercase E, grave accent
*buffer=0xc3;
*(buffer+1)=0x88;
return 2;
case 0xa4: // uppercase E, circumflex
*buffer=0xc3;
*(buffer+1)=0x8a;
return 2;
case 0xa5: // capital letter E with diaresis
*buffer=0xc3;
*(buffer+1)=0x8b;
return 2;
case 0xa6: // lowercase letter e with diaresis
*buffer=0xc3;
*(buffer+1)=0xab;
return 2;
case 0xa7: // uppercase I, circumflex
*buffer=0xc3;
*(buffer+1)=0x8e;
return 2;
case 0xa8: // uppercase I, with diaresis
*buffer=0xc3;
*(buffer+1)=0x8f;
return 2;
case 0xa9: // lowercase i, with diaresis
*buffer=0xc3;
*(buffer+1)=0xaf;
return 2;
case 0xaa: // uppercase O, circumflex
*buffer=0xc3;
*(buffer+1)=0x94;
return 2;
case 0xab: // uppercase U, grave accent
*buffer=0xc3;
*(buffer+1)=0x99;
return 2;
case 0xac: // lowercase u, grave accent
*buffer=0xc3;
*(buffer+1)=0xb9;
return 2;
case 0xad: // uppercase U, circumflex
*buffer=0xc3;
*(buffer+1)=0x9b;
return 2;
case 0xae: // LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
*buffer=0xc2;
*(buffer+1)=0xab;
return 2;
case 0xaf: // RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
*buffer=0xc2;
*(buffer+1)=0xbb;
return 2;
// THIS BLOCK INCLUDES THE 32 EXTENDED (TWO-BYTE) LINE 21 CHARACTERS
// THAT COME FROM HI BYTE=0x13 AND LOW BETWEEN 0x20 AND 0x3F
case 0xb0: // Uppercase A, tilde
*buffer=0xc3;
*(buffer+1)=0x83;
return 2;
case 0xb1: // Lowercase a, tilde
*buffer=0xc3;
*(buffer+1)=0xa3;
return 2;
case 0xb2: // Uppercase I, acute accent
*buffer=0xc3;
*(buffer+1)=0x8d;
return 2;
case 0xb3: // Uppercase I, grave accent
*buffer=0xc3;
*(buffer+1)=0x8c;
return 2;
case 0xb4: // Lowercase i, grave accent
*buffer=0xc3;
*(buffer+1)=0xac;
return 2;
case 0xb5: // Uppercase O, grave accent
*buffer=0xc3;
*(buffer+1)=0x92;
return 2;
case 0xb6: // Lowercase o, grave accent
*buffer=0xc3;
*(buffer+1)=0xb2;
return 2;
case 0xb7: // Uppercase O, tilde
*buffer=0xc3;
*(buffer+1)=0x95;
return 2;
case 0xb8: // Lowercase o, tilde
*buffer=0xc3;
*(buffer+1)=0xb5;
return 2;
case 0xb9: // Open curly brace
*buffer=0x7b;
return 1;
case 0xba: // Closing curly brace
*buffer=0x7d;
return 1;
case 0xbb: // Backslash
*buffer=0x5c;
return 1;
case 0xbc: // Caret
*buffer=0x5e;
return 1;
case 0xbd: // Underscore
*buffer=0x5f;
return 1;
case 0xbe: // Pipe (broken bar)
*buffer=0xc2;
*(buffer+1)=0xa6;
return 2;
case 0xbf: // Tilde
*buffer=0x7e; // Not sure
return 1;
case 0xc0: // Uppercase A, umlaut
*buffer=0xc3;
*(buffer+1)=0x84;
return 2;
case 0xc1: // Lowercase A, umlaut
*buffer=0xc3;
*(buffer+1)=0xa4;
return 2;
case 0xc2: // Uppercase O, umlaut
*buffer=0xc3;
*(buffer+1)=0x96;
return 2;
case 0xc3: // Lowercase o, umlaut
*buffer=0xc3;
*(buffer+1)=0xb6;
return 2;
case 0xc4: // Esszett (sharp S)
*buffer=0xc3;
*(buffer+1)=0x9f;
return 2;
case 0xc5: // Yen symbol
*buffer=0xc2;
*(buffer+1)=0xa5;
return 2;
case 0xc6: // Currency symbol
*buffer=0xc2;
*(buffer+1)=0xa4;
return 2;
case 0xc7: // Vertical bar
*buffer=0x7c;
return 1;
case 0xc8: // Uppercase A, ring
*buffer=0xc3;
*(buffer+1)=0x85;
return 2;
case 0xc9: // Lowercase A, ring
*buffer=0xc3;
*(buffer+1)=0xa5;
return 2;
case 0xca: // Uppercase O, slash
*buffer=0xc3;
*(buffer+1)=0x98;
return 2;
case 0xcb: // Lowercase o, slash
*buffer=0xc3;
*(buffer+1)=0xb8;
return 2;
case 0xcc: // Top left corner
*buffer=0xe2;
*(buffer+1)=0x8c;
*(buffer+2)=0x9c;
return 3;
case 0xcd: // Top right corner
*buffer=0xe2;
*(buffer+1)=0x8c;
*(buffer+2)=0x9d;
return 3;
case 0xce: // Bottom left corner
*buffer=0xe2;
*(buffer+1)=0x8c;
*(buffer+2)=0x9e;
return 3;
case 0xcf: // Bottom right corner
*buffer=0xe2;
*(buffer+1)=0x8c;
*(buffer+2)=0x9f;
return 3;
default: //
*buffer='?'; // I'll do it eventually, I promise
return 1; // This are weird chars anyway
}
}
unsigned char cctolower (unsigned char c)
{
if (c>='A' && c<='Z')
return tolower(c);
switch (c)
{
case 0x7d: // uppercase N tilde
return 0x7e;
case 0x90: // capital letter A with acute
return 0x2a;
case 0x91: // capital letter E with acute
return 0x5c;
case 0x92: // capital letter O with acute
return 0x5f;
case 0x93: // capital letter U with acute
return 0x60;
case 0xa2: // uppercase C with cedilla
return 0x7b;
case 0xa0: // uppercase A, grave accent
return 0x88;
case 0xa3: // uppercase E, grave accent
return 0x8a;
case 0xa1: // uppercase A, circumflex
return 0x8b;
case 0xa4: // uppercase E, circumflex
return 0x8c;
case 0xa7: // uppercase I, circumflex
return 0x8d;
case 0xaa: // uppercase O, circumflex
return 0x8e;
case 0xad: // uppercase U, circumflex
return 0x8f;
case 0x94: // capital letter U with diaresis
return 0x95;
case 0xa5: // capital letter E with diaresis
return 0xa6;
case 0xa8: // uppercase I, with diaresis
return 0xa9;
case 0xab: // uppercase U, grave accent
return 0xac;
case 0xb0: // Uppercase A, tilde
return 0xb1;
case 0xb2: // Uppercase I, acute accent
return 0x5e;
case 0xb3: // Uppercase I, grave accent
return 0xb4;
case 0xb5: // Uppercase O, grave accent
return 0xb6;
case 0xb7: // Uppercase O, tilde
return 0xb8;
case 0xc0: // Uppercase A, umlaut
return 0xc1;
case 0xc2: // Uppercase O, umlaut
return 0xc3;
case 0xc8: // Uppercase A, ring
return 0xc9;
case 0xca: // Uppercase O, slash
return 0xcb;
}
return c;
}
unsigned char cctoupper (unsigned char c)
{
if (c>='a' && c<='z')
return toupper(c);
switch (c)
{
case 0x7e: // lowercase n tilde
return 0x7d;
case 0x2a: // lowercase a, acute accent
return 0x90;
case 0x5c: // lowercase e, acute accent
return 0x91;
case 0x5e: // lowercase i, acute accent
return 0xb2;
case 0x5f: // lowercase o, acute accent
return 0x92;
case 0x60: // lowercase u, acute accent
return 0x93;
case 0x7b: // lowercase c with cedilla
return 0xa2;
case 0x88: // lowercase a, grave accent
return 0xa0;
case 0x8a: // lowercase e, grave accent
return 0xa3;
case 0x8b: // lowercase a, circumflex accent
return 0xa1;
case 0x8c: // lowercase e, circumflex accent
return 0xa4;
case 0x8d: // lowercase i, circumflex accent
return 0xa7;
case 0x8e: // lowercase o, circumflex accent
return 0xaa;
case 0x8f: // lowercase u, circumflex accent
return 0xad;
case 0x95: // lowercase letter U with diaeresis
return 0x94;
case 0xa6: // lowercase letter e with diaresis
return 0xa5;
case 0xa9: // lowercase i, with diaresis
return 0xa8;
case 0xac: // lowercase u, grave accent
return 0xab;
case 0xb1: // Lowercase a, tilde
return 0xb0;
case 0xb4: // Lowercase i, grave accent
return 0xb3;
case 0xb6: // Lowercase o, grave accent
return 0xb5;
case 0xb8: // Lowercase o, tilde
return 0xb7;
case 0xc1: // Lowercase A, umlaut
return 0xc0;
case 0xc3: // Lowercase o, umlaut
return 0xc2;
case 0xc9: // Lowercase A, ring
return 0xc8;
case 0xcb: // Lowercase o, slash
return 0xca;
}
return c;
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,479 +0,0 @@
#include "ccextractor.h"
// Parse the user data for captions. The udtype variable denotes
// to which type of data it belongs:
// 0 .. sequence header
// 1 .. GOP header
// 2 .. picture header
// Return TRUE if the data parsing finished, FALSE otherwise.
// estream->pos is advanced. Data is only processed if ustream->error
// is FALSE, parsing can set ustream->error to TRUE.
int user_data(struct bitstream *ustream, int udtype, struct cc_subtitle *sub)
{
dbg_print(CCX_DMT_VERBOSE, "user_data(%d)\n", udtype);
// Shall not happen
if (ustream->error || ustream->bitsleft <= 0)
{
// ustream->error=1;
return 0; // Actually discarded on call.
// CFS: Seen in a Wobble edited file.
// fatal(EXIT_BUG_BUG, "user_data: Impossible!");
}
// Do something
stat_numuserheaders++;
//header+=4;
unsigned char *ud_header = next_bytes(ustream, 4);
if (ustream->error || ustream->bitsleft <= 0)
{
return 0; // Actually discarded on call.
// CFS: Seen in Stick_VHS.mpg.
// fatal(EXIT_BUG_BUG, "user_data: Impossible!");
}
// DVD CC header, see
// <http://www.geocities.com/mcpoodle43/SCC_TOOLS/DOCS/SCC_FORMAT.HTML>
if ( !memcmp(ud_header,"\x43\x43", 2 ) )
{
stat_dvdccheaders++;
// Probably unneeded, but keep looking for extra caption blocks
int maybeextracb = 1;
read_bytes(ustream, 4); // "43 43 01 F8"
unsigned char pattern_flag = (unsigned char) read_bits(ustream,1);
read_bits(ustream,1);
int capcount=(int) read_bits(ustream,5);
int truncate_flag = (int) read_bits(ustream,1); // truncate_flag - one CB extra
int field1packet = 0; // expect Field 1 first
if (pattern_flag == 0x00)
field1packet=1; // expect Field 1 second
dbg_print(CCX_DMT_VERBOSE, "Reading %d%s DVD CC segments\n",
capcount, (truncate_flag?"+1":""));
capcount += truncate_flag;
// This data comes before the first frame header, so
// in order to get the correct timing we need to set the
// current time to one frame after the maximum time of the
// last GOP. Only usefull when there are frames before
// the GOP.
if (fts_max > 0)
fts_now = fts_max + (LLONG) (1000.0/current_fps);
int rcbcount = 0;
for (int i=0; i<capcount; i++)
{
for (int j=0;j<2;j++)
{
unsigned char data[3];
data[0]=read_u8(ustream);
data[1]=read_u8(ustream);
data[2]=read_u8(ustream);
// Obey the truncate flag.
if ( truncate_flag && i == capcount-1 && j == 1 )
{
maybeextracb = 0;
break;
}
/* Field 1 and 2 data can be in either order,
with marker bytes of \xff and \xfe
Since markers can be repeated, use pattern as well */
if ((data[0]&0xFE) == 0xFE) // Check if valid
{
if (data[0]==0xff && j==field1packet)
data[0]=0x04; // Field 1
else
data[0]=0x05; // Field 2
do_cb(data, sub);
rcbcount++;
}
else
{
dbg_print(CCX_DMT_VERBOSE, "Illegal caption segment - stop here.\n");
maybeextracb = 0;
break;
}
}
}
// Theoretically this should not happen, oh well ...
// Deal with extra closed captions some DVD have.
int ecbcount = 0;
while ( maybeextracb && (next_u8(ustream)&0xFE) == 0xFE )
{
for (int j=0;j<2;j++)
{
unsigned char data[3];
data[0]=read_u8(ustream);
data[1]=read_u8(ustream);
data[2]=read_u8(ustream);
/* Field 1 and 2 data can be in either order,
with marker bytes of \xff and \xfe
Since markers can be repeated, use pattern as well */
if ((data[0]&0xFE) == 0xFE) // Check if valid
{
if (data[0]==0xff && j==field1packet)
data[0]=0x04; // Field 1
else
data[0]=0x05; // Field 2
do_cb(data, sub);
ecbcount++;
}
else
{
dbg_print(CCX_DMT_VERBOSE, "Illegal (extra) caption segment - stop here.\n");
maybeextracb = 0;
break;
}
}
}
dbg_print(CCX_DMT_VERBOSE, "Read %d/%d DVD CC blocks\n", rcbcount, ecbcount);
}
// SCTE 20 user data
else if (ud_header[0] == 0x03)
{
if ((ud_header[1]&0x7F) == 0x01)
{
unsigned char cc_data[3*31+1]; // Maximum cc_count is 31
stat_scte20ccheaders++;
read_bytes(ustream, 2); // "03 01"
unsigned cc_count = (unsigned int) read_bits(ustream,5);
dbg_print(CCX_DMT_VERBOSE, "Reading %d SCTE 20 CC blocks\n", cc_count);
unsigned field_number;
unsigned cc_data1;
unsigned cc_data2;
/* unsigned marker; */
for (unsigned j=0;j<cc_count;j++)
{
skip_bits(ustream,2); // priority - unused
field_number = (unsigned int) read_bits(ustream,2);
skip_bits(ustream,5); // line_offset - unused
cc_data1 = (unsigned int) read_bits(ustream,8);
cc_data2 = (unsigned int) read_bits(ustream,8);
/* marker = (unsigned int)read_bits(ustream,1); // TODO: Add syntax check */
if (ustream->bitsleft < 0)
fatal(EXIT_BUG_BUG, "Oops!");
// Field_number is either
// 0 .. forbiden
// 1 .. field 1 (odd)
// 2 .. field 2 (even)
// 3 .. repeated, from repeat_first_field, effectively field 1
if (field_number < 1)
{
// 0 is invalid
cc_data[j*3]=0x00; // Set to invalid
cc_data[j*3+1]=0x00;
cc_data[j*3+2]=0x00;
}
else
{
// Treat field_number 3 as 1
field_number = (field_number - 1) & 0x01;
// top_field_first also affects to which field the caption
// belongs.
if(!top_field_first)
field_number ^= 0x01;
cc_data[j*3]=0x04|(field_number);
cc_data[j*3+1]=reverse8(cc_data1);
cc_data[j*3+2]=reverse8(cc_data2);
}
}
cc_data[cc_count*3]=0xFF;
store_hdcc(cc_data, cc_count, current_tref, fts_now, sub);
dbg_print(CCX_DMT_VERBOSE, "Reading SCTE 20 CC blocks - done\n");
}
// reserved - unspecified
}
// ReplayTV 4000/5000 caption header - parsing information
// derived from CCExtract.bdl
else if ( (ud_header[0] == 0xbb //ReplayTV 4000
|| ud_header[0] == 0x99) //ReplayTV 5000
&& ud_header[1] == 0x02 )
{
unsigned char data[3];
if (ud_header[0]==0xbb)
stat_replay4000headers++;
else
stat_replay5000headers++;
read_bytes(ustream, 2); // "BB 02" or "99 02"
data[0]=0x05; // Field 2
data[1]=read_u8(ustream);
data[2]=read_u8(ustream);
do_cb(data, sub);
read_bytes(ustream, 2); // Skip "CC 02" for R4000 or "AA 02" for R5000
data[0]=0x04; // Field 1
data[1]=read_u8(ustream);
data[2]=read_u8(ustream);
do_cb(data, sub);
}
// HDTV - see A/53 Part 4 (Video)
else if ( !memcmp(ud_header,"\x47\x41\x39\x34", 4 ) )
{
stat_hdtv++;
read_bytes(ustream, 4); // "47 41 39 34"
unsigned char type_code = read_u8(ustream);
if (type_code==0x03) // CC data.
{
skip_bits(ustream,1); // reserved
unsigned char process_cc_data = (unsigned char) read_bits(ustream,1);
skip_bits(ustream,1); // additional_data - unused
unsigned char cc_count = (unsigned char) read_bits(ustream,5);
read_bytes(ustream, 1); // "FF"
if (process_cc_data)
{
dbg_print(CCX_DMT_VERBOSE, "Reading %d HDTV CC blocks\n", cc_count);
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!");
// Check for proper marker - This read makes sure that
// cc_count*3+1 bytes are read and available in cc_data.
if (read_u8(ustream)!=0xFF)
proceed=0;
if (!proceed)
{
dbg_print(CCX_DMT_VERBOSE, "\rThe following payload is not properly terminated.\n");
dump (CCX_DMT_VERBOSE, cc_data, cc_count*3+1, 0, 0);
}
dbg_print(CCX_DMT_VERBOSE, "Reading %d HD CC blocks\n", cc_count);
// B-frames might be (temporal) before or after the anchor
// frame they belong to. Store the buffer until the next anchor
// frame occurs. The buffer will be flushed (sorted) in the
// picture header (or GOP) section when the next anchor occurs.
// Please note we store the current value of the global
// fts_now variable (and not get_fts()) as we are going to
// re-create the timeline in process_hdcc() (Slightly ugly).
store_hdcc(cc_data, cc_count, current_tref, fts_now, sub);
dbg_print(CCX_DMT_VERBOSE, "Reading HDTV blocks - done\n");
}
}
// reserved - additional_cc_data
}
// DVB closed caption header for Dish Network (Field 1 only) */
else if ( !memcmp(ud_header,"\x05\x02", 2 ) )
{
// Like HDTV (above) Dish Network captions can be stored at each
// frame, but maximal two caption blocks per frame and only one
// field is stored.
// To process this with the HDTV framework we create a "HDTV" caption
// format compatible array. Two times 3 bytes plus one for the 0xFF
// marker at the end. Pre-init to field 1 and set the 0xFF marker.
static unsigned char dishdata[7] = {0x04, 0, 0, 0x04, 0, 0, 0xFF};
int cc_count;
dbg_print(CCX_DMT_VERBOSE, "Reading Dish Network user data\n");
stat_dishheaders++;
read_bytes(ustream, 2); // "05 02"
// The next bytes are like this:
// header[2] : ID: 0x04 (MPEG?), 0x03 (H264?)
// header[3-4]: Two byte counter (counting (sub-)GOPs?)
// header[5-6]: Two bytes, maybe checksum?
// header[7]: Pattern type
// on B-frame: 0x02, 0x04
// on I-/P-frame: 0x05
unsigned char id = read_u8(ustream);
unsigned dishcount = read_u16(ustream);
unsigned something = read_u16(ustream);
unsigned char type = read_u8(ustream);
dbg_print(CCX_DMT_PARSE, "DN ID: %02X Count: %5u Unknown: %04X Pattern: %X",
id, dishcount, something, type);
unsigned char hi;
// The following block needs 4 to 6 bytes starting from the
// current position
unsigned char *dcd = ustream->pos; // dish caption data
switch (type)
{
case 0x02:
// Two byte caption - always on B-frame
// The following 4 bytes are:
// 0 : 0x09
// 1-2: caption block
// 3 : REPEAT - 02: two bytes
// - 04: four bytes (repeat first two)
dbg_print(CCX_DMT_PARSE, "\n02 %02X %02X:%02X - R:%02X :",
dcd[0], dcd[1], dcd[2], dcd[3]);
cc_count = 1;
dishdata[1]=dcd[1];
dishdata[2]=dcd[2];
dbg_print(CCX_DMT_PARSE, "%s", debug_608toASC( dishdata, 0) );
type=dcd[3]; // repeater (0x02 or 0x04)
hi = dishdata[1] & 0x7f; // Get only the 7 low bits
if (type==0x04 && hi<32) // repeat (only for non-character pairs)
{
cc_count = 2;
dishdata[3]=0x04; // Field 1
dishdata[4]=dishdata[1];
dishdata[5]=dishdata[2];
dbg_print(CCX_DMT_PARSE, "%s:\n", debug_608toASC( dishdata+3, 0) );
}
else
{
dbg_print(CCX_DMT_PARSE, ":\n");
}
dishdata[cc_count*3] = 0xFF; // Set end marker
store_hdcc(dishdata, cc_count, current_tref, fts_now, sub);
// Ignore 3 (0x0A, followed by two unknown) bytes.
break;
case 0x04:
// Four byte caption - always on B-frame
// The following 5 bytes are:
// 0 : 0x09
// 1-2: caption block
// 3-4: caption block
dbg_print(CCX_DMT_PARSE, "\n04 %02X %02X:%02X:%02X:%02X :",
dcd[0], dcd[1], dcd[2], dcd[3], dcd[4]);
cc_count = 2;
dishdata[1]=dcd[1];
dishdata[2]=dcd[2];
dishdata[3]=0x04; // Field 1
dishdata[4]=dcd[3];
dishdata[5]=dcd[4];
dishdata[6] = 0xFF; // Set end marker
dbg_print(CCX_DMT_PARSE, "%s", debug_608toASC( dishdata, 0) );
dbg_print(CCX_DMT_PARSE, "%s:\n", debug_608toASC( dishdata+3, 0) );
store_hdcc(dishdata, cc_count, current_tref, fts_now, sub);
// Ignore 4 (0x020A, followed by two unknown) bytes.
break;
case 0x05:
// Buffered caption - always on I-/P-frame
// The following six bytes are:
// 0 : 0x04
// - the following are from previous 0x05 caption header -
// 1 : prev dcd[2]
// 2-3: prev dcd[3-4]
// 4-5: prev dcd[5-6]
dbg_print(CCX_DMT_PARSE, " - %02X pch: %02X %5u %02X:%02X\n",
dcd[0], dcd[1],
(unsigned)dcd[2]*256+dcd[3],
dcd[4], dcd[5]);
dcd+=6; // Skip these 6 bytes
// Now one of the "regular" 0x02 or 0x04 captions follows
dbg_print(CCX_DMT_PARSE, "%02X %02X %02X:%02X",
dcd[0], dcd[1], dcd[2], dcd[3]);
type=dcd[0]; // Number of caption bytes (0x02 or 0x04)
cc_count = 1;
dishdata[1]=dcd[2];
dishdata[2]=dcd[3];
dcd+=4; // Skip the first 4 bytes.
if (type==0x02)
{
type=dcd[0]; // repeater (0x02 or 0x04)
dcd++; // Skip the repeater byte.
dbg_print(CCX_DMT_PARSE, " - R:%02X :%s", type, debug_608toASC( dishdata, 0) );
hi = dishdata[1] & 0x7f; // Get only the 7 low bits
if (type==0x04 && hi<32)
{
cc_count = 2;
dishdata[3]=0x04; // Field 1
dishdata[4]=dishdata[1];
dishdata[5]=dishdata[2];
dbg_print(CCX_DMT_PARSE, "%s:\n", debug_608toASC( dishdata+3, 0) );
}
else
{
dbg_print(CCX_DMT_PARSE, ":\n");
}
dishdata[cc_count*3] = 0xFF; // Set end marker
}
else
{
dbg_print(CCX_DMT_PARSE, ":%02X:%02X ",
dcd[0], dcd[1]);
cc_count = 2;
dishdata[3]=0x04; // Field 1
dishdata[4]=dcd[0];
dishdata[5]=dcd[1];
dishdata[6] = 0xFF; // Set end marker
dbg_print(CCX_DMT_PARSE, ":%s", debug_608toASC( dishdata, 0) );
dbg_print(CCX_DMT_PARSE, "%s:\n", debug_608toASC( dishdata+3, 0) );
}
store_hdcc(dishdata, cc_count, current_tref, fts_now, sub);
// Ignore 3 (0x0A, followed by 2 unknown) bytes.
break;
default:
// printf ("Unknown?\n");
break;
} // switch
dbg_print(CCX_DMT_VERBOSE, "Reading Dish Network user data - done\n");
}
// CEA 608 / aka "Divicom standard", see:
// http://www.pixeltools.com/tech_tip_closed_captioning.html
else if ( !memcmp(ud_header,"\x02\x09", 2 ) )
{
// Either a documentation or more examples are needed.
stat_divicom++;
unsigned char data[3];
read_bytes(ustream, 2); // "02 09"
read_bytes(ustream, 2); // "80 80" ???
read_bytes(ustream, 2); // "02 0A" ???
data[0]=0x04; // Field 1
data[1]=read_u8(ustream);
data[2]=read_u8(ustream);
do_cb(data, sub);
// This is probably incomplete!
}
else
{
// Some other user data
// 06 02 ... Seems to be DirectTV
dbg_print(CCX_DMT_VERBOSE, "Unrecognized user data:\n");
int udatalen = ustream->end - ustream->pos;
dump (CCX_DMT_VERBOSE, ustream->pos, (udatalen > 128 ? 128 : udatalen),0 ,0);
}
dbg_print(CCX_DMT_VERBOSE, "User data - processed\n");
// Read complete
return 1;
}

View File

@@ -1,467 +0,0 @@
#include "ccextractor.h"
long FILEBUFFERSIZE = 1024*1024*16; // 16 Mbytes no less. Minimize number of real read calls()
LLONG buffered_read_opt_file (unsigned char *buffer, unsigned int bytes);
#ifdef _WIN32
WSADATA wsaData = {0};
int iResult = 0;
#endif
LLONG getfilesize (int in)
{
int ret = 0;
LLONG current=LSEEK (in, 0, SEEK_CUR);
LLONG length = LSEEK (in,0,SEEK_END);
if(current < 0 ||length < 0)
return -1;
ret = LSEEK (in,current,SEEK_SET);
if (ret < 0)
return -1;
return length;
}
LLONG gettotalfilessize (void) // -1 if one or more files failed to open
{
LLONG ts=0;
int h;
for (int i=0;i<num_input_files;i++)
{
if (0 == strcmp(inputfile[i],"-")) // Skip stdin
continue;
#ifdef _WIN32
h=OPEN (inputfile[i],O_RDONLY | O_BINARY);
#else
h=OPEN (inputfile[i],O_RDONLY);
#endif
if (h==-1)
{
mprint ("\rUnable to open %s\r\n",inputfile[i]);
return -1;
}
if (!ccx_options.live_stream)
ts+=getfilesize (h);
close (h);
}
return ts;
}
void prepare_for_new_file (void)
{
// Init per file variables
min_pts=0x01FFFFFFFFLL; // 33 bit
sync_pts=0;
pts_set = 0;
// inputsize=0; Now responsibility of switch_to_next_file()
last_reported_progress=-1;
stat_numuserheaders = 0;
stat_dvdccheaders = 0;
stat_scte20ccheaders = 0;
stat_replay5000headers = 0;
stat_replay4000headers = 0;
stat_dishheaders = 0;
stat_hdtv = 0;
stat_divicom = 0;
total_frames_count = 0;
total_pulldownfields = 0;
total_pulldownframes = 0;
cc_stats[0]=0; cc_stats[1]=0; cc_stats[2]=0; cc_stats[3]=0;
false_pict_header=0;
frames_since_last_gop=0;
frames_since_ref_time=0;
gop_time.inited=0;
first_gop_time.inited=0;
gop_rollover=0;
printed_gop.inited=0;
saw_caption_block=0;
past=0;
pts_big_change=0;
startbytes_pos=0;
startbytes_avail=0;
init_file_buffer();
anchor_hdcc(-1);
firstcall = 1;
}
/* Close input file if there is one and let the GUI know */
void close_input_file (void)
{
if (infd!=-1 && ccx_options.input_source==CCX_DS_FILE)
{
close (infd);
infd=-1;
activity_input_file_closed();
}
}
/* Close current file and open next one in list -if any- */
/* bytesinbuffer is the number of bytes read (in some buffer) that haven't been added
to 'past' yet. We provide this number to switch_to_next_file() so a final sanity check
can be done */
int switch_to_next_file (LLONG bytesinbuffer)
{
if (current_file==-1 || !ccx_options.binary_concat)
{
memset (PIDs_seen,0,65536*sizeof (int));
memset (PIDs_programs,0,65536*sizeof (struct PMT_entry *));
}
if (ccx_options.input_source==CCX_DS_STDIN)
{
if (infd!=-1) // Means we had already processed stdin. So we're done.
{
if (ccx_options.print_file_reports)
print_file_report();
return 0;
}
infd=0;
mprint ("\n\r-----------------------------------------------------------------\n");
mprint ("\rReading from standard input\n");
return 1;
}
if (ccx_options.input_source==CCX_DS_NETWORK)
{
if (infd!=-1) // Means we have already bound a socket.
{
if (ccx_options.print_file_reports)
print_file_report();
return 0;
}
infd = start_upd_srv(ccx_options.udpaddr, ccx_options.udpport);
return 1;
if(infd < 0)
fatal (EXIT_BUG_BUG, "socket() failed.");
}
if (ccx_options.input_source==CCX_DS_TCP)
{
if (infd != -1)
{
if (ccx_options.print_file_reports)
print_file_report();
return 0;
}
infd = start_tcp_srv(ccx_options.tcpport, ccx_options.tcp_password);
return 1;
}
/* Close current and make sure things are still sane */
if (infd!=-1)
{
if (ccx_options.print_file_reports)
print_file_report();
close_input_file ();
if (inputsize>0 && ((past+bytesinbuffer) < inputsize) && !processed_enough)
{
mprint("\n\n\n\nATTENTION!!!!!!\n");
mprint("In switch_to_next_file(): Processing of %s %d ended prematurely %lld < %lld, please send bug report.\n\n",
inputfile[current_file], current_file, past, inputsize);
}
if (ccx_options.binary_concat)
{
total_past+=inputsize;
past=0; // Reset always or at the end we'll have double the size
}
}
for (;;)
{
current_file++;
if (current_file>=num_input_files)
break;
// The following \n keeps the progress percentage from being overwritten.
mprint ("\n\r-----------------------------------------------------------------\n");
mprint ("\rOpening file: %s\n", inputfile[current_file]);
#ifdef _WIN32
infd=OPEN (inputfile[current_file],O_RDONLY | O_BINARY);
#else
infd=OPEN (inputfile[current_file],O_RDONLY);
#endif
if (infd == -1)
mprint ("\rWarning: Unable to open input file [%s]\n", inputfile[current_file]);
else
{
activity_input_file_open (inputfile[current_file]);
if (!ccx_options.live_stream)
{
inputsize = getfilesize (infd);
if (!ccx_options.binary_concat)
total_inputsize=inputsize;
}
return 1; // Succeeded
}
}
return 0;
}
void position_sanity_check ()
{
#ifdef SANITY_CHECK
if (in!=-1)
{
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);
}
}
#endif
}
int init_file_buffer(void)
{
filebuffer_start=0;
filebuffer_pos=0;
if (filebuffer==NULL)
{
filebuffer=(unsigned char *) malloc (FILEBUFFERSIZE);
bytesinbuffer=0;
}
if (filebuffer==NULL)
{
fatal (EXIT_NOT_ENOUGH_MEMORY, "Not enough memory\n");
}
return 0;
}
void buffered_seek (int offset)
{
position_sanity_check();
if (offset<0)
{
filebuffer_pos+=offset;
if (filebuffer_pos<0)
{
// 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!");
}
startbytes_pos+=filebuffer_pos;
filebuffer_pos=0;
}
}
else
{
buffered_read_opt (NULL, offset);
position_sanity_check();
}
}
void sleepandchecktimeout (time_t start)
{
if (ccx_options.input_source==CCX_DS_STDIN)
{
// CFS: Not 100% sure about this. Fine for files, not so sure what happens if stdin is
// real time input from hardware.
sleep_secs (1);
ccx_options.live_stream=0;
return;
}
if (ccx_options.live_stream==-1) // Just sleep, no timeout to check
{
sleep_secs (1);
return;
}
if (time(NULL)>start+ccx_options.live_stream) // More than live_stream seconds elapsed. No more live
ccx_options.live_stream=0;
else
sleep_secs(1);
}
void return_to_buffer (unsigned char *buffer, unsigned int bytes)
{
if (bytes == filebuffer_pos)
{
// Usually we're just going back in the buffer and memcpy would be
// unnecessary, but we do it in case we intentionally messed with the
// buffer
memcpy (filebuffer, buffer, bytes);
filebuffer_pos=0;
return;
}
if (filebuffer_pos>0) // Discard old bytes, because we may need the space
{
// Non optimal since data is moved later again but we don't care since
// we're never here in ccextractor.
memmove (filebuffer,filebuffer+filebuffer_pos,bytesinbuffer-filebuffer_pos);
bytesinbuffer-=filebuffer_pos;
bytesinbuffer=0;
filebuffer_pos=0;
}
if (bytesinbuffer + bytes > FILEBUFFERSIZE)
fatal (EXIT_BUG_BUG, "Invalid return_to_buffer() - please submit a bug report.");
memmove (filebuffer+bytes,filebuffer,bytesinbuffer);
memcpy (filebuffer,buffer,bytes);
bytesinbuffer+=bytes;
}
LLONG buffered_read_opt (unsigned char *buffer, unsigned int bytes)
{
LLONG copied=0;
position_sanity_check();
time_t seconds=0;
if (ccx_options.live_stream>0)
time (&seconds);
if (ccx_options.buffer_input || filebuffer_pos<bytesinbuffer)
{
// Needs to return data from filebuffer_start+pos to filebuffer_start+pos+bytes-1;
int eof = (infd==-1);
while ((!eof || ccx_options.live_stream) && bytes)
{
if (eof)
{
// No more data available inmediately, we sleep a while to give time
// for the data to come up
sleepandchecktimeout (seconds);
}
size_t ready = bytesinbuffer-filebuffer_pos;
if (ready==0) // We really need to read more
{
if (!ccx_options.buffer_input)
{
// We got in the buffering code because of the initial buffer for
// detection stuff. However we don't want more buffering so
// we do the rest directly on the final buffer.
int i;
do
{
// No code for network support here, because network is always
// buffered - if here, then it must be files.
if (buffer!=NULL) // Read
{
i=read (infd,buffer,bytes);
if( i == -1)
fatal (EXIT_READ_ERROR, "Error reading input file!\n");
buffer+=i;
}
else // Seek
{
LLONG op, np;
op =LSEEK (infd,0,SEEK_CUR); // Get current pos
if (op+bytes<0) // Would mean moving beyond start of file: Not supported
return 0;
np =LSEEK (infd,bytes,SEEK_CUR); // Pos after moving
i=(int) (np-op);
}
if (i==0 && ccx_options.live_stream)
{
if (ccx_options.input_source==CCX_DS_STDIN)
{
ccx_options.live_stream = 0;
break;
}
else
{
sleepandchecktimeout (seconds);
}
}
else
{
copied+=i;
bytes-=i;
}
}
while ((i || ccx_options.live_stream ||
(ccx_options.binary_concat && switch_to_next_file(copied))) && bytes);
return copied;
}
// Keep the last 8 bytes, so we have a guaranteed
// working seek (-8) - needed by mythtv.
int keep = bytesinbuffer > 8 ? 8 : bytesinbuffer;
memmove (filebuffer,filebuffer+(FILEBUFFERSIZE-keep),keep);
int i;
if (ccx_options.input_source==CCX_DS_FILE || ccx_options.input_source==CCX_DS_STDIN)
i=read (infd, filebuffer+keep,FILEBUFFERSIZE-keep);
else
i = recvfrom(infd,(char *) filebuffer+keep,FILEBUFFERSIZE-keep,0,NULL,NULL);
if (i == -1)
fatal (EXIT_READ_ERROR, "Error reading input stream!\n");
if (i==0)
{
/* If live stream, don't try to switch - acknowledge eof here as it won't
cause a loop end */
if (ccx_options.live_stream || !(ccx_options.binary_concat && switch_to_next_file(copied)))
eof=1;
}
filebuffer_pos=keep;
bytesinbuffer=(int) i+keep;
ready=i;
}
int copy = (int) (ready>=bytes ? bytes:ready);
if (copy)
{
if (buffer!=NULL)
{
memcpy (buffer, filebuffer+filebuffer_pos, copy);
buffer+=copy;
}
filebuffer_pos+=copy;
bytes-=copy;
copied+=copy;
}
}
return copied;
}
else // Read without buffering
{
if (buffer!=NULL)
{
int i;
while (bytes>0 && infd!=-1 &&
((i=read(infd,buffer,bytes))!=0 || ccx_options.live_stream ||
(ccx_options.binary_concat && switch_to_next_file(copied))))
{
if( i == -1)
fatal (EXIT_READ_ERROR, "Error reading input file!\n");
else if (i==0)
sleepandchecktimeout (seconds);
else
{
copied+=i;
bytes-=i;
buffer+=i;
}
}
return copied;
}
// return fread(buffer,1,bytes,in);
//return FSEEK (in,bytes,SEEK_CUR);
while (bytes!=0 && infd!=-1)
{
LLONG op, np;
op =LSEEK (infd,0,SEEK_CUR); // Get current pos
if (op+bytes<0) // Would mean moving beyond start of file: Not supported
return 0;
np =LSEEK (infd,bytes,SEEK_CUR); // Pos after moving
copied=copied+(np-op);
bytes=bytes-(unsigned int) copied;
if (copied==0)
{
if (ccx_options.live_stream)
sleepandchecktimeout (seconds);
else
{
if (ccx_options.binary_concat)
switch_to_next_file(0);
else
break;
}
}
}
return copied;
}
}

View File

@@ -1,846 +0,0 @@
#include "ccextractor.h"
#ifdef _WIN32
#include <io.h>
#else
#include <unistd.h>
#endif
#include "708.h"
#include "dvb_subtitle_decoder.h"
#include "cc_encoders_common.h"
// IMPORTED TRASH INFO, REMOVE
extern long num_nal_unit_type_7;
extern long num_vcl_hrd;
extern long num_nal_hrd;
extern long num_jump_in_frames;
extern long num_unexpected_sei_length;
/* General video information */
unsigned current_hor_size = 0;
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?
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;
unsigned char *filebuffer;
LLONG filebuffer_start; // Position of buffer start relative to file
int filebuffer_pos; // Position of pointer relative to buffer start
int bytesinbuffer; // Number of bytes we actually have on buffer
extern void *cxx_dvb_context;
LLONG process_raw_with_field (struct cc_subtitle *sub);
// Program stream specific data grabber
LLONG ps_getmoredata(void)
{
int enough = 0;
int payload_read = 0;
static unsigned vpesnum=0;
unsigned char nextheader[512]; // Next header in PS
int falsepack=0;
// Read and return the next video PES payload
do
{
if (BUFSIZE-inbuf<500)
{
mprint("Less than 500 left\n");
enough=1; // Stop when less than 500 bytes are left in buffer
}
else
{
buffered_read(nextheader,6);
past+=result;
if (result!=6)
{
// Consider this the end of the show.
end_of_file=1;
break;
}
// Search for a header that is not a picture header (nextheader[3]!=0x00)
while ( !(nextheader[0]==0x00 && nextheader[1]==0x00
&& nextheader[2]==0x01 && nextheader[3]!=0x00) )
{
if( !strangeheader )
{
mprint ("\nNot a recognized header. Searching for next header.\n");
dump (CCX_DMT_GENERIC_NOTICES, nextheader,6,0,0);
// Only print the message once per loop / unrecognized header
strangeheader = 1;
}
unsigned char *newheader;
// The amount of bytes read into nextheader by the buffered_read above
int hlen = 6;
// Find first 0x00
// If there is a 00 in the first element we need to advance
// one step as clearly bytes 1,2,3 are wrong
newheader = (unsigned char *) memchr (nextheader+1, 0, hlen-1);
if (newheader != NULL )
{
int atpos = newheader-nextheader;
memmove (nextheader,newheader,(size_t)(hlen-atpos));
buffered_read(nextheader+(hlen-atpos),atpos);
past+=result;
if (result!=atpos)
{
end_of_file=1;
break;
}
}
else
{
buffered_read(nextheader,hlen);
past+=result;
if (result!=hlen)
{
end_of_file=1;
break;
}
}
}
if (end_of_file)
{
// No more headers
break;
}
// Found 00-00-01 in nextheader, assume a regular header
strangeheader=0;
// PACK header
if ( nextheader[3]==0xBA)
{
dbg_print(CCX_DMT_VERBOSE, "PACK header\n");
buffered_read(nextheader+6,8);
past+=result;
if (result!=8)
{
// Consider this the end of the show.
end_of_file=1;
break;
}
if ( (nextheader[4]&0xC4)!=0x44 || !(nextheader[6]&0x04)
|| !(nextheader[8]&0x04) || !(nextheader[9]&0x01)
|| (nextheader[12]&0x03)!=0x03 )
{
// broken pack header
falsepack=1;
}
// We don't need SCR/SCR_ext
int stufflen=nextheader[13]&0x07;
if (falsepack)
{
mprint ("Warning: Defective Pack header\n");
}
// If not defect, load stuffing
buffered_skip ((int) stufflen);
past+=stufflen;
// fake a result value as something was skipped
result=1;
continue;
}
// Some PES stream
else if (nextheader[3]>=0xBB && nextheader[3]<=0xDF)
{
// System header
// nextheader[3]==0xBB
// 0xBD Private 1
// 0xBE PAdding
// 0xBF Private 2
// 0xC0-0DF audio
unsigned headerlen=nextheader[4]<<8 | nextheader[5];
dbg_print(CCX_DMT_VERBOSE, "non Video PES (type 0x%2X) - len %u\n",
nextheader[3], headerlen);
// The 15000 here is quite arbitrary, the longest packages I
// know of are 12302 bytes (Private 1 data in RTL recording).
if ( headerlen > 15000 )
{
mprint("Suspicious non Video PES (type 0x%2X) - len %u\n",
nextheader[3], headerlen);
mprint("Do not skip over, search for next.\n");
headerlen = 2;
}
// Skip over it
buffered_skip ((int) headerlen);
past+=headerlen;
// fake a result value as something was skipped
result=1;
continue;
}
// Read the next video PES
else if ((nextheader[3]&0xf0)==0xe0)
{
int hlen; // Dummy variable, unused
int peslen = read_video_pes_header(nextheader, &hlen, 0);
if (peslen < 0)
{
end_of_file=1;
break;
}
vpesnum++;
dbg_print(CCX_DMT_VERBOSE, "PES video packet #%u\n", vpesnum);
int want = (int) ((BUFSIZE-inbuf)>peslen ? peslen : (BUFSIZE-inbuf));
if (want != peslen) {
fatal(EXIT_BUFFER_FULL, "Oh Oh, PES longer than remaining buffer space\n");
}
if (want == 0) // Found package with header but without payload
{
continue;
}
buffered_read (buffer+inbuf,want);
past=past+result;
if (result>0) {
payload_read+=(int) result;
}
inbuf+=result;
if (result!=want) { // Not complete - EOF
end_of_file=1;
break;
}
enough = 1; // We got one PES
} else {
// If we are here this is an unknown header type
mprint("Unknown header %02X\n", nextheader[3]);
strangeheader=1;
}
}
}
while (result!=0 && !enough && BUFSIZE!=inbuf);
dbg_print(CCX_DMT_VERBOSE, "PES data read: %d\n", payload_read);
return payload_read;
}
// Returns number of bytes read, or zero for EOF
LLONG general_getmoredata(void)
{
int bytesread = 0;
int want;
do
{
want = (int) (BUFSIZE-inbuf);
buffered_read (buffer+inbuf,want); // This is a macro.
// 'result' HAS the number of bytes read
past=past+result;
inbuf+=result;
bytesread+=(int) result;
} while (result!=0 && result!=want);
return bytesread;
}
#ifdef WTV_DEBUG
// Hexadecimal dump process
void processhex (char *filename)
{
size_t max=(size_t) inputsize+1; // Enough for the whole thing. Hex dumps are small so we can be lazy here
char *line=(char *) malloc (max);
/* const char *mpeg_header="00 00 01 b2 43 43 01 f8 "; // Always present */
FILE *fr = fopen (filename, "rt");
unsigned char *bytes=NULL;
unsigned byte_count=0;
int warning_shown=0;
while(fgets(line, max-1, fr) != NULL)
{
char *c1, *c2=NULL; // Positions for first and second colons
/* int len; */
long timing;
if (line[0]==';') // Skip comments
continue;
c1=strchr (line,':');
if (c1) c2=strchr (c1+1,':');
if (!c2) // Line doesn't contain what we want
continue;
*c1=0;
*c2=0;
/* len=atoi (line); */
timing=atol (c1+2)*(MPEG_CLOCK_FREQ/1000);
current_pts=timing;
if (pts_set==0)
pts_set=1;
set_fts();
c2++;
/*
if (strlen (c2)==8)
{
unsigned char high1=c2[1];
unsigned char low1=c2[2];
int value1=hex2int (high1,low1);
unsigned char high2=c2[4];
unsigned char low2=c2[5];
int value2=hex2int (high2,low2);
buffer[0]=value1;
buffer[1]=value2;
inbuf=2;
process_raw();
continue;
}
if (strlen (c2)<=(strlen (mpeg_header)+1))
continue; */
c2++; // Skip blank
/*
if (strncmp (c2,mpeg_header,strlen (mpeg_header))) // No idea how to deal with this.
{
if (!warning_shown)
{
warning_shown=1;
mprint ("\nWarning: This file contains data I can't process: Please submit .hex for analysis!\n");
}
continue;
}
// OK, seems like a decent chunk of CCdata.
c2+=strlen (mpeg_header);
*/
byte_count=strlen (c2)/3;
/*
if (atoi (line)!=byte_count+strlen (mpeg_header)/3) // Number of bytes reported don't match actual contents
continue;
*/
if (atoi (line)!=byte_count) // Number of bytes reported don't match actual contents
continue;
if (!byte_count) // Nothing to get from this line except timing info, already done.
continue;
bytes=(unsigned char *) malloc (byte_count);
if (!bytes)
fatal (EXIT_NOT_ENOUGH_MEMORY, "Out of memory.\n");
unsigned char *bytes=(unsigned char *) malloc (byte_count);
for (unsigned i=0;i<byte_count;i++)
{
unsigned char high=c2[0];
unsigned char low=c2[1];
int value=hex2int (high,low);
if (value==-1)
fatal (EXIT_FAILURE, "Incorrect format, unexpected non-hex string.");
bytes[i]=value;
c2+=3;
}
memcpy (buffer, bytes, byte_count);
inbuf=byte_count;
process_raw();
continue;
// New wtv format, everything else hopefully obsolete
int ok=0; // Were we able to process the line?
// Attempt to detect how the data is encoded.
// Case 1 (seen in all elderman's samples):
// 18 : 467 : 00 00 01 b2 43 43 01 f8 03 42 ff fd 54 80 fc 94 2c ff
// Always 03 after header, then something unknown (seen 42, 43, c2, c3...),
// then ff, then data with field info, and terminated with ff.
if (byte_count>3 && bytes[0]==0x03 &&
bytes[2]==0xff && bytes[byte_count-1]==0xff)
{
ok=1;
for (unsigned i=3; i<byte_count-2; i+=3)
{
inbuf=3;
buffer[0]=bytes[i];
buffer[1]=bytes[i+1];
buffer[2]=bytes[i+2];
process_raw_with_field();
}
}
// Case 2 (seen in P2Pfiend samples):
// Seems to match McPoodle's descriptions on DVD encoding
else
{
unsigned char magic=bytes[0];
/* unsigned extra_field_flag=magic&1; */
unsigned caption_count=((magic>>1)&0x1F);
unsigned filler=((magic>>6)&1);
/* unsigned pattern=((magic>>7)&1); */
int always_ff=1;
int current_field=0;
if (filler==0 && caption_count*6==byte_count-1) // Note that we are ignoring the extra field for now...
{
ok=1;
for (unsigned i=1; i<byte_count-2; i+=3)
if (bytes[i]!=0xff)
{
// If we only find FF in the first byte then either there's only field 1 data, OR
// there's alternating field 1 and field 2 data. Don't know how to tell apart. For now
// let's assume that always FF means alternating.
always_ff=0;
break;
}
for (unsigned i=1; i<byte_count-2; i+=3)
{
inbuf=3;
if (always_ff) // Try to tell apart the fields based on the pattern field.
{
buffer[0]=current_field | 4; // | 4 to enable the 'valid' bit
current_field = !current_field;
}
else
buffer[0]=bytes[i];
buffer[1]=bytes[i+1];
buffer[2]=bytes[i+2];
process_raw_with_field();
}
}
}
if (!ok && !warning_shown)
{
warning_shown=1;
mprint ("\nWarning: This file contains data I can't process: Please submit .hex for analysis!\n");
}
free (bytes);
}
fclose(fr);
}
#endif
// Raw file process
void raw_loop (void *enc_ctx)
{
LLONG got;
LLONG processed;
struct cc_subtitle dec_sub;
current_pts = 90; // Pick a valid PTS time
pts_set = 1;
set_fts(); // Now set the FTS related variables
memset(&dec_sub, 0, sizeof(dec_sub));
dbg_print(CCX_DMT_VIDES, "PTS: %s (%8u)",
print_mstime(current_pts/(MPEG_CLOCK_FREQ/1000)),
(unsigned) (current_pts));
dbg_print(CCX_DMT_VIDES, " FTS: %s\n", print_mstime(get_fts()));
do
{
inbuf=0;
got=general_getmoredata();
if (got == 0) // Shortcircuit if we got nothing to process
break;
processed=process_raw(&dec_sub);
if (dec_sub.got_output)
{
encode_sub(enc_ctx,&dec_sub);
dec_sub.got_output = 0;
}
int ccblocks = cb_field1;
current_pts += cb_field1*1001/30*(MPEG_CLOCK_FREQ/1000);
set_fts(); // Now set the FTS related variables including fts_max
dbg_print(CCX_DMT_VIDES, "PTS: %s (%8u)",
print_mstime(current_pts/(MPEG_CLOCK_FREQ/1000)),
(unsigned) (current_pts));
dbg_print(CCX_DMT_VIDES, " FTS: %s incl. %d CB\n",
print_mstime(get_fts()), ccblocks);
if (processed<got)
{
mprint ("BUG BUG\n");
}
}
while (inbuf);
}
/* Process inbuf bytes in buffer holding raw caption data (three byte packets, the first being the field).
* The number of processed bytes is returned. */
LLONG process_raw_with_field ( struct cc_subtitle *sub)
{
unsigned char data[3];
data[0]=0x04; // Field 1
current_field=1;
for (unsigned long i=0; i<inbuf; i=i+3)
{
if ( !saw_caption_block && *(buffer+i)==0xff && *(buffer+i+1)==0xff)
{
// Skip broadcast header
}
else
{
data[0]=buffer[i];
data[1]=buffer[i+1];
data[2]=buffer[i+2];
// do_cb increases the cb_field1 counter so that get_fts()
// is correct.
do_cb(data, sub);
}
}
return inbuf;
}
/* Process inbuf bytes in buffer holding raw caption data (two byte packets).
* The number of processed bytes is returned. */
LLONG process_raw (struct cc_subtitle *sub)
{
unsigned char data[3];
data[0]=0x04; // Field 1
current_field=1;
for (unsigned long i=0; i<inbuf; i=i+2)
{
if ( !saw_caption_block && *(buffer+i)==0xff && *(buffer+i+1)==0xff)
{
// Skip broadcast header
}
else
{
data[1]=buffer[i];
data[2]=buffer[i+1];
// do_cb increases the cb_field1 counter so that get_fts()
// is correct.
do_cb(data,sub);
}
}
return inbuf;
}
void general_loop(void *enc_ctx)
{
LLONG overlap=0;
LLONG pos = 0; /* Current position in buffer */
struct cc_subtitle dec_sub;
inbuf = 0; // No data yet
end_of_file = 0;
current_picture_coding_type = CCX_FRAME_TYPE_RESET_OR_UNKNOWN;
memset(&dec_sub, 0,sizeof(dec_sub));
while (!end_of_file && !processed_enough)
{
/* Get rid of the bytes we already processed */
overlap=inbuf-pos;
if ( pos != 0 ) {
// Only when needed as memmove has been seen crashing
// for dest==source and n >0
memmove (buffer,buffer+pos,(size_t) (inbuf-pos));
inbuf-=pos;
}
pos = 0;
// GET MORE DATA IN BUFFER
LLONG i;
position_sanity_check();
switch (stream_mode)
{
case CCX_SM_ELEMENTARY_OR_NOT_FOUND:
i = general_getmoredata();
break;
case CCX_SM_TRANSPORT:
i = ts_getmoredata();
break;
case CCX_SM_PROGRAM:
i = ps_getmoredata();
break;
case CCX_SM_ASF:
i = asf_getmoredata();
break;
case CCX_SM_WTV:
i = wtv_getmoredata();
break;
default:
fatal(EXIT_BUG_BUG, "Impossible stream_mode");
}
position_sanity_check();
if (fh_out_elementarystream!=NULL)
fwrite (buffer+overlap,1,(size_t) (inbuf-overlap),fh_out_elementarystream);
if (i==0)
{
end_of_file = 1;
memset (buffer+inbuf, 0, (size_t) (BUFSIZE-inbuf)); /* Clear buffer at the end */
}
if (inbuf == 0)
{
/* Done: Get outta here */
break;
}
LLONG got; // Means 'consumed' from buffer actually
static LLONG last_pts = 0x01FFFFFFFFLL;
if (ccx_options.hauppauge_mode)
{
got = process_raw_with_field(&dec_sub);
if (pts_set)
set_fts(); // Try to fix timing from TS data
}
else if(ccx_bufferdatatype == CCX_DVB_SUBTITLE)
{
dvbsub_decode(cxx_dvb_context, buffer + 2, inbuf, &dec_sub);
set_fts();
got = inbuf;
}
else if (ccx_bufferdatatype == CCX_PES)
{
got = process_m2v (buffer, inbuf,&dec_sub);
}
else if (ccx_bufferdatatype == CCX_TELETEXT)
{
// Dispatch to Petr Kutalek 's telxcc.
tlt_process_pes_packet (buffer, (uint16_t) inbuf);
got = inbuf;
}
else if (ccx_bufferdatatype == CCX_PRIVATE_MPEG2_CC)
{
got = inbuf; // Do nothing. Still don't know how to process it
}
else if (ccx_bufferdatatype == CCX_RAW) // Raw two byte 608 data from DVR-MS/ASF
{
// The asf_getmoredata() loop sets current_pts when possible
if (pts_set == 0)
{
mprint("DVR-MS/ASF file without useful time stamps - count blocks.\n");
// Otherwise rely on counting blocks
current_pts = 12345; // Pick a valid PTS time
pts_set = 1;
}
if (current_pts != last_pts)
{
// Only initialize the FTS values and reset the cb
// counters when the PTS is different. This happens frequently
// with ASF files.
if (min_pts==0x01FFFFFFFFLL)
{
// First call
fts_at_gop_start = 0;
}
else
fts_at_gop_start = get_fts();
frames_since_ref_time = 0;
set_fts();
last_pts = current_pts;
}
dbg_print(CCX_DMT_VIDES, "PTS: %s (%8u)",
print_mstime(current_pts/(MPEG_CLOCK_FREQ/1000)),
(unsigned) (current_pts));
dbg_print(CCX_DMT_VIDES, " FTS: %s\n", print_mstime(get_fts()));
got = process_raw(&dec_sub);
}
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!");
if (got>inbuf)
{
mprint ("BUG BUG\n");
}
pos+=got;
if (ccx_options.live_stream)
{
int cur_sec = (int) (get_fts() / 1000);
int th=cur_sec/10;
if (last_reported_progress!=th)
{
activity_progress (-1,cur_sec/60, cur_sec%60);
last_reported_progress = th;
}
}
else
{
if (total_inputsize>255) // Less than 255 leads to division by zero below.
{
int progress = (int) ((((total_past+past)>>8)*100)/(total_inputsize>>8));
if (last_reported_progress != progress)
{
LLONG t=get_fts();
if (!t && global_timestamp_inited)
t=global_timestamp-min_global_timestamp;
int cur_sec = (int) (t / 1000);
activity_progress(progress, cur_sec/60, cur_sec%60);
last_reported_progress = progress;
}
}
}
if (dec_sub.got_output)
{
encode_sub(enc_ctx,&dec_sub);
dec_sub.got_output = 0;
}
position_sanity_check();
}
// Flush remaining HD captions
if (has_ccdata_buffered)
process_hdcc(&dec_sub);
if (total_past!=total_inputsize && ccx_options.binary_concat && !processed_enough)
{
mprint("\n\n\n\nATTENTION!!!!!!\n");
mprint("Processing of %s %d ended prematurely %lld < %lld, please send bug report.\n\n",
inputfile[current_file], current_file, past, inputsize);
}
mprint ("\nNumber of NAL_type_7: %ld\n",num_nal_unit_type_7);
mprint ("Number of VCL_HRD: %ld\n",num_vcl_hrd);
mprint ("Number of NAL HRD: %ld\n",num_nal_hrd);
mprint ("Number of jump-in-frames: %ld\n",num_jump_in_frames);
mprint ("Number of num_unexpected_sei_length: %ld", num_unexpected_sei_length);
}
// Raw caption with FTS file process
void rcwt_loop(void *enc_ctx)
{
static unsigned char *parsebuf;
static long parsebufsize = 1024;
struct cc_subtitle dec_sub;
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");
// Generic buffer to hold some data
parsebuf = (unsigned char*)malloc(1024);
LLONG currfts;
uint16_t cbcount = 0;
int bread = 0; // Bytes read
buffered_read(parsebuf,11);
past+=result;
bread+=(int) result;
if (result!=11)
{
mprint("Premature end of file!\n");
end_of_file=1;
return;
}
// Expecting RCWT header
if( !memcmp(parsebuf, "\xCC\xCC\xED", 3 ) )
{
dbg_print(CCX_DMT_PARSE, "\nRCWT header\n");
dbg_print(CCX_DMT_PARSE, "File created by %02X version %02X%02X\nFile format revision: %02X%02X\n",
parsebuf[3], parsebuf[4], parsebuf[5],
parsebuf[6], parsebuf[7]);
}
else
{
fatal(EXIT_MISSING_RCWT_HEADER, "Missing RCWT header. Abort.\n");
}
// Initialize first time. As RCWT files come with the correct FTS the
// initial (minimal) time needs to be set to 0.
current_pts = 0;
pts_set=1;
set_fts(); // Now set the FTS related variables
// Loop until no more data is found
while(1)
{
// Read the data header
buffered_read(parsebuf,10);
past+=result;
bread+=(int) result;
if (result!=10)
{
if (result!=0)
mprint("Premature end of file!\n");
// We are done
end_of_file=1;
break;
}
currfts = *((LLONG*)(parsebuf));
cbcount = *((uint16_t*)(parsebuf+8));
dbg_print(CCX_DMT_PARSE, "RCWT data header FTS: %s blocks: %u\n",
print_mstime(currfts), cbcount);
if ( cbcount > 0 )
{
if ( cbcount*3 > parsebufsize) {
parsebuf = (unsigned char*)realloc(parsebuf, cbcount*3);
if (!parsebuf)
fatal(EXIT_NOT_ENOUGH_MEMORY, "Out of memory");
parsebufsize = cbcount*3;
}
buffered_read(parsebuf,cbcount*3);
past+=result;
bread+=(int) result;
if (result!=cbcount*3)
{
mprint("Premature end of file!\n");
end_of_file=1;
break;
}
// Process the data
current_pts = currfts*(MPEG_CLOCK_FREQ/1000);
if (pts_set==0)
pts_set=1;
set_fts(); // Now set the FTS related variables
dbg_print(CCX_DMT_VIDES, "PTS: %s (%8u)",
print_mstime(current_pts/(MPEG_CLOCK_FREQ/1000)),
(unsigned) (current_pts));
dbg_print(CCX_DMT_VIDES, " FTS: %s\n", print_mstime(get_fts()));
for (int j=0; j<cbcount*3; j=j+3)
{
do_cb(parsebuf+j, &dec_sub);
}
}
if (dec_sub.got_output)
{
encode_sub(enc_ctx,&dec_sub);
dec_sub.got_output = 0;
}
} // end while(1)
dbg_print(CCX_DMT_PARSE, "Processed %d bytes\n", bread);
}

View File

@@ -25,7 +25,7 @@
*
*/
#include "../disable_warnings.h"
#include "disable_warnings.h"
#include <gpac/setup.h>
#ifndef GPAC_DISABLE_AVILIB

View File

@@ -21,7 +21,7 @@
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#include "../disable_warnings.h"
#include "disable_warnings.h"
#include <gpac/internal/isomedia_dev.h>
#ifndef GPAC_DISABLE_ISOM

View File

@@ -21,7 +21,7 @@
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#include "../disable_warnings.h"
#include "disable_warnings.h"
#include <gpac/internal/isomedia_dev.h>
#ifndef GPAC_DISABLE_ISOM
@@ -6159,6 +6159,12 @@ static void gf_isom_check_sample_desc(GF_TrackBox *trak)
u32 i;
i=0;
if(!trak->Media->information->sampleTable->SampleDescription)
{
printf("\nCCEXTRACTOR: Ignore table without description\n");
return;
}
while ((a = (GF_UnknownBox*)gf_list_enum(trak->Media->information->sampleTable->SampleDescription->boxList, &i))) {
switch (a->type) {
case GF_ISOM_BOX_TYPE_MP4S:

View File

@@ -21,7 +21,7 @@
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#include "../disable_warnings.h"
#include "disable_warnings.h"
#include <gpac/internal/isomedia_dev.h>
#include <gpac/network.h>

View File

@@ -21,7 +21,7 @@
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#include "../disable_warnings.h"
#include "disable_warnings.h"
#include <gpac/internal/odf_dev.h>
#include <gpac/constants.h>

View File

@@ -21,7 +21,7 @@
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#include "../disable_warnings.h"
#include "disable_warnings.h"
#include <gpac/tools.h>

View File

@@ -227,7 +227,8 @@ enum
GF_ISOM_SUBTYPE_LSR1 = GF_4CC( 'l', 's', 'r', '1' ),
/* CAPTIONS */
GF_ISOM_SUBTYPE_C608 = GF_4CC ('c', '6', '0', '8' )
GF_ISOM_SUBTYPE_C608 = GF_4CC( 'c', '6', '0', '8' ),
GF_ISOM_SUBTYPE_C708 = GF_4CC( 'c', '7', '0', '8' )
};

View File

@@ -22,7 +22,7 @@
*
*/
#include "../disable_warnings.h"
#include "disable_warnings.h"
#include <gpac/internal/odf_dev.h>
#ifndef GPAC_MINIMAL_ODF

View File

@@ -21,7 +21,7 @@
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#include "../disable_warnings.h"
#include "disable_warnings.h"
#include <gpac/internal/isomedia_dev.h>
#include <gpac/network.h>
#ifndef _WIN32

View File

@@ -22,7 +22,7 @@
*
*/
#include "../disable_warnings.h"
#include "disable_warnings.h"
#include <gpac/internal/isomedia_dev.h>
#include <gpac/constants.h>
@@ -1736,15 +1736,15 @@ GF_Err gf_isom_get_chunks_infos(GF_ISOFile *movie, u32 trackNumber, u32 *dur_min
chunk_dur += dur;
stbl_GetSampleSize(trak->Media->information->sampleTable->SampleSize, k+sample_idx, &size);
chunk_size += size;
}
if (dmin>chunk_dur) dmin = chunk_dur;
if (dmax<chunk_dur) dmax = chunk_dur;
davg += chunk_dur;
if (smin>chunk_size) smin = chunk_size;
if (smax<chunk_size) smax = chunk_size;
savg += chunk_dur;
savg += chunk_size;
tot_chunks ++;
sample_idx += stsc->entries[i].samplesPerChunk;
if (i+1==stsc->nb_entries) break;
@@ -1752,8 +1752,10 @@ GF_Err gf_isom_get_chunks_infos(GF_ISOFile *movie, u32 trackNumber, u32 *dur_min
if (stsc->entries[i].firstChunk + nb_chunk == stsc->entries[i+1].firstChunk) break;
}
}
if (tot_chunks) davg /= tot_chunks;
if (tot_chunks) {
davg /= tot_chunks;
savg /= tot_chunks;
}
if (dur_min) *dur_min = dmin;
if (dur_avg) *dur_avg = (u32) davg;
if (dur_max) *dur_max = dmax;

View File

@@ -22,7 +22,7 @@
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#include "../disable_warnings.h"
#include "disable_warnings.h"
#include <gpac/internal/isomedia_dev.h>
#if !defined(GPAC_DISABLE_ISOM) && !defined(GPAC_DISABLE_ISOM_WRITE)

View File

@@ -21,7 +21,7 @@
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#include "../disable_warnings.h"
#include "disable_warnings.h"
#include <gpac/internal/isomedia_dev.h>
#if !defined(GPAC_DISABLE_ISOM) && !defined(GPAC_DISABLE_ISOM_WRITE)

View File

@@ -21,7 +21,7 @@
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#include "../disable_warnings.h"
#include "disable_warnings.h"
#include <gpac/internal/isomedia_dev.h>
#include <gpac/constants.h>
@@ -333,10 +333,12 @@ GF_Err Media_GetSample(GF_MediaBox *mdia, u32 sampleNumber, GF_ISOSample **samp,
//divided into the original and the edition files
if (mdia->mediaTrack->moov->mov->openMode == GF_ISOM_OPEN_READ) {
//same as last call in read mode
if (!mdia->information->dataHandler || (mdia->information->dataEntryIndex != dataRefIndex)) {
if (!mdia->information->dataHandler) {
e = gf_isom_datamap_open(mdia, dataRefIndex, isEdited);
if (e) return e;
}
if (mdia->information->dataEntryIndex != dataRefIndex)
mdia->information->dataEntryIndex = dataRefIndex;
} else {
e = gf_isom_datamap_open(mdia, dataRefIndex, isEdited);
if (e) return e;

View File

@@ -23,7 +23,7 @@
*
*/
#include "../disable_warnings.h"
#include "disable_warnings.h"
#include <gpac/internal/isomedia_dev.h>
#ifndef GPAC_DISABLE_ISOM

View File

@@ -3,12 +3,13 @@
#include <stdlib.h>
#include <gpac/isomedia.h>
#include "../ccextractor.h"
#include "../utility.h"
#include "../cc_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
#include "lib_ccx.h"
#include "utility.h"
#include "ccx_encoders_common.h"
#include "ccx_common_option.h"
#include "ccx_mp4.h"
#include "activity.h"
#include "ccx_dtvcc.h"
static short bswap16(short v)
{
@@ -26,16 +27,17 @@ static struct {
unsigned type[32];
}s_nalu_stats;
static int process_avc_sample(u32 timescale, GF_AVCConfig* c, GF_ISOSample* s, struct cc_subtitle *sub)
static int process_avc_sample(struct lib_ccx_ctx *ctx, u32 timescale, GF_AVCConfig* c, GF_ISOSample* s, struct cc_subtitle *sub)
{
int status = 0;
u32 i;
s32 signed_cts=(s32) s->CTS_Offset; // Convert from unsigned to signed. GPAC uses u32 but unsigned values are legal.
current_pts=(LLONG )(s->DTS + signed_cts)*MPEG_CLOCK_FREQ/timescale ; // Convert frequency to official one
struct lib_cc_decode *dec_ctx = NULL;
if (pts_set==0)
pts_set=1;
set_fts();
dec_ctx = update_decoder_list(ctx);
set_current_pts(dec_ctx->timing, (s->DTS + signed_cts)*MPEG_CLOCK_FREQ/timescale);
set_fts(dec_ctx->timing);
for(i = 0; i < s->dataLength; )
{
@@ -61,18 +63,21 @@ static int process_avc_sample(u32 timescale, GF_AVCConfig* c, GF_ISOSample* s, s
temp_debug=0;
if (nal_length>0)
do_NAL ((unsigned char *) &(s->data[i]) ,nal_length, sub);
do_NAL (dec_ctx, (unsigned char *) &(s->data[i]) ,nal_length, sub);
i += nal_length;
} // outer for
assert(i == s->dataLength);
return status;
}
static int process_xdvb_track(const char* basename, GF_ISOFile* f, u32 track, struct cc_subtitle *sub)
static int process_xdvb_track(struct lib_ccx_ctx *ctx, const char* basename, GF_ISOFile* f, u32 track, struct cc_subtitle *sub)
{
u32 timescale, i, sample_count;
int status;
struct lib_cc_decode *dec_ctx = NULL;
dec_ctx = update_decoder_list(ctx);
if((sample_count = gf_isom_get_sample_count(f, track)) < 1)
{
return 0;
@@ -90,34 +95,35 @@ static int process_xdvb_track(const char* basename, GF_ISOFile* f, u32 track, st
if (s!=NULL)
{
s32 signed_cts=(s32) s->CTS_Offset; // Convert from unsigned to signed. GPAC uses u32 but unsigned values are legal.
current_pts=(LLONG )(s->DTS + signed_cts)*MPEG_CLOCK_FREQ/timescale ; // Convert frequency to official one
if (pts_set==0)
pts_set=1;
set_fts();
set_current_pts(dec_ctx->timing, (s->DTS + signed_cts)*MPEG_CLOCK_FREQ/timescale);
set_fts(dec_ctx->timing);
process_m2v ((unsigned char *) s->data,s->dataLength, sub);
process_m2v (dec_ctx, (unsigned char *) s->data,s->dataLength, sub);
gf_isom_sample_del(&s);
}
int progress = (int) ((i*100) / sample_count);
if (last_reported_progress != progress)
if (ctx->last_reported_progress != progress)
{
int cur_sec = (int) (get_fts() / 1000);
int cur_sec = (int) (get_fts(dec_ctx->timing, dec_ctx->current_field) / 1000);
activity_progress(progress, cur_sec/60, cur_sec%60);
last_reported_progress = progress;
ctx->last_reported_progress = progress;
}
}
int cur_sec = (int) (get_fts() / 1000);
int cur_sec = (int) (get_fts(dec_ctx->timing, dec_ctx->current_field) / 1000);
activity_progress(100, cur_sec/60, cur_sec%60);
return status;
}
static int process_avc_track(const char* basename, GF_ISOFile* f, u32 track, struct cc_subtitle *sub)
static int process_avc_track(struct lib_ccx_ctx *ctx, const char* basename, GF_ISOFile* f, u32 track, struct cc_subtitle *sub)
{
u32 timescale, i, sample_count, last_sdi = 0;
int status;
GF_AVCConfig* c = NULL;
struct lib_cc_decode *dec_ctx = NULL;
dec_ctx = update_decoder_list(ctx);
if((sample_count = gf_isom_get_sample_count(f, track)) < 1)
{
@@ -154,7 +160,7 @@ static int process_avc_track(const char* basename, GF_ISOFile* f, u32 track, str
last_sdi = sdi;
}
status = process_avc_sample(timescale, c, s, sub);
status = process_avc_sample(ctx, timescale, c, s, sub);
gf_isom_sample_del(&s);
@@ -165,14 +171,14 @@ static int process_avc_track(const char* basename, GF_ISOFile* f, u32 track, str
}
int progress = (int) ((i*100) / sample_count);
if (last_reported_progress != progress)
if (ctx->last_reported_progress != progress)
{
int cur_sec = (int) (get_fts() / 1000);
int cur_sec = (int) (get_fts(dec_ctx->timing, dec_ctx->current_field) / 1000);
activity_progress(progress, cur_sec/60, cur_sec%60);
last_reported_progress = progress;
ctx->last_reported_progress = progress;
}
}
int cur_sec = (int) (get_fts() / 1000);
int cur_sec = (int) (get_fts(dec_ctx->timing, dec_ctx->current_field) / 1000);
activity_progress(100, cur_sec/60, cur_sec%60);
if(c != NULL)
@@ -184,6 +190,87 @@ static int process_avc_track(const char* basename, GF_ISOFile* f, u32 track, str
return status;
}
unsigned char * ccdp_find_data(unsigned char * ccdp_atom_content, unsigned int len, unsigned int *cc_count)
{
unsigned char *data = ccdp_atom_content;
if (len < 4)
{
dbg_print(CCX_DMT_PARSE, "mp4-708-cdp: unexpected size of cdp\n");
return NULL;
}
unsigned int cdp_id = (data[0] << 8) | data[1];
if (cdp_id != 0x9669)
{
dbg_print(CCX_DMT_PARSE, "mp4-708-cdp: unexpected header %hhX %hhX\n", data[0], data[1]);
return NULL;
}
data += 2;
len -= 2;
unsigned int cdp_data_count = data[0];
unsigned int cdp_frame_rate = data[1] >> 4; //frequency could be calculated
if (cdp_data_count != len + 2)
{
dbg_print(CCX_DMT_PARSE, "mp4-708-cdp: unexpected data length %u %u\n", cdp_data_count, len + 2);
return NULL;
}
data += 2;
len -= 2;
unsigned int cdp_flags = data[0];
unsigned int cdp_counter = (data[1] << 8) | data[2];
data += 3;
len -= 3;
unsigned int cdp_timecode_added = (cdp_flags & 0x80) >> 7;
unsigned int cdp_data_added = (cdp_flags & 0x40) >> 6;
if (!cdp_data_added)
{
dbg_print(CCX_DMT_PARSE, "mp4-708-cdp: packet without data\n");
return NULL;
}
if (cdp_timecode_added)
{
data += 4;
len -= 4;
}
if (data[0] != CDP_SECTION_DATA)
{
dbg_print(CCX_DMT_PARSE, "mp4-708-cdp: cdp_data_section byte not found\n");
return NULL;
}
*cc_count = (unsigned int) (data[1] & 0x1F);
if (*cc_count != 10 && *cc_count != 20 && *cc_count != 25 && *cc_count != 30)
{
dbg_print(CCX_DMT_PARSE, "mp4-708-cdp: unexpected cc_count %u\n", *cc_count);
return NULL;
}
data += 2;
len -= 2;
if ((*cc_count) * 3 > len)
{
dbg_print(CCX_DMT_PARSE, "mp4-708-cdp: not enough bytes left (%u) to carry %u*3 bytes\n", len, *cc_count);
return NULL;
}
(void)(cdp_counter);
(void)(cdp_frame_rate);
return data;
}
/*
Here is application algorithm described in some C-like pseudo code:
main(){
@@ -197,11 +284,15 @@ static int process_avc_track(const char* basename, GF_ISOFile* f, u32 track, str
}
*/
int processmp4 (char *file,void *enc_ctx)
int processmp4 (struct lib_ccx_ctx *ctx,struct ccx_s_mp4Cfg *cfg, char *file)
{
GF_ISOFile* f;
u32 i, j, track_count, avc_track_count, cc_track_count;
struct cc_subtitle dec_sub;
struct lib_cc_decode *dec_ctx = NULL;
struct encoder_ctx *enc_ctx = update_encoder_list(ctx);
dec_ctx = update_decoder_list(ctx);
memset(&dec_sub,0,sizeof(dec_sub));
mprint("opening \'%s\': ", file);
@@ -230,22 +321,25 @@ int processmp4 (char *file,void *enc_ctx)
(unsigned char) ((type>>16)%0x100),(unsigned char) ((type>>8)%0x100),(unsigned char) (type%0x100),
(unsigned char) (subtype>>24%0x100),
(unsigned char) ((subtype>>16)%0x100),(unsigned char) ((subtype>>8)%0x100),(unsigned char) (subtype%0x100));
if (type == GF_ISOM_MEDIA_CAPTIONS && subtype == GF_ISOM_SUBTYPE_C608)
cc_track_count++;
if( type == GF_ISOM_MEDIA_VISUAL && subtype == GF_ISOM_SUBTYPE_AVC_H264)
if ((type == GF_ISOM_MEDIA_CAPTIONS && subtype == GF_ISOM_SUBTYPE_C608) ||
(type == GF_ISOM_MEDIA_CAPTIONS && subtype == GF_ISOM_SUBTYPE_C708))
cc_track_count++;
if (type == GF_ISOM_MEDIA_VISUAL && subtype == GF_ISOM_SUBTYPE_AVC_H264)
avc_track_count++;
}
mprint("mp4: found %u tracks: %u avc and %u cc\n", track_count, avc_track_count, cc_track_count);
for(i = 0; i < track_count; i++)
{
const u32 type = gf_isom_get_media_type(f, i + 1);
const u32 subtype = gf_isom_get_media_subtype(f, i + 1, 1);
if ( type == GF_ISOM_MEDIA_VISUAL && subtype == GF_ISOM_SUBTYPE_XDVB)
{
if (cc_track_count && !ccx_options.mp4vidtrack)
if (cc_track_count && !cfg->mp4vidtrack)
continue;
if(process_xdvb_track(file, f, i + 1, &dec_sub) != 0)
if(process_xdvb_track(ctx, file, f, i + 1, &dec_sub) != 0)
{
mprint("error\n");
return -3;
@@ -258,8 +352,8 @@ int processmp4 (char *file,void *enc_ctx)
}
if( type == GF_ISOM_MEDIA_VISUAL && subtype == GF_ISOM_SUBTYPE_AVC_H264)
{
if (cc_track_count && !ccx_options.mp4vidtrack)
{
if (cc_track_count && !cfg->mp4vidtrack)
continue;
GF_AVCConfig *cnf = gf_isom_avc_config_get(f,i+1,1);
if (cnf!=NULL)
@@ -267,11 +361,11 @@ int processmp4 (char *file,void *enc_ctx)
for (j=0; j<gf_list_count(cnf->sequenceParameterSets);j++)
{
GF_AVCConfigSlot* seqcnf=(GF_AVCConfigSlot* )gf_list_get(cnf->sequenceParameterSets,j);
do_NAL ((unsigned char *) seqcnf->data, seqcnf->size, &dec_sub);
do_NAL (dec_ctx, (unsigned char *) seqcnf->data, seqcnf->size, &dec_sub);
}
}
if(process_avc_track(file, f, i + 1, &dec_sub) != 0)
if(process_avc_track(ctx, file, f, i + 1, &dec_sub) != 0)
{
mprint("error\n");
return -3;
@@ -281,22 +375,21 @@ int processmp4 (char *file,void *enc_ctx)
encode_sub(enc_ctx, &dec_sub);
dec_sub.got_output = 0;
}
}
if (type == GF_ISOM_MEDIA_CAPTIONS && subtype == GF_ISOM_SUBTYPE_C608)
{
if (avc_track_count && ccx_options.mp4vidtrack)
if (type == GF_ISOM_MEDIA_CAPTIONS &&
(subtype == GF_ISOM_SUBTYPE_C608 || subtype == GF_ISOM_SUBTYPE_C708))
{
if (avc_track_count && cfg->mp4vidtrack)
continue;
#ifdef MP4_DEBUG
unsigned num_streams = gf_isom_get_sample_description_count (f,i+1);
#endif
unsigned num_samples = gf_isom_get_sample_count (f,i+1);
u32 ProcessingStreamDescriptionIndex = 0; // Current track we are processing, 0 = we don't know yet
u32 timescale = gf_isom_get_media_timescale(f,i+1);
#ifdef MP$DEBUG
#ifdef MP4_DEBUG
u64 duration = gf_isom_get_media_duration(f,i+1);
mprint ("%u streams\n",num_streams);
mprint ("%u sample counts\n",num_samples);
@@ -305,7 +398,7 @@ int processmp4 (char *file,void *enc_ctx)
#endif
for (unsigned k = 0; k <num_samples; k++)
{
u32 StreamDescriptionIndex;
u32 StreamDescriptionIndex;
GF_ISOSample *sample= gf_isom_get_sample(f, i+1, k+1, &StreamDescriptionIndex);
if (ProcessingStreamDescriptionIndex && ProcessingStreamDescriptionIndex!=StreamDescriptionIndex)
{
@@ -321,10 +414,8 @@ int processmp4 (char *file,void *enc_ctx)
mprint ("Data length: %lu\n",sample->dataLength);
const LLONG timestamp = (LLONG )((sample->DTS + sample->CTS_Offset) * 1000) / timescale;
#endif
current_pts=(LLONG )(sample->DTS + sample->CTS_Offset)*MPEG_CLOCK_FREQ/timescale ; // Convert frequency to official one
if (pts_set==0)
pts_set=1;
set_fts();
set_current_pts(dec_ctx->timing, (sample->DTS + sample->CTS_Offset)*MPEG_CLOCK_FREQ/timescale);
set_fts(dec_ctx->timing);
int atomStart = 0;
// process Atom by Atom
@@ -332,47 +423,116 @@ int processmp4 (char *file,void *enc_ctx)
{
char *data = sample->data + atomStart;
unsigned int atomLength = RB32(data);
if(atomLength < 8 || atomLength > sample->dataLength)
if (atomLength < 8 || atomLength > sample->dataLength)
{
mprint ("Invalid atom.\n");
mprint ("Invalid atom length. Atom length: %u, should be: %u\n", atomLength, sample->dataLength);
break;
}
data += 4;
if (!strncmp(data, "cdat", 4) || !strncmp(data, "cdt2", 4))
{
int ret = 0;
int len = atomLength - 8;
data += 4;
#ifdef MP4_DEBUG
dump(256, (unsigned char *)data, atomLength - 8, 0, 1);
dump(256, (unsigned char *)data, atomLength - 8, 0, 1);
#endif
do
data += 4;
int is_ccdp = !strncmp(data, "ccdp", 4);
if (!strncmp(data, "cdat", 4) || !strncmp(data, "cdt2", 4) || is_ccdp)
{
if (subtype == GF_ISOM_SUBTYPE_C708)
{
ret = process608((unsigned char*)data, len, &context_cc608_field_1, &dec_sub);
len -= ret;
data += ret;
if(dec_sub.got_output)
if (!is_ccdp)
{
encode_sub(enc_ctx, &dec_sub);
dec_sub.got_output = 0;
mprint("Your video file seems to be an interesting sample for us\n");
mprint("We haven't met c708 subtitle not in a \'ccdp\' atom before\n");
mprint("Please, report\n");
break;
}
} while (len > 0);
unsigned int cc_count;
data += 4;
unsigned char *cc_data = ccdp_find_data((unsigned char *) data, sample->dataLength - 8, &cc_count);
if (!cc_data)
{
dbg_print(CCX_DMT_PARSE, "mp4-708: no cc data found in ccdp\n");
break;
}
ctx->dec_global_setting->settings_dtvcc->enabled = 1;
unsigned char temp[4];
for (int cc_i = 0; cc_i < cc_count; cc_i++, cc_data += 3)
{
unsigned char cc_info = cc_data[0];
unsigned char cc_valid = (unsigned char) ((cc_info & 4) >> 2);
unsigned char cc_type = (unsigned char) (cc_info & 3);
if (cc_info == CDP_SECTION_SVC_INFO || cc_info == CDP_SECTION_FOOTER)
{
dbg_print(CCX_DMT_PARSE, "mp4-708: premature end of sample (0x73 or 0x74)\n");
break;
}
if ((cc_info == 0xFA || cc_info == 0xFC || cc_info == 0xFD)
&& (cc_data[1] & 0x7F) == 0 && (cc_data[2] & 0x7F) == 0)
{
dbg_print(CCX_DMT_PARSE, "mp4-708: skipped (zero cc data)\n");
continue;
}
temp[0] = cc_valid;
temp[1] = cc_type;
temp[2] = cc_data[1];
temp[3] = cc_data[2];
if (cc_type < 2)
{
dbg_print(CCX_DMT_PARSE, "mp4-708: atom skipped (cc_type < 2)\n");
continue;
}
dec_ctx->dtvcc->encoder = (void *)enc_ctx; //WARN: otherwise cea-708 will not work
//TODO is it really always 4-bytes long?
ccx_dtvcc_process_data(dec_ctx, (unsigned char *) temp, 4);
cb_708++;
}
atomStart = sample->dataLength;
}
else //subtype == GF_ISOM_SUBTYPE_C608
{
if (is_ccdp)
{
mprint("Your video file seems to be an interesting sample for us\n");
mprint("We haven't met c608 subtitle in a \'ccdp\' atom before\n");
mprint("Please, report\n");
break;
}
int ret = 0;
int len = atomLength - 8;
data += 4;
do {
ret = process608((unsigned char *) data, len, dec_ctx,
&dec_sub);
len -= ret;
data += ret;
if (dec_sub.got_output) {
encode_sub(enc_ctx, &dec_sub);
dec_sub.got_output = 0;
}
} while (len > 0);
}
}
atomStart += atomLength;
}
// End of change
int progress = (int) ((k*100) / num_samples);
if (last_reported_progress != progress)
if (ctx->last_reported_progress != progress)
{
int cur_sec = (int) (get_fts() / 1000);
int cur_sec = (int) (get_fts(dec_ctx->timing, dec_ctx->current_field) / 1000);
activity_progress(progress, cur_sec/60, cur_sec%60);
last_reported_progress = progress;
ctx->last_reported_progress = progress;
}
}
int cur_sec = (int) (get_fts() / 1000);
int cur_sec = (int) (get_fts(dec_ctx->timing, dec_ctx->current_field) / 1000);
activity_progress(100, cur_sec/60, cur_sec%60);
}
}
@@ -396,9 +556,7 @@ int processmp4 (char *file,void *enc_ctx)
else
mprint ("found no dedicated CC track(s).\n");
file_report.mp4_cc_track_cnt = cc_track_count;
if (ccx_options.print_file_reports)
print_file_report();
ctx->freport.mp4_cc_track_cnt = cc_track_count;
return 0;
}

View File

@@ -21,7 +21,7 @@
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#include "../disable_warnings.h"
#include "disable_warnings.h"
#include <gpac/tools.h>
#if defined(_WIN32_WCE)

View File

@@ -21,7 +21,7 @@
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#include "../disable_warnings.h"
#include "disable_warnings.h"
#include <gpac/internal/isomedia_dev.h>
#ifndef GPAC_DISABLE_ISOM

View File

@@ -21,7 +21,7 @@
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#include "../disable_warnings.h"
#include "disable_warnings.h"
#include <gpac/internal/isomedia_dev.h>
#include <gpac/constants.h>

View File

@@ -21,7 +21,7 @@
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#include "../disable_warnings.h"
#include "disable_warnings.h"
#include <gpac/internal/isomedia_dev.h>
#include <gpac/constants.h>

View File

@@ -21,7 +21,7 @@
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#include "../disable_warnings.h"
#include "disable_warnings.h"
#include <gpac/network.h>
/* the length of the URL separator ("://" || "|//") */

View File

@@ -0,0 +1,52 @@
cmake_policy (SET CMP0037 NEW)
set (CMAKE_C_FLAGS "-O0 -Wall -g -std=gnu99")
if (WITH_FFMPEG)
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DENABLE_FFMPEG")
endif (WITH_FFMPEG)
if (WITH_OCR)
find_package(PkgConfig)
pkg_check_modules(TESSERACT REQUIRED tesseract)
pkg_check_modules(LEPTONICA REQUIRED lept)
set (EXTRA_LIBS ${EXTRA_LIBS} ${TESSERACT_STATIC_LIBRARIES})
set (EXTRA_LIBS ${EXTRA_LIBS} ${LEPTONICA_STATIC_LIBRARIES})
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DENABLE_OCR ${TESSERACT_CFLAGS} ${LEPTONICA_CFLAGS}")
endif (WITH_OCR)
aux_source_directory ("${PROJECT_SOURCE_DIR}/lib_ccx/" SOURCEFILE)
aux_source_directory ("${PROJECT_SOURCE_DIR}/gpacmp4/" SOURCEFILE)
add_library (ccx ${SOURCEFILE} ccx_dtvcc.h ccx_dtvcc.c)
if (MINGW OR CYGWIN)
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DGPAC_CONFIG_WIN32")
endif (MINGW OR CYGWIN)
if (${CMAKE_SYSTEM_NAME} MATCHES "Linux")
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DGPAC_CONFIG_LINUX")
endif (${CMAKE_SYSTEM_NAME} MATCHES "Linux")
if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DGPAC_CONFIG_DARWIN")
endif (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
file (GLOB HeaderFiles *.h)
file (WRITE ccx.pc "prefix=${CMAKE_INSTALL_PREFIX}\n"
"includedir=\${prefix}/include\n"
"libdir=\${prefix}/lib\n\n"
"Name: ccx\n"
"Description: Closed Caption Extraction library\n"
"Version: 0.75\n"
"Cflags: -I\${includedir}/\n"
"Libs: -L\${libdir} -lccx -lpng\n"
"Libs.private: -lpng\n"
)
install (TARGETS ccx DESTINATION lib)
install (FILES ${HeaderFiles} DESTINATION include)
install (FILES ccx.pc DESTINATION lib/pkgconfig)

136
src/lib_ccx/activity.c Normal file
View File

@@ -0,0 +1,136 @@
/* This file contains functions that report the user of the GUI of
relevant events. */
#include "lib_ccx.h"
#include "ccx_common_option.h"
static int credits_shown=0;
unsigned long net_activity_gui=0;
/* Print current progress. For percentage, -1 -> streaming mode */
void activity_progress (int percentage, int cur_min, int cur_sec)
{
if (!ccx_options.no_progress_bar)
{
if (percentage==-1)
mprint ("\rStreaming | %02d:%02d", cur_min, cur_sec);
else
mprint ("\r%3d%% | %02d:%02d",percentage, cur_min, cur_sec);
}
fflush (stdout);
if (ccx_options.gui_mode_reports)
{
fprintf (stderr, "###PROGRESS#%d#%d#%d\n", percentage, cur_min, cur_sec);
fflush (stderr);
}
}
void activity_input_file_open (const char *filename)
{
if (ccx_options.gui_mode_reports)
{
fprintf (stderr, "###INPUTFILEOPEN#%s\n", filename);
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_video_info (int hor_size,int vert_size,
const char *aspect_ratio, const char *framerate)
{
if (ccx_options.gui_mode_reports)
{
fprintf (stderr, "###VIDEOINFO#%u#%u#%s#%s\n",
hor_size,vert_size, aspect_ratio, framerate);
fflush (stderr);
}
}
void activity_message (const char *fmt, ...)
{
if (ccx_options.gui_mode_reports)
{
va_list args;
fprintf (stderr, "###MESSAGE#");
va_start(args, fmt);
fprintf(stderr, fmt, args);
fprintf(stderr, "\n");
va_end(args);
fflush (stderr);
}
}
void activity_input_file_closed (void)
{
if (ccx_options.gui_mode_reports)
{
fprintf (stderr, "###INPUTFILECLOSED\n");
fflush (stderr);
}
}
void activity_program_number (unsigned program_number)
{
if (ccx_options.gui_mode_reports)
{
fprintf (stderr, "###TSPROGRAMNUMBER#%u\n", program_number);
fflush (stderr);
}
}
void activity_report_version (void)
{
if (ccx_options.gui_mode_reports)
{
fprintf (stderr, "###VERSION#CCExtractor#%s\n", VERSION);
fflush (stderr);
}
}
void activity_report_data_read (void)
{
if (ccx_options.gui_mode_reports)
{
fprintf (stderr, "###DATAREAD#%lu\n", net_activity_gui/1000);
fflush (stderr);
}
}
void activity_header (void)
{
if (!credits_shown)
{
credits_shown = 1;
mprint ("CCExtractor %s, Carlos Fernandez Sanz, Volker Quetschke.\n", VERSION);
mprint ("Teletext portions taken from Petr Kutalek's telxcc\n");
mprint ("--------------------------------------------------------------------------\n");
}
}

17
src/lib_ccx/activity.h Normal file
View File

@@ -0,0 +1,17 @@
#ifndef ACTIVITY_H
#define ACTIVITY_H
extern unsigned long net_activity_gui;
void activity_header (void);
void activity_progress (int percentaje, int cur_min, int cur_sec);
void activity_report_version (void);
void activity_input_file_closed (void);
void activity_input_file_open (const char *filename);
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_library_process(enum ccx_common_logging_gui message_type, ...);
void activity_report_data_read (void);
#endif

View File

@@ -85,10 +85,10 @@ typedef struct {
// Payload parsing information
int MultiplePayloads; // ASF
int PacketLType; // ASF
int ReplicatedLType; // ASF
int OffsetMediaLType; // ASF
int MediaNumberLType; // ASF
int StreamNumberLType; // ASF
int ReplicatedLType; // ASF
int OffsetMediaLType; // ASF
int MediaNumberLType; // ASF
int StreamNumberLType; // ASF
uint32_t PacketLength;
uint32_t PaddingLength;
} asf_data;
} asf_data;

1057
src/lib_ccx/asf_functions.c Normal file

File diff suppressed because it is too large Load Diff

1181
src/lib_ccx/avc_functions.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,55 @@
#ifndef AVC_FUNCTION_H
#define AVC_FUNCTION_H
struct avc_ctx
{
unsigned char cc_count;
// buffer to hold cc data
unsigned char *cc_data;
long cc_databufsize;
int cc_buffer_saved; // Was the CC buffer saved after it was last updated?
int got_seq_para;
unsigned nal_ref_idc;
LLONG seq_parameter_set_id;
int log2_max_frame_num;
int pic_order_cnt_type;
int log2_max_pic_order_cnt_lsb;
int frame_mbs_only_flag;
// Use and throw stats for debug, remove this uglyness soon
long num_nal_unit_type_7;
long num_vcl_hrd;
long num_nal_hrd;
long num_jump_in_frames;
long num_unexpected_sei_length;
int ccblocks_in_avc_total;
int ccblocks_in_avc_lost;
LLONG frame_num;
LLONG lastframe_num;
int currref;
int maxidx;
int lastmaxidx;
// Used to find tref zero in PTS mode
int minidx;
int lastminidx;
// Used to remember the max temporal reference number (poc mode)
int maxtref;
int last_gop_maxtref;
// Used for PTS ordering of CC blocks
LLONG currefpts;
LLONG last_pic_order_cnt_lsb;
LLONG last_slice_pts;
};
struct avc_ctx *init_avc(void);
void dinit_avc(struct avc_ctx **ctx);
void do_NAL (struct lib_cc_decode *ctx, unsigned char *NALstart, LLONG NAL_length, struct cc_subtitle *sub);
size_t process_avc(struct lib_cc_decode *ctx, unsigned char *avcbuf, size_t avcbuflen, struct cc_subtitle *sub);
#endif

View File

@@ -9,22 +9,22 @@
// end is used to check that nothing is read at "end" or after it.
struct bitstream
{
unsigned char *pos;
int bpos;
unsigned char *end;
// Indicate how many bits are left in the stream after the previous
// read call. A negative number indicates that a read after the
// end of the stream was attempted.
int64_t bitsleft;
// Indicate an error occured while parsing the bitstream.
// This is meant to store high level syntax errors, i.e a function
// using the bitstream functions found a syntax error.
int error;
// Internal (private) variable - used to store the the bitstream
// position until it is decided if the bitstream pointer will be
// increased by the calling function, or not.
unsigned char *_i_pos;
int _i_bpos;
unsigned char *pos;
int bpos;
unsigned char *end;
// Indicate how many bits are left in the stream after the previous
// read call. A negative number indicates that a read after the
// end of the stream was attempted.
int64_t bitsleft;
// Indicate an error occured while parsing the bitstream.
// This is meant to store high level syntax errors, i.e a function
// using the bitstream functions found a syntax error.
int error;
// Internal (private) variable - used to store the the bitstream
// position until it is decided if the bitstream pointer will be
// increased by the calling function, or not.
unsigned char *_i_pos;
int _i_bpos;
};
#define read_u8(bstream) (uint8_t)bitstream_get_num(bstream,1,1)

375
src/lib_ccx/cc_bitstream.c Normal file
View File

@@ -0,0 +1,375 @@
#include "lib_ccx.h"
// Hold functions to read streams on a bit or byte oriented basis
// plus some data related helper functions.
// Guidelines for all bitsream functions:
// * No function shall advance the pointer past the end marker
// * If bitstream.bitsleft < 0 do not attempt any read access,
// but decrease bitsleft by the number of bits that were
// attempted to read.
// Initialize bitstream
int init_bitstream(struct bitstream *bstr, unsigned char *start, unsigned char *end)
{
bstr->pos = start;
bstr->bpos = 8;
bstr->end = end;
bstr->bitsleft = (bstr->end - bstr->pos)*8;
bstr->error = 0;
bstr->_i_pos = NULL;
bstr->_i_bpos = 0;
if(bstr->bitsleft < 0)
{
// See if we can somehow recover of this disaster by reporting the problem instead of terminating.
mprint ( "init_bitstream: bitstream has negative length!");
return 1;
}
return 0;
}
// Read bnum bits from bitstream bstr with the most significant
// bit read first without advancing the bitstream pointer.
// A 64 bit unsigned integer is returned. 0 is returned when
// there are not enough bits left in the bitstream.
uint64_t next_bits(struct bitstream *bstr, unsigned bnum)
{
uint64_t res = 0;
if(bnum > 64)
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(CCX_COMMON_EXIT_BUG_BUG, "next_bits: bitstream has negative length!");
// Keep a negative bitstream.bitsleft, but correct it.
if (bstr->bitsleft <= 0)
{
bstr->bitsleft -= bnum;
return 0;
}
// Calculate the remaining number of bits in bitstream after reading.
bstr->bitsleft = 0LL + (bstr->end - bstr->pos - 1)*8 + bstr->bpos - bnum;
if (bstr->bitsleft < 0)
return 0;
// Special case for reading zero bits. Return zero
if(bnum == 0)
return 0;
int vbit = bstr->bpos;
unsigned char *vpos = bstr->pos;
if(vbit < 1 || vbit > 8)
{
fatal(CCX_COMMON_EXIT_BUG_BUG, "next_bits: Illegal bit position value %d!", vbit);
}
while( 1 )
{
if(vpos >= bstr->end)
{
// We should not get here ...
fatal(CCX_COMMON_EXIT_BUG_BUG, "next_bits: Reading after end of data ...");
}
res |= (*vpos & (0x01 << (vbit-1)) ? 1 : 0);
vbit--;
bnum--;
if(vbit == 0)
{
vpos++;
vbit = 8;
}
if(bnum)
{
res <<= 1;
}
else
break;
}
// Remember the bitstream position
bstr->_i_bpos = vbit;
bstr->_i_pos = vpos;
return res;
}
// Read bnum bits from bitstream bstr with the most significant
// bit read first. A 64 bit unsigned integer is returned.
uint64_t read_bits(struct bitstream *bstr, unsigned bnum)
{
uint64_t res = next_bits(bstr, bnum);
// Special case for reading zero bits. Also abort when not enough
// bits are left. Return zero
if(bnum == 0 || bstr->bitsleft < 0)
return 0;
// Advance the bitstream
bstr->bpos = bstr->_i_bpos;
bstr->pos = bstr->_i_pos;
return res;
}
// This function will advance the bitstream by bnum bits, if possible.
// Advancing of more than 64 bits is possible.
// Return TRUE when successfull, otherwise FALSE
int skip_bits(struct bitstream *bstr, unsigned bnum)
{
// Sanity check
if(bstr->end - bstr->pos < 0)
fatal(CCX_COMMON_EXIT_BUG_BUG, "skip_bits: bitstream has negative length!");
// Keep a negative bstr->bitsleft, but correct it.
if (bstr->bitsleft < 0)
{
bstr->bitsleft -= bnum;
return 0;
}
// Calculate the remaining number of bits in bitstream after reading.
bstr->bitsleft = 0LL + (bstr->end - bstr->pos - 1)*8 + bstr->bpos - bnum;
if (bstr->bitsleft < 0)
return 0;
// Special case for reading zero bits. Return zero
if(bnum == 0)
return 1;
bstr->bpos -= bnum%8;
bstr->pos += bnum/8;
if (bstr->bpos < 1)
{
bstr->bpos += 8;
bstr->pos += 1;
}
return 1;
}
// Return TRUE if the current position in the bitstream is on a byte
// boundary, i.e., the next bit in the bitstream is the first bit in
// a byte, otherwise return FALSE
int is_byte_aligned(struct bitstream *bstr)
{
// Sanity check
if(bstr->end - bstr->pos < 0)
fatal(CCX_COMMON_EXIT_BUG_BUG, "is_byte_aligned: bitstream has negative length!");
int vbit = bstr->bpos;
if(vbit == 0 || vbit > 8)
{
fatal(CCX_COMMON_EXIT_BUG_BUG, "is_byte_aligned: Illegal bit position value %d!\n", vbit);
}
if (vbit == 8)
return 1;
else
return 0;
}
// Move bitstream to next byte border. Adjust bitsleft.
void make_byte_aligned(struct bitstream *bstr)
{
// Sanity check
if(bstr->end - bstr->pos < 0)
fatal(CCX_COMMON_EXIT_BUG_BUG, "make_byte_aligned: bitstream has negative length!");
int vbit = bstr->bpos;
if(vbit == 0 || vbit > 8)
{
fatal(CCX_COMMON_EXIT_BUG_BUG, "make_byte_aligned: Illegal bit position value %d!\n", vbit);
}
// Keep a negative bstr->bitsleft, but correct it.
if (bstr->bitsleft < 0)
{
// Pay attention to the bit alignment
bstr->bitsleft = (bstr->bitsleft-7)/8 *8;
return;
}
if(bstr->bpos != 8)
{
bstr->bpos = 8;
bstr->pos += 1;
}
// Reset, in case a next_???() function was used before
bstr->bitsleft = 0LL + 8*(bstr->end-bstr->pos-1)+bstr->bpos;
return;
}
// Return pointer to first of bynum bytes from the bitstream if the
// following conditions are TRUE:
// The bitstream is byte aligned and there are enough bytes left in
// it to read bynum bytes. Otherwise return NULL.
// This function does not advance the bitstream pointer.
unsigned char *next_bytes(struct bitstream *bstr, unsigned bynum)
{
// Sanity check
if(bstr->end - bstr->pos < 0)
fatal(CCX_COMMON_EXIT_BUG_BUG, "next_bytes: bitstream has negative length!");
// Keep a negative bstr->bitsleft, but correct it.
if (bstr->bitsleft < 0)
{
bstr->bitsleft -= bynum*8;
return NULL;
}
bstr->bitsleft = 0LL + (bstr->end - bstr->pos - 1)*8 + bstr->bpos - bynum*8;
if (!is_byte_aligned(bstr) || bstr->bitsleft < 0 || bynum < 1)
return NULL;
// Remember the bitstream position
bstr->_i_bpos = 8;
bstr->_i_pos = bstr->pos + bynum;
return bstr->pos;
}
// Return pointer to first of bynum bytes from the bitstream if the
// following conditions are TRUE:
// The bitstream is byte aligned and there are enough bytes left in
// it to read bynum bytes. Otherwise return NULL.
// This function does advance the bitstream pointer.
unsigned char *read_bytes(struct bitstream *bstr, unsigned bynum)
{
unsigned char *res = next_bytes(bstr, bynum);
// Advance the bitstream when a read was possible
if(res)
{
bstr->bpos = bstr->_i_bpos;
bstr->pos = bstr->_i_pos;
}
return res;
}
// Return an integer number with "bytes" precision from the current
// bitstream position. Allowed "bytes" values are 1,2,4,8.
// This function does advance the bitstream pointer when "advance" is
// set to TRUE.
// Numbers come MSB (most significant first), and we need to account for
// little-endian and big-endian CPUs.
uint64_t bitstream_get_num(struct bitstream *bstr, unsigned bytes, int advance)
{
void *bpos;
uint64_t rval=0;
if (advance)
bpos = read_bytes(bstr, bytes);
else
bpos = next_bytes(bstr, bytes);
if (!bpos)
return 0;
switch (bytes)
{
case 1:
case 2:
case 4:
case 8:
break;
default:
fatal (CCX_COMMON_EXIT_BUG_BUG, "bitstream_get_num: Illegal precision value [%u]!",
bytes);
break;
}
for (unsigned i=0;i<bytes;i++)
{
unsigned char *ucpos=((unsigned char *)bpos) +bytes-i-1; // Read backwards
unsigned char uc=*ucpos;
rval=(rval<<8) + uc;
}
return rval;
}
// Read unsigned Exp-Golomb code from bitstream
uint64_t ue(struct bitstream *bstr)
{
uint64_t res = 0;
int zeros=0;
while(!read_bits(bstr,1))
zeros++;
res = (0x01 << zeros) - 1 + read_bits(bstr,zeros);
return res;
}
// Read signed Exp-Golomb code from bitstream
int64_t se(struct bitstream *bstr)
{
int64_t res = 0;
res = ue(bstr);
// The following function might truncate when res+1 overflows
//res = (res+1)/2 * (res % 2 ? 1 : -1);
// Use this:
res = (res/2+(res%2 ? 1 : 0)) * (res % 2 ? 1 : -1);
return res;
}
// Read unsigned integer with bnum bits length. Basically an
// alias for read_bits().
uint64_t u(struct bitstream *bstr, unsigned bnum)
{
return read_bits(bstr, bnum);
}
// Read signed integer with bnum bits length.
int64_t i(struct bitstream *bstr, unsigned bnum)
{
uint64_t res = read_bits(bstr, bnum);
// Special case for reading zero bits. Return zero
if(bnum == 0)
return 0;
return (0xFFFFFFFFFFFFFFFFULL << bnum) | res;
}
// Return the value with the bit order reversed.
uint8_t reverse8(uint8_t data)
{
uint8_t res = 0;
for (int k=0;k<8;k++)
{
res <<= 1;
res |= (data & (0x01 << k) ? 1 : 0);
}
return res;
}

View File

@@ -0,0 +1,840 @@
#include <ctype.h>
void get_char_in_latin_1 (unsigned char *buffer, unsigned char c)
{
unsigned char c1='?';
if (c<0x80)
{
// Regular line-21 character set, mostly ASCII except these exceptions
switch (c)
{
case 0x2a: // lowercase a, acute accent
c1=0xe1;
break;
case 0x5c: // lowercase e, acute accent
c1=0xe9;
break;
case 0x5e: // lowercase i, acute accent
c1=0xed;
break;
case 0x5f: // lowercase o, acute accent
c1=0xf3;
break;
case 0x60: // lowercase u, acute accent
c1=0xfa;
break;
case 0x7b: // lowercase c with cedilla
c1=0xe7;
break;
case 0x7c: // division symbol
c1=0xf7;
break;
case 0x7d: // uppercase N tilde
c1=0xd1;
break;
case 0x7e: // lowercase n tilde
c1=0xf1;
break;
default:
c1=c;
break;
}
*buffer=c1;
return;
}
switch (c)
{
// THIS BLOCK INCLUDES THE 16 EXTENDED (TWO-BYTE) LINE 21 CHARACTERS
// THAT COME FROM HI BYTE=0x11 AND LOW BETWEEN 0x30 AND 0x3F
case 0x80: // Registered symbol (R)
c1=0xae;
break;
case 0x81: // degree sign
c1=0xb0;
break;
case 0x82: // 1/2 symbol
c1=0xbd;
break;
case 0x83: // Inverted (open) question mark
c1=0xbf;
break;
case 0x84: // Trademark symbol (TM) - Does not exist in Latin 1
break;
case 0x85: // Cents symbol
c1=0xa2;
break;
case 0x86: // Pounds sterling
c1=0xa3;
break;
case 0x87: // Music note - Not in latin 1, so we use 'pilcrow'
c1=0xb6;
break;
case 0x88: // lowercase a, grave accent
c1=0xe0;
break;
case 0x89: // transparent space, we make it regular
c1=0x20;
break;
case 0x8a: // lowercase e, grave accent
c1=0xe8;
break;
case 0x8b: // lowercase a, circumflex accent
c1=0xe2;
break;
case 0x8c: // lowercase e, circumflex accent
c1=0xea;
break;
case 0x8d: // lowercase i, circumflex accent
c1=0xee;
break;
case 0x8e: // lowercase o, circumflex accent
c1=0xf4;
break;
case 0x8f: // lowercase u, circumflex accent
c1=0xfb;
break;
// THIS BLOCK INCLUDES THE 32 EXTENDED (TWO-BYTE) LINE 21 CHARACTERS
// THAT COME FROM HI BYTE=0x12 AND LOW BETWEEN 0x20 AND 0x3F
case 0x90: // capital letter A with acute
c1=0xc1;
break;
case 0x91: // capital letter E with acute
c1=0xc9;
break;
case 0x92: // capital letter O with acute
c1=0xd3;
break;
case 0x93: // capital letter U with acute
c1=0xda;
break;
case 0x94: // capital letter U with diaresis
c1=0xdc;
break;
case 0x95: // lowercase letter U with diaeresis
c1=0xfc;
break;
case 0x96: // apostrophe
c1=0x27;
break;
case 0x97: // inverted exclamation mark
c1=0xa1;
break;
case 0x98: // asterisk
c1=0x2a;
break;
case 0x99: // apostrophe (yes, duped). See CCADI source code.
c1=0x27;
break;
case 0x9a: // em dash
c1=0x2d;
break;
case 0x9b: // copyright sign
c1=0xa9;
break;
case 0x9c: // Service Mark - not available in latin 1
break;
case 0x9d: // Full stop (.)
c1=0x2e;
break;
case 0x9e: // Quoatation mark
c1=0x22;
break;
case 0x9f: // Quoatation mark
c1=0x22;
break;
case 0xa0: // uppercase A, grave accent
c1=0xc0;
break;
case 0xa1: // uppercase A, circumflex
c1=0xc2;
break;
case 0xa2: // uppercase C with cedilla
c1=0xc7;
break;
case 0xa3: // uppercase E, grave accent
c1=0xc8;
break;
case 0xa4: // uppercase E, circumflex
c1=0xca;
break;
case 0xa5: // capital letter E with diaresis
c1=0xcb;
break;
case 0xa6: // lowercase letter e with diaresis
c1=0xeb;
break;
case 0xa7: // uppercase I, circumflex
c1=0xce;
break;
case 0xa8: // uppercase I, with diaresis
c1=0xcf;
break;
case 0xa9: // lowercase i, with diaresis
c1=0xef;
break;
case 0xaa: // uppercase O, circumflex
c1=0xd4;
break;
case 0xab: // uppercase U, grave accent
c1=0xd9;
break;
case 0xac: // lowercase u, grave accent
c1=0xf9;
break;
case 0xad: // uppercase U, circumflex
c1=0xdb;
break;
case 0xae: // LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
c1=0xab;
break;
case 0xaf: // RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
c1=0xbb;
break;
// THIS BLOCK INCLUDES THE 32 EXTENDED (TWO-BYTE) LINE 21 CHARACTERS
// THAT COME FROM HI BYTE=0x13 AND LOW BETWEEN 0x20 AND 0x3F
case 0xb0: // Uppercase A, tilde
c1=0xc3;
break;
case 0xb1: // Lowercase a, tilde
c1=0xe3;
break;
case 0xb2: // Uppercase I, acute accent
c1=0xcd;
break;
case 0xb3: // Uppercase I, grave accent
c1=0xcc;
break;
case 0xb4: // Lowercase i, grave accent
c1=0xec;
break;
case 0xb5: // Uppercase O, grave accent
c1=0xd2;
break;
case 0xb6: // Lowercase o, grave accent
c1=0xf2;
break;
case 0xb7: // Uppercase O, tilde
c1=0xd5;
break;
case 0xb8: // Lowercase o, tilde
c1=0xf5;
break;
case 0xb9: // Open curly brace
c1=0x7b;
break;
case 0xba: // Closing curly brace
c1=0x7d;
break;
case 0xbb: // Backslash
c1=0x5c;
break;
case 0xbc: // Caret
c1=0x5e;
break;
case 0xbd: // Underscore
c1=0x5f;
break;
case 0xbe: // Pipe (broken bar)
c1=0xa6;
break;
case 0xbf: // Tilde
c1=0x7e;
break;
case 0xc0: // Uppercase A, umlaut
c1=0xc4;
break;
case 0xc1: // Lowercase A, umlaut
c1=0xe3;
break;
case 0xc2: // Uppercase O, umlaut
c1=0xd6;
break;
case 0xc3: // Lowercase o, umlaut
c1=0xf6;
break;
case 0xc4: // Esszett (sharp S)
c1=0xdf;
break;
case 0xc5: // Yen symbol
c1=0xa5;
break;
case 0xc6: // Currency symbol
c1=0xa4;
break;
case 0xc7: // Vertical bar
c1=0x7c;
break;
case 0xc8: // Uppercase A, ring
c1=0xc5;
break;
case 0xc9: // Lowercase A, ring
c1=0xe5;
break;
case 0xca: // Uppercase O, slash
c1=0xd8;
break;
case 0xcb: // Lowercase o, slash
c1=0xf8;
break;
case 0xcc: // Upper left corner
case 0xcd: // Upper right corner
case 0xce: // Lower left corner
case 0xcf: // Lower right corner
default: // For those that don't have representation
*buffer='?'; // I'll do it eventually, I promise
break; // This are weird chars anyway
}
*buffer=c1;
}
void get_char_in_unicode (unsigned char *buffer, unsigned char c)
{
unsigned char c1,c2;
switch (c)
{
case 0x84: // Trademark symbol (TM)
c2=0x21;
c1=0x22;
break;
case 0x87: // Music note
c2=0x26;
c1=0x6a;
break;
case 0x9c: // Service Mark
c2=0x21;
c1=0x20;
break;
case 0xcc: // Upper left corner
c2=0x23;
c1=0x1c;
break;
case 0xcd: // Upper right corner
c2=0x23;
c1=0x1d;
break;
case 0xce: // Lower left corner
c2=0x23;
c1=0x1e;
break;
case 0xcf: // Lower right corner
c2=0x23;
c1=0x1f;
break;
default: // Everything else, same as latin-1 followed by 00
get_char_in_latin_1 (&c1,c);
c2=0;
break;
}
*buffer=c1;
*(buffer+1)=c2;
}
int get_char_in_utf_8 (unsigned char *buffer, unsigned char c) // Returns number of bytes used
{
if (c<0x80) // Regular line-21 character set, mostly ASCII except these exceptions
{
switch (c)
{
case 0x2a: // lowercase a, acute accent
*buffer=0xc3;
*(buffer+1)=0xa1;
return 2;
case 0x5c: // lowercase e, acute accent
*buffer=0xc3;
*(buffer+1)=0xa9;
return 2;
case 0x5e: // lowercase i, acute accent
*buffer=0xc3;
*(buffer+1)=0xad;
return 2;
case 0x5f: // lowercase o, acute accent
*buffer=0xc3;
*(buffer+1)=0xb3;
return 2;
case 0x60: // lowercase u, acute accent
*buffer=0xc3;
*(buffer+1)=0xba;
return 2;
case 0x7b: // lowercase c with cedilla
*buffer=0xc3;
*(buffer+1)=0xa7;
return 2;
case 0x7c: // division symbol
*buffer=0xc3;
*(buffer+1)=0xb7;
return 2;
case 0x7d: // uppercase N tilde
*buffer=0xc3;
*(buffer+1)=0x91;
return 2;
case 0x7e: // lowercase n tilde
*buffer=0xc3;
*(buffer+1)=0xb1;
return 2;
case 0x7f: // Solid block
*buffer=0xe2;
*(buffer+1)=0x96;
*(buffer+2)=0xa0;
return 3;
default:
*buffer=c;
return 1;
}
}
switch (c)
{
// THIS BLOCK INCLUDES THE 16 EXTENDED (TWO-BYTE) LINE 21 CHARACTERS
// THAT COME FROM HI BYTE=0x11 AND LOW BETWEEN 0x30 AND 0x3F
case 0x80: // Registered symbol (R)
*buffer=0xc2;
*(buffer+1)=0xae;
return 2;
case 0x81: // degree sign
*buffer=0xc2;
*(buffer+1)=0xb0;
return 2;
case 0x82: // 1/2 symbol
*buffer=0xc2;
*(buffer+1)=0xbd;
return 2;
case 0x83: // Inverted (open) question mark
*buffer=0xc2;
*(buffer+1)=0xbf;
return 2;
case 0x84: // Trademark symbol (TM)
*buffer=0xe2;
*(buffer+1)=0x84;
*(buffer+2)=0xa2;
return 3;
case 0x85: // Cents symbol
*buffer=0xc2;
*(buffer+1)=0xa2;
return 2;
case 0x86: // Pounds sterling
*buffer=0xc2;
*(buffer+1)=0xa3;
return 2;
case 0x87: // Music note
*buffer=0xe2;
*(buffer+1)=0x99;
*(buffer+2)=0xaa;
return 3;
case 0x88: // lowercase a, grave accent
*buffer=0xc3;
*(buffer+1)=0xa0;
return 2;
case 0x89: // transparent space, we make it regular
*buffer=0x20;
return 1;
case 0x8a: // lowercase e, grave accent
*buffer=0xc3;
*(buffer+1)=0xa8;
return 2;
case 0x8b: // lowercase a, circumflex accent
*buffer=0xc3;
*(buffer+1)=0xa2;
return 2;
case 0x8c: // lowercase e, circumflex accent
*buffer=0xc3;
*(buffer+1)=0xaa;
return 2;
case 0x8d: // lowercase i, circumflex accent
*buffer=0xc3;
*(buffer+1)=0xae;
return 2;
case 0x8e: // lowercase o, circumflex accent
*buffer=0xc3;
*(buffer+1)=0xb4;
return 2;
case 0x8f: // lowercase u, circumflex accent
*buffer=0xc3;
*(buffer+1)=0xbb;
return 2;
// THIS BLOCK INCLUDES THE 32 EXTENDED (TWO-BYTE) LINE 21 CHARACTERS
// THAT COME FROM HI BYTE=0x12 AND LOW BETWEEN 0x20 AND 0x3F
case 0x90: // capital letter A with acute
*buffer=0xc3;
*(buffer+1)=0x81;
return 2;
case 0x91: // capital letter E with acute
*buffer=0xc3;
*(buffer+1)=0x89;
return 2;
case 0x92: // capital letter O with acute
*buffer=0xc3;
*(buffer+1)=0x93;
return 2;
case 0x93: // capital letter U with acute
*buffer=0xc3;
*(buffer+1)=0x9a;
return 2;
case 0x94: // capital letter U with diaresis
*buffer=0xc3;
*(buffer+1)=0x9c;
return 2;
case 0x95: // lowercase letter U with diaeresis
*buffer=0xc3;
*(buffer+1)=0xbc;
return 2;
case 0x96: // apostrophe
*buffer=0x27;
return 1;
case 0x97: // inverted exclamation mark
*buffer=0xc2;
*(buffer+1)=0xa1;
return 2;
case 0x98: // asterisk
*buffer=0x2a;
return 1;
case 0x99: // Plain single quote
*buffer=0x27;
return 1;
case 0x9a: // em dash
*buffer=0xe2;
*(buffer+1)=0x80;
*(buffer+2)=0x94;
return 3;
case 0x9b: // copyright sign
*buffer=0xc2;
*(buffer+1)=0xa9;
return 2;
case 0x9c: // Service mark
*buffer=0xe2;
*(buffer+1)=0x84;
*(buffer+2)=0xa0;
return 3;
case 0x9d: // Round bullet
*buffer=0xe2;
*(buffer+1)=0x80;
*(buffer+2)=0xa2;
return 3;
case 0x9e: // Opening double quotes
*buffer=0xe2;
*(buffer+1)=0x80;
*(buffer+2)=0x9c;
return 3;
case 0x9f: // Closing double quotes
*buffer=0xe2;
*(buffer+1)=0x80;
*(buffer+2)=0x9d;
return 3;
case 0xa0: // uppercase A, grave accent
*buffer=0xc3;
*(buffer+1)=0x80;
return 2;
case 0xa1: // uppercase A, circumflex
*buffer=0xc3;
*(buffer+1)=0x82;
return 2;
case 0xa2: // uppercase C with cedilla
*buffer=0xc3;
*(buffer+1)=0x87;
return 2;
case 0xa3: // uppercase E, grave accent
*buffer=0xc3;
*(buffer+1)=0x88;
return 2;
case 0xa4: // uppercase E, circumflex
*buffer=0xc3;
*(buffer+1)=0x8a;
return 2;
case 0xa5: // capital letter E with diaresis
*buffer=0xc3;
*(buffer+1)=0x8b;
return 2;
case 0xa6: // lowercase letter e with diaresis
*buffer=0xc3;
*(buffer+1)=0xab;
return 2;
case 0xa7: // uppercase I, circumflex
*buffer=0xc3;
*(buffer+1)=0x8e;
return 2;
case 0xa8: // uppercase I, with diaresis
*buffer=0xc3;
*(buffer+1)=0x8f;
return 2;
case 0xa9: // lowercase i, with diaresis
*buffer=0xc3;
*(buffer+1)=0xaf;
return 2;
case 0xaa: // uppercase O, circumflex
*buffer=0xc3;
*(buffer+1)=0x94;
return 2;
case 0xab: // uppercase U, grave accent
*buffer=0xc3;
*(buffer+1)=0x99;
return 2;
case 0xac: // lowercase u, grave accent
*buffer=0xc3;
*(buffer+1)=0xb9;
return 2;
case 0xad: // uppercase U, circumflex
*buffer=0xc3;
*(buffer+1)=0x9b;
return 2;
case 0xae: // LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
*buffer=0xc2;
*(buffer+1)=0xab;
return 2;
case 0xaf: // RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
*buffer=0xc2;
*(buffer+1)=0xbb;
return 2;
// THIS BLOCK INCLUDES THE 32 EXTENDED (TWO-BYTE) LINE 21 CHARACTERS
// THAT COME FROM HI BYTE=0x13 AND LOW BETWEEN 0x20 AND 0x3F
case 0xb0: // Uppercase A, tilde
*buffer=0xc3;
*(buffer+1)=0x83;
return 2;
case 0xb1: // Lowercase a, tilde
*buffer=0xc3;
*(buffer+1)=0xa3;
return 2;
case 0xb2: // Uppercase I, acute accent
*buffer=0xc3;
*(buffer+1)=0x8d;
return 2;
case 0xb3: // Uppercase I, grave accent
*buffer=0xc3;
*(buffer+1)=0x8c;
return 2;
case 0xb4: // Lowercase i, grave accent
*buffer=0xc3;
*(buffer+1)=0xac;
return 2;
case 0xb5: // Uppercase O, grave accent
*buffer=0xc3;
*(buffer+1)=0x92;
return 2;
case 0xb6: // Lowercase o, grave accent
*buffer=0xc3;
*(buffer+1)=0xb2;
return 2;
case 0xb7: // Uppercase O, tilde
*buffer=0xc3;
*(buffer+1)=0x95;
return 2;
case 0xb8: // Lowercase o, tilde
*buffer=0xc3;
*(buffer+1)=0xb5;
return 2;
case 0xb9: // Open curly brace
*buffer=0x7b;
return 1;
case 0xba: // Closing curly brace
*buffer=0x7d;
return 1;
case 0xbb: // Backslash
*buffer=0x5c;
return 1;
case 0xbc: // Caret
*buffer=0x5e;
return 1;
case 0xbd: // Underscore
*buffer=0x5f;
return 1;
case 0xbe: // Pipe (broken bar)
*buffer=0xc2;
*(buffer+1)=0xa6;
return 2;
case 0xbf: // Tilde
*buffer=0x7e; // Not sure
return 1;
case 0xc0: // Uppercase A, umlaut
*buffer=0xc3;
*(buffer+1)=0x84;
return 2;
case 0xc1: // Lowercase A, umlaut
*buffer=0xc3;
*(buffer+1)=0xa4;
return 2;
case 0xc2: // Uppercase O, umlaut
*buffer=0xc3;
*(buffer+1)=0x96;
return 2;
case 0xc3: // Lowercase o, umlaut
*buffer=0xc3;
*(buffer+1)=0xb6;
return 2;
case 0xc4: // Esszett (sharp S)
*buffer=0xc3;
*(buffer+1)=0x9f;
return 2;
case 0xc5: // Yen symbol
*buffer=0xc2;
*(buffer+1)=0xa5;
return 2;
case 0xc6: // Currency symbol
*buffer=0xc2;
*(buffer+1)=0xa4;
return 2;
case 0xc7: // Vertical bar
*buffer=0x7c;
return 1;
case 0xc8: // Uppercase A, ring
*buffer=0xc3;
*(buffer+1)=0x85;
return 2;
case 0xc9: // Lowercase A, ring
*buffer=0xc3;
*(buffer+1)=0xa5;
return 2;
case 0xca: // Uppercase O, slash
*buffer=0xc3;
*(buffer+1)=0x98;
return 2;
case 0xcb: // Lowercase o, slash
*buffer=0xc3;
*(buffer+1)=0xb8;
return 2;
case 0xcc: // Top left corner
*buffer=0xe2;
*(buffer+1)=0x8c;
*(buffer+2)=0x9c;
return 3;
case 0xcd: // Top right corner
*buffer=0xe2;
*(buffer+1)=0x8c;
*(buffer+2)=0x9d;
return 3;
case 0xce: // Bottom left corner
*buffer=0xe2;
*(buffer+1)=0x8c;
*(buffer+2)=0x9e;
return 3;
case 0xcf: // Bottom right corner
*buffer=0xe2;
*(buffer+1)=0x8c;
*(buffer+2)=0x9f;
return 3;
default: //
*buffer='?'; // I'll do it eventually, I promise
return 1; // This are weird chars anyway
}
}
unsigned char cctolower (unsigned char c)
{
if (c>='A' && c<='Z')
return tolower(c);
switch (c)
{
case 0x7d: // uppercase N tilde
return 0x7e;
case 0x90: // capital letter A with acute
return 0x2a;
case 0x91: // capital letter E with acute
return 0x5c;
case 0x92: // capital letter O with acute
return 0x5f;
case 0x93: // capital letter U with acute
return 0x60;
case 0xa2: // uppercase C with cedilla
return 0x7b;
case 0xa0: // uppercase A, grave accent
return 0x88;
case 0xa3: // uppercase E, grave accent
return 0x8a;
case 0xa1: // uppercase A, circumflex
return 0x8b;
case 0xa4: // uppercase E, circumflex
return 0x8c;
case 0xa7: // uppercase I, circumflex
return 0x8d;
case 0xaa: // uppercase O, circumflex
return 0x8e;
case 0xad: // uppercase U, circumflex
return 0x8f;
case 0x94: // capital letter U with diaresis
return 0x95;
case 0xa5: // capital letter E with diaresis
return 0xa6;
case 0xa8: // uppercase I, with diaresis
return 0xa9;
case 0xab: // uppercase U, grave accent
return 0xac;
case 0xb0: // Uppercase A, tilde
return 0xb1;
case 0xb2: // Uppercase I, acute accent
return 0x5e;
case 0xb3: // Uppercase I, grave accent
return 0xb4;
case 0xb5: // Uppercase O, grave accent
return 0xb6;
case 0xb7: // Uppercase O, tilde
return 0xb8;
case 0xc0: // Uppercase A, umlaut
return 0xc1;
case 0xc2: // Uppercase O, umlaut
return 0xc3;
case 0xc8: // Uppercase A, ring
return 0xc9;
case 0xca: // Uppercase O, slash
return 0xcb;
}
return c;
}
unsigned char cctoupper (unsigned char c)
{
if (c>='a' && c<='z')
return toupper(c);
switch (c)
{
case 0x7e: // lowercase n tilde
return 0x7d;
case 0x2a: // lowercase a, acute accent
return 0x90;
case 0x5c: // lowercase e, acute accent
return 0x91;
case 0x5e: // lowercase i, acute accent
return 0xb2;
case 0x5f: // lowercase o, acute accent
return 0x92;
case 0x60: // lowercase u, acute accent
return 0x93;
case 0x7b: // lowercase c with cedilla
return 0xa2;
case 0x88: // lowercase a, grave accent
return 0xa0;
case 0x8a: // lowercase e, grave accent
return 0xa3;
case 0x8b: // lowercase a, circumflex accent
return 0xa1;
case 0x8c: // lowercase e, circumflex accent
return 0xa4;
case 0x8d: // lowercase i, circumflex accent
return 0xa7;
case 0x8e: // lowercase o, circumflex accent
return 0xaa;
case 0x8f: // lowercase u, circumflex accent
return 0xad;
case 0x95: // lowercase letter U with diaeresis
return 0x94;
case 0xa6: // lowercase letter e with diaresis
return 0xa5;
case 0xa9: // lowercase i, with diaresis
return 0xa8;
case 0xac: // lowercase u, grave accent
return 0xab;
case 0xb1: // Lowercase a, tilde
return 0xb0;
case 0xb4: // Lowercase i, grave accent
return 0xb3;
case 0xb6: // Lowercase o, grave accent
return 0xb5;
case 0xb8: // Lowercase o, tilde
return 0xb7;
case 0xc1: // Lowercase A, umlaut
return 0xc0;
case 0xc3: // Lowercase o, umlaut
return 0xc2;
case 0xc9: // Lowercase A, ring
return 0xc8;
case 0xcb: // Lowercase o, slash
return 0xca;
}
return c;
}

View File

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

View File

@@ -0,0 +1,128 @@
#include "ccx_common_common.h"
int cc608_parity_table[256];
/* 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;
}
int add_cc_sub_text(struct cc_subtitle *sub, char *str, LLONG start_time,
LLONG end_time, char *info, char *mode, enum ccx_encoding_type e_type)
{
if (sub->nb_data)
{
for(;sub->next;sub = sub->next);
sub->next = malloc(sizeof(struct cc_subtitle));
if(!sub->next)
return -1;
sub->next->prev = sub;
sub = sub->next;
}
sub->type = CC_TEXT;
sub->enc_type = e_type;
sub->data = strdup(str);
sub->nb_data = strlen(str);
sub->start_time = start_time;
sub->end_time = end_time;
if(info)
strncpy(sub->info, info, 4);
if(mode)
strncpy(sub->mode, mode, 4);
sub->got_output = 1;
sub->next = NULL;
return 0;
}
int cc608_parity(unsigned int byte)
{
int ones = 0;
for (int i = 0; i < 7; i++)
{
if (byte & (1 << i))
ones++;
}
return ones & 1;
}
void cc608_build_parity_table(int *parity_table)
{
unsigned int byte;
int parity_v;
for (byte = 0; byte <= 127; byte++)
{
parity_v = cc608_parity(byte);
/* CC uses odd parity (i.e., # of 1's in byte is odd.) */
parity_table[byte] = parity_v;
parity_table[byte | 0x80] = !parity_v;
}
}
void build_parity_table (void)
{
cc608_build_parity_table(cc608_parity_table);
}

View File

@@ -0,0 +1,50 @@
#ifndef _CC_COMMON_COMMON
#define _CC_COMMON_COMMON
#include "ccx_common_platform.h"
#include "ccx_common_structs.h"
// Define possible exit codes that will be passed on to the fatal function
/* Exit codes. Take this seriously as the GUI depends on them.
0 means OK as usual,
<100 means display whatever was output to stderr as a warning
>=100 means display whatever was output to stdout as an error
*/
#define EXIT_OK 0
#define EXIT_NO_INPUT_FILES 2
#define EXIT_TOO_MANY_INPUT_FILES 3
#define EXIT_INCOMPATIBLE_PARAMETERS 4
#define EXIT_UNABLE_TO_DETERMINE_FILE_SIZE 6
#define EXIT_MALFORMED_PARAMETER 7
#define EXIT_READ_ERROR 8
#define EXIT_NOT_CLASSIFIED 300
#define EXIT_ERROR_IN_CAPITALIZATION_FILE 501
#define EXIT_BUFFER_FULL 502
#define EXIT_MISSING_ASF_HEADER 1001
#define EXIT_MISSING_RCWT_HEADER 1002
#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
#define CCX_OK 0
#define CCX_FALSE 0
#define CCX_TRUE 1
#define CCX_EAGAIN -100
#define CCX_EOF -101
#define CCX_EINVAL -102
#define CCX_ENOSUPP -103
#define CCX_ENOMEM -104
// Declarations
void fdprintf(int fd, const char *fmt, ...);
void mstotime(LLONG milli, unsigned *hours, unsigned *minutes,unsigned *seconds, unsigned *ms);
void freep(void *arg);
void dbg_print(LLONG mask, const char *fmt, ...);
unsigned char *debug_608toASC(unsigned char *ccdata, int channel);
int add_cc_sub_text(struct cc_subtitle *sub, char *str, LLONG start_time,
LLONG end_time, char *info, char *mode, enum ccx_encoding_type);
extern int cc608_parity_table[256]; // From myth
#endif

View File

@@ -0,0 +1,138 @@
#include "ccx_common_constants.h"
// RCWT header (11 bytes):
//byte(s) value description (All values below are hex numbers, not
// actual numbers or values
//0-2 CCCCED magic number, for Closed Caption CC Extractor Data
//3 CC Creating program. Legal values: CC = CC Extractor
//4-5 0050 Program version number
//6-7 0001 File format version
//8-10 000000 Padding, required :-)
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};
const unsigned char UTF8_BOM[]={0xef, 0xbb,0xbf};
const unsigned char DVD_HEADER[8]={0x00,0x00,0x01,0xb2,0x43,0x43,0x01,0xf8};
const unsigned char lc1[1]={0x8a};
const unsigned char lc2[1]={0x8f};
const unsigned char lc3[2]={0x16,0xfe};
const unsigned char lc4[2]={0x1e,0xfe};
const unsigned char lc5[1]={0xff};
const unsigned char lc6[1]={0xfe};
const double framerates_values[16]=
{
0,
24000.0/1001, /* 23.976 */
24.0,
25.0,
30000.0/1001, /* 29.97 */
30.0,
50.0,
60000.0/1001, /* 59.94 */
60.0,
0,
0,
0,
0,
0
};
const char *framerates_types[16]=
{
"00 - forbidden",
"01 - 23.976",
"02 - 24",
"03 - 25",
"04 - 29.97",
"05 - 30",
"06 - 50",
"07 - 59.94",
"08 - 60",
"09 - reserved",
"10 - reserved",
"11 - reserved",
"12 - reserved",
"13 - reserved",
"14 - reserved",
"15 - reserved"
};
const char *aspect_ratio_types[16]=
{
"00 - forbidden",
"01 - 1:1",
"02 - 4:3",
"03 - 16:9",
"04 - 2.21:1",
"05 - reserved",
"06 - reserved",
"07 - reserved",
"08 - reserved",
"09 - reserved",
"10 - reserved",
"11 - reserved",
"12 - reserved",
"13 - reserved",
"14 - reserved",
"15 - reserved"
};
const char *pict_types[8]=
{
"00 - ilegal (0)",
"01 - I",
"02 - P",
"03 - B",
"04 - ilegal (D)",
"05 - ilegal (5)",
"06 - ilegal (6)",
"07 - ilegal (7)"
};
const char *slice_types[10]=
{
"0 - P",
"1 - B",
"2 - I",
"3 - SP",
"4 - SI",
"5 - P",
"6 - B",
"7 - I",
"8 - SP",
"9 - SI"
};
const char *cc_types[4] =
{
"NTSC line 21 field 1 closed captions",
"NTSC line 21 field 2 closed captions",
"DTVCC Channel Packet Data",
"DTVCC Channel Packet Start"
};
enum
{
NTSC_CC_f1 = 0,
NTSC_CC_f2 = 1,
DTVCC_PACKET_DATA = 2,
DTVCC_PACKET_START = 3,
};
/**
* After Adding a new language here, dont forget
* to increase NB_LANGUAGE define ccx_common_constants.h
*/
const char *language[NB_LANGUAGE] =
{
"und",
"eng",
"fin",
"spa",
NULL
};

View File

@@ -1,6 +1,13 @@
#ifndef CCX_CONSTANTS_H
#define CCX_CONSTANTS_H
#include "stdio.h"
#ifndef __cplusplus
#define false 0
#define true 1
#endif
extern const char *framerates_types[16];
extern const double framerates_values[16];
@@ -20,7 +27,7 @@ extern const unsigned char lc4[2];
extern const unsigned char lc5[1];
extern const unsigned char lc6[1];
extern const unsigned char rcwt_header[11];
extern unsigned char rcwt_header[11];
#define ONEPASS 120 /* Bytes we can always look ahead without going out of limits */
#define BUFSIZE (2048*1024+ONEPASS) /* 2 Mb plus the safety pass */
@@ -29,26 +36,28 @@ extern const unsigned char rcwt_header[11];
#define TS_PACKET_PAYLOAD_LENGTH 184 // From specs
#define SUBLINESIZE 2048 // Max. length of a .srt line - TODO: Get rid of this
#define STARTBYTESLENGTH (1024*1024)
#define UTF8_MAX_BYTES 6
#define XMLRPC_CHUNK_SIZE (64*1024) // 64 Kb per chunk, to avoid too many realloc()
enum ccx_debug_message_types
enum ccx_debug_message_types
{
/* Each debug message now belongs to one of these types. Use bitmaps in case
we want one message to belong to more than one type. */
/* Each debug message now belongs to one of these types. Use bitmaps in case
we want one message to belong to more than one type. */
CCX_DMT_PARSE=1, // Show information related to parsing the container
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_708=0x20, // Show CC-708 decoder debug?
CCX_DMT_XDS=0x40, // Show XDS decoder debug?
CCX_DMT_DECODER_608=0x10, // Show CC-608 decoder debug?
CCX_DMT_708=0x20, // Show CC-708 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?
CCX_DMT_PAT=0x400, // Program Allocation Table dump
CCX_DMT_PMT=0x800, // Program Map Table dump
CCX_DMT_LEVENSHTEIN=0x1000, // Levenshtein distance calculations
CCX_DMT_DUMPDEF=0x2000 // Dump defective TS packets
};
// AVC NAL types
@@ -74,7 +83,7 @@ enum ccx_avc_nal_types
CCX_NAL_TYPE_RESERVED_17 = 18,
CCX_NAL_TYPE_RESERVED_18 = 18,
CCX_NAL_TYPE_CODED_SLICE_AUXILIARY_PICTURE = 19,
CCX_NAL_TYPE_CODED_SLICE_EXTENSION = 20,
CCX_NAL_TYPE_CODED_SLICE_EXTENSION = 20,
CCX_NAL_TYPE_RESERVED_21 = 21,
CCX_NAL_TYPE_RESERVED_22 = 22,
CCX_NAL_TYPE_RESERVED_23 = 23,
@@ -91,39 +100,40 @@ enum ccx_avc_nal_types
// MPEG-2 TS stream types
enum ccx_stream_type
{
CCX_STREAM_TYPE_UNKNOWNSTREAM = 0,
CCX_STREAM_TYPE_VIDEO_MPEG1 = 0x01,
CCX_STREAM_TYPE_VIDEO_MPEG2 = 0x02,
CCX_STREAM_TYPE_AUDIO_MPEG1 = 0x03,
CCX_STREAM_TYPE_AUDIO_MPEG2 = 0x04,
CCX_STREAM_TYPE_UNKNOWNSTREAM = 0,
CCX_STREAM_TYPE_VIDEO_MPEG1 = 0x01,
CCX_STREAM_TYPE_VIDEO_MPEG2 = 0x02,
CCX_STREAM_TYPE_AUDIO_MPEG1 = 0x03,
CCX_STREAM_TYPE_AUDIO_MPEG2 = 0x04,
CCX_STREAM_TYPE_PRIVATE_TABLE_MPEG2 = 0x05,
CCX_STREAM_TYPE_PRIVATE_MPEG2 = 0x06,
CCX_STREAM_TYPE_MHEG_PACKETS = 0x07,
CCX_STREAM_TYPE_MPEG2_ANNEX_A_DSM_CC = 0x08,
CCX_STREAM_TYPE_ITU_T_H222_1 = 0x09,
CCX_STREAM_TYPE_ITU_T_H222_1 = 0x09,
CCX_STREAM_TYPE_ISO_IEC_13818_6_TYPE_A = 0x0A,
CCX_STREAM_TYPE_ISO_IEC_13818_6_TYPE_B = 0x0B,
CCX_STREAM_TYPE_ISO_IEC_13818_6_TYPE_C = 0x0C,
CCX_STREAM_TYPE_ISO_IEC_13818_6_TYPE_D = 0x0D,
CCX_STREAM_TYPE_AUDIO_AAC = 0x0f,
CCX_STREAM_TYPE_VIDEO_MPEG4 = 0x10,
CCX_STREAM_TYPE_VIDEO_H264 = 0x1b,
CCX_STREAM_TYPE_AUDIO_AAC = 0x0f,
CCX_STREAM_TYPE_VIDEO_MPEG4 = 0x10,
CCX_STREAM_TYPE_VIDEO_H264 = 0x1b,
CCX_STREAM_TYPE_PRIVATE_USER_MPEG2=0x80,
CCX_STREAM_TYPE_AUDIO_AC3 = 0x81,
CCX_STREAM_TYPE_AUDIO_HDMV_DTS = 0x82,
CCX_STREAM_TYPE_AUDIO_DTS = 0x8a,
CCX_STREAM_TYPE_AUDIO_AC3 = 0x81,
CCX_STREAM_TYPE_AUDIO_HDMV_DTS = 0x82,
CCX_STREAM_TYPE_AUDIO_DTS = 0x8a,
};
enum ccx_mpeg_descriptor
{
CCX_MPEG_DSC_REGISTRATION = 0x05,
CCX_MPEG_DSC_REGISTRATION = 0x05,
CCX_MPEG_DSC_DATA_STREAM_ALIGNMENT = 0x06,
CCX_MPEG_DSC_ISO639_LANGUAGE = 0x0A,
CCX_MPEG_DSC_VBI_DATA_DESCRIPTOR = 0x45,
CCX_MPEG_DSC_VBI_TELETEXT_DESCRIPTOR = 0x46,
CCX_MPEG_DSC_TELETEXT_DESCRIPTOR = 0x56,
CCX_MPEG_DSC_DVB_SUBTITLE = 0x59,
CCX_MPEG_DSC_CAPTION_SERVICE = 0x86,
CCX_MPEG_DESC_DATA_COMP = 0xfd,
};
@@ -144,15 +154,17 @@ enum ccx_datasource
enum ccx_output_format
{
CCX_OF_RAW = 0,
CCX_OF_SRT = 1,
CCX_OF_SAMI = 2,
CCX_OF_TRANSCRIPT = 3,
CCX_OF_RCWT = 4,
CCX_OF_RAW = 0,
CCX_OF_SRT = 1,
CCX_OF_SAMI = 2,
CCX_OF_TRANSCRIPT = 3,
CCX_OF_RCWT = 4,
CCX_OF_NULL = 5,
CCX_OF_SMPTETT = 6,
CCX_OF_SPUPNG = 7,
CCX_OF_SPUPNG = 7,
CCX_OF_DVDRAW = 8, // See -d at http://www.geocities.com/mcpoodle43/SCC_TOOLS/DOCS/SCC_TOOLS.HTML#CCExtract
CCX_OF_WEBVTT = 9,
CCX_OF_SIMPLE_XML = 10,
};
enum ccx_output_date_format
@@ -166,47 +178,49 @@ enum ccx_output_date_format
enum ccx_stream_mode_enum
{
CCX_SM_ELEMENTARY_OR_NOT_FOUND=0,
CCX_SM_TRANSPORT=1,
CCX_SM_PROGRAM=2,
CCX_SM_ASF=3,
CCX_SM_MCPOODLESRAW = 4,
CCX_SM_RCWT = 5, // Raw Captions With Time, not used yet.
CCX_SM_MYTH = 6, // Use the myth loop
CCX_SM_ELEMENTARY_OR_NOT_FOUND=0,
CCX_SM_TRANSPORT=1,
CCX_SM_PROGRAM=2,
CCX_SM_ASF=3,
CCX_SM_MCPOODLESRAW = 4,
CCX_SM_RCWT = 5, // Raw Captions With Time, not used yet.
CCX_SM_MYTH = 6, // Use the myth loop
CCX_SM_MP4 = 7, // MP4, ISO-
#ifdef WTV_DEBUG
CCX_SM_HEX_DUMP = 8, // Hexadecimal dump generated by wtvccdump
#endif
CCX_SM_WTV = 9,
CCX_SM_AUTODETECT = 16
CCX_SM_WTV = 9,
CCX_SM_AUTODETECT = 16
};
enum ccx_encoding_type
{
CCX_ENC_UNICODE = 0,
CCX_ENC_LATIN_1 = 1,
CCX_ENC_UTF_8 = 2
CCX_ENC_UNICODE = 0,
CCX_ENC_LATIN_1 = 1,
CCX_ENC_UTF_8 = 2,
CCX_ENC_ASCII = 3
};
enum ccx_bufferdata_type
{
CCX_UNKNOWN = 0,
CCX_PES = 1,
CCX_RAW = 2,
CCX_H264 = 3,
CCX_UNKNOWN = 0,
CCX_PES = 1,
CCX_RAW = 2,
CCX_H264 = 3,
CCX_HAUPPAGE = 4,
CCX_TELETEXT = 5,
CCX_PRIVATE_MPEG2_CC = 6,
CCX_DVB_SUBTITLE = 7,
CCX_ISDB_SUBTITLE = 8,
};
enum ccx_frame_type
{
CCX_FRAME_TYPE_RESET_OR_UNKNOWN = 0,
CCX_FRAME_TYPE_I_FRAME = 1,
CCX_FRAME_TYPE_P_FRAME = 2,
CCX_FRAME_TYPE_B_FRAME = 3,
CCX_FRAME_TYPE_D_FRAME = 4
CCX_FRAME_TYPE_RESET_OR_UNKNOWN = 0,
CCX_FRAME_TYPE_I_FRAME = 1,
CCX_FRAME_TYPE_P_FRAME = 2,
CCX_FRAME_TYPE_B_FRAME = 3,
CCX_FRAME_TYPE_D_FRAME = 4
};
typedef enum {
@@ -215,13 +229,23 @@ typedef enum {
UNDEF = 0xff
} bool_t;
enum cxx_code_type
enum ccx_code_type
{
CCX_CODEC_ANY,
CCX_CODEC_TELETEXT,
CCX_CODEC_DVB,
CCX_CODEC_ISDB_CC,
CCX_CODEC_ATSC_CC,
CCX_CODEC_NONE,
};
enum cdp_section_type
{
CDP_SECTION_DATA = 0x72,
CDP_SECTION_SVC_INFO = 0x73,
CDP_SECTION_FOOTER = 0x74
};
/*
* This Macro check whether descriptor tag is valid for teletext
* codec or not.
@@ -229,19 +253,19 @@ enum cxx_code_type
* @param desc descriptor tag given for each stream
*
* @return if descriptor tag is valid then it return 1 otherwise 0
*
*
*/
#define IS_VALID_TELETEXT_DESC(desc) ( ((desc) == CCX_MPEG_DSC_VBI_DATA_DESCRIPTOR )|| \
( (desc) == CCX_MPEG_DSC_VBI_TELETEXT_DESCRIPTOR ) || \
( (desc) == CCX_MPEG_DSC_TELETEXT_DESCRIPTOR ) )
( (desc) == CCX_MPEG_DSC_VBI_TELETEXT_DESCRIPTOR ) || \
( (desc) == CCX_MPEG_DSC_TELETEXT_DESCRIPTOR ) )
/*
* This macro to be used when you want to find out whether you
* should parse f_sel subtitle codec type or not
*
* @param u_sel pass the codec selected by user to be searched in
* all elementry stream, we ignore the not to be selected stream
* all elementary stream, we ignore the not to be selected stream
* if we find stream this is selected stream. since setting
* selected stream and not selected to same codec does not
* make ay sense.
@@ -254,15 +278,18 @@ enum cxx_code_type
* to parse.
*/
#define IS_FEASIBLE(u_sel,u_nsel,f_sel) ( ( (u_sel) == CCX_CODEC_ANY && (u_nsel) != (f_sel) ) || (u_sel) == (f_sel) )
#define CCX_TXT_FORBIDDEN 0 // Ignore teletext packets
#define CCX_TXT_AUTO_NOT_YET_FOUND 1
#define CCX_TXT_IN_USE 2 // Positive autodetected, or forced, etc
#define CCX_TXT_FORBIDDEN 0 // Ignore teletext packets
#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];
#define NB_LANGUAGE 5
extern const char *language[NB_LANGUAGE];
#define DEF_VAL_STARTCREDITSNOTBEFORE "0"
// To catch the theme after the teaser in TV shows
#define DEF_VAL_STARTCREDITSNOTAFTER "5:00"
#define DEF_VAL_STARTCREDITSFORATLEAST "2"
#define DEF_VAL_STARTCREDITSFORATMOST "5"
#define DEF_VAL_ENDCREDITSFORATLEAST "2"
#define DEF_VAL_ENDCREDITSFORATMOST "5"
#endif

View File

@@ -0,0 +1,132 @@
#include "ccx_common_option.h"
#include "ccx_encoders_common.h"
#include "ccx_decoders_708.h"
#include "utility.h"
extern ccx_encoders_transcript_format ccx_encoders_default_transcript_settings;
/* Parameters */
void init_options (struct ccx_s_options *options)
{
#ifdef _WIN32
options->buffer_input = 1; // In Windows buffering seems to help
#else
options->buffer_input = 0; // In linux, not so much.
#endif
options->nofontcolor=0; // 1 = don't put <font color> tags
options->notypesetting=0; // 1 = Don't put <i>, <u>, etc typesetting tags
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.
/* Credit stuff */
options->extract = 1; // Extract 1st field only (primary language)
options->cc_channel = 1; // Channel we want to dump in srt mode
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->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
options->enc_cfg.sentence_cap =0 ; // FIX CASE? = Fix case?
options->sentence_cap_file=NULL; // Extra words file?
options->live_stream=0; // 0 -> A regular file
options->messages_target=1; // 1=stdout
options->print_file_reports=0;
/* Levenshtein's parameters, for string comparison */
options->levdistmincnt=2; // Means 2 fails or less is "the same"...
options->levdistmaxpct=10; // ...10% or less is also "the same"
options->investigate_packets = 0; // Look for captions in all packets when everything else fails
options->fullbin=0; // Disable pruning of padding cc blocks
options->nosync=0; // Disable syncing
options->hauppauge_mode=0; // If 1, use PID=1003, process specially and so on
options->wtvconvertfix = 0; // Fix broken Windows 7 conversion
options->wtvmpeg2 = 0;
options->auto_myth = 2; // 2=auto
/* MP4 related stuff */
options->mp4vidtrack=0; // Process the video track even if a CC dedicated track exists.
/* General stuff */
options->usepicorder = 0; // Force the use of pic_order_cnt_lsb in AVC/H.264 data streams
options->xmltv=0; // 1 = full output. 2 = live output. 3 = both
options->xmltvliveinterval=10; // interval in seconds between writting xmltv output files in live mode
options->xmltvoutputinterval=0; // interval in seconds between writting xmltv full file output
options->xmltvonlycurrent=0; // 0 off 1 on
options->transcript_settings = ccx_encoders_default_transcript_settings;
options->millis_separator=',';
options->write_format=CCX_OF_SRT; // 0=Raw, 1=srt, 2=SMI
options->date_format=ODF_NONE;
options->output_filename = NULL;
options->debug_mask=CCX_DMT_GENERIC_NOTICES; // dbg_print will use this mask to print or ignore different types
options->debug_mask_on_debug=CCX_DMT_VERBOSE; // If we're using temp_debug to enable/disable debug "live", this is the mask when temp_debug=1
/* Networking */
options->udpaddr = NULL;
options->udpport=0; // Non-zero => Listen for UDP packets on this port, no files.
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->noautotimeref=0; // Do NOT set time automatically?
options->input_source=CCX_DS_FILE; // Files, stdin or network
options->multiprogram = 0;
options->out_interval = -1;
options->subs_delay = 0;
/* Select subtitle codec */
options->demux_cfg.codec = CCX_CODEC_ANY;
options->demux_cfg.nocodec = CCX_CODEC_NONE;
options->demux_cfg.auto_stream = CCX_SM_AUTODETECT;
options->demux_cfg.m2ts = 0;
options->demux_cfg.out_elementarystream_filename=NULL;
options->demux_cfg.ts_autoprogram =0; // Try to find a stream with captions automatically (no -pn needed)
options->demux_cfg.ts_cappids[0] = 0; // PID for stream that holds caption information
options->demux_cfg.nb_ts_cappid = 0;
options->demux_cfg.ts_forced_program = -1; // Specific program to process in TS files, if ts_forced_program_selected==1
options->demux_cfg.ts_forced_program_selected=0;
options->demux_cfg.ts_datastreamtype = CCX_STREAM_TYPE_UNKNOWNSTREAM; // User WANTED stream type (i.e. use the stream that has this type)
options->demux_cfg.ts_forced_streamtype=CCX_STREAM_TYPE_UNKNOWNSTREAM; // User selected (forced) stream type
options->enc_cfg.autodash=0; // Add dashes (-) before each speaker automatically?
options->enc_cfg.trim_subs=0; // " Remove spaces at sides? "
options->enc_cfg.in_format = 1;
options->enc_cfg.line_terminator_lf=0; // 0 = CRLF
options->enc_cfg.start_credits_text=NULL;
options->enc_cfg.end_credits_text=NULL;
options->enc_cfg.encoding = CCX_ENC_UTF_8;
options->enc_cfg.no_bom = 0; // Use BOM by default.
options->enc_cfg.services_charsets = NULL;
options->enc_cfg.all_services_charset = NULL;
options->settings_dtvcc.enabled = 0;
options->settings_dtvcc.active_services_count = 0;
options->settings_dtvcc.print_file_reports = 1;
options->settings_dtvcc.no_rollup = 0;
options->settings_dtvcc.report = NULL;
memset(options->settings_dtvcc.services_enabled, 0, CCX_DTVCC_MAX_SERVICES);
// Prepare time structures
init_boundary_time (&options->extraction_start);
init_boundary_time (&options->extraction_end);
init_boundary_time (&options->enc_cfg.startcreditsnotbefore);
init_boundary_time (&options->enc_cfg.startcreditsnotafter);
init_boundary_time (&options->enc_cfg.startcreditsforatleast);
init_boundary_time (&options->enc_cfg.startcreditsforatmost);
init_boundary_time (&options->enc_cfg.endcreditsforatleast);
init_boundary_time (&options->enc_cfg.endcreditsforatmost);
// Sensible default values for credits
stringztoms (DEF_VAL_STARTCREDITSNOTBEFORE, &options->enc_cfg.startcreditsnotbefore);
stringztoms (DEF_VAL_STARTCREDITSNOTAFTER, &options->enc_cfg.startcreditsnotafter);
stringztoms (DEF_VAL_STARTCREDITSFORATLEAST, &options->enc_cfg.startcreditsforatleast);
stringztoms (DEF_VAL_STARTCREDITSFORATMOST, &options->enc_cfg.startcreditsforatmost);
stringztoms (DEF_VAL_ENDCREDITSFORATLEAST, &options->enc_cfg.endcreditsforatleast);
stringztoms (DEF_VAL_ENDCREDITSFORATMOST, &options->enc_cfg.endcreditsforatmost);
}

View File

@@ -0,0 +1,144 @@
#ifndef CCX_COMMON_OPTION_H
#define CCX_COMMON_OPTION_H
#include "ccx_common_timing.h"
#include "ccx_decoders_608.h"
#include "ccx_encoders_structs.h"
#include "list.h"
struct demuxer_cfg
{
int m2ts; // Regular TS or M2TS
enum ccx_stream_mode_enum auto_stream;
char *out_elementarystream_filename;
/* subtitle codec type */
enum ccx_code_type codec;
enum ccx_code_type nocodec;
unsigned ts_autoprogram; // Try to find a stream with captions automatically (no -pn needed)
unsigned ts_allprogram;
unsigned ts_cappids[128]; // PID for stream that holds caption information
int nb_ts_cappid;
unsigned ts_forced_cappid ; // If 1, never mess with the selected PID
int ts_forced_program; // Specific program to process in TS files, if ts_forced_program_selected==1
unsigned ts_forced_program_selected;
int ts_datastreamtype ; // User WANTED stream type (i.e. use the stream that has this type)
unsigned ts_forced_streamtype; // User selected (forced) stream type
};
struct encoder_cfg
{
int extract; // Extract 1st, 2nd or both fields
int dtvcc_extract; // 1 or 0
int gui_mode_reports; // If 1, output in stderr progress updates so the GUI can grab them
char *output_filename;
enum ccx_output_format write_format; // 0=Raw, 1=srt, 2=SMI
enum ccx_encoding_type encoding;
enum ccx_output_date_format date_format;
char millis_separator;
int autodash; // Add dashes (-) before each speaker automatically?
int trim_subs; // " Remove spaces at sides? "
int sentence_cap ; // FIX CASE? = Fix case?
/* Credit stuff */
char *start_credits_text;
char *end_credits_text;
struct ccx_boundary_time startcreditsnotbefore, startcreditsnotafter; // Where to insert start credits, if possible
struct ccx_boundary_time startcreditsforatleast, startcreditsforatmost; // How long to display them?
struct ccx_boundary_time endcreditsforatleast, endcreditsforatmost;
ccx_encoders_transcript_format transcript_settings; // Keeps the settings for generating transcript output files.
unsigned int send_to_srv;
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!
char *first_input_file;
int multiple_files;
int no_font_color;
int no_type_setting;
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.
int line_terminator_lf; // 0 = CRLF, 1=LF
LLONG subs_delay; // ms to delay (or advance) subs
int program_number;
unsigned char in_format;
//CEA-708
int services_enabled[CCX_DTVCC_MAX_SERVICES];
char** services_charsets;
char* all_services_charset;
};
struct ccx_s_options // Options from user parameters
{
int extract; // Extract 1st, 2nd or both fields
int no_rollup;
int cc_channel; // Channel we want to dump in srt mode
int buffer_input;
int nofontcolor;
int notypesetting;
struct ccx_boundary_time extraction_start, extraction_end; // Segment we actually process
int print_file_reports;
ccx_decoder_608_settings settings_608; // Contains the settings for the 608 decoder.
ccx_decoder_dtvcc_settings settings_dtvcc; //Same for 708 decoder
char millis_separator;
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 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
char *sentence_cap_file; // Extra words file?
int live_stream; /* -1 -> Not a complete file but a live stream, without timeout
0 -> A regular file
>0 -> Live stream with a timeout of this value in seconds */
int messages_target; // 0 = nowhere (quiet), 1=stdout, 2=stderr
/* Levenshtein's parameters, for string comparison */
int levdistmincnt, levdistmaxpct; // Means 2 fails or less is "the same", 10% or less is also "the same"
int investigate_packets; // Look for captions in all packets when everything else fails
int fullbin; // Disable pruning of padding cc blocks
int nosync; // Disable syncing
unsigned int hauppauge_mode; // If 1, use PID=1003, process specially and so on
int wtvconvertfix; // Fix broken Windows 7 conversion
int wtvmpeg2;
int auto_myth; // Use myth-tv mpeg code? 0=no, 1=yes, 2=auto
/* MP4 related stuff */
unsigned mp4vidtrack; // Process the video track even if a CC dedicated track exists.
/* General settings */
int usepicorder; // Force the use of pic_order_cnt_lsb in AVC/H.264 data streams
int xmltv; // 1 = full output. 2 = live output. 3 = both
int xmltvliveinterval; // interval in seconds between writting xmltv output files in live mode
int xmltvoutputinterval; // interval in seconds between writting xmltv full file output
int xmltvonlycurrent; // 0 off 1 on
ccx_encoders_transcript_format transcript_settings; // Keeps the settings for generating transcript output files.
enum ccx_output_date_format date_format;
unsigned send_to_srv;
enum ccx_output_format write_format; // 0=Raw, 1=srt, 2=SMI
LLONG debug_mask; // dbg_print will use this mask to print or ignore different types
LLONG debug_mask_on_debug; // If we're using temp_debug to enable/disable debug "live", this is the mask when temp_debug=1
/* Networking */
char *udpaddr;
unsigned udpport; // Non-zero => Listen for UDP packets on this port, no files.
char *tcpport;
char *tcp_password;
char *tcp_desc;
char *srv_addr;
char *srv_port;
int noautotimeref; // Do NOT set time automatically?
enum ccx_datasource input_source; // Files, stdin or network
char *output_filename;
char **inputfile; // List of files to process
int num_input_files; // How many?
struct demuxer_cfg demux_cfg;
struct encoder_cfg enc_cfg;
LLONG subs_delay; // ms to delay (or advance) subs
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.
int multiprogram;
int out_interval;
};
extern struct ccx_s_options ccx_options;
void init_options (struct ccx_s_options *options);
#endif

View File

@@ -0,0 +1,115 @@
#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
#define inline _inline
#define typeof decltype
#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

View File

@@ -0,0 +1,74 @@
#ifndef _CC_COMMON_STRUCTS
#define _CC_COMMON_STRUCTS
#include "ccx_common_constants.h"
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 {
LLONG 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)
};
extern struct ccx_common_logging_t ccx_common_logging;
enum subtype
{
CC_BITMAP,
CC_608,
CC_708,
CC_TEXT,
CC_RAW,
};
/**
* Raw Subtitle struct used as output of decoder (cc608)
* and input for encoder (sami, srt, transcript or smptett etc)
*
* if subtype CC_BITMAP then data contain nb_data numbers of rectangle
* which have to be displayed at same time.
*/
struct cc_subtitle
{
/**
* A generic data which contain data according to decoder
* @warn decoder cant output multiple types of data
*/
void *data;
/** number of data */
unsigned int nb_data;
/** type of subtitle */
enum subtype type;
/** Encoding type of Text, must be ignored in case of subtype as bitmap or cc_screen*/
enum ccx_encoding_type enc_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;
char mode[5];
char info[4];
struct cc_subtitle *next;
struct cc_subtitle *prev;
};
#endif

View File

@@ -0,0 +1,367 @@
#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
*/
// Count 608 (per field) and 708 blocks since last set_fts() call
int cb_field1, cb_field2, cb_708;
int MPEG_CLOCK_FREQ = 90000; // This "constant" is part of the standard
int max_dif = 5;
unsigned pts_big_change;
// PTS timing related stuff
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;
struct gop_time_code gop_time, first_gop_time, printed_gop;
LLONG fts_at_gop_start = 0;
int gop_rollover = 0;
struct ccx_common_timing_settings_t ccx_common_timing_settings;
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 dinit_timing_ctx(struct ccx_common_timing_ctx **arg)
{
freep(arg);
}
struct ccx_common_timing_ctx *init_timing_ctx(struct ccx_common_timing_settings_t *cfg)
{
struct ccx_common_timing_ctx *ctx = malloc(sizeof(struct ccx_common_timing_ctx));
if(!ctx)
return NULL;
ctx->pts_set = 0;
ctx->current_tref = 0;
ctx->current_pts = 0;
ctx->current_picture_coding_type = CCX_FRAME_TYPE_RESET_OR_UNKNOWN;
ctx->min_pts = 0x01FFFFFFFFLL; // 33 bit
ctx->max_pts = 0;
ctx->sync_pts = 0;
ctx->minimum_fts = 0;
ctx->fts_now = 0; // Time stamp of current file (w/ fts_offset, w/o fts_global)
ctx->fts_offset = 0; // Time before first sync_pts
ctx->fts_fc_offset = 0; // Time before first GOP
ctx->fts_max = 0; // Remember the maximum fts that we saw in current file
ctx->fts_global = 0; // Duration of previous files (-ve mode), see c1global
return ctx;
}
void add_current_pts(struct ccx_common_timing_ctx *ctx, LLONG pts)
{
set_current_pts(ctx, ctx->current_pts + pts);
}
void set_current_pts(struct ccx_common_timing_ctx *ctx, LLONG pts)
{
ctx->current_pts = pts;
if(ctx->pts_set == 0)
ctx->pts_set = 1;
dbg_print(CCX_DMT_VIDES, "PTS: %s (%8u)", print_mstime(ctx->current_pts/(MPEG_CLOCK_FREQ/1000)),
(unsigned) (ctx->current_pts));
dbg_print(CCX_DMT_VIDES, " FTS: %s \n",print_mstime(ctx->fts_now));
}
int set_fts(struct ccx_common_timing_ctx *ctx)
{
int pts_jump = 0;
// ES don't have PTS unless GOP timing is used
if (!ctx->pts_set && ccx_common_timing_settings.is_elementary_stream)
return CCX_OK;
// First check for timeline jump (only when min_pts was set (implies sync_pts)).
int dif = 0;
if (ctx->pts_set == 2)
{
dif=(int) (ctx->current_pts - ctx->sync_pts)/MPEG_CLOCK_FREQ;
if (ccx_common_timing_settings.disable_sync_check){
// Disables sync check. Used for several input formats.
dif = 0;
}
if (dif < -0.2 || dif >= max_dif )
{
// ATSC specs: More than 3501 ms means missing component
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",ctx->sync_pts);
ccx_common_logging.log_ftn ("Current PTS value: %lld\n",ctx->current_pts);
pts_jump = 1;
pts_big_change = 1;
// Discard the gap if it is not on an I-frame or temporal reference zero.
if(ctx->current_tref != 0 && ctx->current_picture_coding_type != CCX_FRAME_TYPE_I_FRAME)
{
ctx->fts_now = ctx->fts_max;
ccx_common_logging.log_ftn ("Change did not occur on first frame - probably a broken GOP\n");
return CCX_OK;
}
}
}
// Set min_pts, fts_offset
if (ctx->pts_set != 0)
{
ctx->pts_set = 2;
// Use this part only the first time min_pts is set. Later treat
// it as a reference clock change
if (ctx->current_pts < ctx->min_pts && !pts_jump)
{
// If this is the first GOP, and seq 0 was not encountered yet
// we might reset min_pts/fts_offset again
ctx->min_pts = ctx->current_pts;
// Avoid next async test
ctx->sync_pts = (LLONG)(ctx->current_pts
-ctx->current_tref*1000.0/current_fps
*(MPEG_CLOCK_FREQ/1000));
if(ctx->current_tref == 0)
{ // Earliest time in GOP.
ctx->fts_offset = 0;
}
else if ( total_frames_count-frames_since_ref_time == 0 )
{ // If this is the first frame (PES) there cannot be an offset.
// This part is also reached for dvr-ms/NTSC (RAW) as
// total_frames_count = frames_since_ref_time = 0 when
// this is called for the first time.
ctx->fts_offset = 0;
}
else
{ // It needs to be "+1" because the current frame is
// not yet counted.
ctx->fts_offset = (LLONG)((total_frames_count
-frames_since_ref_time+1)
*1000.0/current_fps);
}
ccx_common_logging.debug_ftn(CCX_DMT_TIME, "\nFirst sync time PTS: %s %+lldms (time before this PTS)\n",
print_mstime(ctx->min_pts/(MPEG_CLOCK_FREQ/1000)),
ctx->fts_offset );
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 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
// time of the frames since then.
ctx->fts_offset = ctx->fts_offset
+ (ctx->sync_pts - ctx->min_pts)/(MPEG_CLOCK_FREQ/1000)
+ (LLONG) (frames_since_ref_time*1000/current_fps);
ctx->fts_max = ctx->fts_offset;
// Start counting again from here
ctx->pts_set = 1; // Force min to be set again
// Avoid next async test - the gap might have occured on
// current_tref != 0.
ctx->sync_pts = (LLONG) (ctx->current_pts
-ctx->current_tref*1000.0/current_fps
*(MPEG_CLOCK_FREQ/1000));
// Set min_pts = sync_pts as this is used for fts_now
ctx->min_pts = ctx->sync_pts;
ccx_common_logging.debug_ftn(CCX_DMT_TIME, "\nNew min PTS time: %s %+lldms (time before this PTS)\n",
print_mstime(ctx->min_pts/(MPEG_CLOCK_FREQ/1000)),
ctx->fts_offset );
}
}
// Set sync_pts, fts_offset
if(ctx->current_tref == 0)
ctx->sync_pts = ctx->current_pts;
// Reset counters
cb_field1 = 0;
cb_field2 = 0;
cb_708 = 0;
// Avoid wrong "Calc. difference" and "Asynchronous by" numbers
// for uninitialized min_pts
if (1) // CFS: Remove or think decent condition
{
if ( ctx->pts_set )
{
// If pts_set is TRUE we have min_pts
ctx->fts_now = (LLONG)((ctx->current_pts - ctx->min_pts)/(MPEG_CLOCK_FREQ/1000)
+ ctx->fts_offset);
}
else
{
// No PTS info at all!!
ccx_common_logging.log_ftn("Set PTS called without any global timestamp set\n");
return CCX_EINVAL;
}
}
if ( ctx->fts_now > ctx->fts_max )
{
ctx->fts_max = ctx->fts_now;
}
return CCX_OK;
}
LLONG get_fts(struct ccx_common_timing_ctx *ctx, int current_field)
{
LLONG fts;
switch (current_field)
{
case 1:
fts = ctx->fts_now + ctx->fts_global + cb_field1*1001/30;
break;
case 2:
fts = ctx->fts_now + ctx->fts_global + cb_field2*1001/30;
break;
case 3:
fts = ctx->fts_now + ctx->fts_global + cb_708*1001/30;
break;
default:
ccx_common_logging.fatal_ftn(CCX_COMMON_EXIT_BUG_BUG, "get_fts: unhandled branch");
}
// ccx_common_logging.debug_ftn(CCX_DMT_TIME, "[FTS] "
// "fts: %llu, fts_now: %llu, fts_global: %llu, current_field: %llu, cb_708: %llu\n",
// fts, fts_now, fts_global, current_field, cb_708);
return fts;
}
LLONG get_fts_max(struct ccx_common_timing_ctx *ctx)
{
// This returns the maximum FTS that belonged to a frame. Caption block
// counters are not applicable.
return ctx->fts_max + ctx->fts_global;
}
/* Fill a static buffer with a time string (hh:mm:ss:ms) corresponding
to the microsecond value in mstime. */
char *print_mstime2buf( LLONG mstime , char *buf )
{
unsigned hh,mm,ss,ms;
int signoffset = (mstime < 0 ? 1 : 0);
if (mstime<0) // Avoid loss of data warning with abs()
mstime=-mstime;
hh = (unsigned) (mstime/1000/60/60);
mm = (unsigned) (mstime/1000/60 - 60*hh);
ss = (unsigned) (mstime/1000 - 60*(mm + 60*hh));
ms = (int) (mstime - 1000*(ss + 60*(mm + 60*hh)));
buf[0]='-';
sprintf (buf+signoffset, "%02u:%02u:%02u:%03u",hh,mm,ss,ms);
return buf;
}
/**
* Fill buffer with a time string using specified format
* @param fmt has to contain 4 format specifiers for h, m, s and ms respectively
*/
size_t mstime_sprintf(LLONG mstime, char *fmt, char *buf)
{
unsigned hh, mm, ss, ms;
int signoffset = (mstime < 0 ? 1 : 0);
if (mstime < 0) // Avoid loss of data warning with abs()
mstime = -mstime;
hh = (unsigned) (mstime / 1000 / 60 / 60);
mm = (unsigned) (mstime / 1000 / 60 - 60 * hh);
ss = (unsigned) (mstime / 1000 - 60 * (mm + 60 * hh));
ms = (unsigned) (mstime - 1000 * (ss + 60 * (mm + 60 * hh)));
buf[0] = '-';
return (size_t) sprintf(buf + signoffset, fmt, hh, mm, ss, ms);
}
/* Fill a static buffer with a time string (hh:mm:ss:ms) corresponding
to the microsecond value in mstime. */
char *print_mstime( LLONG mstime )
{
static char buf[15]; // 14 should be long enough
return print_mstime2buf (mstime, buf);
}
/* Helper function for to display debug timing info. */
void print_debug_timing(struct ccx_common_timing_ctx *ctx)
{
// Avoid wrong "Calc. difference" and "Asynchronous by" numbers
// for uninitialized min_pts
LLONG tempmin_pts = (ctx->min_pts==0x01FFFFFFFFLL ? ctx->sync_pts : ctx->min_pts);
ccx_common_logging.log_ftn("Sync time stamps: PTS: %s ",
print_mstime((ctx->sync_pts)/(MPEG_CLOCK_FREQ/1000)) );
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);
// Length at last sync point
LLONG ptslenms = (unsigned)((ctx->sync_pts-tempmin_pts)/(MPEG_CLOCK_FREQ/1000)
+ ctx->fts_offset);
ccx_common_logging.log_ftn("Last FTS: %s",
print_mstime(get_fts_max(ctx)));
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
ccx_common_logging.log_ftn("Max FTS diff. to PTS: %6lldms GOP: %6lldms\n\n",
get_fts_max(ctx)+(LLONG)(1000.0/current_fps)-ptslenms,
get_fts_max(ctx)+(LLONG)(1000.0/current_fps)-goplenms);
}
void calculate_ms_gop_time (struct gop_time_code *g)
{
int seconds=(g->time_code_hours*3600)+(g->time_code_minutes*60)+g->time_code_seconds;
g->ms = (LLONG)( 1000*(seconds + g->time_code_pictures/current_fps) );
if (gop_rollover)
g->ms += 24*60*60*1000;
}
int gop_accepted(struct gop_time_code* g )
{
if (! ((g->time_code_hours <= 23)
&& (g->time_code_minutes <= 59)
&& (g->time_code_seconds <= 59)
&& (g->time_code_pictures <= 59)))
return 0;
if (gop_time.time_code_hours==23 && gop_time.time_code_minutes==59 &&
g->time_code_hours==0 && g->time_code_minutes==0)
{
gop_rollover = 1;
return 1;
}
if (gop_time.inited)
{
if (gop_time.ms > g->ms)
{
// We are going back in time but it's not a complete day rollover
return 0;
}
}
return 1;
}

View File

@@ -0,0 +1,85 @@
#ifndef __Timing_H__
#define __Timing_H__
#include "ccx_common_platform.h"
#include "ccx_common_constants.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
};
extern struct ccx_common_timing_settings_t ccx_common_timing_settings;
struct ccx_boundary_time
{
int hh,mm,ss;
LLONG time_in_ms;
int set;
};
struct ccx_common_timing_ctx
{
int pts_set; //0 = No, 1 = received, 2 = min_pts set
LLONG current_pts;
enum ccx_frame_type current_picture_coding_type;
int current_tref; // Store temporal reference of current frame
LLONG min_pts;
LLONG max_pts;
LLONG sync_pts;
LLONG minimum_fts; // No screen should start before this FTS
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; // 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 MPEG_CLOCK_FREQ; // This is part of the standard
extern int max_dif;
extern unsigned pts_big_change;
extern enum ccx_frame_type current_picture_coding_type;
extern double current_fps;
extern int frames_since_ref_time;
extern unsigned total_frames_count;
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 dinit_timing_ctx(struct ccx_common_timing_ctx **arg);
struct ccx_common_timing_ctx *init_timing_ctx(struct ccx_common_timing_settings_t *cfg);
void set_current_pts(struct ccx_common_timing_ctx *ctx, LLONG pts);
void add_current_pts(struct ccx_common_timing_ctx *ctx, LLONG pts);
int set_fts(struct ccx_common_timing_ctx *ctx);
LLONG get_fts(struct ccx_common_timing_ctx *ctx, int current_field);
LLONG get_fts_max(struct ccx_common_timing_ctx *ctx);
char *print_mstime(LLONG mstime);
char *print_mstime2buf(LLONG mstime, char *buf);
size_t mstime_sprintf(LLONG mstime, char *fmt, char *buf);
void print_debug_timing(struct ccx_common_timing_ctx *ctx);
int gop_accepted(struct gop_time_code* g);
void calculate_ms_gop_time(struct gop_time_code *g);
#endif

View File

@@ -1,15 +1,17 @@
#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
int in_xds_mode=0;
unsigned char str[2048]; // Another generic general purpose buffer
//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,17 +47,6 @@ 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[] =
@@ -95,7 +86,8 @@ static const char *cc_modes_text[]=
"Pop-Up captions"
};
#endif
const char *color_text[][2]=
const char *color_text[MAX_COLOR][2]=
{
{"white",""},
{"green","<font color=\"#00ff00\">"},
@@ -110,25 +102,34 @@ 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)
void ccx_decoder_608_dinit_library(void **ctx)
{
freep(ctx);
}
ccx_decoder_608_context* ccx_decoder_608_init_library(struct ccx_decoder_608_settings *settings, int channel,
int field, int *halt,
int cc_to_stdout,
enum ccx_output_format output_format, struct ccx_common_timing_ctx *timing)
{
ccx_decoder_608_context *data = NULL;
data = malloc(sizeof(ccx_decoder_608_context));
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;
@@ -137,7 +138,6 @@ void init_context_cc608(struct s_context_cc608 *data, int field)
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;
@@ -145,11 +145,27 @@ void init_context_cc608(struct s_context_cc608 *data, int field)
data->new_channel=1;
data->bytes_processed_608 = 0;
data->my_field = field;
data->out = NULL;
data->my_channel = channel;
data->have_cursor_position = 0;
data->output_format = output_format;
data->cc_to_stdout = cc_to_stdout;
data->textprinted = 0;
data->ts_start_of_current_line = 0;
data->halt = halt;
data->settings = settings;
data->current_color = data->settings->default_color;
data->report = settings->report;
data->timing = timing;
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,75 +189,77 @@ 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;
if (use_buffer->empty)
{
if (MODE_POPON != context->mode)
context->current_visible_start_ms = get_visible_start();
context->current_visible_start_ms = get_visible_start(context->timing, context->my_field);
}
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();
context->ts_last_char_received = get_fts();
context->ts_start_of_current_line = get_fts(context->timing, context->my_field);
context->ts_last_char_received = get_fts(context->timing, context->my_field);
}
}
/* 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 +268,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 +278,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,14 +286,14 @@ 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;
}
data = get_current_visible_buffer(context);
if (context->mode == MODE_FAKE_ROLLUP_1 && // Use the actual start of data instead of last buffer change
@@ -283,7 +301,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(context->timing, context->my_field);
sub->type = CC_608;
data->format = SFORMAT_CC_SCREEN;
data->start_time = 0;
@@ -292,12 +310,12 @@ int write_cc_buffer(struct s_context_cc608 *context, struct cc_subtitle *sub)
data->channel = context->channel;
data->my_field = context->my_field;
if (!data->empty)
if (!data->empty && context->output_format != CCX_OF_NULL)
{
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 +327,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,33 +347,31 @@ 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;
LLONG end_time;
int i = 0;
int wrote_something=0;
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;
end_time = get_fts(context->timing, context->my_field);
sub->type = CC_608;
data->format = SFORMAT_CC_LINE;
data->format = SFORMAT_CC_LINE;
data->start_time = 0;
data->end_time = 0;
data->mode = context->mode;
data->channel = context->channel;
data->my_field = context->my_field;
ret = get_decoder_line_basic (subline, context->cursor_row, data);
if( ret > 0 )
if (!data->empty)
{
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 +390,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) );
@@ -391,11 +407,11 @@ int write_cc_line(struct s_context_cc608 *context, struct cc_subtitle *sub)
}
}
return wrote_something;
}
// 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 +467,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 +510,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 +519,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 +546,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 +557,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 +574,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 +593,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(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 +640,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 +662,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 +735,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 (context->output_format == CCX_OF_TRANSCRIPT)
{
write_cc_line(context,sub);
}
@@ -730,18 +746,18 @@ 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 (context->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
}
}
roll_up(context); // The roll must be done anyway of course.
context->ts_start_of_current_line = -1; // Unknown.
if (changes)
context->current_visible_start_ms = get_visible_start();
context->current_visible_start_ms = get_visible_start(context->timing, context->my_field);
context->cursor_column = 0;
break;
case COM_ERASENONDISPLAYEDMEMORY:
@@ -750,7 +766,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 (context->output_format == CCX_OF_TRANSCRIPT &&
(context->mode == MODE_FAKE_ROLLUP_1 ||
context->mode == MODE_ROLLUP_2 ||
context->mode == MODE_ROLLUP_3 ||
@@ -763,13 +779,13 @@ void handle_command(/*const */ unsigned char c1, const unsigned char c2, struct
}
else
{
if (ccx_options.write_format==CCX_OF_TRANSCRIPT)
if (context->output_format == CCX_OF_TRANSCRIPT)
context->ts_start_of_current_line = context->current_visible_start_ms;
if (write_cc_buffer(context, sub))
context->screenfuls_counter++;
}
erase_memory(context, true);
context->current_visible_start_ms = get_visible_start();
context->current_visible_start_ms = get_visible_start(context->timing, context->my_field);
break;
case COM_ENDOFCAPTION: // Switch buffers
// The currently *visible* buffer is leaving, so now we know its ending
@@ -777,10 +793,10 @@ void handle_command(/*const */ unsigned char c1, const unsigned char c2, struct
if (write_cc_buffer(context, sub))
context->screenfuls_counter++;
context->visible_buffer = (context->visible_buffer == 1) ? 2 : 1;
context->current_visible_start_ms = get_visible_start();
context->current_visible_start_ms = get_visible_start(context->timing, context->my_field);
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 +809,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 flush_608_context(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 +830,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 +883,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 +911,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,11 +942,11 @@ 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;
use_buffer->row_used[j]=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 +954,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
@@ -955,16 +971,16 @@ void erase_both_memories(struct s_context_cc608 *context, struct cc_subtitle *su
// time. Time to actually write it to file.
if (write_cc_buffer(context, sub))
context->screenfuls_counter++;
context->current_visible_start_ms = get_visible_start();
context->current_visible_start_ms = get_visible_start(context->timing, context->my_field);
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 +989,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 +1003,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;
@@ -1053,13 +1069,31 @@ int disCommand(unsigned char hi, unsigned char lo, struct s_context_cc608 *conte
return wrote_to_screen;
}
/* 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)
/* If private data is NULL, then only XDS will be processed */
int process608(const unsigned char *data, int length, void *private_data, struct cc_subtitle *sub)
{
static int textprinted = 0;
struct ccx_decoder_608_report *report = NULL;
struct lib_cc_decode *dec_ctx = private_data;
struct ccx_decoder_608_context *context;
int i;
if(dec_ctx->current_field == 1)
{
context = dec_ctx->context_cc608_field_1;
}
else if (dec_ctx->current_field == 2 && dec_ctx->extract == 1)
{
context = NULL;
}
else
{
context = dec_ctx->context_cc608_field_2;
}
if (context)
{
report = context->report;
context->bytes_processed_608 += length;
}
if (!data)
{
return -1;
@@ -1079,10 +1113,11 @@ 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;
if(report)
report->cc_channels[ch - 1] = 1;
}
if (hi >= 0x01 && hi <= 0x0E && (context == NULL || context->my_field == 2)) // XDS can only exist in field 2.
@@ -1091,16 +1126,16 @@ int process608(const unsigned char *data, int length, struct s_context_cc608 *co
context->channel = 3;
if (!in_xds_mode)
{
ts_start_of_xds=get_fts();
in_xds_mode=1;
ts_start_of_xds = get_fts(dec_ctx->timing, dec_ctx->current_field);
in_xds_mode = 1;
}
file_report.xds=1;
if(report)
report->xds = 1;
}
if (hi == 0x0F && in_xds_mode && (context == NULL || context->my_field == 2)) // End of XDS block
{
in_xds_mode=0;
do_end_of_xds (sub, lo);
do_end_of_xds (sub, dec_ctx->xds_ctx, lo);
if (context)
context->channel = context->new_channel; // Switch from channel 3
continue;
@@ -1109,22 +1144,24 @@ int process608(const unsigned char *data, int length, struct s_context_cc608 *co
// http://www.geocities.com/mcpoodle43/SCC_TOOLS/DOCS/CC_CODES.HTML
// http://www.geocities.com/mcpoodle43/SCC_TOOLS/DOCS/CC_CHARS.HTML
{
// We were writing characters before, start a new line for
// diagnostic output from disCommand()
if (textprinted == 1 )
{
dbg_print(CCX_DMT_608, "\n");
textprinted = 0;
}
if (!context || context->my_field == 2)
in_xds_mode=0; // Back to normal (CEA 608-8.6.2)
if (!context) // Not XDS and we don't have a writebuffer, nothing else would have an effect
continue;
// We were writing characters before, start a new line for
// diagnostic output from disCommand()
if (context->textprinted == 1 )
{
ccx_common_logging.debug_ftn(CCX_DMT_DECODER_608, "\n");
context->textprinted = 0;
}
if (context->last_c1 == hi && context->last_c2 == lo)
{
// 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;
@@ -1140,7 +1177,7 @@ int process608(const unsigned char *data, int length, struct s_context_cc608 *co
{
if (in_xds_mode && (context == NULL || context->my_field == 2))
{
process_xds_bytes (hi,lo);
process_xds_bytes (dec_ctx->xds_ctx, hi, lo);
continue;
}
if (!context) // No XDS code after this point, and user doesn't want captions.
@@ -1152,13 +1189,13 @@ 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 )
if( context->textprinted == 0 )
{
dbg_print(CCX_DMT_608, "\n");
textprinted = 1;
ccx_common_logging.debug_ftn(CCX_DMT_DECODER_608, "\n");
context->textprinted = 1;
}
handle_single(hi, context);
@@ -1168,16 +1205,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 (!context->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(dec_ctx->timing, context->my_field)));
//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 ||
@@ -1185,10 +1222,10 @@ int process608(const unsigned char *data, int length, struct s_context_cc608 *co
{
// We don't increase screenfuls_counter here.
write_cc_buffer(context, sub);
context->current_visible_start_ms = get_visible_start();
context->current_visible_start_ms = get_visible_start(context->timing, context->my_field);
}
}
if (wrote_to_screen && cc_to_stdout)
if (wrote_to_screen && context->cc_to_stdout)
fflush (stdout);
} // for
return i;

View File

@@ -0,0 +1,148 @@
#ifndef CCX_DECODER_608_H
#define CCX_DECODER_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
{
uint8_t xds : 1;
uint8_t cc_channels[4];
};
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
struct ccx_decoder_608_report *report;
} 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
int have_cursor_position;
int *halt; // Can be used to halt the feeding of caption data. Set to 1 if screens_to_progress != -1 && screenfuls_counter >= screens_to_process
int cc_to_stdout; // If this is set to 1, the stdout will be flushed when data was written to the screen during a process_608 call.
struct ccx_decoder_608_report *report;
LLONG subs_delay; // ms to delay (or advance) subs
enum ccx_output_format output_format; // What kind of output format should be used?
int textprinted;
struct ccx_common_timing_ctx *timing;
} ccx_decoder_608_context;
#define MAX_COLOR 10
extern const char *color_text[MAX_COLOR][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
};
void ccx_decoder_608_dinit_library(void **ctx);
/*
*
*/
ccx_decoder_608_context* ccx_decoder_608_init_library(struct ccx_decoder_608_settings *settings, int channel,
int field, int *halt,
int cc_to_stdout,
enum ccx_output_format output_format, struct ccx_common_timing_ctx *timing);
/**
* @param data raw cc608 data to be processed
*
* @param length length of data passed
*
* @param private_data 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, void *private_data, struct cc_subtitle *sub);
/**
* Issue a EraseDisplayedMemory here so if there's any captions pending
* they get written to cc_subtitle
*/
void flush_608_context(ccx_decoder_608_context *context, struct cc_subtitle *sub);
int write_cc_buffer(ccx_decoder_608_context *context, struct cc_subtitle *sub);
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,372 @@
#ifndef _INCLUDE_708_
#define _INCLUDE_708_
#include <sys/stat.h>
#include "ccx_common_platform.h"
#include "ccx_common_constants.h"
#include "ccx_common_structs.h"
#define CCX_DTVCC_MAX_PACKET_LENGTH 128 //According to EIA-708B, part 5
#define CCX_DTVCC_MAX_SERVICES 63
#define CCX_DTVCC_MAX_ROWS 15
/**
* This value should be 32, but there were 16-bit encoded samples (from Korea),
* where RowCount calculated another way and equals 46 (23[8bit]*2)
*/
#define CCX_DTVCC_MAX_COLUMNS (32*2)
#define CCX_DTVCC_SCREENGRID_ROWS 75
#define CCX_DTVCC_SCREENGRID_COLUMNS 210
#define CCX_DTVCC_MAX_WINDOWS 8
#define CCX_DTVCC_FILENAME_TEMPLATE ".p%u.svc%02u"
#define CCX_DTVCC_NO_LAST_SEQUENCE -1
enum CCX_DTVCC_COMMANDS_C0_CODES
{
CCX_DTVCC_C0_NUL = 0x00,
CCX_DTVCC_C0_ETX = 0x03,
CCX_DTVCC_C0_BS = 0x08,
CCX_DTVCC_C0_FF = 0x0c,
CCX_DTVCC_C0_CR = 0x0d,
CCX_DTVCC_C0_HCR = 0x0e,
CCX_DTVCC_C0_EXT1 = 0x10,
CCX_DTVCC_C0_P16 = 0x18
};
enum CCX_DTVCC_COMMANDS_C1_CODES
{
CCX_DTVCC_C1_CW0 = 0x80,
CCX_DTVCC_C1_CW1 = 0x81,
CCX_DTVCC_C1_CW2 = 0x82,
CCX_DTVCC_C1_CW3 = 0x83,
CCX_DTVCC_C1_CW4 = 0x84,
CCX_DTVCC_C1_CW5 = 0x85,
CCX_DTVCC_C1_CW6 = 0x86,
CCX_DTVCC_C1_CW7 = 0x87,
CCX_DTVCC_C1_CLW = 0x88,
CCX_DTVCC_C1_DSW = 0x89,
CCX_DTVCC_C1_HDW = 0x8A,
CCX_DTVCC_C1_TGW = 0x8B,
CCX_DTVCC_C1_DLW = 0x8C,
CCX_DTVCC_C1_DLY = 0x8D,
CCX_DTVCC_C1_DLC = 0x8E,
CCX_DTVCC_C1_RST = 0x8F,
CCX_DTVCC_C1_SPA = 0x90,
CCX_DTVCC_C1_SPC = 0x91,
CCX_DTVCC_C1_SPL = 0x92,
CCX_DTVCC_C1_RSV93 = 0x93,
CCX_DTVCC_C1_RSV94 = 0x94,
CCX_DTVCC_C1_RSV95 = 0x95,
CCX_DTVCC_C1_RSV96 = 0x96,
CCX_DTVCC_C1_SWA = 0x97,
CCX_DTVCC_C1_DF0 = 0x98,
CCX_DTVCC_C1_DF1 = 0x99,
CCX_DTVCC_C1_DF2 = 0x9A,
CCX_DTVCC_C1_DF3 = 0x9B,
CCX_DTVCC_C1_DF4 = 0x9C,
CCX_DTVCC_C1_DF5 = 0x9D,
CCX_DTVCC_C1_DF6 = 0x9E,
CCX_DTVCC_C1_DF7 = 0x9F
};
struct CCX_DTVCC_S_COMMANDS_C1
{
int code;
const char *name;
const char *description;
int length;
};
enum ccx_dtvcc_window_justify
{
CCX_DTVCC_WINDOW_JUSTIFY_LEFT = 0,
CCX_DTVCC_WINDOW_JUSTIFY_RIGHT = 1,
CCX_DTVCC_WINDOW_JUSTIFY_CENTER = 2,
CCX_DTVCC_WINDOW_JUSTIFY_FULL = 3
};
enum ccx_dtvcc_window_pd //Print Direction
{
CCX_DTVCC_WINDOW_PD_LEFT_RIGHT = 0, //left -> right
CCX_DTVCC_WINDOW_PD_RIGHT_LEFT = 1,
CCX_DTVCC_WINDOW_PD_TOP_BOTTOM = 2,
CCX_DTVCC_WINDOW_PD_BOTTOM_TOP = 3
};
enum ccx_dtvcc_window_sd //Scroll Direction
{
CCX_DTVCC_WINDOW_SD_LEFT_RIGHT = 0,
CCX_DTVCC_WINDOW_SD_RIGHT_LEFT = 1,
CCX_DTVCC_WINDOW_SD_TOP_BOTTOM = 2,
CCX_DTVCC_WINDOW_SD_BOTTOM_TOP = 3
};
enum ccx_dtvcc_window_sde //Scroll Display Effect
{
CCX_DTVCC_WINDOW_SDE_SNAP = 0,
CCX_DTVCC_WINDOW_SDE_FADE = 1,
CCX_DTVCC_WINDOW_SDE_WIPE = 2
};
enum ccx_dtvcc_window_ed //Effect Direction
{
CCX_DTVCC_WINDOW_ED_LEFT_RIGHT = 0,
CCX_DTVCC_WINDOW_ED_RIGHT_LEFT = 1,
CCX_DTVCC_WINDOW_ED_TOP_BOTTOM = 2,
CCX_DTVCC_WINDOW_ED_BOTTOM_TOP = 3
};
enum ccx_dtvcc_window_fo //Fill Opacity
{
CCX_DTVCC_WINDOW_FO_SOLID = 0,
CCX_DTVCC_WINDOW_FO_FLASH = 1,
CCX_DTVCC_WINDOW_FO_TRANSLUCENT = 2,
CCX_DTVCC_WINDOW_FO_TRANSPARENT = 3
};
enum ccx_dtvcc_window_border
{
CCX_DTVCC_WINDOW_BORDER_NONE = 0,
CCX_DTVCC_WINDOW_BORDER_RAISED = 1,
CCX_DTVCC_WINDOW_BORDER_DEPRESSED = 2,
CCX_DTVCC_WINDOW_BORDER_UNIFORM = 3,
CCX_DTVCC_WINDOW_BORDER_SHADOW_LEFT = 4,
CCX_DTVCC_WINDOW_BORDER_SHADOW_RIGHT = 5
};
enum ccx_dtvcc_pen_size
{
CCX_DTVCC_PEN_SIZE_SMALL = 0,
CCX_DTVCC_PEN_SIZE_STANDART = 1,
CCX_DTVCC_PEN_SIZE_LARGE = 2
};
enum ccx_dtvcc_pen_font_style
{
CCX_DTVCC_PEN_FONT_STYLE_DEFAULT_OR_UNDEFINED = 0,
CCX_DTVCC_PEN_FONT_STYLE_MONOSPACED_WITH_SERIFS = 1,
CCX_DTVCC_PEN_FONT_STYLE_PROPORTIONALLY_SPACED_WITH_SERIFS = 2,
CCX_DTVCC_PEN_FONT_STYLE_MONOSPACED_WITHOUT_SERIFS = 3,
CCX_DTVCC_PEN_FONT_STYLE_PROPORTIONALLY_SPACED_WITHOUT_SERIFS = 4,
CCX_DTVCC_PEN_FONT_STYLE_CASUAL_FONT_TYPE = 5,
CCX_DTVCC_PEN_FONT_STYLE_CURSIVE_FONT_TYPE = 6,
CCX_DTVCC_PEN_FONT_STYLE_SMALL_CAPITALS = 7
};
enum ccx_dtvcc_pen_text_tag
{
CCX_DTVCC_PEN_TEXT_TAG_DIALOG = 0,
CCX_DTVCC_PEN_TEXT_TAG_SOURCE_OR_SPEAKER_ID = 1,
CCX_DTVCC_PEN_TEXT_TAG_ELECTRONIC_VOICE = 2,
CCX_DTVCC_PEN_TEXT_TAG_FOREIGN_LANGUAGE = 3,
CCX_DTVCC_PEN_TEXT_TAG_VOICEOVER = 4,
CCX_DTVCC_PEN_TEXT_TAG_AUDIBLE_TRANSLATION = 5,
CCX_DTVCC_PEN_TEXT_TAG_SUBTITLE_TRANSLATION = 6,
CCX_DTVCC_PEN_TEXT_TAG_VOICE_QUALITY_DESCRIPTION = 7,
CCX_DTVCC_PEN_TEXT_TAG_SONG_LYRICS = 8,
CCX_DTVCC_PEN_TEXT_TAG_SOUND_EFFECT_DESCRIPTION = 9,
CCX_DTVCC_PEN_TEXT_TAG_MUSICAL_SCORE_DESCRIPTION = 10,
CCX_DTVCC_PEN_TEXT_TAG_EXPLETIVE = 11,
CCX_DTVCC_PEN_TEXT_TAG_UNDEFINED_12 = 12,
CCX_DTVCC_PEN_TEXT_TAG_UNDEFINED_13 = 13,
CCX_DTVCC_PEN_TEXT_TAG_UNDEFINED_14 = 14,
CCX_DTVCC_PEN_TEXT_TAG_NOT_TO_BE_DISPLAYED = 15
};
enum ccx_dtvcc_pen_offset
{
CCX_DTVCC_PEN_OFFSET_SUBSCRIPT = 0,
CCX_DTVCC_PEN_OFFSET_NORMAL = 1,
CCX_DTVCC_PEN_OFFSET_SUPERSCRIPT = 2
};
enum ccx_dtvcc_pen_edge
{
CCX_DTVCC_PEN_EDGE_NONE = 0,
CCX_DTVCC_PEN_EDGE_RAISED = 1,
CCX_DTVCC_PEN_EDGE_DEPRESSED = 2,
CCX_DTVCC_PEN_EDGE_UNIFORM = 3,
CCX_DTVCC_PEN_EDGE_LEFT_DROP_SHADOW = 4,
CCX_DTVCC_PEN_EDGE_RIGHT_DROP_SHADOW = 5
};
enum ccx_dtvcc_pen_anchor_point
{
CCX_DTVCC_ANCHOR_POINT_TOP_LEFT = 0,
CCX_DTVCC_ANCHOR_POINT_TOP_CENTER = 1,
CCX_DTVCC_ANCHOR_POINT_TOP_RIGHT = 2,
CCX_DTVCC_ANCHOR_POINT_MIDDLE_LEFT = 3,
CCX_DTVCC_ANCHOR_POINT_MIDDLE_CENTER = 4,
CCX_DTVCC_ANCHOR_POINT_MIDDLE_RIGHT = 5,
CCX_DTVCC_ANCHOR_POINT_BOTTOM_LEFT = 6,
CCX_DTVCC_ANCHOR_POINT_BOTTOM_CENTER = 7,
CCX_DTVCC_ANCHOR_POINT_BOTTOM_RIGHT = 8
};
typedef struct ccx_dtvcc_pen_color
{
int fg_color;
int fg_opacity;
int bg_color;
int bg_opacity;
int edge_color;
} ccx_dtvcc_pen_color;
typedef struct ccx_dtvcc_pen_attribs
{
int pen_size;
int offset;
int text_tag;
int font_tag;
int edge_type;
int underline;
int italic;
} ccx_dtvcc_pen_attribs;
typedef struct ccx_dtvcc_window_attribs
{
int justify;
int print_direction;
int scroll_direction;
int word_wrap;
int display_effect;
int effect_direction;
int effect_speed;
int fill_color;
int fill_opacity;
int border_type;
int border_color;
} ccx_dtvcc_window_attribs;
/**
* Since 1-byte and 2-byte symbols could appear in captions and
* since we have to keep symbols alignment and several windows could appear on a screen at one time,
* we use special structure for holding symbols
*/
typedef struct ccx_dtvcc_symbol
{
unsigned short sym; //symbol itself, at least 16 bit
unsigned char len; //length. could be 1 or 2
} ccx_dtvcc_symbol;
#define CCX_DTVCC_SYM_SET(x, c) {x.len = 1; x.sym = c;}
#define CCX_DTVCC_SYM_SET_16(x, c1, c2) {x.len = 2; x.sym = (c1 << 8) | c2;}
#define CCX_DTVCC_SYM_IS_16(x) (x.len == 2)
#define CCX_DTVCC_SYM(x) ((unsigned char)(x.sym))
#define CCX_DTVCC_SYM_16_FIRST(x) ((unsigned char)(x.sym >> 8))
#define CCX_DTVCC_SYM_16_SECOND(x) ((unsigned char)(x.sym & 0xff))
#define CCX_DTVCC_SYM_IS_EMPTY(x) (x.len == 0)
#define CCX_DTVCC_SYM_IS_SET(x) (x.len > 0)
typedef struct ccx_dtvcc_window
{
int is_defined;
int number;
int priority;
int col_lock;
int row_lock;
int visible;
int anchor_vertical;
int relative_pos;
int anchor_horizontal;
int row_count;
int anchor_point;
int col_count;
int pen_style;
int win_style;
unsigned char commands[6]; // Commands used to create this window
ccx_dtvcc_window_attribs attribs;
int pen_row;
int pen_column;
ccx_dtvcc_symbol *rows[CCX_DTVCC_MAX_ROWS];
ccx_dtvcc_pen_color pen_colors[CCX_DTVCC_MAX_ROWS];
ccx_dtvcc_pen_attribs pen_attribs[CCX_DTVCC_MAX_ROWS];
int memory_reserved;
int is_empty;
LLONG time_ms_show;
LLONG time_ms_hide;
} ccx_dtvcc_window;
typedef struct dtvcc_tv_screen
{
ccx_dtvcc_symbol chars[CCX_DTVCC_SCREENGRID_ROWS][CCX_DTVCC_SCREENGRID_COLUMNS];
ccx_dtvcc_pen_color pen_colors[CCX_DTVCC_SCREENGRID_ROWS];
ccx_dtvcc_pen_attribs pen_attribs[CCX_DTVCC_SCREENGRID_ROWS];
LLONG time_ms_show;
LLONG time_ms_hide;
unsigned int cc_count;
int service_number;
} dtvcc_tv_screen;
/**
* Holds data on the CEA 708 services that are encountered during file parse
* This can be interesting, so CCExtractor uses it for the report functionality.
*/
typedef struct ccx_decoder_dtvcc_report
{
int reset_count;
unsigned services[CCX_DTVCC_MAX_SERVICES];
} ccx_decoder_dtvcc_report;
typedef struct ccx_dtvcc_service_decoder
{
ccx_dtvcc_window windows[CCX_DTVCC_MAX_WINDOWS];
int current_window;
dtvcc_tv_screen *tv;
int cc_count;
} ccx_dtvcc_service_decoder;
typedef struct ccx_decoder_dtvcc_settings
{
int enabled;
int print_file_reports;
int no_rollup;
ccx_decoder_dtvcc_report *report;
int active_services_count;
int services_enabled[CCX_DTVCC_MAX_SERVICES];
struct ccx_common_timing_ctx *timing;
} ccx_decoder_dtvcc_settings;
/**
* TODO
* solution requires "sink" or "writer" entity to write captions to output file
* decoders have to know nothing about output files
*/
typedef struct ccx_dtvcc_ctx
{
int is_active;
int active_services_count;
int services_active[CCX_DTVCC_MAX_SERVICES]; //0 - inactive, 1 - active
int report_enabled;
ccx_decoder_dtvcc_report *report;
ccx_dtvcc_service_decoder decoders[CCX_DTVCC_MAX_SERVICES];
unsigned char current_packet[CCX_DTVCC_MAX_PACKET_LENGTH];
int current_packet_length;
int last_sequence;
void *encoder; //we can't include header, so keeping it this way
int no_rollup;
struct ccx_common_timing_ctx *timing;
} ccx_dtvcc_ctx;
void ccx_dtvcc_clear_packet(ccx_dtvcc_ctx *ctx);
void ccx_dtvcc_windows_reset(ccx_dtvcc_service_decoder *decoder);
void ccx_dtvcc_decoder_flush(ccx_dtvcc_ctx *dtvcc, ccx_dtvcc_service_decoder *decoder);
void ccx_dtvcc_process_current_packet(ccx_dtvcc_ctx *dtvcc);
void ccx_dtvcc_process_service_block(ccx_dtvcc_ctx *dtvcc,
ccx_dtvcc_service_decoder *decoder,
unsigned char *data,
int data_length);
#endif

View File

@@ -0,0 +1,45 @@
/********************************************************
256 BYTES IS ENOUGH FOR ALL THE SUPPORTED CHARACTERS IN
EIA-708, SO INTERNALLY WE USE THIS TABLE (FOR CONVENIENCE)
00-1F -> Characters that are in the G2 group in 20-3F,
except for 06, which is used for the closed captions
sign "CC" which is defined in group G3 as 00. (this
is by the article 33).
20-7F -> Group G0 as is - corresponds to the ASCII code
80-9F -> Characters that are in the G2 group in 60-7F
(there are several blank characters here, that's OK)
A0-FF -> Group G1 as is - non-English characters and symbols
*/
unsigned char dtvcc_get_internal_from_G0(unsigned char g0_char)
{
return g0_char;
}
unsigned char dtvcc_get_internal_from_G1(unsigned char g1_char)
{
return g1_char;
}
// TODO: Probably not right
// G2: Extended Control Code Set 1
unsigned char dtvcc_get_internal_from_G2(unsigned char g2_char)
{
if (g2_char >= 0x20 && g2_char <= 0x3F)
return g2_char - (unsigned char)0x20;
if (g2_char >= 0x60 && g2_char <= 0x7F)
return g2_char + (unsigned char)0x20;
// Rest unmapped, so we return a blank space
return 0x20;
}
// TODO: Probably not right
// G3: Future Characters and Icon Expansion
unsigned char dtvcc_get_internal_from_G3(unsigned char g3_char)
{
if (g3_char == 0xa0) // The "CC" (closed captions) sign
return 0x06;
// Rest unmapped, so we return a blank space
return 0x20;
}

View File

@@ -0,0 +1,9 @@
#ifndef _CCX_DECODERS_708_ENCODING_H_
#define _CCX_DECODERS_708_ENCODING_H_
unsigned char dtvcc_get_internal_from_G0(unsigned char g0_char);
unsigned char dtvcc_get_internal_from_G1(unsigned char g1_char);
unsigned char dtvcc_get_internal_from_G2(unsigned char g2_char);
unsigned char dtvcc_get_internal_from_G3(unsigned char g3_char);
#endif /*_CCX_DECODERS_708_ENCODING_H_*/

View File

@@ -0,0 +1,425 @@
#include "ccx_decoders_708_output.h"
#include "ccx_encoders_common.h"
#include "utility.h"
#include "ccx_common_common.h"
int _dtvcc_is_row_empty(dtvcc_tv_screen *tv, int row_index)
{
for (int j = 0; j < CCX_DTVCC_SCREENGRID_COLUMNS; j++)
{
if (CCX_DTVCC_SYM_IS_SET(tv->chars[row_index][j]))
return 0;
}
return 1;
}
int _dtvcc_is_screen_empty(dtvcc_tv_screen *tv)
{
for (int i = 0; i < CCX_DTVCC_SCREENGRID_ROWS; i++)
{
if (!_dtvcc_is_row_empty(tv, i))
return 0;
}
return 1;
}
void _dtvcc_get_write_interval(dtvcc_tv_screen *tv, int row_index, int *first, int *last)
{
for (*first = 0; *first < CCX_DTVCC_SCREENGRID_COLUMNS; (*first)++)
if (CCX_DTVCC_SYM_IS_SET(tv->chars[row_index][*first]))
break;
for (*last = CCX_DTVCC_SCREENGRID_COLUMNS - 1; *last > 0; (*last)--)
if (CCX_DTVCC_SYM_IS_SET(tv->chars[row_index][*last]))
break;
}
void _dtvcc_color_to_hex(int color, unsigned *hR, unsigned *hG, unsigned *hB)
{
*hR = (unsigned) (color >> 4);
*hG = (unsigned) ((color >> 2) & 0x3);
*hB = (unsigned) (color & 0x3);
ccx_common_logging.debug_ftn(CCX_DMT_708, "[CEA-708] Color: %d [%06x] %u %u %u\n",
color, color, *hR, *hG, *hB);
}
void _dtvcc_write_tag_open(dtvcc_tv_screen *tv, struct encoder_ctx *encoder, int row_index)
{
char *buf = (char *) encoder->buffer;
size_t buf_len = 0;
if (tv->pen_attribs[row_index].italic)
buf_len += sprintf(buf + buf_len, "<i>");
if (tv->pen_attribs[row_index].underline)
buf_len += sprintf(buf + buf_len, "<u>");
if (tv->pen_colors[row_index].fg_color != 0x3f && !encoder->no_font_color) //assuming white is default
{
unsigned red, green, blue;
_dtvcc_color_to_hex(tv->pen_colors[row_index].fg_color, &red, &green, &blue);
red = (255 / 3) * red;
green = (255 / 3) * green;
blue = (255 / 3) * blue;
buf_len += sprintf(buf + buf_len, "<font color=\"%02x%02x%02x\">", red, green, blue);
}
write(encoder->dtvcc_writers[tv->service_number - 1].fd, buf, buf_len);
}
void _dtvcc_write_tag_close(dtvcc_tv_screen *tv, struct encoder_ctx *encoder, int row_index)
{
char *buf = (char *) encoder->buffer;
size_t buf_len = 0;
if (tv->pen_colors[row_index].fg_color != 0x3f && !encoder->no_font_color)
buf_len += sprintf(buf + buf_len, "</font>");
if (tv->pen_attribs[row_index].underline)
buf_len += sprintf(buf + buf_len, "</u>");
if (tv->pen_attribs[row_index].italic)
buf_len += sprintf(buf + buf_len, "</i>");
write(encoder->dtvcc_writers[tv->service_number - 1].fd, buf, buf_len);
}
void _dtvcc_write_row(ccx_dtvcc_writer_ctx *writer, dtvcc_tv_screen *tv, int row_index, struct encoder_ctx *encoder)
{
char *buf = (char *) encoder->buffer;
size_t buf_len = 0;
memset(buf, 0, INITIAL_ENC_BUFFER_CAPACITY * sizeof(char));
int first, last;
_dtvcc_get_write_interval(tv, row_index, &first, &last);
for (int j = first; j <= last; j++)
{
if (CCX_DTVCC_SYM_IS_16(tv->chars[row_index][j]))
{
buf[buf_len++] = CCX_DTVCC_SYM_16_FIRST(tv->chars[row_index][j]);
buf[buf_len++] = CCX_DTVCC_SYM_16_SECOND(tv->chars[row_index][j]);
}
else
{
buf[buf_len++] = CCX_DTVCC_SYM(tv->chars[row_index][j]);
}
}
int fd = encoder->dtvcc_writers[tv->service_number - 1].fd;
if (writer->cd != (iconv_t) -1)
{
char *encoded_buf = calloc(INITIAL_ENC_BUFFER_CAPACITY, sizeof(char));
if (!encoded_buf)
ccx_common_logging.fatal_ftn(EXIT_NOT_ENOUGH_MEMORY, "_dtvcc_write_row");
char *encoded_buf_start = encoded_buf;
size_t in_bytes_left = buf_len;
size_t out_bytes_left = INITIAL_ENC_BUFFER_CAPACITY * sizeof(char);
size_t result = iconv(writer->cd, &buf, &in_bytes_left, &encoded_buf, &out_bytes_left);
if (result == -1)
ccx_common_logging.log_ftn("[CEA-708] _dtvcc_write_row: "
"conversion failed: %s\n", strerror(errno));
write(fd, encoded_buf_start, encoded_buf - encoded_buf_start);
free(encoded_buf_start);
}
else
{
write(fd, buf, buf_len);
}
}
void ccx_dtvcc_write_srt(ccx_dtvcc_writer_ctx *writer, dtvcc_tv_screen *tv, struct encoder_ctx *encoder)
{
if (_dtvcc_is_screen_empty(tv))
return;
if (tv->time_ms_show + encoder->subs_delay < 0)
return;
char *buf = (char *) encoder->buffer;
memset(buf, 0, INITIAL_ENC_BUFFER_CAPACITY);
sprintf(buf, "%u%s", tv->cc_count, encoder->encoded_crlf);
mstime_sprintf(tv->time_ms_show + encoder->subs_delay,
"%02u:%02u:%02u,%03u", buf + strlen(buf));
sprintf(buf + strlen(buf), " --> ");
mstime_sprintf(tv->time_ms_hide + encoder->subs_delay,
"%02u:%02u:%02u,%03u", buf + strlen(buf));
sprintf(buf + strlen(buf), (char *) encoder->encoded_crlf);
write(encoder->dtvcc_writers[tv->service_number - 1].fd, buf, strlen(buf));
for (int i = 0; i < CCX_DTVCC_SCREENGRID_ROWS; i++)
{
if (!_dtvcc_is_row_empty(tv, i))
{
_dtvcc_write_tag_open(tv, encoder, i);
_dtvcc_write_row(writer, tv, i, encoder);
_dtvcc_write_tag_close(tv, encoder, i);
write(encoder->dtvcc_writers[tv->service_number - 1].fd,
encoder->encoded_crlf, encoder->encoded_crlf_length);
}
}
write(encoder->dtvcc_writers[tv->service_number - 1].fd,
encoder->encoded_crlf, encoder->encoded_crlf_length);
}
void ccx_dtvcc_write_debug(dtvcc_tv_screen *tv)
{
char tbuf1[SUBLINESIZE],
tbuf2[SUBLINESIZE];
print_mstime2buf(tv->time_ms_show, tbuf1);
print_mstime2buf(tv->time_ms_hide, tbuf2);
ccx_common_logging.debug_ftn(CCX_DMT_GENERIC_NOTICES, "\r%s --> %s\n", tbuf1, tbuf2);
for (int i = 0; i < CCX_DTVCC_SCREENGRID_ROWS; i++)
{
if (!_dtvcc_is_row_empty(tv, i))
{
int first, last;
_dtvcc_get_write_interval(tv, i, &first, &last);
for (int j = first; j <= last; j++)
ccx_common_logging.debug_ftn(CCX_DMT_GENERIC_NOTICES, "%c", tv->chars[i][j]);
ccx_common_logging.debug_ftn(CCX_DMT_GENERIC_NOTICES, "\n");
}
}
}
void ccx_dtvcc_write_transcript(ccx_dtvcc_writer_ctx *writer, dtvcc_tv_screen *tv, struct encoder_ctx *encoder)
{
if (_dtvcc_is_screen_empty(tv))
return;
if (tv->time_ms_show + encoder->subs_delay < 0) // Drop screens that because of subs_delay start too early
return;
char *buf = (char *) encoder->buffer;
for (int i = 0; i < CCX_DTVCC_SCREENGRID_ROWS; i++)
{
if (!_dtvcc_is_row_empty(tv, i))
{
buf[0] = 0;
if (encoder->transcript_settings->showStartTime)
mstime_sprintf(tv->time_ms_show + encoder->subs_delay,
"%02u:%02u:%02u,%03u|", buf + strlen(buf));
if (encoder->transcript_settings->showEndTime)
mstime_sprintf(tv->time_ms_hide + encoder->subs_delay,
"%02u:%02u:%02u,%03u|", buf + strlen(buf));
if (encoder->transcript_settings->showCC)
sprintf(buf + strlen(buf), "CC1|"); //always CC1 because CEA-708 is field-independent
if (encoder->transcript_settings->showMode)
sprintf(buf + strlen(buf), "POP|"); //TODO caption mode(pop, rollup, etc.)
if (strlen(buf))
write(encoder->dtvcc_writers[tv->service_number - 1].fd, buf, strlen(buf));
_dtvcc_write_row(writer, tv, i, encoder);
write(encoder->dtvcc_writers[tv->service_number - 1].fd,
encoder->encoded_crlf, encoder->encoded_crlf_length);
}
}
}
void _dtvcc_write_sami_header(dtvcc_tv_screen *tv, struct encoder_ctx *encoder)
{
char *buf = (char *) encoder->buffer;
memset(buf, 0, INITIAL_ENC_BUFFER_CAPACITY);
size_t buf_len = 0;
buf_len += sprintf(buf + buf_len, "<sami>%s", encoder->encoded_crlf);
buf_len += sprintf(buf + buf_len, "<head>%s", encoder->encoded_crlf);
buf_len += sprintf(buf + buf_len, "<style type=\"text/css\">%s", encoder->encoded_crlf);
buf_len += sprintf(buf + buf_len, "<!--%s", encoder->encoded_crlf);
buf_len += sprintf(buf + buf_len,
"p {margin-left: 16pt; margin-right: 16pt; margin-bottom: 16pt; margin-top: 16pt;%s",
encoder->encoded_crlf);
buf_len += sprintf(buf + buf_len,
"text-align: center; font-size: 18pt; font-family: arial; font-weight: bold; color: #f0f0f0;}%s",
encoder->encoded_crlf);
buf_len += sprintf(buf + buf_len, ".unknowncc {Name:Unknown; lang:en-US; SAMIType:CC;}%s", encoder->encoded_crlf);
buf_len += sprintf(buf + buf_len, "-->%s", encoder->encoded_crlf);
buf_len += sprintf(buf + buf_len, "</style>%s", encoder->encoded_crlf);
buf_len += sprintf(buf + buf_len, "</head>%s%s", encoder->encoded_crlf, encoder->encoded_crlf);
buf_len += sprintf(buf + buf_len, "<body>%s", encoder->encoded_crlf);
write(encoder->dtvcc_writers[tv->service_number - 1].fd, buf, buf_len);
}
void _dtvcc_write_sami_footer(dtvcc_tv_screen *tv, struct encoder_ctx *encoder)
{
char *buf = (char *) encoder->buffer;
sprintf(buf, "</body></sami>");
write(encoder->dtvcc_writers[tv->service_number - 1].fd, buf, strlen(buf));
write(encoder->dtvcc_writers[tv->service_number - 1].fd,
encoder->encoded_crlf, encoder->encoded_crlf_length);
}
void ccx_dtvcc_write_sami(ccx_dtvcc_writer_ctx *writer, dtvcc_tv_screen *tv, struct encoder_ctx *encoder)
{
if (_dtvcc_is_screen_empty(tv))
return;
if (tv->time_ms_show + encoder->subs_delay < 0)
return;
if (tv->cc_count == 1)
_dtvcc_write_sami_header(tv, encoder);
char *buf = (char *) encoder->buffer;
buf[0] = 0;
sprintf(buf, "<sync start=%llu><p class=\"unknowncc\">%s",
(unsigned long long) tv->time_ms_show + encoder->subs_delay,
encoder->encoded_crlf);
write(encoder->dtvcc_writers[tv->service_number - 1].fd, buf, strlen(buf));
for (int i = 0; i < CCX_DTVCC_SCREENGRID_ROWS; i++)
{
if (!_dtvcc_is_row_empty(tv, i))
{
_dtvcc_write_tag_open(tv, encoder, i);
_dtvcc_write_row(writer, tv, i, encoder);
_dtvcc_write_tag_close(tv, encoder, i);
write(encoder->dtvcc_writers[tv->service_number - 1].fd,
encoder->encoded_br, encoder->encoded_br_length);
write(encoder->dtvcc_writers[tv->service_number - 1].fd,
encoder->encoded_crlf, encoder->encoded_crlf_length);
}
}
sprintf(buf, "<sync start=%llu><p class=\"unknowncc\">&nbsp;</p></sync>%s%s",
(unsigned long long) tv->time_ms_hide + encoder->subs_delay,
encoder->encoded_crlf, encoder->encoded_crlf);
write(encoder->dtvcc_writers[tv->service_number - 1].fd, buf, strlen(buf));
}
void _ccx_dtvcc_write(ccx_dtvcc_writer_ctx *writer, dtvcc_tv_screen *tv, struct encoder_ctx *encoder)
{
switch (encoder->write_format)
{
case CCX_OF_NULL:
break;
case CCX_OF_SRT:
ccx_dtvcc_write_srt(writer, tv, encoder);
break;
case CCX_OF_TRANSCRIPT:
ccx_dtvcc_write_transcript(writer, tv, encoder);
break;
case CCX_OF_SAMI:
ccx_dtvcc_write_sami(writer, tv, encoder);
break;
default:
ccx_dtvcc_write_debug(tv);
break;
}
}
void ccx_dtvcc_write_done(dtvcc_tv_screen *tv, struct encoder_ctx *encoder)
{
switch (encoder->write_format)
{
case CCX_OF_SAMI:
_dtvcc_write_sami_footer(tv, encoder);
break;
default:
ccx_common_logging.debug_ftn(
CCX_DMT_708, "[CEA-708] ccx_dtvcc_write_done: no handling required\n");
break;
}
}
void ccx_dtvcc_writer_init(ccx_dtvcc_writer_ctx *writer,
char *base_filename,
int program_number,
int service_number,
enum ccx_output_format write_format,
struct encoder_cfg *cfg)
{
ccx_common_logging.debug_ftn(CCX_DMT_708, "[CEA-708] ccx_dtvcc_writer_init\n");
writer->fd = -1;
writer->cd = (iconv_t) -1;
if (write_format == CCX_OF_NULL)
{
writer->filename = NULL;
return;
}
ccx_common_logging.debug_ftn(CCX_DMT_708, "[CEA-708] ccx_dtvcc_writer_init: "
"[%s][%d][%d]\n", base_filename, program_number, service_number);
char *ext = get_file_extension(write_format);
char suffix[32];
sprintf(suffix, CCX_DTVCC_FILENAME_TEMPLATE, program_number, service_number);
writer->filename = create_outfilename(base_filename, suffix, ext);
if (!writer->filename)
ccx_common_logging.fatal_ftn(
EXIT_NOT_ENOUGH_MEMORY, "[CEA-708] _dtvcc_decoder_init_write: not enough memory");
ccx_common_logging.debug_ftn(CCX_DMT_708, "[CEA-708] ccx_dtvcc_writer_init: inited [%s]\n", writer->filename);
char *charset = cfg->all_services_charset ?
cfg->all_services_charset :
cfg->services_charsets[service_number - 1];
if (charset)
{
writer->cd = iconv_open("UTF-8", charset);
if (writer->cd == (iconv_t) -1)
{
ccx_common_logging.fatal_ftn(EXIT_FAILURE, "[CEA-708] dtvcc_init: "
"can't create iconv for charset \"%s\": %s\n",
charset, strerror(errno));
}
}
free(ext);
}
void ccx_dtvcc_writer_cleanup(ccx_dtvcc_writer_ctx *writer)
{
if (writer->fd >= 0 && writer->fd != STDOUT_FILENO)
close(writer->fd);
free(writer->filename);
if (writer->cd == (iconv_t) -1)
{
//TODO nothing to do here
}
else
iconv_close(writer->cd);
}
void ccx_dtvcc_writer_output(ccx_dtvcc_writer_ctx *writer, dtvcc_tv_screen *tv, struct encoder_ctx *encoder)
{
ccx_common_logging.debug_ftn(CCX_DMT_708, "[CEA-708] ccx_dtvcc_writer_output: "
"writing... [%s][%d]\n", writer->filename, writer->fd);
if (!writer->filename && writer->fd < 0)
return;
if (writer->filename && writer->fd < 0) //first request to write
{
ccx_common_logging.debug_ftn(CCX_DMT_708, "[CEA-708] "
"ccx_dtvcc_writer_output: creating %s\n", writer->filename);
writer->fd = open(writer->filename, O_RDWR | O_CREAT | O_TRUNC | O_BINARY, S_IREAD | S_IWRITE);
if (writer->fd == -1)
{
ccx_common_logging.fatal_ftn(
CCX_COMMON_EXIT_FILE_CREATION_FAILED, "[CEA-708] Failed to open a file\n");
}
if (!encoder->no_bom)
write(writer->fd, UTF8_BOM, sizeof(UTF8_BOM));
}
_ccx_dtvcc_write(writer, tv, encoder);
}

View File

@@ -0,0 +1,19 @@
#ifndef _CCX_DECODERS_708_OUTPUT_H_
#define _CCX_DECODERS_708_OUTPUT_H_
#include "ccx_decoders_708.h"
#include "ccx_encoders_common.h"
#include "ccx_common_option.h"
void ccx_dtvcc_write_done(dtvcc_tv_screen *tv, struct encoder_ctx *encoder);
void ccx_dtvcc_writer_init(ccx_dtvcc_writer_ctx *writer,
char *base_filename,
int program_number,
int service_number,
enum ccx_output_format write_format,
struct encoder_cfg *cfg);
void ccx_dtvcc_writer_cleanup(ccx_dtvcc_writer_ctx *writer);
void ccx_dtvcc_writer_output(ccx_dtvcc_writer_ctx *writer, dtvcc_tv_screen *tv, struct encoder_ctx *encoder);
#endif /*_CCX_DECODERS_708_OUTPUT_H_*/

View File

@@ -0,0 +1,392 @@
/* 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"
#include "ccx_common_common.h"
#include "lib_ccx.h"
#include "ccx_decoders_608.h"
#include "ccx_decoders_708.h"
#include "ccx_decoders_xds.h"
#include "ccx_dtvcc.h"
uint64_t utc_refvalue = UINT64_MAX; /* _UI64_MAX means don't use UNIX, 0 = use current system time as reference, +1 use a specific reference */
extern int in_xds_mode;
/* 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 (struct ccx_common_timing_ctx *ctx, int current_field)
{
LLONG fts = get_fts(ctx, current_field);
if (fts <= ctx->minimum_fts)
fts = ctx->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 ctxget_visible_start */
LLONG get_visible_end (struct ccx_common_timing_ctx *ctx, int current_field)
{
LLONG fts = get_fts(ctx, current_field);
if (fts > ctx->minimum_fts)
ctx->minimum_fts = fts;
ccx_common_logging.debug_ftn(CCX_DMT_DECODER_608, "Visible End time=%s\n", print_mstime(fts));
return fts;
}
int process_cc_data (struct lib_cc_decode *ctx, unsigned char *cc_data, int cc_count, struct cc_subtitle *sub)
{
int ret = -1;
for (int j = 0; j < cc_count * 3; j = j + 3)
{
if (validate_cc_data_pair( cc_data + j ) )
continue;
ret = do_cb(ctx, cc_data + j, sub);
if (ret == 1) //1 means success here
ret = 0;
}
return ret;
}
int validate_cc_data_pair (unsigned char *cc_data_pair)
{
unsigned char cc_valid = (*cc_data_pair & 4) >>2;
unsigned char cc_type = *cc_data_pair & 3;
if (!cc_valid)
return -1;
if (cc_type==0 || cc_type==1)
{
// For EIA-608 data we verify parity.
if (!cc608_parity_table[cc_data_pair[2]])
{
// If the second byte doesn't pass parity, ignore pair
return -1;
}
if (!cc608_parity_table[cc_data_pair[1]])
{
// The first byte doesn't pass parity, we replace it with a solid blank
// and process the pair.
cc_data_pair[1]=0x7F;
}
}
return 0;
}
int do_cb (struct lib_cc_decode *ctx, unsigned char *cc_block, struct cc_subtitle *sub)
{
unsigned char cc_valid = (*cc_block & 4) >>2;
unsigned char cc_type = *cc_block & 3;
int timeok = 1;
if ( ctx->fix_padding
&& cc_valid==0 && cc_type <= 1 // Only fix NTSC packets
&& cc_block[1]==0 && cc_block[2]==0 )
{
/* Padding */
cc_valid=1;
cc_block[1]=0x80;
cc_block[2]=0x80;
}
if ( ctx->write_format!=CCX_OF_RAW && // In raw we cannot skip padding because timing depends on it
ctx->write_format!=CCX_OF_DVDRAW &&
(cc_block[0]==0xFA || cc_block[0]==0xFC || cc_block[0]==0xFD )
&& (cc_block[1]&0x7F)==0 && (cc_block[2]&0x7F)==0) // CFS: Skip non-data, makes debugging harder.
return 1;
// Print raw data with FTS.
dbg_print(CCX_DMT_CBRAW, "%s %d %02X:%c%c:%02X", print_mstime(ctx->timing->fts_now + ctx->timing->fts_global),in_xds_mode,
cc_block[0], cc_block[1]&0x7f,cc_block[2]&0x7f, cc_block[2]);
/* In theory the writercwtdata() function could return early and not
* go through the 608/708 cases below. We do that to get accurate
* counts for cb_field1, cb_field2 and cb_708.
* Note that printdata() and dtvcc_process_data() must not be called for
* the CCX_OF_RCWT case. */
if (cc_valid || cc_type==3)
{
ctx->cc_stats[cc_type]++;
switch (cc_type)
{
case 0:
dbg_print(CCX_DMT_CBRAW, " %s .. ..\n", debug_608toASC( cc_block, 0));
ctx->current_field = 1;
ctx->saw_caption_block = 1;
if (ctx->extraction_start.set &&
get_fts(ctx->timing, ctx->current_field) < ctx->extraction_start.time_in_ms)
timeok = 0;
if (ctx->extraction_end.set &&
get_fts(ctx->timing, ctx->current_field) > ctx->extraction_end.time_in_ms)
{
timeok = 0;
ctx->processed_enough=1;
}
if (timeok)
{
if(ctx->write_format!=CCX_OF_RCWT)
printdata (ctx, cc_block+1,2,0,0, sub);
else
writercwtdata(ctx, cc_block, sub);
}
cb_field1++;
break;
case 1:
dbg_print(CCX_DMT_CBRAW, " .. %s ..\n", debug_608toASC( cc_block, 1));
ctx->current_field = 2;
ctx->saw_caption_block = 1;
if (ctx->extraction_start.set &&
get_fts(ctx->timing, ctx->current_field) < ctx->extraction_start.time_in_ms)
timeok = 0;
if (ctx->extraction_end.set &&
get_fts(ctx->timing, ctx->current_field) > ctx->extraction_end.time_in_ms)
{
timeok = 0;
ctx->processed_enough=1;
}
if (timeok)
{
if(ctx->write_format!=CCX_OF_RCWT)
printdata (ctx, 0,0,cc_block+1,2, sub);
else
writercwtdata(ctx, cc_block, sub);
}
cb_field2++;
break;
case 2: //EIA-708
// DTVCC packet data
// Fall through
case 3: //EIA-708
dbg_print(CCX_DMT_CBRAW, " .. .. DD\n");
// DTVCC packet start
ctx->current_field = 3;
if (ctx->extraction_start.set &&
get_fts(ctx->timing, ctx->current_field) < ctx->extraction_start.time_in_ms)
timeok = 0;
if (ctx->extraction_end.set &&
get_fts(ctx->timing, ctx->current_field) > ctx->extraction_end.time_in_ms)
{
timeok = 0;
ctx->processed_enough=1;
}
char temp[4];
temp[0]=cc_valid;
temp[1]=cc_type;
temp[2]=cc_block[1];
temp[3]=cc_block[2];
if (timeok)
{
if (ctx->write_format != CCX_OF_RCWT)
ccx_dtvcc_process_data(ctx, (const unsigned char *) temp, 4);
else
writercwtdata(ctx, cc_block, sub);
}
cb_708++;
// Check for bytes read
// printf ("Warning: Losing EIA-708 data!\n");
break;
default:
fatal(CCX_COMMON_EXIT_BUG_BUG, "Cannot be reached!");
} // switch (cc_type)
} // cc_valid
else
{
dbg_print(CCX_DMT_CBRAW, " .. .. ..\n");
dbg_print(CCX_DMT_VERBOSE, "Found !(cc_valid || cc_type==3) - ignore this block\n");
}
return 1;
}
void dinit_cc_decode(struct lib_cc_decode **ctx)
{
struct lib_cc_decode *lctx = *ctx;
ccx_dtvcc_free(&lctx->dtvcc);
dinit_avc(&lctx->avc_ctx);
ccx_decoder_608_dinit_library(&lctx->context_cc608_field_1);
ccx_decoder_608_dinit_library(&lctx->context_cc608_field_2);
dinit_timing_ctx(&lctx->timing);
freep(ctx);
}
struct lib_cc_decode* init_cc_decode (struct ccx_decoders_common_settings_t *setting)
{
struct lib_cc_decode *ctx = NULL;
ctx = malloc(sizeof(struct lib_cc_decode));
if(!ctx)
return NULL;
ctx->avc_ctx = init_avc();
ctx->codec = setting->codec;
ctx->timing = init_timing_ctx(&ccx_common_timing_settings);
setting->settings_dtvcc->timing = ctx->timing;
setting->settings_608->no_rollup = setting->no_rollup;
setting->settings_dtvcc->no_rollup = setting->no_rollup;
ctx->no_rollup = setting->no_rollup;
ctx->dtvcc = ccx_dtvcc_init(setting->settings_dtvcc);
ctx->dtvcc->is_active = setting->settings_dtvcc->enabled;
if(setting->codec == CCX_CODEC_ATSC_CC)
{
// Prepare 608 context
ctx->context_cc608_field_1 = ccx_decoder_608_init_library(
setting->settings_608,
setting->cc_channel,
1,
&ctx->processed_enough,
setting->cc_to_stdout,
setting->output_format,
ctx->timing
);
ctx->context_cc608_field_2 = ccx_decoder_608_init_library(
setting->settings_608,
setting->cc_channel,
2,
&ctx->processed_enough,
setting->cc_to_stdout,
setting->output_format,
ctx->timing
);
}
else
{
ctx->context_cc608_field_1 = NULL;
ctx->context_cc608_field_2 = NULL;
}
ctx->current_field = 1;
ctx->private_data = setting->private_data;
ctx->fix_padding = setting->fix_padding;
ctx->write_format = setting->output_format;
ctx->subs_delay = setting->subs_delay;
ctx->extract = setting->extract;
ctx->fullbin = setting->fullbin;
ctx->hauppauge_mode = setting->hauppauge_mode;
ctx->program_number = setting->program_number;
ctx->processed_enough = 0;
ctx->max_gop_length = 0;
ctx->has_ccdata_buffered = 0;
ctx->in_bufferdatatype = CCX_UNKNOWN;
ctx->frames_since_last_gop = 0;
memcpy(&ctx->extraction_start, &setting->extraction_start,sizeof(struct ccx_boundary_time));
memcpy(&ctx->extraction_end, &setting->extraction_end,sizeof(struct ccx_boundary_time));
if (setting->send_to_srv)
ctx->writedata = net_send_cc;
else if (setting->output_format==CCX_OF_RAW ||
setting->output_format==CCX_OF_DVDRAW ||
setting->output_format==CCX_OF_RCWT )
ctx->writedata = writeraw;
else if (setting->output_format==CCX_OF_SMPTETT ||
setting->output_format==CCX_OF_SAMI ||
setting->output_format==CCX_OF_SRT ||
setting->output_format == CCX_OF_WEBVTT ||
setting->output_format==CCX_OF_TRANSCRIPT ||
setting->output_format==CCX_OF_SPUPNG ||
setting->output_format==CCX_OF_SIMPLE_XML ||
setting->output_format==CCX_OF_NULL)
ctx->writedata = process608;
else
fatal(CCX_COMMON_EXIT_BUG_BUG, "Invalid Write Format Selected");
memset (&ctx->dec_sub, 0,sizeof(ctx->dec_sub));
// Initialize HDTV caption buffer
init_hdcc(ctx);
ctx->current_hor_size = 0;
ctx->current_vert_size = 0;
ctx->current_aspect_ratio = 0;
ctx->current_frame_rate = 4; // Assume standard fps, 29.97
//Variables used while parsing elementry stream
ctx->no_bitstream_error = 0;
ctx->saw_seqgoppic = 0;
ctx->in_pic_data = 0;
ctx->current_progressive_sequence = 2;
ctx->current_pulldownfields = 32768;
ctx->temporal_reference = 0;
ctx->maxtref = 0;
ctx->picture_coding_type = CCX_FRAME_TYPE_RESET_OR_UNKNOWN;
ctx->picture_structure = 0;
ctx->top_field_first = 0;
ctx->repeat_first_field = 0;
ctx->progressive_frame = 0;
ctx->pulldownfields = 0;
//es parser related variable ends here
memset(ctx->cc_stats, 0, 4 * sizeof(int));
ctx->anchor_seq_number = -1;
// Init XDS buffers
if(setting->ignore_xds == CCX_TRUE)
ctx->xds_ctx = NULL;
else
ctx->xds_ctx = ccx_decoders_xds_init_library(ctx->timing);
//xds_cea608_test(ctx->xds_ctx);
return ctx;
}
void flush_cc_decode(struct lib_cc_decode *ctx, struct cc_subtitle *sub)
{
if(ctx->codec == CCX_CODEC_ATSC_CC)
{
if (ctx->extract != 2)
{
if (ctx->write_format==CCX_OF_SMPTETT || ctx->write_format==CCX_OF_SAMI ||
ctx->write_format==CCX_OF_SRT || ctx->write_format==CCX_OF_TRANSCRIPT ||
ctx->write_format == CCX_OF_WEBVTT || ctx->write_format == CCX_OF_SPUPNG)
{
flush_608_context(ctx->context_cc608_field_1, sub);
}
else if(ctx->write_format == CCX_OF_RCWT)
{
// Write last header and data
writercwtdata (ctx, NULL, sub);
}
}
if (ctx->extract != 1)
{
if (ctx->write_format == CCX_OF_SMPTETT || ctx->write_format == CCX_OF_SAMI ||
ctx->write_format == CCX_OF_SRT || ctx->write_format == CCX_OF_TRANSCRIPT ||
ctx->write_format == CCX_OF_WEBVTT || ctx->write_format == CCX_OF_SPUPNG)
{
flush_608_context(ctx->context_cc608_field_2, sub);
}
}
}
if (ctx->dtvcc->is_active)
{
for (int i = 0; i < CCX_DTVCC_MAX_SERVICES; i++)
{
ccx_dtvcc_service_decoder *decoder = &ctx->dtvcc->decoders[i];
if (!ctx->dtvcc->services_active[i])
continue;
if (decoder->cc_count > 0)
{
ctx->current_field = 3;
ccx_dtvcc_decoder_flush(ctx->dtvcc, decoder);
}
}
}
}

View File

@@ -0,0 +1,28 @@
#ifndef _CC_DECODER_COMMON
#define _CC_DECODER_COMMON
#include "ccx_common_platform.h"
#include "ccx_common_constants.h"
#include "ccx_common_structs.h"
#include "ccx_decoders_structs.h"
#include "ccx_common_option.h"
extern uint64_t utc_refvalue; // UTC referential value
// Declarations
LLONG get_visible_start (struct ccx_common_timing_ctx *ctx, int current_field);
LLONG get_visible_end (struct ccx_common_timing_ctx *ctx, int current_field);
unsigned int get_decoder_str_basic(unsigned char *buffer, unsigned char *line, int trim_subs, enum ccx_encoding_type encoding);
void ccx_decoders_common_settings_init(LLONG subs_delay, enum ccx_output_format output_format);
int validate_cc_data_pair (unsigned char *cc_data_pair);
int process_cc_data (struct lib_cc_decode *ctx, unsigned char *cc_data, int cc_count, struct cc_subtitle *sub);
int do_cb (struct lib_cc_decode *ctx, unsigned char *cc_block, struct cc_subtitle *sub);
void printdata (struct lib_cc_decode *ctx, const unsigned char *data1, int length1,
const unsigned char *data2, int length2, struct cc_subtitle *sub);
struct lib_cc_decode* init_cc_decode (struct ccx_decoders_common_settings_t *setting);
void dinit_cc_decode(struct lib_cc_decode **ctx);
void flush_cc_decode(struct lib_cc_decode *ctx, struct cc_subtitle *sub);
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,13 @@
#ifndef ISDB_H
#define ISDB_H
#include "ccx_common_platform.h"
#include "ccx_common_structs.h"
#include "ccx_decoders_structs.h"
int isdb_set_global_time(struct lib_cc_decode *dec_ctx, uint64_t timestamp);
int isdbsub_decode(struct lib_cc_decode *dec_ctx, const uint8_t *buf, size_t buf_size, struct cc_subtitle *sub);
void delete_isdb_decoder(void **isdb_ctx);
void *init_isdb_decoder(void);
#endif

View File

@@ -0,0 +1,186 @@
#ifndef CCX_DECODERS_STRUCTS_H
#define CCX_DECODERS_STRUCTS_H
#include "ccx_common_platform.h"
#include "ccx_common_constants.h"
#include "ccx_common_timing.h"
#include "ccx_common_structs.h"
#include "list.h"
#include "ccx_decoders_708.h"
// Define max width in characters/columns on the screen
#define CCX_DECODER_608_SCREEN_WIDTH 32
#define MAXBFRAMES 50
#define SORTBUF (2*MAXBFRAMES+1)
/* 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];
#ifdef ENABLE_OCR
char *ocr_text;
#endif
};
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_decoders_common_settings_t
{
LLONG subs_delay; // ms to delay (or advance) subs
enum ccx_output_format output_format; // What kind of output format should be used?
int fix_padding; // Replace 0000 with 8080 in HDTV (needed for some cards)
struct ccx_boundary_time extraction_start, extraction_end; // Segment we actually process
int cc_to_stdout;
int extract; // Extract 1st, 2nd or both fields
int fullbin; // Disable pruning of padding cc blocks
int no_rollup;
struct ccx_decoder_608_settings *settings_608; // Contains the settings for the 608 decoder.
ccx_decoder_dtvcc_settings *settings_dtvcc; //Same for cea 708 captions decoder (dtvcc)
int cc_channel; // Channel we want to dump in srt mode
unsigned send_to_srv;
unsigned int hauppauge_mode; // If 1, use PID=1003, process specially and so on
int program_number;
enum ccx_code_type codec;
int ignore_xds;
void *private_data;
};
struct lib_cc_decode
{
int cc_stats[4];
int saw_caption_block;
int processed_enough; // If 1, we have enough lines, time, etc.
/* 608 contexts - note that this shouldn't be global, they should be
per program */
void *context_cc608_field_1;
void *context_cc608_field_2;
int no_rollup; // If 1, write one line at a time
int fix_padding; // Replace 0000 with 8080 in HDTV (needed for some cards)
enum ccx_output_format write_format; // 0=Raw, 1=srt, 2=SMI
struct ccx_boundary_time extraction_start, extraction_end; // Segment we actually process
LLONG subs_delay; // ms to delay (or advance) subs
int extract; // Extract 1st, 2nd or both fields
int fullbin; // Disable pruning of padding cc blocks
struct cc_subtitle dec_sub;
enum ccx_bufferdata_type in_bufferdatatype;
unsigned int hauppauge_mode; // If 1, use PID=1003, process specially and so on
int frames_since_last_gop;
/* GOP-based timing */
int saw_gop_header;
/* Time info for timed-transcript */
int max_gop_length; // (Maximum) length of a group of pictures
int last_gop_length; // Length of the previous group of pictures
unsigned total_pulldownfields;
unsigned total_pulldownframes;
int program_number;
struct list_head list;
struct ccx_common_timing_ctx *timing;
enum ccx_code_type codec;
// Set to true if data is buffered
int has_ccdata_buffered;
struct avc_ctx *avc_ctx;
void *private_data;
/* General video information */
unsigned int current_hor_size;
unsigned int current_vert_size;
unsigned int current_aspect_ratio;
unsigned int current_frame_rate; // Assume standard fps, 29.97
/* Reguired in es_function.c */
int no_bitstream_error;
int saw_seqgoppic;
int in_pic_data;
unsigned int current_progressive_sequence;
unsigned int current_pulldownfields ;
int temporal_reference;
enum ccx_frame_type picture_coding_type;
unsigned picture_structure;
unsigned repeat_first_field;
unsigned progressive_frame;
unsigned pulldownfields;
/* Reguired in es_function.c and es_userdata.c */
unsigned top_field_first; // Needs to be global
ccx_dtvcc_ctx *dtvcc;
int current_field;
// Analyse/use the picture information
int maxtref; // Use to remember the temporal reference number
int cc_data_count[SORTBUF];
// Store fts;
LLONG cc_fts[SORTBUF];
// Store HD CC packets
unsigned char cc_data_pkts[SORTBUF][10*31*3+1]; // *10, because MP4 seems to have different limits
// The sequence number of the current anchor frame. All currently read
// B-Frames belong to this I- or P-frame.
int anchor_seq_number;
struct ccx_decoders_xds_context *xds_ctx;
int (*writedata)(const unsigned char *data, int length, void *private_data, struct cc_subtitle *sub);
};
#endif

View File

@@ -0,0 +1,966 @@
#include "ccx_decoders_xds.h"
#include "ccx_common_constants.h"
#include "ccx_common_timing.h"
#include "ccx_common_common.h"
LLONG ts_start_of_xds = -1; // Time at which we switched to XDS mode, =-1 hasn't happened yet
static const char *XDSclasses[]=
{
"Current",
"Future",
"Channel",
"Miscellaneous",
"Public service",
"Reserved",
"Private data",
"End"
};
static const char *XDSProgramTypes[]=
{
"Education","Entertainment", "Movie", "News", "Religious",
"Sports", "Other", "Action","Advertisement", "Animated",
"Anthology","Automobile","Awards","Baseball","Basketball",
"Bulletin","Business","Classical","College","Combat",
"Comedy","Commentary","Concert","Consumer","Contemporary",
"Crime","Dance","Documentary","Drama","Elementary",
"Erotica","Exercise","Fantasy","Farm","Fashion",
"Fiction","Food","Football","Foreign","Fund-Raiser",
"Game/Quiz","Garden","Golf","Government","Health",
"High_School","History","Hobby","Hockey","Home",
"Horror","Information","Instruction","International","Interview",
"Language","Legal","Live","Local","Math",
"Medical","Meeting","Military","Mini-Series","Music",
"Mystery","National","Nature","Police","Politics",
"Premiere","Pre-Recorded","Product","Professional","Public",
"Racing","Reading","Repair","Repeat","Review",
"Romance","Science","Series","Service","Shopping",
"Soap_Opera","Special","Suspense","Talk","Technical",
"Tennis","Travel","Variety","Video","Weather",
"Western"
};
#define XDS_CLASS_CURRENT 0
#define XDS_CLASS_FUTURE 1
#define XDS_CLASS_CHANNEL 2
#define XDS_CLASS_MISC 3
#define XDS_CLASS_PUBLIC 4
#define XDS_CLASS_RESERVED 5
#define XDS_CLASS_PRIVATE 6
#define XDS_CLASS_END 7
#define XDS_CLASS_OUT_OF_BAND 0x40 // Not a real class, a marker for packets for out-of-band data.
// Types for the classes current and future
#define XDS_TYPE_PIN_START_TIME 1
#define XDS_TYPE_LENGH_AND_CURRENT_TIME 2
#define XDS_TYPE_PROGRAM_NAME 3
#define XDS_TYPE_PROGRAM_TYPE 4
#define XDS_TYPE_CONTENT_ADVISORY 5
#define XDS_TYPE_AUDIO_SERVICES 6
#define XDS_TYPE_CGMS 8 // Copy Generation Management System
#define XDS_TYPE_ASPECT_RATIO_INFO 9 // Appears in CEA-608-B but in E it's been removed as is "reserved"
#define XDS_TYPE_PROGRAM_DESC_1 0x10
#define XDS_TYPE_PROGRAM_DESC_2 0x11
#define XDS_TYPE_PROGRAM_DESC_3 0x12
#define XDS_TYPE_PROGRAM_DESC_4 0x13
#define XDS_TYPE_PROGRAM_DESC_5 0x14
#define XDS_TYPE_PROGRAM_DESC_6 0x15
#define XDS_TYPE_PROGRAM_DESC_7 0x16
#define XDS_TYPE_PROGRAM_DESC_8 0x17
// Types for the class channel
#define XDS_TYPE_NETWORK_NAME 1
#define XDS_TYPE_CALL_LETTERS_AND_CHANNEL 2
#define XDS_TYPE_TSID 4 // Transmission Signal Identifier
// Types for miscellaneous packets
#define XDS_TYPE_TIME_OF_DAY 1
#define XDS_TYPE_LOCAL_TIME_ZONE 4
#define XDS_TYPE_OUT_OF_BAND_CHANNEL_NUMBER 0x40
#define NUM_XDS_BUFFERS 9 // CEA recommends no more than one level of interleaving. Play it safe
#define NUM_BYTES_PER_PACKET 35 // Class + type (repeated for convenience) + data + zero
struct xds_buffer
{
unsigned in_use;
int xds_class;
int xds_type;
unsigned char bytes[NUM_BYTES_PER_PACKET]; // Class + type (repeated for convenience) + data + zero
unsigned char used_bytes;
} ;
typedef struct ccx_decoders_xds_context
{
// Program Identification Number (Start Time) for current program
int current_xds_min;
int current_xds_hour;
int current_xds_date;
int current_xds_month;
int current_program_type_reported; // No.
int xds_start_time_shown;
int xds_program_length_shown;
char xds_program_description[8][33];
char current_xds_network_name[33];
char current_xds_program_name[33];
char current_xds_call_letters[7];
char current_xds_program_type[33];
struct xds_buffer xds_buffers[NUM_XDS_BUFFERS];
int cur_xds_buffer_idx;
int cur_xds_packet_class;
unsigned char *cur_xds_payload;
int cur_xds_payload_length;
int cur_xds_packet_type;
struct ccx_common_timing_ctx *timing;
} ccx_decoders_xds_context_t;
struct ccx_decoders_xds_context *ccx_decoders_xds_init_library(struct ccx_common_timing_ctx *timing)
{
int i;
struct ccx_decoders_xds_context *ctx = NULL;
ctx = malloc(sizeof(struct ccx_decoders_xds_context));
if(!ctx)
return NULL;
ctx->current_xds_min = -1;
ctx->current_xds_hour = -1;
ctx->current_xds_date = -1;
ctx->current_xds_month = -1;
ctx->current_program_type_reported = 0; // No.
ctx->xds_start_time_shown = 0;
ctx->xds_program_length_shown = 0;
for (i = 0; i < NUM_XDS_BUFFERS; i++)
{
ctx->xds_buffers[i].in_use = 0;
ctx->xds_buffers[i].xds_class = -1;
ctx->xds_buffers[i].xds_type = -1;
ctx->xds_buffers[i].used_bytes = 0;
memset(ctx->xds_buffers[i].bytes, 0, NUM_BYTES_PER_PACKET);
}
for (i = 0; i < 9; i++)
memset(ctx->xds_program_description, 0, 32);
memset(ctx->current_xds_network_name, 0, 33);
memset(ctx->current_xds_program_name, 0, 33);
memset(ctx->current_xds_call_letters, 0, 7);
memset(ctx->current_xds_program_type, 0, 33);
ctx->cur_xds_buffer_idx = -1;
ctx->cur_xds_packet_class = -1;
ctx->cur_xds_payload = NULL;
ctx->cur_xds_payload_length = 0;
ctx->cur_xds_packet_type = 0;
ctx->timing = timing;
return ctx;
}
int write_xds_string(struct cc_subtitle *sub, struct ccx_decoders_xds_context *ctx, char *p, size_t len)
{
struct eia608_screen *data = NULL;
data = (struct eia608_screen *) realloc(sub->data,( sub->nb_data + 1 ) * sizeof(*data));
if (!data)
{
freep(&sub->data);
sub->nb_data = 0;
ccx_common_logging.log_ftn("No Memory left");
return -1;
}
else
{
sub->data = data;
data = (struct eia608_screen *)sub->data + sub->nb_data;
data->format = SFORMAT_XDS;
data->start_time = ts_start_of_xds;
data->end_time = get_fts(ctx->timing, 2);
data->xds_str = p;
data->xds_len = len;
data->cur_xds_packet_class = ctx->cur_xds_packet_class;
sub->nb_data++;
sub->type = CC_608;
sub->got_output = 1;
}
return 0;
}
void xdsprint (struct cc_subtitle *sub, struct ccx_decoders_xds_context *ctx, const char *fmt,...)
{
/* Guess we need no more than 100 bytes. */
int n, size = 100;
char *p, *np;
va_list ap;
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_xds_string(sub, ctx, p, n);
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;
}
}
}
void xds_debug_test(struct ccx_decoders_xds_context *ctx, struct cc_subtitle *sub)
{
process_xds_bytes (ctx, 0x05, 0x02);
process_xds_bytes (ctx, 0x20, 0x20);
do_end_of_xds (sub, ctx, 0x2a);
}
void xds_cea608_test(struct ccx_decoders_xds_context *ctx, struct cc_subtitle *sub)
{
/* This test is the sample data that comes in CEA-608. It sets the program name
to be "Star Trek". The checksum is 0x1d and the validation must succeed. */
process_xds_bytes (ctx, 0x01,0x03);
process_xds_bytes (ctx, 0x53,0x74);
process_xds_bytes (ctx, 0x61,0x72);
process_xds_bytes (ctx, 0x20,0x54);
process_xds_bytes (ctx, 0x72,0x65);
process_xds_bytes (ctx, 0x02,0x03);
process_xds_bytes (ctx, 0x02,0x03);
process_xds_bytes (ctx, 0x6b,0x00);
do_end_of_xds (sub, ctx, 0x1d);
}
int how_many_used(struct ccx_decoders_xds_context *ctx)
{
int c=0;
for (int i=0;i<NUM_XDS_BUFFERS;i++)
if (ctx->xds_buffers[i].in_use)
c++;
return c;
}
void clear_xds_buffer (struct ccx_decoders_xds_context *ctx, int num)
{
ctx->xds_buffers[num].in_use=0;
ctx->xds_buffers[num].xds_class=-1;
ctx->xds_buffers[num].xds_type=-1;
ctx->xds_buffers[num].used_bytes=0;
memset (ctx->xds_buffers[num].bytes , 0, NUM_BYTES_PER_PACKET);
}
void process_xds_bytes (struct ccx_decoders_xds_context *ctx, const unsigned char hi, int lo)
{
int is_new;
if(!ctx)
return;
if (hi>=0x01 && hi<=0x0f)
{
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
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(ctx));
int first_free_buf=-1;
int matching_buf=-1;
for (int i=0;i<NUM_XDS_BUFFERS;i++)
{
if (ctx->xds_buffers[i].in_use &&
ctx->xds_buffers[i].xds_class==xds_class &&
ctx->xds_buffers[i].xds_type==lo)
{
matching_buf=i;
break;
}
if (first_free_buf==-1 && !ctx->xds_buffers[i].in_use)
first_free_buf=i;
}
/* Here, 3 possibilities:
1) We already had a buffer for this class/type and matching_buf points to it
2) We didn't have a buffer for this class/type and first_free_buf points to an unused one
3) All buffers are full and we will have to skip this packet.
*/
if (matching_buf==-1 && first_free_buf==-1)
{
ccx_common_logging.log_ftn ("Note: All XDS buffers full (bug or suicidal stream). Ignoring this one (%d,%d).\n",xds_class,lo);
ctx->cur_xds_buffer_idx=-1;
return;
}
ctx->cur_xds_buffer_idx=(matching_buf!=-1)? matching_buf:first_free_buf;
if (is_new || !ctx->xds_buffers[ctx->cur_xds_buffer_idx].in_use)
{
// Whatever we had before we discard; must belong to an interrupted packet
ctx->xds_buffers[ctx->cur_xds_buffer_idx].xds_class=xds_class;
ctx->xds_buffers[ctx->cur_xds_buffer_idx].xds_type=lo;
ctx->xds_buffers[ctx->cur_xds_buffer_idx].used_bytes=0;
ctx->xds_buffers[ctx->cur_xds_buffer_idx].in_use=1;
memset (ctx->xds_buffers[ctx->cur_xds_buffer_idx].bytes,0,NUM_BYTES_PER_PACKET);
}
if (!is_new)
{
// Continue codes aren't added to packet.
return;
}
}
else
{
// Informational: 00, or 0x20-0x7F, so 01-0x1f forbidden
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))
{
ccx_common_logging.log_ftn ("\rNote: Illegal XDS data");
return;
}
}
if (ctx->xds_buffers[ctx->cur_xds_buffer_idx].used_bytes<=32)
{
// Should always happen
ctx->xds_buffers[ctx->cur_xds_buffer_idx].bytes[ctx->xds_buffers[ctx->cur_xds_buffer_idx].used_bytes++]=hi;
ctx->xds_buffers[ctx->cur_xds_buffer_idx].bytes[ctx->xds_buffers[ctx->cur_xds_buffer_idx].used_bytes++]=lo;
ctx->xds_buffers[ctx->cur_xds_buffer_idx].bytes[ctx->xds_buffers[ctx->cur_xds_buffer_idx].used_bytes]=0;
}
}
/**
* ctx XDS context can be NULL, if user dont want to write xds in transcript
*/
void xds_do_copy_generation_management_system (struct cc_subtitle *sub, struct ccx_decoders_xds_context *ctx, unsigned c1, unsigned c2)
{
static unsigned last_c1=-1, last_c2=-1;
static char copy_permited[256];
static char aps[256];
static char rcd[256];
int changed=0;
unsigned c1_6=(c1&0x40)>>6;
/* unsigned unused1=(c1&0x20)>>5; */
unsigned cgms_a_b4=(c1&0x10)>>4;
unsigned cgms_a_b3=(c1&0x8)>>3;
unsigned aps_b2=(c1&0x4)>>2;
unsigned aps_b1=(c1&0x2)>>1;
/* unsigned asb_0=(c1&0x1); */
unsigned c2_6=(c2&0x40)>>6;
/* unsigned c2_5=(c2&0x20)>>5; */
/* unsigned c2_4=(c2&0x10)>>4; */
/* unsigned c2_3=(c2&0x8)>>3; */
/* unsigned c2_2=(c2&0x4)>>2; */
/* unsigned c2_1=(c2&0x2)>>1; */
unsigned rcd0=(c2&0x1);
/* User dont need xds */
if(!ctx)
return;
if (!c1_6 || !c2_6) // These must be high. If not, not following specs
return;
if (last_c1!=c1 || last_c2!=c2)
{
changed=1;
last_c1=c1;
last_c2=c2;
// Changed since last time, decode
const char *copytext[4]={"Copy permited (no restrictions)", "No more copies (one generation copy has been made)",
"One generation of copies can be made", "No copying is permited"};
const char *apstext[4]={"No APS", "PSP On; Split Burst Off", "PSP On; 2 line Split Burst On", "PSP On; 4 line Split Burst On"};
sprintf (copy_permited,"CGMS: %s", copytext[cgms_a_b4*2+cgms_a_b3]);
sprintf (aps,"APS: %s", apstext[aps_b2*2+aps_b1]);
sprintf (rcd,"Redistribution Control Descriptor: %d", rcd0);
}
xdsprint(sub, ctx, copy_permited);
xdsprint(sub, ctx, aps);
xdsprint(sub, ctx, rcd);
if (changed)
{
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);
}
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, struct ccx_decoders_xds_context *ctx, unsigned c1, unsigned c2)
{
static unsigned last_c1=-1, last_c2=-1;
static char age[256];
static char content[256];
static char rating[256];
int changed=0;
// Insane encoding
unsigned c1_6=(c1&0x40)>>6;
unsigned Da2=(c1&0x20)>>5;
unsigned a1=(c1&0x10)>>4;
unsigned a0=(c1&0x8)>>3;
unsigned r2=(c1&0x4)>>2;
unsigned r1=(c1&0x2)>>1;
unsigned r0=(c1&0x1);
unsigned c2_6=(c2&0x40)>>6;
unsigned FV=(c2&0x20)>>5;
unsigned S=(c2&0x10)>>4;
unsigned La3=(c2&0x8)>>3;
unsigned g2=(c2&0x4)>>2;
unsigned g1=(c2&0x2)>>1;
unsigned g0=(c2&0x1);
unsigned supported=0;
if(!ctx)
return;
if (!c1_6 || !c2_6) // These must be high. If not, not following specs
return;
if (last_c1!=c1 || last_c2!=c2)
{
changed=1;
last_c1=c1;
last_c2=c2;
// Changed since last time, decode
// Bits a1 and a0 determine the encoding. I'll add parsing as more samples become available
if (!a1 && a0) // US TV parental guidelines
{
const char *agetext[8]={"None", "TV-Y (All Children)", "TV-Y7 (Older Children)",
"TV-G (General Audience)", "TV-PG (Parental Guidance Suggested)",
"TV-14 (Parents Strongly Cautioned)", "TV-MA (Mature Audience Only)", "None"};
sprintf (age,"ContentAdvisory: US TV Parental Guidelines. Age Rating: %s", agetext[g2*4+g1*2+g0]);
content[0]=0;
if (!g2 && g1 && !g0) // For TV-Y7 (Older chidren), the Violence bit is "fantasy violence"
{
if (FV)
strcpy (content, "[Fantasy Violence] ");
}
else // For all others, is real
{
if (FV)
strcpy (content, "[Violence] ");
}
if (S)
strcat (content, "[Sexual Situations] ");
if (La3)
strcat (content, "[Adult Language] ");
if (Da2)
strcat (content, "[Sexually Suggestive Dialog] ");
supported=1;
}
if (!a0) // MPA
{
const char *ratingtext[8]={"N/A", "G", "PG", "PG-13", "R", "NC-17", "X", "Not Rated"};
sprintf (rating,"ContentAdvisory: MPA Rating: %s", ratingtext[r2*4+r1*2+r0]);
supported=1;
}
if (a0 && a1 && !Da2 && !La3) // Canadian English Language Rating
{
const char *ratingtext[8]={"Exempt", "Children", "Children eight years and older",
"General programming suitable for all audiences", "Parental Guidance",
"Viewers 14 years and older", "Adult Programming", "[undefined]"};
sprintf (rating,"ContentAdvisory: Canadian English Rating: %s", ratingtext[g2*4+g1*2+g0]);
supported=1;
}
if (a0 && a1 && Da2 && !La3) // Canadian French Language Rating
{
const char *ratingtext[8] = { "Exempt?es", "G?n?ral", "G?n?ral - D?conseill? aux jeunes enfants",
"Cette ?mission peut ne pas convenir aux enfants de moins de 13 ans",
"Cette ?mission ne convient pas aux moins de 16 ans",
"Cette ?mission est r?serv?e aux adultes", "[invalid]", "[invalid]" };
sprintf(rating, "ContentAdvisory: Canadian French Rating: %s", ratingtext[g2 * 4 + g1 * 2 + g0]);
supported = 1;
}
}
// Bits a1 and a0 determine the encoding. I'll add parsing as more samples become available
if (!a1 && a0) // US TV parental guidelines
{
xdsprint(sub, ctx, age);
xdsprint(sub, ctx, content);
if (changed)
{
ccx_common_logging.log_ftn ("\rXDS: %s\n ",age);
ccx_common_logging.log_ftn ("\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
(a0 && a1 && Da2 && !La3) // Canadian French Language Rating
)
{
xdsprint(sub, ctx, rating);
if (changed)
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)
ccx_common_logging.log_ftn ("XDS: Unsupported ContentAdvisory encoding, please submit sample.\n");
}
int xds_do_current_and_future (struct cc_subtitle *sub, struct ccx_decoders_xds_context *ctx)
{
int was_proc=0;
char *str = malloc(1024);
char *tstr = NULL;
int str_len = 1024;
if(!ctx)
return CCX_EINVAL;
switch (ctx->cur_xds_packet_type)
{
case XDS_TYPE_PIN_START_TIME:
was_proc=1;
if (ctx->cur_xds_payload_length<7) // We need 4 data bytes
break;
int min=ctx->cur_xds_payload[2] & 0x3f; // 6 bits
int hour = ctx->cur_xds_payload[3] & 0x1f; // 5 bits
int date = ctx->cur_xds_payload[4] & 0x1f; // 5 bits
int month = ctx->cur_xds_payload[5] & 0xf; // 4 bits
/* int changed=0; */
if (ctx->current_xds_min!=min ||
ctx->current_xds_hour!=hour ||
ctx->current_xds_date!=date ||
ctx->current_xds_month!=month)
{
/* changed=1; */
ctx->xds_start_time_shown=0;
ctx->current_xds_min=min;
ctx->current_xds_hour=hour;
ctx->current_xds_date=date;
ctx->current_xds_month=month;
}
ccx_common_logging.debug_ftn(CCX_DMT_DECODER_XDS, "PIN (Start Time): %s %02d-%02d %02d:%02d\n",
(ctx->cur_xds_packet_class==XDS_CLASS_CURRENT?"Current":"Future"),
date,month,hour,min);
xdsprint (sub, ctx, "PIN (Start Time): %s %02d-%02d %02d:%02d\n",
(ctx->cur_xds_packet_class==XDS_CLASS_CURRENT?"Current":"Future"),
date,month,hour,min);
if (!ctx->xds_start_time_shown && ctx->cur_xds_packet_class==XDS_CLASS_CURRENT)
{
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,
ctx->current_xds_min, ctx->current_xds_hour, ctx->current_xds_date, ctx->current_xds_month);
ctx->xds_start_time_shown=1;
}
break;
case XDS_TYPE_LENGH_AND_CURRENT_TIME:
{
was_proc=1;
if (ctx->cur_xds_payload_length<5) // We need 2 data bytes
break;
int min=ctx->cur_xds_payload[2] & 0x3f; // 6 bits
int hour = ctx->cur_xds_payload[3] & 0x1f; // 5 bits
if (!ctx->xds_program_length_shown)
ccx_common_logging.log_ftn ("\rXDS: Program length (HH:MM): %02d:%02d ",hour,min);
else
ccx_common_logging.debug_ftn(CCX_DMT_DECODER_XDS, "\rXDS: Program length (HH:MM): %02d:%02d ",hour,min);
xdsprint(sub, ctx, "Program length (HH:MM): %02d:%02d ",hour,min);
if (ctx->cur_xds_payload_length>6) // Next two bytes (optional) available
{
int el_min=ctx->cur_xds_payload[4] & 0x3f; // 6 bits
int el_hour = ctx->cur_xds_payload[5] & 0x1f; // 5 bits
if (!ctx->xds_program_length_shown)
ccx_common_logging.log_ftn ("Elapsed (HH:MM): %02d:%02d",el_hour,el_min);
else
ccx_common_logging.debug_ftn(CCX_DMT_DECODER_XDS, "Elapsed (HH:MM): %02d:%02d",el_hour,el_min);
xdsprint(sub, ctx, "Elapsed (HH:MM): %02d:%02d",el_hour,el_min);
}
if (ctx->cur_xds_payload_length>8) // Next two bytes (optional) available
{
int el_sec=ctx->cur_xds_payload[6] & 0x3f; // 6 bits
if (!ctx->xds_program_length_shown)
ccx_common_logging.debug_ftn(CCX_DMT_DECODER_XDS, ":%02d",el_sec);
xdsprint(sub, ctx, "Elapsed (SS) :%02d",el_sec);
}
if (!ctx->xds_program_length_shown)
ccx_common_logging.log_ftn("\n");
else
ccx_common_logging.debug_ftn(CCX_DMT_DECODER_XDS, "\n");
ctx->xds_program_length_shown=1;
}
break;
case XDS_TYPE_PROGRAM_NAME:
{
was_proc=1;
char xds_program_name[33];
int i;
for (i=2;i<ctx->cur_xds_payload_length-1;i++)
xds_program_name[i-2]=ctx->cur_xds_payload[i];
xds_program_name[i-2]=0;
ccx_common_logging.debug_ftn(CCX_DMT_DECODER_XDS, "\rXDS Program name: %s\n",xds_program_name);
xdsprint(sub, ctx, "Program name: %s",xds_program_name);
if (ctx->cur_xds_packet_class==XDS_CLASS_CURRENT &&
strcmp (xds_program_name, ctx->current_xds_program_name)) // Change of program
{
ccx_common_logging.log_ftn ("\rXDS Notice: Program is now %s\n", xds_program_name);
strncpy (ctx->current_xds_program_name,xds_program_name, 33);
ccx_common_logging.gui_ftn(CCX_COMMON_LOGGING_GUI_XDS_PROGRAM_NAME, xds_program_name);
}
break;
}
break;
case XDS_TYPE_PROGRAM_TYPE:
was_proc=1;
if (ctx->cur_xds_payload_length<5) // We need 2 data bytes
break;
if (ctx->current_program_type_reported)
{
// Check if we should do it again
for (int i=0;i<ctx->cur_xds_payload_length ; i++)
{
if (ctx->cur_xds_payload[i]!=ctx->current_xds_program_type[i])
{
ctx->current_program_type_reported=0;
break;
}
}
}
//if (!(ccx_common_logging.debug_mask & CCX_DMT_DECODER_XDS) && ctx->current_program_type_reported)
// break;
memcpy (ctx->current_xds_program_type,ctx->cur_xds_payload,ctx->cur_xds_payload_length);
ctx->current_xds_program_type[ctx->cur_xds_payload_length]=0;
if (!ctx->current_program_type_reported)
ccx_common_logging.log_ftn ("\rXDS Program Type: ");
*str = '\0';
tstr = str;
for (int i=2;i<ctx->cur_xds_payload_length - 1; i++)
{
if (ctx->cur_xds_payload[i]==0) // Padding
continue;
if (!ctx->current_program_type_reported)
ccx_common_logging.log_ftn ("[%02X-", ctx->cur_xds_payload[i]);
if (ctx->cur_xds_payload[i]>=0x20 && ctx->cur_xds_payload[i]<0x7F)
{
snprintf(tstr,str_len - (tstr - str),"[%s] ",XDSProgramTypes[ctx->cur_xds_payload[i]-0x20]);
tstr += strlen(tstr);
}
if (!ctx->current_program_type_reported)
{
if (ctx->cur_xds_payload[i]>=0x20 && ctx->cur_xds_payload[i]<0x7F)
ccx_common_logging.log_ftn ("%s",XDSProgramTypes[ctx->cur_xds_payload[i]-0x20]);
else
ccx_common_logging.log_ftn ("ILLEGAL VALUE");
ccx_common_logging.log_ftn ("] ");
}
}
xdsprint(sub, ctx, "Program type %s",str);
if (!ctx->current_program_type_reported)
ccx_common_logging.log_ftn ("\n");
ctx->current_program_type_reported=1;
break;
case XDS_TYPE_CONTENT_ADVISORY:
was_proc=1;
if (ctx->cur_xds_payload_length<5) // We need 2 data bytes
break;
xds_do_content_advisory (sub, ctx, ctx->cur_xds_payload[2],ctx->cur_xds_payload[3]);
break;
case XDS_TYPE_AUDIO_SERVICES:
was_proc=1; // I don't have any sample with this.
break;
case XDS_TYPE_CGMS:
was_proc=1;
xds_do_copy_generation_management_system (sub, ctx, ctx->cur_xds_payload[2],ctx->cur_xds_payload[3]);
break;
case XDS_TYPE_ASPECT_RATIO_INFO:
{
unsigned ar_start, ar_end;
was_proc = 1;
if (ctx->cur_xds_payload_length < 5) // We need 2 data bytes
break;
if (!ctx->cur_xds_payload[2] & 20 || !ctx->cur_xds_payload[3] & 20) // Bit 6 must be 1
break;
/* CEA-608-B: The starting line is computed by adding 22 to the decimal number
represented by bits S0 to S5. The ending line is computing by substracting
the decimal number represented by bits E0 to E5 from 262 */
ar_start = (ctx->cur_xds_payload[2] & 0x1F) + 22;
ar_end = 262 - (ctx->cur_xds_payload[3] & 0x1F);
unsigned active_picture_height = ar_end - ar_start;
float aspect_ratio = (float) 320 / active_picture_height;
ccx_common_logging.log_ftn("\rXDS Notice: Aspect ratio info, start line=%u, end line=%u\n", ar_start,ar_end);
ccx_common_logging.log_ftn("\rXDS Notice: Aspect ratio info, active picture height=%u, ratio=%f\n", active_picture_height, aspect_ratio);
}
case XDS_TYPE_PROGRAM_DESC_1:
case XDS_TYPE_PROGRAM_DESC_2:
case XDS_TYPE_PROGRAM_DESC_3:
case XDS_TYPE_PROGRAM_DESC_4:
case XDS_TYPE_PROGRAM_DESC_5:
case XDS_TYPE_PROGRAM_DESC_6:
case XDS_TYPE_PROGRAM_DESC_7:
case XDS_TYPE_PROGRAM_DESC_8:
{
was_proc=1;
int changed=0;
char xds_desc[33];
int i;
for (i=2;i<ctx->cur_xds_payload_length-1;i++)
xds_desc[i-2]=ctx->cur_xds_payload[i];
xds_desc[i-2]=0;
if (xds_desc[0])
{
int line_num=ctx->cur_xds_packet_type-XDS_TYPE_PROGRAM_DESC_1;
if (strcmp (xds_desc, ctx->xds_program_description[line_num]))
changed=1;
if (changed)
{
ccx_common_logging.log_ftn ("\rXDS description line %d: %s\n",line_num,xds_desc);
strcpy (ctx->xds_program_description[line_num], xds_desc);
}
else
{
ccx_common_logging.debug_ftn(CCX_DMT_DECODER_XDS, "\rXDS description line %d: %s\n",line_num,xds_desc);
}
xdsprint(sub, ctx, "XDS description line %d: %s",line_num,xds_desc);
ccx_common_logging.gui_ftn(CCX_COMMON_LOGGING_GUI_XDS_PROGRAM_DESCRIPTION, line_num, xds_desc);
}
break;
}
}
free(str);
return was_proc;
}
int xds_do_channel (struct cc_subtitle *sub, struct ccx_decoders_xds_context *ctx)
{
int was_proc=0;
if(!ctx)
return CCX_EINVAL;
switch (ctx->cur_xds_packet_type)
{
case XDS_TYPE_NETWORK_NAME:
was_proc=1;
char xds_network_name[33];
int i;
for (i=2;i<ctx->cur_xds_payload_length-1;i++)
xds_network_name[i-2]=ctx->cur_xds_payload[i];
xds_network_name[i-2]=0;
ccx_common_logging.debug_ftn(CCX_DMT_DECODER_XDS, "XDS Network name: %s\n",xds_network_name);
xdsprint (sub, ctx, "Network: %s",xds_network_name);
if (strcmp (xds_network_name, ctx->current_xds_network_name)) // Change of station
{
ccx_common_logging.log_ftn ("XDS Notice: Network is now %s\n", xds_network_name);
strcpy (ctx->current_xds_network_name,xds_network_name);
}
break;
case XDS_TYPE_CALL_LETTERS_AND_CHANNEL:
{
was_proc=1;
char xds_call_letters[7];
if (ctx->cur_xds_payload_length != 7 && ctx->cur_xds_payload_length != 9) // We need 4-6 data bytes
break;
for (i=2;i<ctx->cur_xds_payload_length-1;i++)
{
if (ctx->cur_xds_payload)
xds_call_letters[i-2]=ctx->cur_xds_payload[i];
}
xds_call_letters[i-2]=0;
ccx_common_logging.debug_ftn(CCX_DMT_DECODER_XDS, "XDS Network call letters: %s\n",xds_call_letters);
xdsprint (sub, ctx, "Call Letters: %s",xds_call_letters);
if (strncmp (xds_call_letters, ctx->current_xds_call_letters, 7)) // Change of station
{
ccx_common_logging.log_ftn ("XDS Notice: Network call letters now %s\n", xds_call_letters);
strncpy (ctx->current_xds_call_letters, xds_call_letters, 7);
ccx_common_logging.gui_ftn(CCX_COMMON_LOGGING_GUI_XDS_CALL_LETTERS, ctx->current_xds_call_letters);
}
}
break;
case XDS_TYPE_TSID:
// According to CEA-608, data here (4 bytes) are used to identify the
// "originating analog licensee". No interesting data for us.
was_proc=1;
if (ctx->cur_xds_payload_length<7) // We need 4 data bytes
break;
unsigned b1=(ctx->cur_xds_payload[2])&0x10; // Only low 4 bits from each byte
unsigned b2=(ctx->cur_xds_payload[3])&0x10;
unsigned b3=(ctx->cur_xds_payload[4])&0x10;
unsigned b4=(ctx->cur_xds_payload[5])&0x10;
unsigned tsid=(b4<<12) | (b3<<8) | (b2<<4) | b1;
if (tsid)
xdsprint (sub, ctx, "TSID: %u",tsid);
break;
}
return was_proc;
}
int xds_do_private_data (struct cc_subtitle *sub, struct ccx_decoders_xds_context *ctx)
{
char *str;
int i;
if(!ctx)
return CCX_EINVAL;
str = malloc((ctx->cur_xds_payload_length *3) + 1);
if (str==NULL) // Only thing we can do with private data is dump it.
return 1;
for (i = 2; i < ctx->cur_xds_payload_length - 1; i++)
sprintf(str, "%02X ",ctx->cur_xds_payload[i]);
xdsprint(sub, ctx, str);
free(str);
return 1;
}
int xds_do_misc (struct ccx_decoders_xds_context *ctx)
{
int was_proc=0;
if(!ctx)
return CCX_EINVAL;
switch (ctx->cur_xds_packet_type)
{
case XDS_TYPE_TIME_OF_DAY:
{
was_proc=1;
if (ctx->cur_xds_payload_length<9) // We need 6 data bytes
break;
int min=ctx->cur_xds_payload[2] & 0x3f; // 6 bits
int hour = ctx->cur_xds_payload[3] & 0x1f; // 5 bits
int date = ctx->cur_xds_payload[4] & 0x1f; // 5 bits
int month = ctx->cur_xds_payload[5] & 0xf; // 4 bits
int reset_seconds = (ctx->cur_xds_payload[5] & 0x20);
int day_of_week = ctx->cur_xds_payload[6] & 0x7;
int year = (ctx->cur_xds_payload[7] & 0x3f) + 1990;
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;
}
case XDS_TYPE_LOCAL_TIME_ZONE:
{
was_proc=1;
if (ctx->cur_xds_payload_length<5) // We need 2 data bytes
break;
// int b6 = (ctx->cur_xds_payload[2] & 0x40) >>6; // Bit 6 should always be 1
int dst = (ctx->cur_xds_payload[2] & 0x20) >>5; // Daylight Saving Time
int hour = ctx->cur_xds_payload[2] & 0x1f; // 5 bits
ccx_common_logging.debug_ftn(CCX_DMT_DECODER_XDS, "Local Time Zone: %02d DST: %d\n",
hour, dst);
break;
}
default:
was_proc=0;
break;
}
return was_proc;
}
void do_end_of_xds (struct cc_subtitle *sub, struct ccx_decoders_xds_context *ctx, unsigned char expected_checksum)
{
int cs = 0;
int i;
if(!ctx)
return;
if (ctx->cur_xds_buffer_idx== -1 || /* Unknown buffer, or not in use (bug) */
!ctx->xds_buffers[ctx->cur_xds_buffer_idx].in_use)
return;
ctx->cur_xds_packet_class = ctx->xds_buffers[ctx->cur_xds_buffer_idx].xds_class;
ctx->cur_xds_payload = ctx->xds_buffers[ctx->cur_xds_buffer_idx].bytes;
ctx->cur_xds_payload_length=ctx->xds_buffers[ctx->cur_xds_buffer_idx].used_bytes;
ctx->cur_xds_packet_type=ctx->cur_xds_payload[1];
ctx->cur_xds_payload[ctx->cur_xds_payload_length++]=0x0F; // The end byte itself, added to the packet
for (i = 0; i < ctx->cur_xds_payload_length; i++)
{
cs=cs+ctx->cur_xds_payload[i];
cs=cs & 0x7f; // Keep 7 bits only
int c=ctx->cur_xds_payload[i]&0x7F;
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
ccx_common_logging.debug_ftn(CCX_DMT_DECODER_XDS, "End of XDS. Class=%d (%s), size=%d Checksum OK: %d Used buffers: %d\n",
ctx->cur_xds_packet_class,XDSclasses[ctx->cur_xds_packet_class],
ctx->cur_xds_payload_length,
cs==expected_checksum, how_many_used(ctx));
if (cs!=expected_checksum || ctx->cur_xds_payload_length<3)
{
ccx_common_logging.debug_ftn(CCX_DMT_DECODER_XDS, "Expected checksum: %02X Calculated: %02X\n", expected_checksum, cs);
clear_xds_buffer (ctx, ctx->cur_xds_buffer_idx);
return; // Bad packets ignored as per specs
}
int was_proc=0; /* Indicated if the packet was processed. Not processed means "code to do it doesn't exist yet", not an error. */
if (ctx->cur_xds_packet_type & 0x40) // Bit 6 set
{
ctx->cur_xds_packet_class = XDS_CLASS_OUT_OF_BAND;
}
switch (ctx->cur_xds_packet_class)
{
case XDS_CLASS_FUTURE: // Info on future program
if (!(ccx_common_logging.debug_mask & CCX_DMT_DECODER_XDS)) // Don't bother processing something we don't need
{
was_proc=1;
break;
}
case XDS_CLASS_CURRENT: // Info on current program
was_proc = xds_do_current_and_future(sub, ctx);
break;
case XDS_CLASS_CHANNEL:
was_proc = xds_do_channel(sub, ctx);
break;
case XDS_CLASS_MISC:
was_proc = xds_do_misc(ctx);
break;
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.
was_proc = xds_do_private_data(sub, ctx);
break;
case XDS_CLASS_OUT_OF_BAND:
ccx_common_logging.debug_ftn(CCX_DMT_DECODER_XDS, "Out-of-band data, ignored.");
was_proc = 1;
break;
}
if (!was_proc)
{
ccx_common_logging.log_ftn ("Note: We found an currently unsupported XDS packet.\n");
}
clear_xds_buffer (ctx, ctx->cur_xds_buffer_idx);
}

View File

@@ -0,0 +1,13 @@
#ifndef CCX_DECODER_XDS_H
#define CCX_DECODER_XDS_H
#include "ccx_decoders_common.h"
struct ccx_decoders_xds_context;
void process_xds_bytes (struct ccx_decoders_xds_context *ctx, const unsigned char hi, int lo);
void do_end_of_xds (struct cc_subtitle *sub, struct ccx_decoders_xds_context *ctx, unsigned char expected_checksum);
struct ccx_decoders_xds_context *ccx_decoders_xds_init_library(struct ccx_common_timing_ctx *timing);
void xds_cea608_test();
#endif

381
src/lib_ccx/ccx_demuxer.c Normal file
View File

@@ -0,0 +1,381 @@
#include "ccx_demuxer.h"
#include "activity.h"
#include "lib_ccx.h"
#include "utility.h"
static void ccx_demuxer_reset(struct ccx_demuxer *ctx)
{
ctx->startbytes_pos=0;
ctx->startbytes_avail=0;
memset (ctx->PIDs_seen, 0, 65536*sizeof (int));
memset (ctx->PIDs_programs, 0, 65536*sizeof (struct PMT_entry *));
}
static void ccx_demuxer_close(struct ccx_demuxer *ctx)
{
ctx->past = 0;
if (ctx->infd!=-1 && ccx_options.input_source==CCX_DS_FILE)
{
close (ctx->infd);
ctx->infd=-1;
activity_input_file_closed();
}
}
static int ccx_demuxer_isopen(struct ccx_demuxer *ctx)
{
return ctx->infd != -1;
}
static int ccx_demuxer_open(struct ccx_demuxer *ctx, const char *file)
{
init_file_buffer(ctx);
if (ccx_options.input_source==CCX_DS_STDIN)
{
if (ctx->infd != -1) // Means we had already processed stdin. So we're done.
{
if (ccx_options.print_file_reports)
print_file_report(ctx->parent);
return -1;
}
ctx->infd = 0;
mprint ("\n\r-----------------------------------------------------------------\n");
mprint ("\rReading from standard input\n");
}
else if (ccx_options.input_source == CCX_DS_NETWORK)
{
if (ctx->infd != -1) // Means we have already bound a socket.
{
if (ccx_options.print_file_reports)
print_file_report(ctx->parent);
return -1;
}
ctx->infd = start_upd_srv(ccx_options.udpaddr, ccx_options.udpport);
if(ctx->infd < 0)
{
print_error(ccx_options.gui_mode_reports,"socket() failed.");
return CCX_COMMON_EXIT_BUG_BUG;
}
}
else if (ccx_options.input_source == CCX_DS_TCP)
{
if (ctx->infd != -1)
{
if (ccx_options.print_file_reports)
print_file_report(ctx->parent);
return -1;
}
ctx->infd = start_tcp_srv(ccx_options.tcpport, ccx_options.tcp_password);
}
else
{
#ifdef _WIN32
ctx->infd = OPEN (file, O_RDONLY | O_BINARY);
#else
ctx->infd = OPEN (file, O_RDONLY);
#endif
if (ctx->infd < 0)
return -1;
}
if (ctx->auto_stream == CCX_SM_AUTODETECT)
{
detect_stream_type(ctx);
switch (ctx->stream_mode)
{
case CCX_SM_ELEMENTARY_OR_NOT_FOUND:
mprint ("\rFile seems to be an elementary stream, enabling ES mode\n");
break;
case CCX_SM_TRANSPORT:
mprint ("\rFile seems to be a transport stream, enabling TS mode\n");
break;
case CCX_SM_PROGRAM:
mprint ("\rFile seems to be a program stream, enabling PS mode\n");
break;
case CCX_SM_ASF:
mprint ("\rFile seems to be an ASF, enabling DVR-MS mode\n");
break;
case CCX_SM_WTV:
mprint ("\rFile seems to be a WTV, enabling WTV mode\n");
break;
case CCX_SM_MCPOODLESRAW:
mprint ("\rFile seems to be McPoodle raw data\n");
break;
case CCX_SM_RCWT:
mprint ("\rFile seems to be a raw caption with time data\n");
break;
case CCX_SM_MP4:
mprint ("\rFile seems to be a MP4\n");
break;
#ifdef WTV_DEBUG
case CCX_SM_HEX_DUMP:
mprint ("\rFile seems to be an hexadecimal dump\n");
break;
#endif
case CCX_SM_MYTH:
case CCX_SM_AUTODETECT:
fatal(CCX_COMMON_EXIT_BUG_BUG, "Cannot be reached!");
break;
}
}
else
{
ctx->stream_mode = ctx->auto_stream;
}
// The myth loop autodetect will only be used with ES or PS streams
switch (ccx_options.auto_myth)
{
case 0:
// Use whatever stream mode says
break;
case 1:
// Force stream mode to myth
ctx->stream_mode=CCX_SM_MYTH;
break;
case 2:
// autodetect myth files, but only if it does not conflict with
// the current stream mode
switch (ctx->stream_mode)
{
case CCX_SM_ELEMENTARY_OR_NOT_FOUND:
case CCX_SM_PROGRAM:
if ( detect_myth(ctx->parent) )
{
ctx->stream_mode=CCX_SM_MYTH;
}
break;
default:
// Keep stream_mode
break;
}
break;
}
ctx->past = 0;
ctx->min_global_timestamp = 0;
ctx->global_timestamp_inited = 0;
ctx->last_global_timestamp = 0;
ctx->offset_global_timestamp = 0;
return 0;
}
LLONG ccx_demuxer_getfilesize (struct ccx_demuxer *ctx)
{
LLONG ret = 0;
int in = ctx->infd;
LLONG current=LSEEK (in, 0, SEEK_CUR);
LLONG length = LSEEK (in,0,SEEK_END);
if(current < 0 ||length < 0)
return -1;
ret = LSEEK (in, current, SEEK_SET);
if (ret < 0)
return -1;
return length;
}
static int ccx_demuxer_get_stream_mode(struct ccx_demuxer *ctx)
{
return ctx->stream_mode;
}
static void ccx_demuxer_print_cfg(struct ccx_demuxer *ctx)
{
switch (ctx->auto_stream)
{
case CCX_SM_ELEMENTARY_OR_NOT_FOUND:
mprint ("Elementary");
break;
case CCX_SM_TRANSPORT:
mprint ("Transport");
break;
case CCX_SM_PROGRAM:
mprint ("Program");
break;
case CCX_SM_ASF:
mprint ("DVR-MS");
break;
case CCX_SM_WTV:
mprint ("Windows Television (WTV)");
break;
case CCX_SM_MCPOODLESRAW:
mprint ("McPoodle's raw");
break;
case CCX_SM_AUTODETECT:
mprint ("Autodetect");
break;
case CCX_SM_RCWT:
mprint ("BIN");
break;
case CCX_SM_MP4:
mprint ("MP4");
break;
#ifdef WTV_DEBUG
case CCX_SM_HEX_DUMP:
mprint ("Hex");
break;
#endif
default:
fatal(CCX_COMMON_EXIT_BUG_BUG, "BUG: Unknown stream mode.\n");
break;
}
}
int ccx_demuxer_write_es(struct ccx_demuxer *ctx, unsigned char* buf, size_t len)
{
if (ctx->fh_out_elementarystream!=NULL)
fwrite (buf, 1, len,ctx->fh_out_elementarystream);
return CCX_OK;
}
void ccx_demuxer_delete(struct ccx_demuxer **ctx)
{
struct ccx_demuxer *lctx = *ctx;
int i;
dinit_cap(lctx);
freep(&lctx->last_pat_payload);
for (i = 0; i < MAX_PSI_PID; i++)
{
if(lctx->PID_buffers[i]!=NULL && lctx->PID_buffers[i]->buffer!=NULL)
{
free(lctx->PID_buffers[i]->buffer);
lctx->PID_buffers[i]->buffer=NULL;
lctx->PID_buffers[i]->buffer_length=0;
}
freep(&lctx->PID_buffers[i]);
}
for (i = 0; i < MAX_PID; i++)
{
if( lctx->PIDs_programs[i])
freep(lctx->PIDs_programs + i);
}
if (lctx->fh_out_elementarystream != NULL)
fclose (lctx->fh_out_elementarystream);
freep(&lctx->filebuffer);
freep(ctx);
}
struct ccx_demuxer *init_demuxer(void *parent, struct demuxer_cfg *cfg)
{
int i;
struct ccx_demuxer *ctx = malloc(sizeof(struct ccx_demuxer));
if(!ctx)
return NULL;
ctx->infd = -1;//Set to -1 to indicate no file is open.
ctx->m2ts = cfg->m2ts;
ctx->auto_stream = cfg->auto_stream;
ctx->stream_mode = CCX_SM_ELEMENTARY_OR_NOT_FOUND;
ctx->ts_autoprogram = cfg->ts_autoprogram;
ctx->ts_allprogram = cfg->ts_allprogram;
ctx->ts_datastreamtype = cfg->ts_datastreamtype;
ctx->nb_program = 0;
ctx->multi_stream_per_prog = 0;
if(cfg->ts_forced_program != -1)
{
ctx->pinfo[ctx->nb_program].pid = CCX_UNKNOWN;
ctx->pinfo[ctx->nb_program].program_number = cfg->ts_forced_program;
ctx->flag_ts_forced_pn = CCX_TRUE;
ctx->nb_program++;
}
else
{
ctx->flag_ts_forced_pn = CCX_FALSE;
}
INIT_LIST_HEAD(&ctx->cinfo_tree.all_stream);
INIT_LIST_HEAD(&ctx->cinfo_tree.sib_stream);
INIT_LIST_HEAD(&ctx->cinfo_tree.pg_stream);
ctx->codec = cfg->codec;
ctx->flag_ts_forced_cappid = CCX_FALSE;
for(i = 0; i < cfg->nb_ts_cappid; i++)
{
if(ctx->codec == CCX_CODEC_ANY)
update_capinfo(ctx, cfg->ts_cappids[i], cfg->ts_datastreamtype, CCX_CODEC_NONE, 0, NULL);
else
update_capinfo(ctx, cfg->ts_cappids[i], cfg->ts_datastreamtype, ctx->codec, 0, NULL);
}
ctx->flag_ts_forced_cappid = cfg->nb_ts_cappid ? CCX_TRUE : CCX_FALSE;
ctx->nocodec = cfg->nocodec;
ctx->reset = ccx_demuxer_reset;
ctx->close = ccx_demuxer_close;
ctx->open = ccx_demuxer_open;
ctx->is_open = ccx_demuxer_isopen;
ctx->get_filesize = ccx_demuxer_getfilesize;
ctx->get_stream_mode = ccx_demuxer_get_stream_mode;
ctx->print_cfg = ccx_demuxer_print_cfg;
ctx->write_es = ccx_demuxer_write_es;
ctx->hauppauge_warning_shown = 0;
ctx->parent = parent;
ctx->last_pat_payload = NULL;
ctx->last_pat_length = 0;
ctx->fh_out_elementarystream = NULL;
ctx->warning_program_not_found_shown = CCX_FALSE;
ctx->strangeheader = 0;
memset(&ctx->freport, 0, sizeof(ctx->freport));
if (cfg->out_elementarystream_filename != NULL)
{
if ((ctx->fh_out_elementarystream = fopen (cfg->out_elementarystream_filename,"wb"))==NULL)
{
print_error(CCX_COMMON_EXIT_FILE_CREATION_FAILED, "Unable to open clean file: %s\n", cfg->out_elementarystream_filename);
return NULL;
}
}
for(i = 0; i < MAX_PSI_PID; i++)
ctx->PID_buffers[i]=NULL;
init_ts(ctx);
ctx->filebuffer = NULL;
return ctx;
}
void delete_demuxer_data(struct demuxer_data *data)
{
free(data->buffer);
free(data);
}
struct demuxer_data* alloc_demuxer_data(void)
{
struct demuxer_data* data = malloc(sizeof(struct demuxer_data));
if(!data)
{
return NULL;
}
data->buffer = (unsigned char *) malloc (BUFSIZE);
if(!data->buffer)
{
free(data);
return NULL;
}
data->len = 0;
data->bufferdatatype = CCX_PES;
data->program_number = -1;
data->stream_pid = -1;
data->codec = CCX_CODEC_NONE;
data->len = 0;
data->pts = CCX_NOPTS;
data->next_stream = 0;
data->next_program = 0;
return data;
}

174
src/lib_ccx/ccx_demuxer.h Normal file
View File

@@ -0,0 +1,174 @@
#ifndef CCX_DEMUXER_H
#define CCX_DEMUXER_H
#include "ccx_common_constants.h"
#include "ccx_common_option.h"
#include "ts_functions.h"
#include "list.h"
#include "activity.h"
/* Report information */
#define SUB_STREAMS_CNT 10
#define MAX_PID 65536
#define MAX_PSI_PID 8191
#define TS_PMT_MAP_SIZE 128
#define MAX_PROGRAM 128
#define MAX_PROGRAM_NAME_LEN 128
struct ccx_demux_report
{
unsigned program_cnt;
unsigned dvb_sub_pid[SUB_STREAMS_CNT];
unsigned tlt_sub_pid[SUB_STREAMS_CNT];
unsigned mp4_cc_track_cnt;
};
struct program_info
{
int pid;
int program_number;
uint8_t analysed_PMT_once:1;
uint8_t version;
uint8_t saved_section[1021];
int32_t crc;
uint8_t valid_crc:1;
char name[MAX_PROGRAM_NAME_LEN];
/**
* -1 pid represent that pcr_pid is not available
*/
int16_t pcr_pid;
};
struct cap_info
{
int pid;
int program_number;
enum ccx_stream_type stream;
enum ccx_code_type codec;
long capbufsize;
unsigned char *capbuf;
long capbuflen; // Bytes read in capbuf
int saw_pesstart;
int prev_counter;
void *codec_private_data;
int ignore;
/**
List joining all stream in TS
*/
struct list_head all_stream;
/**
List joining all sibling Stream in Program
*/
struct list_head sib_head;
struct list_head sib_stream;
/**
List joining all sibling Stream in Program
*/
struct list_head pg_stream;
};
struct ccx_demuxer
{
int m2ts;
enum ccx_stream_mode_enum stream_mode;
enum ccx_stream_mode_enum auto_stream;
// Small buffer to help us with the initial sync
unsigned char startbytes[STARTBYTESLENGTH];
unsigned int startbytes_pos;
int startbytes_avail;
// User Specified Param
int ts_autoprogram;
int ts_allprogram;
int flag_ts_forced_pn;
int flag_ts_forced_cappid;
int ts_datastreamtype;
struct program_info pinfo[MAX_PROGRAM];
int nb_program;
/* subtitle codec type */
enum ccx_code_type codec;
enum ccx_code_type nocodec;
struct cap_info cinfo_tree;
/* File handles */
FILE *fh_out_elementarystream;
int infd; // descriptor number to input.
LLONG past; /* Position in file, if in sync same as ftell() */
// TODO relates to fts_global
int64_t global_timestamp;
int64_t min_global_timestamp;
int64_t offset_global_timestamp;
int64_t last_global_timestamp;
int global_timestamp_inited;
struct PSI_buffer *PID_buffers[MAX_PSI_PID];
int PIDs_seen[MAX_PID];
struct PMT_entry *PIDs_programs[MAX_PID];
struct ccx_demux_report freport;
/* Hauppauge support */
unsigned hauppauge_warning_shown; // Did we detect a possible Hauppauge capture and told the user already?
int multi_stream_per_prog;
unsigned char *last_pat_payload;
unsigned last_pat_length;
unsigned char *filebuffer;
LLONG filebuffer_start; // Position of buffer start relative to file
unsigned int filebuffer_pos; // Position of pointer relative to buffer start
unsigned int bytesinbuffer; // Number of bytes we actually have on buffer
int warning_program_not_found_shown;
// Remember if the last header was valid. Used to suppress too much output
// and the expected unrecognized first header for TiVo files.
int strangeheader;
void *parent;
void (*print_cfg)(struct ccx_demuxer *ctx);
void (*reset)(struct ccx_demuxer *ctx);
void (*close)(struct ccx_demuxer *ctx);
int (*open)(struct ccx_demuxer *ctx, const char *file_name);
int (*is_open)(struct ccx_demuxer *ctx);
int (*get_stream_mode)(struct ccx_demuxer *ctx);
LLONG (*get_filesize) (struct ccx_demuxer *ctx);
int (*write_es)(struct ccx_demuxer *ctx, unsigned char* buf, size_t len);
};
struct demuxer_data
{
int program_number;
int stream_pid;
enum ccx_code_type codec;
enum ccx_bufferdata_type bufferdatatype;
unsigned char *buffer;
size_t len;
LLONG pts;
struct demuxer_data *next_stream;
struct demuxer_data *next_program;
};
struct cap_info *get_sib_stream_by_type(struct cap_info* program, enum ccx_code_type type);
struct ccx_demuxer *init_demuxer(void *parent, struct demuxer_cfg *cfg);
void ccx_demuxer_delete(struct ccx_demuxer **ctx);
struct demuxer_data* alloc_demuxer_data(void);
void delete_demuxer_data(struct demuxer_data *data);
int update_capinfo(struct ccx_demuxer *ctx, int pid, enum ccx_stream_type stream, enum ccx_code_type codec, int pn, void *private_data);
struct cap_info * get_cinfo(struct ccx_demuxer *ctx, int pid);
int need_capInfo(struct ccx_demuxer *ctx, int program_number);
int need_capInfo_for_pid(struct ccx_demuxer *ctx, int pid);
struct demuxer_data *get_best_data(struct demuxer_data *data);
struct demuxer_data *get_data_stream(struct demuxer_data *data, int pid);
int get_best_stream(struct ccx_demuxer *ctx);
void ignore_other_stream(struct ccx_demuxer *ctx, int pid);
void dinit_cap (struct ccx_demuxer *ctx);
int get_programme_number(struct ccx_demuxer *ctx, int pid);
struct cap_info* get_best_sib_stream(struct cap_info* program);
void ignore_other_sib_stream(struct cap_info* head, int pid);
#endif

147
src/lib_ccx/ccx_dtvcc.c Normal file
View File

@@ -0,0 +1,147 @@
#include "ccx_dtvcc.h"
#include "ccx_common_common.h"
#include "ccx_encoders_common.h"
#include "ccx_decoders_708_output.h"
void ccx_dtvcc_process_data(struct lib_cc_decode *ctx,
const unsigned char *data,
int data_length)
{
/*
* Note: the data has following format:
* 1 byte for cc_valid
* 1 byte for cc_type
* 2 bytes for the actual data
*/
ccx_dtvcc_ctx *dtvcc = ctx->dtvcc;
if (!dtvcc->is_active && !dtvcc->report_enabled)
return;
for (int i = 0; i < data_length; i += 4)
{
unsigned char cc_valid = data[i];
unsigned char cc_type = data[i + 1];
switch (cc_type)
{
case 2:
ccx_common_logging.debug_ftn (CCX_DMT_708, "[CEA-708] dtvcc_process_data: DTVCC Channel Packet Data\n");
if (cc_valid == 0) // This ends the previous packet
ccx_dtvcc_process_current_packet(dtvcc);
else
{
if (dtvcc->current_packet_length > 253)
{
ccx_common_logging.debug_ftn(CCX_DMT_708, "[CEA-708] dtvcc_process_data: "
"Warning: Legal packet size exceeded (1), data not added.\n");
}
else
{
dtvcc->current_packet[dtvcc->current_packet_length++] = data[i + 2];
dtvcc->current_packet[dtvcc->current_packet_length++] = data[i + 3];
}
}
break;
case 3:
ccx_common_logging.debug_ftn (CCX_DMT_708, "[CEA-708] dtvcc_process_data: DTVCC Channel Packet Start\n");
ccx_dtvcc_process_current_packet(dtvcc);
if (cc_valid)
{
if (dtvcc->current_packet_length > CCX_DTVCC_MAX_PACKET_LENGTH - 1)
{
ccx_common_logging.debug_ftn(CCX_DMT_708, "[CEA-708] dtvcc_process_data: "
"Warning: Legal packet size exceeded (2), data not added.\n");
}
else
{
dtvcc->current_packet[dtvcc->current_packet_length++] = data[i + 2];
dtvcc->current_packet[dtvcc->current_packet_length++] = data[i + 3];
}
}
break;
default:
ccx_common_logging.fatal_ftn (CCX_COMMON_EXIT_BUG_BUG, "[CEA-708] dtvcc_process_data: "
"shouldn't be here - cc_type: %d\n", cc_type);
}
}
}
//--------------------------------------------------------------------------------------
ccx_dtvcc_ctx *ccx_dtvcc_init(struct ccx_decoder_dtvcc_settings *opts)
{
ccx_common_logging.debug_ftn(CCX_DMT_708, "[CEA-708] initializing dtvcc decoder\n");
ccx_dtvcc_ctx *ctx = (ccx_dtvcc_ctx *) malloc(sizeof(ccx_dtvcc_ctx));
if (!ctx)
{
ccx_common_logging.fatal_ftn(EXIT_NOT_ENOUGH_MEMORY, "[CEA-708] ccx_dtvcc_init");
return NULL;
}
ctx->report = opts->report;
ctx->report->reset_count = 0;
ctx->is_active = 0;
ctx->report_enabled = 0;
ctx->no_rollup = opts->no_rollup;
ctx->active_services_count = opts->active_services_count;
memcpy(ctx->services_active, opts->services_enabled, CCX_DTVCC_MAX_SERVICES * sizeof(int));
ccx_dtvcc_clear_packet(ctx);
ctx->last_sequence = CCX_DTVCC_NO_LAST_SEQUENCE;
ctx->report_enabled = opts->print_file_reports;
ctx->timing = opts->timing;
ccx_common_logging.debug_ftn(CCX_DMT_708, "[CEA-708] initializing services\n");
for (int i = 0; i < CCX_DTVCC_MAX_SERVICES; i++)
{
if (!ctx->services_active[i])
continue;
ccx_dtvcc_service_decoder *decoder = &ctx->decoders[i];
decoder->cc_count = 0;
decoder->tv = (dtvcc_tv_screen *) malloc(sizeof(dtvcc_tv_screen));
decoder->tv->service_number = i + 1;
decoder->tv->cc_count = 0;
if (!decoder->tv)
ccx_common_logging.fatal_ftn(EXIT_NOT_ENOUGH_MEMORY, "ccx_dtvcc_init");
for (int j = 0; j < CCX_DTVCC_MAX_WINDOWS; j++)
decoder->windows[j].memory_reserved = 0;
ccx_dtvcc_windows_reset(decoder);
}
return ctx;
}
void ccx_dtvcc_free(ccx_dtvcc_ctx **ctx_ptr)
{
ccx_common_logging.debug_ftn(CCX_DMT_708, "[CEA-708] dtvcc_free: cleaning up\n");
ccx_dtvcc_ctx *ctx = *ctx_ptr;
for (int i = 0; i < CCX_DTVCC_MAX_SERVICES; i++)
{
if (!ctx->services_active[i])
continue;
ccx_dtvcc_service_decoder *decoder = &ctx->decoders[i];
for (int j = 0; j < CCX_DTVCC_MAX_WINDOWS; j++)
if (decoder->windows[j].memory_reserved)
{
for (int k = 0; k < CCX_DTVCC_MAX_ROWS; k++)
free(decoder->windows[j].rows[k]);
decoder->windows[j].memory_reserved = 0;
}
free(decoder->tv);
}
freep(ctx_ptr);
}

14
src/lib_ccx/ccx_dtvcc.h Normal file
View File

@@ -0,0 +1,14 @@
#ifndef CCEXTRACTOR_CCX_DTVCC_H
#define CCEXTRACTOR_CCX_DTVCC_H
#include "ccx_decoders_708.h"
#include "ccx_common_option.h"
void ccx_dtvcc_process_data(struct lib_cc_decode *ctx,
const unsigned char *data,
int data_length);
ccx_dtvcc_ctx *ccx_dtvcc_init(ccx_decoder_dtvcc_settings *opts);
void ccx_dtvcc_free(ccx_dtvcc_ctx **);
#endif //CCEXTRACTOR_CCX_DTVCC_H

Some files were not shown because too many files have changed in this diff Show More