Compare commits

...

783 Commits
v0.75 ... v0.82

Author SHA1 Message Date
Carlos Fernandez
fc14c61ac1 Merge branch 'pr/n411_Abhinav95' 2016-08-16 10:33:50 -07:00
Carlos Fernandez
c4073d1813 leptonica/tesseract version upgrade in release build (VS) 2016-08-16 10:33:17 -07:00
Abhinav Shukla
a78f7d2a05 Only processing the stream specified by dvblang 2016-08-16 05:23:44 -07:00
Carlos Fernandez
cfa8f5ac31 Merge branch 'pr/n410_Abhinav95' 2016-08-15 16:36:50 -07:00
Abhinav Shukla
4b239fd2ee Adding ocrlang and dvblang, removing special cases for languages 2016-08-15 16:24:06 -07:00
Carlos Fernandez
676539cf8c Updated Tesseract and leptonica versions, included the files in the repo because there's a royal pain to find and/or build. 2016-08-15 16:15:50 -07:00
Carlos Fernandez
9bd4f5acdb Merge branch 'pr/n408_Abhinav95' 2016-08-15 15:18:52 -07:00
Abhinav Shukla
0ad7ae6f66 Merge remote-tracking branch 'upstream/master' 2016-08-13 05:32:22 -07:00
Abhinav Shukla
625b477c23 Remove misleading comment 2016-08-12 15:09:08 -07:00
Carlos Fernandez
a75ba7edd4 Merge branch 'pr/n408_Abhinav95' 2016-08-12 15:07:59 -07:00
Abhinav Shukla
3a24024aaf Setting default language file directory to TESSERACT_PREFIX/tessdata 2016-08-12 15:05:52 -07:00
Carlos Fernandez
e4769fd0e6 Merge branch 'pr/n408_Abhinav95' 2016-08-12 10:23:13 -07:00
Abhinav Shukla
cd706068c8 Fixing problem with windows paths for traineddata 2016-08-12 03:40:59 -07:00
Carlos Fernandez
00a2dcfa77 Merge branch 'pr/n407_Abhinav95' 2016-08-11 12:54:34 -07:00
Carlos Fernandez
a27c8019a6 Minor typo correction 2016-08-11 12:53:49 -07:00
Abhinav Shukla
3f27fd7dc1 Fixing error with path of tesseract traineddata 2016-08-11 12:21:24 -07:00
Abhinav Shukla
a83467f595 Removing excessive language notices 2016-08-11 11:58:46 -07:00
Abhinav Shukla
45d8c63a45 Adding 99 possible languages to DVB subtitle OCR 2016-08-11 11:17:39 -07:00
Abhinav Shukla
0fd7967e7f Improving documentation readability 2016-08-10 12:54:34 -07:00
Abhinav Shukla
e2f850192f Italic Detection and improved documentation 2016-08-10 09:33:08 -07:00
Abhinav Shukla
5a6dfd0c18 Added correct progress display and hue image filter for colored subs 2016-08-10 06:43:58 -07:00
Abhinav Shukla
ef8141c8a9 User documentation 2016-08-10 03:39:01 -07:00
Carlos Fernandez
5a4aa337b3 Removed compile warnings. 2016-08-08 14:41:32 -07:00
Carlos Fernandez
7687576e1f Pushed version number to 0.82 2016-08-08 14:13:48 -07:00
Carlos Fernandez
8ca63e02eb Merge branch 'pr/n405_Abhinav95' 2016-08-08 14:05:23 -07:00
Carlos Fernandez
606a5a56bc Final changes for the max 80 characters correction in help screen. 2016-08-08 12:14:45 -07:00
Carlos Fernandez
af8a79757e More changes in help screen 2016-08-08 12:05:30 -07:00
Carlos Fernandez
e920c06dc0 More help screen changes. 2016-08-08 12:02:27 -07:00
Carlos Fernandez
ed8592f5f8 More changes in help screen 2016-08-08 11:59:12 -07:00
Carlos Fernandez
f5bb5fba27 More changes in help screen. 2016-08-08 11:56:56 -07:00
Carlos Fernandez
43acdce578 More help screen changes. 2016-08-08 11:55:48 -07:00
Abhinav Shukla
92b899dc2a Cleanliness is all. 2016-08-08 11:55:31 -07:00
Carlos Fernandez
f4c60c3aed More help screen corrections. 2016-08-08 11:53:41 -07:00
Carlos Fernandez
057a1d11b1 More help corrections 2016-08-08 11:42:31 -07:00
Carlos Fernandez
030635a86b help screen corrections 2016-08-08 11:36:23 -07:00
Carlos Fernandez
af248ffd24 Correction in help screen 2016-08-08 11:26:40 -07:00
Abhinav Shukla
fa60e2ad68 Fixing build error when HardsubX not enabled 2016-08-05 12:33:17 -07:00
Abhinav Shukla
b2784bd3da Dumping HardsubX parameters 2016-08-05 12:21:35 -07:00
Carlos Fernandez
8bfcb24d15 Added new lines to bitmap -> transcript 2016-08-05 11:02:46 -07:00
Abhinav Shukla
1aaf8b465f Fixing bug with time interval in packet processing 2016-08-04 00:34:58 -07:00
Abhinav Shukla
ffb85d90a3 Update Makefile to check if libav present 2016-08-03 20:09:19 -07:00
Abhinav Shukla
37d9f93eb5 Merge remote-tracking branch 'upstream/master' 2016-08-01 11:26:29 -07:00
Abhinav Shukla
39559413f5 Fix errors with classifiers, write debug display function 2016-08-01 11:19:48 -07:00
Carlos Fernandez
8c845f5135 Merge branch 'pr/n403_canihavesomecoffee' 2016-08-01 10:46:04 -07:00
Carlos Fernandez
ef7ad10fdb Merge branch 'pr/n404_Abhinav95' 2016-08-01 10:45:30 -07:00
Carlos Fernandez
e6ca4274ec Undo part of the clever capitalization stuff. Doesn't work well for TV stations that are all caps except for hard of hearing notes. 2016-08-01 10:44:44 -07:00
Abhinav Shukla
d97c51139f Freeing result iterator after a frame is processed 2016-08-01 00:02:05 -07:00
Abhinav Shukla
52dfc82054 Setting up different levels of subtitle classifiers 2016-07-31 23:54:48 -07:00
Abhinav Shukla
773fb63f92 Accurate time base conversion, changing file structure 2016-07-31 23:21:44 -07:00
Abhinav Shukla
7ce4c4008c Adding HardsubX parameter parsing 2016-07-31 22:11:13 -07:00
Abhinav Shukla
178db0a085 Merge remote-tracking branch 'upstream/master' 2016-07-31 13:51:20 -07:00
Abhinav Shukla
bc833c47dc Setting up other hardsubx parameters 2016-07-31 13:51:13 -07:00
Abhinav Shukla
617b4658b4 Creating new macro and updating Makefile, hadnling errors 2016-07-31 12:13:45 -07:00
canihavesomecoffee
98a79e0e55 Re-add the VERSION_FILE_PRESENT flag 2016-07-30 18:37:32 +02:00
Carlos Fernandez
878106386c Corrected capitalization stuff: Don't touch lines that already have both upper and lower case (i.e. assume they are correct already) and don't force new sentence between frames as that's just not correct. Long sentences will take more than one frame for sure. 2016-07-29 16:41:06 -07:00
Abhinav Shukla
3c870eef7d Freeing color detection tables 2016-07-26 23:21:27 -07:00
Abhinav Shukla
4f3d61a7eb Fixing memory leaks in frame processing 2016-07-26 23:17:14 -07:00
Carlos Fernandez
470e80a194 Minor correction in help screen 2016-07-25 16:16:05 -07:00
Abhinav Shukla
92885635ed Generating a basic, correctly timed output file with simple OCR 2016-07-23 18:18:32 -07:00
Abhinav Shukla
722cecf0d3 Resolving merge conflict with dvbcolor and syncing with upstream 2016-07-22 19:51:51 -07:00
Abhinav Shukla
6a9d7e7da2 Fixing segfault for empty OCR line 2016-07-22 17:54:32 -07:00
Abhinav Shukla
22ec6b96b2 Fixing compilation warnings for image_copy struct 2016-07-22 07:01:05 -07:00
Abhinav Shukla
0c8471438a Fixing error with invalid next size and correctly formatting SRT/VTT color output 2016-07-22 06:46:11 -07:00
Abhinav Shukla
3a74381318 Modifying API call not present in tesseract 3.03 2016-07-21 16:13:59 -07:00
Abhinav Shukla
0fcf9298bb Merge remote-tracking branch 'upstream/master' into dvbcolor 2016-07-21 15:29:12 -07:00
Carlos Fernandez
c8bd4e22a5 Added missing library for OCR 2016-07-21 14:59:56 -07:00
Carlos Fernandez
a918bc2798 Added OCR to linux build script
Skip another to the SCTE 57 2003 sections in PMT
2016-07-21 14:56:17 -07:00
Abhinav Shukla
9d81498bd9 Moving tesseract handle to hardsubx ctx 2016-07-21 14:54:33 -07:00
Abhinav Shukla
a2eced9201 Color output in <font> tags for SRT and WebVTT 2016-07-20 12:08:42 -07:00
Abhinav Shukla
36b08c5d74 Working color detection and output for SRT from DVB 2016-07-19 19:25:46 -07:00
Abhinav Shukla
f280feff65 Passing DVB region background color 2016-07-16 06:16:42 -07:00
Abhinav Shukla
f37e944ac4 Fixed errors in word color recognition 2016-07-09 20:39:38 -07:00
Abhinav Shukla
cf281c22ce Detecting color of every word 2016-07-07 19:42:10 -07:00
Abhinav Shukla
4d8cb4d4d4 Creating copy of image before quantization 2016-07-07 15:15:59 -07:00
Abhinav Shukla
7426841b5e Basic structure for color detection in DVB 2016-07-07 04:00:20 -07:00
Abhinav Shukla
89efdb6178 Sauvola Binarization, color independent thresholding 2016-07-06 19:15:44 -07:00
Abhinav Shukla
a37a08ef70 Merge remote-tracking branch 'upstream/master' 2016-07-06 19:08:34 -07:00
Carlos Fernandez
db80caf74a - WebVTT from DVB
- Added X-TIMESTAMP-MAP to the WebVTT header
2016-07-06 12:18:40 -07:00
Carlos Fernandez
672010711d spung: Embedded OCR comments inside the spupng tags (instead of below), much more readable. 2016-07-05 15:20:28 -07:00
Carlos Fernandez
a4cea54db8 Passed CRLF to OCR 2016-07-05 14:48:54 -07:00
Carlos Fernandez
ddbf8124a8 Merge branch 'pr/n399_canihavesomecoffee' 2016-07-05 10:34:22 -07:00
canihavesomecoffee
5655db6cd2 Update Linux & Mac build
Update the Linux & Mac build to reflect the changes made for the version
file.
2016-07-05 18:10:19 +02:00
canihavesomecoffee
c764ced536 Update compile info 2016-07-05 18:05:44 +02:00
canihavesomecoffee
9f4bff884f Update build script for windows
-
2016-07-05 18:01:47 +02:00
canihavesomecoffee
b002d58259 Updates git ignore for new file
Add a git ignore for the "real" dynamic header file, remove the ignore
for the other one.
2016-07-05 17:57:47 +02:00
Anshul Maheshwari
bdf3f6d833 close #394 Illegal .srt being created from DVBs 2016-07-03 23:59:19 +05:30
Anshul Maheshwari
7f183193d5 resolve Tesseract fail cause spngpng to fail #391
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2016-07-03 23:03:23 +05:30
Anshul Maheshwari
d3ae186f6b Merge remote-tracking branch 'origin/master' 2016-07-03 13:05:09 +05:30
Anshul Maheshwari
18cd92e5a8 close #397 Incorrect progress display 2016-07-03 13:04:17 +05:30
Abhinav Shukla
0e4281d4a2 Merge remote-tracking branch 'upstream/master' 2016-06-30 14:29:04 -07:00
Abhinav Shukla
7d19fa971d Setting up encoder 2016-06-30 14:19:50 -07:00
Anshul Maheshwari
a66c5aae06 Correcting y offset 2016-06-28 23:25:20 +05:30
Anshul Maheshwari
eea1792f0e Fix memory leakage in spupng
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2016-06-27 00:54:44 +05:30
Anshul Maheshwari
e6bd773762 Fixing missing lines in spupng
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2016-06-27 00:33:06 +05:30
Abhinav Shukla
98f1e15666 Limiting sutitle region to bottom 25% of the frame 2016-06-21 07:31:01 -07:00
Abhinav Shukla
c61e787bca Midterm evaluation - initial code 2016-06-21 06:48:10 -07:00
Abhinav Shukla
2dfa3778cb Added seeking to a frame at a particular time instead of linear iteration 2016-06-16 04:57:21 -07:00
Abhinav Shukla
d99dc4c6f8 Setting up binary neighbourhood search workflow and other helpers 2016-06-15 17:01:44 -07:00
Abhinav Shukla
8507a842be Added HSV colorspace conversion 2016-06-15 16:25:39 -07:00
Abhinav Shukla
8e5b9b2655 Merge remote-tracking branch 'upstream/master' 2016-06-14 12:02:08 -07:00
Abhinav Shukla
954724e12a Added vertical edge detection and morphology to get subtitle ROI 2016-06-14 11:59:10 -07:00
Carlos Fernandez
97dd511452 Merge branch 'pr/n390_rkuchumov' 2016-06-14 10:57:09 -07:00
Kuchumov Ruslan
93b1e64896 skipping redundant bytes at the end of tx3g atom 2016-06-14 09:44:35 +03:00
Carlos Fernandez
933dc50c62 Updates CHANGES.TXT 2016-06-13 12:00:46 -07:00
Kuchumov Ruslan
8b740f4af2 void atom hotfix 2016-06-12 19:59:22 +03:00
Abhinav Shukla
13db1dfbfa Fixing error with frame numbers of parsed packets, now parsing video only 2016-06-09 16:31:25 -07:00
Carlos Fernandez
03cd838ff4 Fixed some of the legit warnings from Visual Studio. 2016-06-09 14:16:37 -07:00
Abhishek Vinjamoori
c8aa7b17a7 Corrected initialisation of two variables related to stats 2016-06-09 23:56:01 +05:30
Carlos Fernandez
67fb6235f4 - Fix for signal support (for file rotation) in linux
- Add hack to ignore table_id=0xc0 (Program Information) in PMT without ignoring the full PMT.
2016-06-08 17:54:56 -07:00
Carlos Fernandez
7d5f8031ca Merge branch 'pr/n379_abhishek-vinjamoori' 2016-06-08 10:30:36 -07:00
canihavesomecoffee
b8eec82f2a Update file to copy necessary DLL to output folder
Updates the project file to copy the two DLL's after compiling, so that
we can run from that directory.
2016-06-08 02:50:23 +02:00
canihavesomecoffee
04be7be06b Add OCR build support
Adds OCR build support by creating two new build configs (one debug, one
release) and some instructions about what VS expects on those configs.
2016-06-08 02:25:13 +02:00
Abhishek Vinjamoori
b224b57a43 Added feature list to CHANGES.txt 2016-06-08 00:06:20 +05:30
Abhishek Vinjamoori
f764e23881 Corrected closing of files issue. 2016-06-07 23:55:25 +05:30
Abhishek Vinjamoori
8fefe8c1b3 Fixed memory issues caused by strdup. 2016-06-07 12:47:36 +05:30
Abhishek Vinjamoori
dd93e9d672 Corrected append parameter assignment 2016-06-07 01:27:48 +05:30
Abhishek Vinjamoori
7b69100de9 Changed append parameter into ccx_s_write struct 2016-06-07 00:26:46 +05:30
Abhishek Vinjamoori
9819dbe0c1 Merge remote-tracking branch 'upstream/master' into Rotation 2016-06-06 23:07:03 +05:30
Abhishek Vinjamoori
6a5bb8bab4 Corrected the conditional statement error. File always in create mode 2016-06-06 23:06:41 +05:30
Carlos Fernandez
48878185de Merge branch 'pr/n382_canihavesomecoffee' 2016-06-06 10:24:08 -07:00
Abhishek Vinjamoori
9c5d3cdde1 Added --append paramter for preventing overwriting of files. 2016-06-05 01:26:29 +05:30
canihavesomecoffee
6ea677cd7a Move debug statement to more appropriate location
Now shows reset count for every file switched instead of keeping it
once. Also closes #375
2016-06-04 20:42:18 +02:00
canihavesomecoffee
05e451d41e Rename ccextractor to ccextractorwin for compilation 2016-06-04 20:40:34 +02:00
Abhishek Vinjamoori
ff41c56e82 Removed string errors 2016-06-04 16:53:53 +05:30
Abhishek Vinjamoori
554c1077a0 Modified rotation renaming 2016-06-04 16:09:22 +05:30
Abhinav Shukla
bc40119b72 Basic text output 2016-06-03 12:55:56 -07:00
Abhinav Shukla
65587815ff Basic video frame processing with ffmpeg 2016-06-02 13:57:08 -07:00
Abhinav Shukla
c3eabcfd96 Setting up ffmpeg frame processing (-s in the Makefile to reduce executable size) 2016-06-01 17:37:58 -07:00
Abhishek Vinjamoori
fa563c6542 Removed another debugging statement 2016-06-01 13:26:40 +05:30
Abhishek Vinjamoori
7219f91648 Checked for errors and returning original encoder in such cases. Removed debug statements 2016-06-01 13:21:31 +05:30
Abhishek Vinjamoori
8d22988808 Modified a few parameters. Now feature works fine 2016-06-01 12:50:59 +05:30
Abhishek Vinjamoori
6f249c92d6 File rotation feature 2016-06-01 02:17:55 +05:30
Abhinav Shukla
204543af9a Setting up preliminary HardsubX context 2016-05-30 14:38:50 -07:00
Abhinav Shukla
c8345643c6 Adding HardsubX workflow 2016-05-30 10:44:55 -07:00
Carlos Fernandez
4a61570a50 On missing headers don't dump the payload by default. 2016-05-27 17:29:48 -07:00
Carlos Fernandez
57b060b15d Added -sem to CHANGES.TXT 2016-05-27 17:16:09 -07:00
Carlos Fernandez
c31b3e823f Add more details on "premature end of file" condition 2016-05-27 16:43:58 -07:00
Carlos Fernandez
5d3aa26cdc Detailed premature end of file error on cut TS 2016-05-27 12:16:27 -07:00
Carlos Fernandez
0b2e12ce0c Changed target to XP 2016-05-27 10:45:27 -07:00
Carlos Fernandez
3a6ed7a243 Added -sem to create a semaphore file when we have an open file so external tools won't move or delete files before they are ready. 2016-05-27 10:43:27 -07:00
Carlos Fernandez
2541666333 Merge branch 'pr/n372_canihavesomecoffee' 2016-05-26 15:11:49 -07:00
Abhinav Shukla
5bcb974b96 Fixes #353 - Memory consumption reduced by 180 MB 2016-05-26 14:37:02 -07:00
Abhinav Shukla
5c65ccc12b Fixing high memory usage 2016-05-26 13:23:10 -07:00
canihavesomecoffee
61ee4b25fe Fixing warnings
- Removed unused variables
- Renamed remainder variables to better name
- Moved sha256_buf to external to avoid C4127 warning
2016-05-26 10:40:19 +02:00
Carlos Fernandez
35017de391 Fix: For MP4 files on multiple inputs CCExtractor was processing always the first file (due to using a hardcoded 0) 2016-05-25 18:38:14 -07:00
Carlos Fernandez
5efe51720c Merge branch 'pr/n367_abhishek-vinjamoori' 2016-05-25 13:28:47 -07:00
canihavesomecoffee
410c39986b Gitignore remove blank line
-
2016-05-25 21:06:37 +02:00
canihavesomecoffee
928f57bd4c Small fix added
-
2016-05-25 20:59:27 +02:00
canihavesomecoffee
6b0e57f07d Update files to reflect upcoming .81
-
2016-05-25 20:58:42 +02:00
Abhishek Vinjamoori
111258d2f0 Removed EXIT variables 2016-05-25 22:26:14 +05:30
Carlos Fernandez
db1fab51f4 Merge branch 'pr/n351_abhishek-vinjamoori' 2016-05-25 08:11:17 -07:00
Abhishek Vinjamoori
04893f4347 Changed the return variable directly without checking 2016-05-25 11:21:52 +05:30
Abhinav Shukla
e1083a030c Removing debug print statement 2016-05-24 10:13:09 -07:00
Abhinav Shukla
fa373115ad Fixing wrong function prototype 2016-05-24 10:05:20 -07:00
Abhinav Shukla
4b8f14eab1 Fixes #139 - Case fixing in teletext 2016-05-24 09:36:49 -07:00
Abhishek Vinjamoori
653795ceef Fixes #315. Force File Buffer Flushing issue. 2016-05-23 23:23:14 +05:30
Abhishek Vinjamoori
115a6103d4 Completed the other statistics 2016-05-23 17:59:49 +05:30
canihavesomecoffee
a238352fb3 Changing file permissions (attempt 2) 2016-05-23 11:57:06 +02:00
canihavesomecoffee
1322f89fcd Fixes
- pre-build.sh executable by default now
- git ignore updated so the updated compile_info.h won't show up when
it's being changed after building CCExtractor
2016-05-23 11:52:46 +02:00
canihavesomecoffee
c1ec393bed Better small file fix
Not calculating every time, but once the file is opened, using existing
code.
2016-05-22 17:56:39 +02:00
canihavesomecoffee
243cd64d56 Merge remote-tracking branch 'CCExtractor/master' 2016-05-22 11:38:14 +02:00
canihavesomecoffee
e06be2d2f1 Manual implementation of York He Fix
-
2016-05-22 11:35:12 +02:00
Carlos Fernandez
8cfbf87420 Merge branch 'pr/n362_Abhinav95' 2016-05-22 01:30:12 -07:00
canihavesomecoffee
ff3be07df5 Add linux/mac build scripts
-
2016-05-22 09:44:55 +02:00
canihavesomecoffee
a0787e740e Add windows pre-build event
Updates the .h file that contains the build date & git commit hash (if
available)
2016-05-22 08:13:53 +02:00
canihavesomecoffee
e5b21a3a91 Adds --version parameter
Start of the --version parameter. Displays version & file hash already,
git commit & compilation date not yet finished.
2016-05-22 03:50:16 +02:00
canihavesomecoffee
f694c95510 Add hashing library and update makefiles
- Adds a open-source hashing lib for SHA2 (SHA-256, SHA-386, SHA-512)
from http://www.aarongifford.com/computers/sha.html, with some small
modifications to make it work unders windows too
- Updates build commands to reflect this change
2016-05-22 03:49:31 +02:00
canihavesomecoffee
b5731a279a Add compile info header
Will be used to show compilation date & git commit if they're available
2016-05-22 03:47:17 +02:00
canihavesomecoffee
6bb86efa97 Add VS extension to gitignore 2016-05-22 03:45:53 +02:00
Abhinav Shukla
c54027562f Updating CHANGES.txt 2016-05-21 14:42:46 -07:00
Abhinav Shukla
a2163adc95 Merge remote-tracking branch 'upstream/master' 2016-05-21 14:00:57 -07:00
Abhinav Shukla
73c35ccb30 Correcting display of sub mode and info in transcripts 2016-05-21 13:59:27 -07:00
Carlos Fernandez
bcfdda5f8d Merge branch 'pr/n357_gshruti95' 2016-05-20 19:06:52 -07:00
Abhinav Shukla
1dd5e3089c Fix #359 - Teletext page number in -ucla 2016-05-19 12:06:58 -07:00
Shruti
74c1d6d30d Fixes #354 : Excessive XDS notices 2016-05-10 19:55:47 +05:30
Shruti
0579d7d8d7 Fixes #354 : Excessive XDS notices 2016-05-10 19:51:08 +05:30
Shruti
1d31c784e7 Fixes #354 : Excessive XDS notices 2016-05-10 19:50:16 +05:30
Abhishek Vinjamoori
0de521f22b Fixed No preview in GUI versions. 2016-04-21 00:58:49 +05:30
Abhishek Vinjamoori
c027b449cf Fixes issue #285. Added Previews which were missing after refactoring 2016-04-17 19:13:12 +05:30
David Liontooth
b385fa74b0 Update build.command
Include zvbi to fix #346
2016-04-16 16:17:47 -07:00
cfsmp3
0427878dbd Merge branch 'pr/n348_Abhinav95' 2016-03-29 18:25:37 +02:00
Abhinav Shukla
93797023e3 Fixing error in setting xds_write_to_file 2016-03-28 15:02:38 -07:00
Abhinav Shukla
02cd11ec7c Fixing xds_write_to_file 2016-03-28 13:25:44 -07:00
Abhinav Shukla
edc3d85cd5 Minor Refactoring 2016-03-28 13:22:12 -07:00
Abhinav Shukla
0e9d0e6e46 Fixing problems with XDS 2016-03-28 11:50:40 -07:00
cfsmp3
07e9d8a04e Merge branch 'pr/n343_at25sep' 2016-03-28 12:42:32 +02:00
cfsmp3
524ec68a63 Merge branch 'pr/n329_abhishek-vinjamoori' 2016-03-25 19:43:37 +01:00
canihavesomecoffee
046fd4c435 Fix windows build
Fixes windows build by adding zvbi folder to includes
2016-03-21 23:08:21 +01:00
at25sep
2fb03f3af3 Fix #257 2016-03-21 12:14:54 +05:30
cfsmp3
cd4267bc2e Merge branch 'pr/n336_Abhinav95' 2016-03-19 11:16:13 +01:00
Abhinav Shukla
48c4306cdc Fixing naming and indent 2016-03-19 02:58:32 -07:00
cfsmp3
63fd4ad847 Merge branch 'pr/n324_YorkHe' 2016-03-18 09:51:37 +01:00
cfsmp3
2cf86d46ff Merge branch 'pr/n331_at25sep' 2016-03-18 09:49:36 +01:00
bigharshrag
3c3f7afb32 Fix * displaying instead of @ 2016-03-18 10:43:22 +05:30
Abhinav Shukla
a046be0ebb Fixing issue of timestamp not incrementing if global timestamp not initialized (+ removing errors in last commit) 2016-03-17 16:54:59 -07:00
cfsmp3
dc2af919eb Merge branch 'pr/n335_bigharshrag' 2016-03-17 23:05:00 +01:00
bigharshrag
23b7470daf Bugfixes for Latin G2 subset
Bug fix for accented latin characters

Bugfixes for Latin G2 subsets and accented characters
2016-03-18 02:26:41 +05:30
Abhinav Shukla
78585c84b4 ISDB timestamps now incrementing by setting current timestamp to the FTS 2016-03-17 08:30:36 -07:00
Abhinav Shukla
02b93fa73f ISDB - Fixing end timestamp and ignoring teletext page value NA in -ucla 2016-03-16 16:19:33 -07:00
cfsmp3
3c6aff704c Added CR 2016-03-16 18:18:01 +01:00
cfsmp3
beeb797b6e Merge branch 'pr/n328_abhishek-vinjamoori' 2016-03-16 18:16:56 +01:00
cfsmp3
d275463039 Removed double space (trivial change) 2016-03-16 17:32:25 +01:00
Abhinav Shukla
51dae0ba8d Fixing broken end timestamp in -ucla (Removing unnecessary changes) 2016-03-16 09:16:59 -07:00
Abhinav Shukla
850f5f98b6 Fixing broken end timestamp in -ucla 2016-03-16 09:08:34 -07:00
Abhishek Vinjamoori
0424a474bc Fixed Segfault while parsing unterminated outinterval(without paramters) 2016-03-16 21:23:37 +05:30
at25sep
37496f8a1a typo mistake 2016-03-16 19:57:47 +05:30
at25sep
02593c9867 mfra mp4 box weight changed to 1 #273 2016-03-16 19:55:21 +05:30
Abhishek Vinjamoori
79ab53876c Target file NULL fixed 2016-03-16 11:44:41 +05:30
Abhishek Vinjamoori
a917695029 Fixed SegFaults while parsing parameters. Fixes issue #326 2016-03-16 10:55:26 +05:30
Neha Bagari
b2bfebce6f Check for number of args
Fixes #326

Usage of -codec and -nocodec options at the end without any following option
gives 'Segmentation fault'.

Added checks to overcome this.

Signed-off-by: Neha Bagari <neha.bagari.eee11@iitbhu.ac.in>
2016-03-16 09:52:23 +05:30
York
5b5f358919 Referring Issue #270. Detailed opening file error message 2016-03-14 19:38:49 +08:00
cfsmp3
92df11162c Merge branch 'pr/n307_Aesmade' 2016-03-14 10:23:58 +01:00
cfsmp3
6feef59d75 Replaced OSX build.command by a new one submitted by email by Alex Karahalios <alex@karahalios.org> 2016-03-14 09:58:22 +01:00
cfsmp3
944c6d25a2 Merge branch 'pr/n319_bigharshrag' 2016-03-13 19:21:53 +01:00
cfsmp3
9e94520a54 Merge branch 'pr/n317_Abhinav95' 2016-03-13 18:41:34 +01:00
bigharshrag
d249b1cf1b Added Cyrillic support (+ removed debugging statements) 2016-03-13 20:37:50 +05:30
bigharshrag
5661e4f37b Added Cyrilic support 2016-03-13 20:20:55 +05:30
bigharshrag
e8ae2874d6 Testing first buffer error 2016-03-13 19:48:47 +05:30
bigharshrag
f3c386f729 Clearer code 2016-03-13 17:32:43 +05:30
bigharshrag
03b8f93e04 Partial fix for Cyrilic support 2016-03-13 04:51:16 +05:30
bigharshrag
2a583883dc Partial fix for Cyrilic support 2016-03-13 04:48:22 +05:30
Abhinav Shukla
1cee9200b2 Fixing broken links 2016-03-12 05:31:32 -08:00
barun511
c634cf5ada Fixed a typo
The command that was ccextrator "name of input" should have been ccextractor "name of input"
2016-03-12 15:40:53 +05:30
Abhinav Shukla
804c6414ee Merge remote-tracking branch 'upstream/master' 2016-03-11 10:14:56 -08:00
Abhinav Shukla
0cc9642851 Removing changes to string_cmp2 2016-03-11 09:52:20 -08:00
Nikos Filippakis
286398c15d Added --forceflush (-ff) option for forcing a flush on the output buffer whenever content is written, closes #306 2016-03-11 14:10:00 +02:00
Nikos Filippakis
d0b57ecb1f Fix issue #274, caused by commit 8d073accd4 2016-03-09 18:16:21 +02:00
cfsmp3
5b11c6a5c6 Merge branch 'pr/n294_abhishek-vinjamoori' 2016-03-09 07:53:16 +01:00
cfsmp3
90c8da76bd Merge branch 'pr/n302_vinayakathavale' 2016-03-09 07:46:44 +01:00
York
e87ed5ba1c fix issue #288 2016-03-09 14:30:01 +08:00
York
1aa9a7c4d9 Merge remote-tracking branch 'upstream/master' into fallout 2016-03-09 14:04:08 +08:00
vinayak
509cb9839d Made code ISO/IEC 14496-12:2015 compliant 2016-03-09 11:06:10 +05:30
Abhinav Shukla
0089901b07 Fixed segfault on using -sc for a blank line 2016-03-08 07:45:50 -08:00
cfsmp3
877ee7b2c7 Fix fflush() segfault 2016-03-08 08:55:55 +01:00
cfsmp3
d117dacf0f fflush() after writing subtitles 2016-03-08 15:03:57 +08:00
York
1ea58bd200 Revert "fflush() after writing subtitles"
This reverts commit 4d4af9ff7f.
2016-03-08 15:01:20 +08:00
cfsmp3
dcc8af915f Merge branch 'pr/n292_abhishek-vinjamoori' 2016-03-07 18:33:40 +01:00
cfsmp3
4d4af9ff7f fflush() after writing subtitles 2016-03-07 10:15:26 +01:00
YorkHe
a9a861e8f2 Fix CMakeLists.txt 2016-03-07 14:44:49 +08:00
=
ab70c8b382 Additional Argument added to sprintf giving the correct format specifier. 2016-03-06 23:24:57 +05:30
=
d8e99ef810 Fixed format specifier for uint64_t 2016-03-06 20:15:11 +05:30
=
c92e92f73d Fixed function declaration issues in lib_ccx.h(Funciton defined in output.c) 2016-03-06 19:55:40 +05:30
Willem
d3862ba88b Fix path
-
2016-03-05 13:19:20 +01:00
Anshul Maheshwari
0023c6545b make code windows compatible
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2016-02-17 21:13:09 +05:30
Anshul Maheshwari
2ca835ea1b update linux build scripts
Signed-off-by: Anshul Maheshwari <anshul.ffmpeg@gmail.com>
2016-02-09 16:27:49 +01:00
Anshul Maheshwari
20859d3ee7 Adding GXF support
Signed-off-by: Anshul Maheshwari <anshul.ffmpeg@gmail.com>
2016-02-09 16:12:15 +01:00
Carlos Fernandez
e79700ea93 added -koc (keep output closed) for -simplexml. 2016-02-05 10:25:11 -08:00
Carlos Fernandez
e02d9bd98b Merge branch 'pr/n272_anshul1912' 2016-01-31 06:57:58 -08:00
Anshul Maheshwari
d7136a8390 Move FFmpeg demuxer in cc_demuxer from ccextractor
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2016-01-28 17:49:42 +05:30
cfsmp3
e1d8da9d37 Merge branch 'pr/n267_anshul1912' 2016-01-23 09:15:21 +01:00
cfsmp3
cfecd67500 Added GPL 2 to the document directory 2016-01-23 09:14:26 +01:00
Anshul Maheshwari
26623b2428 Merge branch 'master' of https://github.com/anshul1912/ccextractor 2016-01-20 16:33:09 +05:30
Anshul Maheshwari
44d9117d8d reverted back the changes for issue #269
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2016-01-20 16:31:25 +05:30
Anshul Maheshwari
31de878ea7 error check before file open
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2016-01-16 14:10:19 +05:30
cfsmp3
9768555e7c Added g608 explanation document. 2016-01-09 18:07:30 +01:00
cfsmp3
72e422d76e Correct minor warning. Added release date to CHANGES.TXT 2016-01-09 17:52:07 +01:00
cfsmp3
8860be13e4 Versión number bump 2016-01-09 15:35:33 +01:00
Anshul Maheshwari
3b7ad97f0a newline at start of print
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2016-01-09 19:22:07 +05:30
Anshul Maheshwari
5e305f2769 print total_frames_time only when atsc caption
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2016-01-09 19:20:28 +05:30
cfsmp3
0a798606ee Added --noscte20 option to help screen. 2016-01-09 11:15:28 +01:00
Anshul Maheshwari
3775daf36c Added --noscte20 close #244
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2016-01-09 15:29:51 +05:30
Anshul Maheshwari
8c5de01034 Add --nohtmlescape
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2016-01-08 11:21:14 +05:30
Anshul Maheshwari
1c352e67e4 Add --nohtmlescape
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2016-01-08 11:20:29 +05:30
Anshul Maheshwari
79838077f2 cleanup telexcc
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2016-01-08 11:03:52 +05:30
Anshul Maheshwari
058bb83a25 updated CHANGE for bugs resolved
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2016-01-07 16:11:19 +05:30
Anshul Maheshwari
d2f840bb36 portable conversion of number to character
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2016-01-07 15:14:59 +05:30
Anshul Maheshwari
a576c90f4e G608 encoder file
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2016-01-07 14:51:33 +05:30
Anshul Maheshwari
a1bd01de5f Added g608 support
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2016-01-07 14:46:44 +05:30
Anshul Maheshwari
9a5e817f36 Add -h and --help option
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2016-01-04 16:11:33 +05:30
Anshul Maheshwari
bc20bc3f45 print teletext number of packet processed
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2016-01-04 16:01:36 +05:30
Anshul Maheshwari
783a6e2aa0 Remove False Message for Teletext
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2016-01-04 15:35:29 +05:30
Anshul Maheshwari
992c56b262 no xml header when teletext
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2016-01-04 15:14:06 +05:30
Anshul Maheshwari
c674cef79e Remove seg-fault at invalid mp4 detection
Signed-off-by: Anshul Maheshwari <er.anshul.maheshwari@gmail.com>
2016-01-01 16:04:23 +05:30
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
192 changed files with 45345 additions and 14238 deletions

17
.gitignore vendored
View File

@@ -9,10 +9,25 @@ CVS
*.o
linux/ccextractor
linux/depend
windows/debug/*
windows/Debug/**
windows/Release/**
build/
####
# Visual Studio project Ignored files
*.suo
*.sdf
*.opensdf
*.user
*.opendb
####
# Ignore the header file that is updated upon build
src/lib_ccx/compile_info_real.h
#### Ignore windows OCR libraries and folders
windows/libs/leptonica/**
windows/libs/tesseract/**
windows/Release-OCR/**
windows/Debug-OCR/**

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.75
V = 0.77
DISTFILES = ccextractor.${V:S/.//}-src.zip
MASTER_SITES = ${MASTER_SITE_SOURCEFORGE:=ccextractor/}
DISTNAME = ccextractor-$V

View File

@@ -1,12 +1,12 @@
ccextractor
===========
Carlos' version (mainstream) is most stable branch.
Carlos' version (mainstream) is the most stable branch.
Extracting subtitles were never so easy then following command:
ccextrator "name of input"
Extracting subtitles has never been so easy. Just type the following command:
ccextractor "name of input"
Gui lovers please download Sorceforge version of CCExtractor, Git Version is not your cup of tea.
GUI lovers should download the Sourceforge 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,5 +1,92 @@
0.75
-----------
0.82(2016-08-15)
-----------------
- New: HardsubX - Burned in subtitle extraction subsystem.
- New: Color Detection in DVB Subtitles
- Fix: Corrected sentence capitalization
- Fix: Skipping redundant bytes at the end of tx3g atom in MP4
- Fix: Illegal SRT files being created from DVB subtitles
- Fix: Incorrect Progress Display
0.81 (2016-06-13)
-----------------
- New: --version parameter for extensive version information (version number, compile date, executable hash, git commit (if appropriate))
- New: Add -sem (semaphore) to create a .sem file when an output file is open and delete it when it's closed.
- New: Add --append parameter. This will prevent overwriting of existing files.
- New: File Rotation support added. The user has to send a USR1 signal to rotate.
- Fix: Issues with files <1 Mb
- Fix: Preview of generated transcript.
- Fix: Statistics were not generated anymore.
- Fix: Correcting display of sub mode and info in transcripts.
- Fix: Teletext page number displayed in -UCLA.
- Fix: Removal of excessive XDS notices about aspect ratio info.
- Fix: Force Flushing of file buffers works for all files now.
- Fix: mp4 void atoms that was causing some .mp4 files to fail.
- Fix: Memory usage caused by EPG processing was high due to many non-dynamic buffers.
- Fix: Project files for Visual Studio now include OCR support in Windows.
0.80 (2016-04-24)
-----------------
- Fix: "Premature end of file" (one of the scenarios)
- Fix: XDS data is always parsed again (needed to extract information such as program name)
- Fix: Teletext parsing: @ was incorrectly exported as * - X/26 packet specifications in ETS 300 706 v1.2.1 now better followed
- Fix: Teletext parsing: Latin G2 subsets and accented characters not displaying properly
- Fix: Timing in -ucla
- Fix: Timing in ISDB (some instances)
- Fix: "mfra" mp4 box weight changed to 1 (this helps with correct file format detection)
- Fix: Fix for TARGET File is null.
- Fix: Fixed SegFaults while parsing parameters (if mandatory parameter is not present in -outinterval, -codec or -nocodec)
- Fix: Crash when input small is too small
- Fix: Update some URLs in code (references to docs)
- Fix: -delay now updates final timestamp in ISDB, too
- Fix: Removed minor compiler warnings
- Fix: Visual Studio solution files working again
- Fix: ffmpeg integration working again
- New: Added --forceflush (-ff). If used, output file descriptors will be flushed immediately after being written to
- New: Hexdump XDS packets that we cannot parse (shouldn't be many of those anyway)
- New: If input file cannot be open, provide a decent human readable explanation
- New: GXF support
0.79 (2016-01-09)
-----------------
- Support for Grid Format (g608)
- Show Correct number of teletext packet processed
- Removed Segfault on incorrect mp4 detection
- Remove xml header from transcript format
- Help message updated for Teletext
- Added --help and -h for help message
- Added --nohtmlescape option
- Added --noscte20 option
0.78 (2015-12-12)
-----------------
- Support to extract Closed Caption from MultiProgram at once.
- 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
@@ -7,8 +94,8 @@
builds don't add it (because it messes with text processing tools).
You can use -bom and -nobom to change the behaviour.
0.74
-----------
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
@@ -17,19 +104,19 @@
- 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
-----------
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
-----------
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
@@ -39,8 +126,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
@@ -80,8 +167,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.
@@ -100,8 +187,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.
@@ -115,8 +202,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.
@@ -136,8 +223,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
@@ -215,8 +302,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)
@@ -234,8 +321,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
@@ -255,8 +342,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
@@ -264,8 +351,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
@@ -287,8 +374,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.
@@ -298,8 +385,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.
@@ -309,8 +396,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.
@@ -338,8 +425,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.
@@ -363,18 +450,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.
@@ -389,8 +476,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
@@ -403,8 +490,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.
@@ -430,8 +517,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
@@ -456,14 +543,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,
@@ -480,8 +567,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.
@@ -494,9 +581,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
@@ -516,8 +602,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
@@ -528,8 +614,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
@@ -537,16 +623,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.
@@ -558,15 +644,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.
@@ -599,8 +685,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
@@ -630,8 +716,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.
@@ -640,8 +726,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
@@ -692,8 +778,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
@@ -712,8 +798,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,
@@ -732,8 +818,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.
@@ -741,20 +827,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.
@@ -763,20 +849,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
@@ -786,8 +872,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).
@@ -801,8 +887,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
@@ -813,8 +899,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
@@ -831,8 +917,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
@@ -843,8 +929,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
@@ -852,8 +938,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
@@ -866,8 +952,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/G608.TXT Normal file
View File

@@ -0,0 +1,58 @@
G608
====
G608 (for grid 608) is generated by CCExtractor by using -out=g608.
This is a verbose format that exports the contents of the 608 grid verbatim
so there's no loss of positioning or colors due the limitations or complexy
or other output formats.
G608 is a text file with a structure based on .srt and looks like this:
1
00:00:02,019 --> 00:00:03,585
99999999999999999999999999999999RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR
99999999999999999999999999999999RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR
99999999999999999999999999999999RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR
99999999999999999999999999999999RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR
99999999999999999999999999999999RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR
99999999999999999999999999999999RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR
99999999999999999999999999999999RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR
99999999999999999999999999999999RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR
99999999999999999999999999999999RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR
99999999999999999999999999999999RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR
99999999999999999999999999999999RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR
99999999999999999999999999999999RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR
99999999999999999999999999999999RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR
- Previously on The Tudors... 90000000000000000000000000000009RIIIIIIIIIIIIIIIIRRRRRRRRRRRRRRR
- Your Holy Father offs you 99000000000000000000000000000999RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR
For each subtitle frame there's exactly 15 rows (which represent the 15 rows of the 608 screen)
of 96 characters each.
Each row is divided in 3 blocks: 32 characters for the text, 32 characters for the color, and
32 characters for the font.
The possible color values are:
COL_WHITE = 0,
COL_GREEN = 1,
COL_BLUE = 2,
COL_CYAN = 3,
COL_RED = 4,
COL_YELLOW = 5,
COL_MAGENTA = 6,
COL_USERDEFINED = 7,
COL_BLACK = 8,
COL_TRANSPARENT = 9
And the possible font values are:
R => Regular
I => Italic
U => Underlined
B => Underlined + italic
If a 'E' is found in ether color or font that means a bug in CCExtractor. Should you ever get
an E please send us a .bin file that causes it.
This format is intended for post processing tools that need to represent the output of a 608
decoder accurately but that don't want to deal with the madness of other more generic subtitle
formats.

45
docs/HARDSUBX.txt Normal file
View File

@@ -0,0 +1,45 @@
Overview
========
Subtitles which are burned into the video (or hard subbed) can be extracted using the -hardsubx flag.
The system works by processing video frames and extracting only the subtitles from them, followed
by an OCR recognition using Tesseract.
Dependencies
============
Tesseract (OCR library by Google)
Leptonica (C Image processing library)
FFMpeg (Video Processing Library)
Compilation
===========
Linux
-----
Make sure Tesseract, Leptonica and FFMPeg are installed, and that their libraries can be found using pkg-config.
Refer to OCR.txt for installation details.
To install FFmpeg (libav), follow the steps at:-
https://trac.ffmpeg.org/wiki/CompilationGuide/Ubuntu - For Ubuntu, Debian and Linux Mint
https://trac.ffmpeg.org/wiki/CompilationGuide/Generic - For generic Linux compilation
To validate your FFMpeg installation, make sure you can run the following commands on your terminal:-
pkg-config --cflags libavcodec
pkg-config --cflags libavformat
pkg-config --cflags libavutil
pkg-config --cflags libswscale
pkg-config --libs libavcodec
pkg-config --libs libavformat
pkg-config --libs libavutil
pkg-config --libs libswscale
On success, you should see the correct include directory path and the linker flags.
To build the program with hardsubx support, from the linux directory run:-
make ENABLE_HARDSUBX=yes
Windows
-------
Coming Soon

View File

@@ -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
@@ -57,11 +58,8 @@ 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.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.75
ccextractor, 0.81
-----------------
Authors: Carlos Fernández (cfsmp3), Volker Quetschke.
Maintainer: cfsmp3
@@ -14,10 +14,19 @@ You can subscribe to new releases notifications at freshmeat:
http://freshmeat.net/projects/ccextractor
Google Summer of Code 2014 students
- Willem van iseghem
- Willem Van Iseghem
- 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.

339
docs/gpl-2.0.txt Normal file
View File

@@ -0,0 +1,339 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
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.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License.

View File

@@ -24,5 +24,8 @@ 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

@@ -2,9 +2,10 @@ SHELL = /bin/sh
CC = gcc
SYS := $(shell gcc -dumpmachine)
CFLAGS = -O3 -std=gnu99
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
CFLAGS = -O3 -std=gnu99 -s
INCLUDE = -I../src/gpacmp4/ -I../src/libpng -I../src/lib_hash -I../src/zlib -I../src/lib_ccx -I../src/.
INCLUDE += -I../src/zvbi
ALL_FLAGS = -Wno-write-strings -D_FILE_OFFSET_BITS=64 -DVERSION_FILE_PRESENT
LDFLAGS = -lm
ifneq (, $(findstring linux, $(SYS)))
@@ -13,7 +14,7 @@ endif
TARGET = ccextractor
OBJS_DIR = objs
VPATH = ../src:../src/gpacmp4:../src/libpng:../src/zlib:../src/lib_ccx
VPATH = ../src:../src/gpacmp4:../src/libpng:../src/zlib:../src/lib_ccx:../src/zvbi:../src/lib_hash
SRCS_DIR = ../src
SRCS_C = $(wildcard $(SRCS_DIR)/*.c)
@@ -27,6 +28,10 @@ SRCS_PNG_DIR = $(SRCS_DIR)/libpng
SRCS_PNG = $(wildcard $(SRCS_PNG_DIR)/*.c)
OBJS_PNG = $(SRCS_PNG:$(SRCS_PNG_DIR)/%.c=$(OBJS_DIR)/%.o)
SRCS_ZVBI_DIR = $(SRCS_DIR)/zvbi
SRCS_ZVBI = $(wildcard $(SRCS_ZVBI_DIR)/*.c)
OBJS_ZVBI = $(SRCS_ZVBI:$(SRCS_ZVBI_DIR)/%.c=$(OBJS_DIR)/%.o)
SRCS_GPACMP4_DIR = $(SRCS_DIR)/gpacmp4
SRCS_GPACMP4_C = $(wildcard $(SRCS_GPACMP4_DIR)/*.c)
SRCS_GPACMP4_CPP = $(wildcard $(SRCS_GPACMP4_DIR)/*.cpp)
@@ -37,12 +42,35 @@ SRCS_ZLIB_DIR = $(SRCS_DIR)/zlib
SRCS_ZLIB = $(wildcard $(SRCS_ZLIB_DIR)/*.c)
OBJS_ZLIB = $(SRCS_ZLIB:$(SRCS_ZLIB_DIR)/%.c=$(OBJS_DIR)/%.o)
SRCS_HASH_DIR = $(SRCS_DIR)/lib_hash
SRCS_HASH = $(wildcard $(SRCS_HASH_DIR)/*.c)
OBJS_HASH = $(SRCS_HASH:$(SRCS_HASH_DIR)/%.c=$(OBJS_DIR)/%.o)
INSTLALL = cp -f -p
INSTLALL_PROGRAM = $(INSTLALL)
DESTDIR = /usr/bin
ifeq ($(ENABLE_HARDSUBX),yes)
ENABLE_OCR=yes
CFLAGS+=-DENABLE_HARDSUBX
CFLAGS+= $(shell pkg-config --cflags libavcodec)
CFLAGS+= $(shell pkg-config --cflags libavformat)
CFLAGS+= $(shell pkg-config --cflags libavutil)
CFLAGS+= $(shell pkg-config --cflags libswscale)
AV_LDFLAGS+= $(shell pkg-config --libs libavcodec )
AV_LDFLAGS+= $(shell pkg-config --libs libavformat )
AV_LDFLAGS+= $(shell pkg-config --libs libavutil )
AV_LDFLAGS+= $(shell pkg-config --libs libswscale )
ifeq ($(AV_LDFLAGS),$(EMPTY))
$(error **ERROR** "libav not found")
else
$(info "libav found")
endif
LDFLAGS+= $(AV_LDFLAGS)
endif
ifeq ($(ENABLE_OCR),yes)
CFLAGS+=-DENABLE_OCR
CFLAGS+=-DENABLE_OCR -DPNG_NO_CONFIG_H
TESS_LDFLAGS+= $(shell pkg-config --libs tesseract)
LEPT_LDFLAGS+= $(shell pkg-config --libs lept)
@@ -78,14 +106,14 @@ LDFLAGS+= $(shell pkg-config --libs libavutil )
endif
.PHONY: all
all: objs_dir $(TARGET)
all: pre-build objs_dir $(TARGET)
.PHONY: objs_dir
objs_dir:
mkdir -p $(OBJS_DIR)
$(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 $@
$(TARGET): $(OBJS) $(OBJS_PNG) $(OBJS_GPACMP4) $(OBJS_ZVBI) $(OBJS_ZLIB) $(OBJS_HASH) $(OBJS_CCX)
$(CC) $(ALL_FLAGS) $(CFLAGS) $(OBJS) $(OBJS_CCX) $(OBJS_PNG) $(OBJS_ZVBI) $(OBJS_GPACMP4) $(OBJS_ZLIB) $(OBJS_HASH) $(LDFLAGS) -o $@
$(OBJS_DIR)/%.o: %.c
$(CC) -c $(ALL_FLAGS) $(INCLUDE) $(CFLAGS) $< -o $@
@@ -93,12 +121,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_CCX) $(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_HASH) $(OBJS) 2>/dev/null || true
rm -rdf $(OBJS_DIR) 2>/dev/null || true
rm -rf .depend 2>/dev/null || true
.PHONY: install
install: $(TARGET)
@@ -110,8 +141,12 @@ uninstall:
.PHONY: depend dep
depend dep:
$(CC) $(CFLAGS) -E -MM $(SRCS_C) $(SRCS_PNG) $(SRCS_ZLIB) $(SRCS_CXX) \
$(CC) $(CFLAGS) $(INCLUDE) -E -MM $(SRCS_C) $(SRCS_PNG) $(SRCS_ZVBI) $(SRCS_ZLIB) $(SRCS_HASH) $(SRCS_CCX) \
$(SRCS_GPACMP4_C) $(SRCS_GPACMP4_CPP) |\
sed 's/^[a-zA-Z_0-9]*.o/$(OBJS_DIR)\/&/' > .depend
.PHONY: pre-build
pre-build:
./pre-build.sh
-include .depend

View File

@@ -1,2 +1,14 @@
#!/bin/bash
gcc -std=gnu99 -Wno-write-strings -DGPAC_CONFIG_LINUX -D_FILE_OFFSET_BITS=64 -I../src/lib_ccx/ -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 -DVERSION_FILE_PRESENT -DENABLE_OCR"
BLD_INCLUDE="-I /usr/include/leptonica/ -I /usr/include/tesseract/ -I../src/lib_ccx/ -I../src/gpacmp4/ -I../src/libpng/ -I../src/zlib/ -I../src/zvbi -I../src/lib_hash"
SRC_LIBPNG="$(find ../src/libpng/ -name '*.c')"
SRC_ZLIB="$(find ../src/zlib/ -name '*.c')"
SRC_ZVBI="$(find ../src/zvbi/ -name '*.c')"
SRC_CCX="$(find ../src/lib_ccx/ -name '*.c')"
SRC_GPAC="$(find ../src/gpacmp4/ -name '*.c')"
SRC_HASH="$(find ../src/lib_hash/ -name '*.c')"
BLD_SOURCES="../src/ccextractor.c $SRC_CCX $SRC_GPAC $SRC_ZLIB $SRC_ZVBI $SRC_LIBPNG $SRC_HASH"
BLD_LINKER="-lm -zmuldefs -l tesseract -l lept"
./pre-build.sh
gcc $BLD_FLAGS $BLD_INCLUDE -o ccextractor $BLD_SOURCES $BLD_LINKER

View File

@@ -1,2 +1,14 @@
#!/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 -DVERSION_FILE_PRESENT"
BLD_INCLUDE="-I../src/lib_ccx/ -I../src/gpacmp4/ -I../src/libpng/ -I../src/zlib/ -I../src/zvbi -I../src/lib_hash"
SRC_LIBPNG="$(find ../src/libpng/ -name '*.c')"
SRC_ZLIB="$(find ../src/zlib/ -name '*.c')"
SRC_ZVBI="$(find ../src/zvbi/ -name '*.c')"
SRC_CCX="$(find ../src/lib_ccx/ -name '*.c')"
SRC_GPAC="$(find ../src/gpacmp4/ -name '*.c')"
SRC_HASH="$(find ../src/lib_hash/ -name '*.c')"
BLD_SOURCES="../src/ccextractor.c $SRC_CCX $SRC_GPAC $SRC_ZLIB $SRC_ZVBI $SRC_LIBPNG $SRC_HASH"
BLD_LINKER="-lm -zmuldefs"
./pre-build.sh
gcc $BLD_FLAGS $BLD_INCLUDE -o ccextractor $BLD_SOURCES $BLD_LINKER

34
linux/pre-build.sh Executable file
View File

@@ -0,0 +1,34 @@
#!/bin/bash
echo "Obtaining Git commit"
commit=(`git rev-parse HEAD 2>/dev/null`)
if [ -z "$commit" ]; then
echo "Git command not present, trying folder approach"
if [ -d "../.git" ]; then
echo "Git folder found, using HEAD file"
head="`cat ../.git/HEAD`"
ref_pos=(`expr match "$head" 'ref: '`)
if [ $ref_pos -eq 5 ]; then
echo "HEAD file contains a ref, following"
commit=(`cat "../.git/${head:5}"`)
echo "Extracted commit: $commit"
else
echo "HEAD contains a commit, using it"
commit="$head"
echo "Extracted commit: $commit"
fi
fi
fi
if [ -z "$commit" ]; then
commit="Unknown"
fi
builddate=`date +%Y-%m-%d`
echo "Storing variables in file"
echo "Commit: $commit"
echo "Date: $builddate"
echo "#ifndef CCX_CCEXTRACTOR_COMPILE_REAL_H" > ../src/lib_ccx/compile_info_real.h
echo "#define CCX_CCEXTRACTOR_COMPILE_REAL_H" >> ../src/lib_ccx/compile_info_real.h
echo "#define GIT_COMMIT \"$commit\"" >> ../src/lib_ccx/compile_info_real.h
echo "#define COMPILE_DATE \"$builddate\"" >> ../src/lib_ccx/compile_info_real.h
echo "#endif" >> ../src/lib_ccx/compile_info_real.h
echo "Stored all in compile.h"
echo "Done."

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

@@ -1 +1,17 @@
gcc -std=gnu99 -Wno-write-strings -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') $(find ../src/ -name '*.c')
#!/bin/bash
cd `dirname $0`
BLD_FLAGS="-std=gnu99 -Wno-write-strings -DGPAC_CONFIG_DARWIN -D_FILE_OFFSET_BITS=64 -DVERSION_FILE_PRESENT -Dfopen64=fopen -Dopen64=open -Dlseek64=lseek"
BLD_INCLUDE="-I../src/lib_ccx -I../src/gpacmp4 -I../src/libpng -I../src/zlib -I../src/zvbi -I../src/lib_hash"
SRC_LIBPNG="$(find ../src/libpng -name '*.c')"
SRC_ZLIB="$(find ../src/zlib -name '*.c')"
SRC_ZVBI="$(find ../src/zvbi -name '*.c')"
SRC_CCX="$(find ../src/lib_ccx -name '*.c')"
SRC_GPAC="$(find ../src/gpacmp4 -name '*.c')"
SRC_LIB_HASH="$(find ../src/lib_hash -name '*.c')"
BLD_SOURCES="../src/ccextractor.c $SRC_CCX $SRC_GPAC $SRC_ZVBI $SRC_ZLIB $SRC_LIBPNG $SRC_LIB_HASH"
BLD_LINKER="-lm -liconv"
./pre-build.sh
gcc $BLD_FLAGS $BLD_INCLUDE -o ccextractor $BLD_SOURCES $BLD_LINKER

34
mac/pre-build.sh Executable file
View File

@@ -0,0 +1,34 @@
#!/bin/bash
echo "Obtaining Git commit"
commit=(`git rev-parse HEAD 2>/dev/null`)
if [ -z "$commit" ]; then
echo "Git command not present, trying folder approach"
if [ -d "../.git" ]; then
echo "Git folder found, using HEAD file"
head="`cat ../.git/HEAD`"
ref_pos=(`expr match "$head" 'ref: '`)
if [ $ref_pos -eq 5 ]; then
echo "HEAD file contains a ref, following"
commit=(`cat "../.git/${head:5}"`)
echo "Extracted commit: $commit"
else
echo "HEAD contains a commit, using it"
commit="$head"
echo "Extracted commit: $commit"
fi
fi
fi
if [ -z "$commit" ]; then
commit="Unknown"
fi
builddate=`date +%Y-%m-%d`
echo "Storing variables in file"
echo "Commit: $commit"
echo "Date: $builddate"
echo "#ifndef CCX_CCEXTRACTOR_COMPILE_REAL_H" > ../src/lib_ccx/compile_info_real.h
echo "#define CCX_CCEXTRACTOR_COMPILE_REAL_H" >> ../src/lib_ccx/compile_info_real.h
echo "#define GIT_COMMIT \"$commit\"" >> ../src/lib_ccx/compile_info_real.h
echo "#define COMPILE_DATE \"$builddate\"" >> ../src/lib_ccx/compile_info_real.h
echo "#endif" >> ../src/lib_ccx/compile_info_real.h
echo "Stored all in compile.h"
echo "Done."

View File

@@ -2,10 +2,12 @@ cmake_minimum_required (VERSION 3.0.2)
project (CCExtractor)
option(WITH_FFMPEG "Build using FFmpeg demuxer and decoder" OFF)
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 75)
set (CCEXTRACTOR_VERSION_MINOR 77)
# configure a header file to pass some of the CMake settings
# to the source code
@@ -18,37 +20,77 @@ configure_file (
include_directories ("${PROJECT_SOURCE_DIR}")
include_directories ("${PROJECT_SOURCE_DIR}/lib_ccx")
include_directories ("${PROJECT_SOURCE_DIR}/gpacmp4/")
include_directories ("${PROJECT_SOURCE_DIR}/libccx_common/")
include_directories ("${PROJECT_SOURCE_DIR}/zvbi")
aux_source_directory ("${PROJECT_SOURCE_DIR}/zvbi" SOURCEFILE)
#Adding some platform specific library path
LINK_DIRECTORIES(/opt/local/lib)
LINK_DIRECTORIES(/usr/local/lib)
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")
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)
aux_source_directory (${PROJECT_SOURCE_DIR} SOURCEFILE)
set (EXTRA_LIBS ${EXTRA_LIBS} ccx)
set (EXTRA_LIBS ${EXTRA_LIBS} png)
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/")
include_directories ("${PROJEXT_SOURCE_DIR}/zlib/")
aux_source_directory ("${PROJECT_SOURCE_DIR}/libpng/" SOURCEFILE)
aux_source_directory ("${PROJECT_SOURCE_DIR}/zlib/" SOURCEFILE)
endif(PNG_FOUND)
else(PKG_CONFIG_FOUND)
include_directories ("${PROJECT_SOURCE_DIR}/libpng/")
include_directories ("${PROJEXT_SOURCE_DIR}/zlib/")
aux_source_directory ("${PROJECT_SOURCE_DIR}/libpng/" SOURCEFILE)
aux_source_directory ("${PROJECT_SOURCE_DIR}/zlib/" SOURCEFILE)
endif (PKG_CONFIG_FOUND)
########################################################
# Build using FFmpeg libraries
#
if (WITH_FFMPEG)
########################################################
find_package(PkgConfig)
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} )
if (PKG_CONFIG_FOUND AND WITH_FFMPEG)
SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DENABLE_FFMPEG")
endif (WITH_FFMPEG)
pkg_check_modules (AVFORMAT REQUIRED libavformat)
pkg_check_modules (AVUTIL REQUIRED libavutil)
pkg_check_modules (AVCODEC REQUIRED libavcodec)
add_executable(ccextractor ${SOURCEFILE})
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

@@ -8,10 +8,9 @@ License: GPL 2.0
#include <sys/types.h>
#include <sys/stat.h>
#include <signal.h>
#include "ffmpeg_intgr.h"
#include "ccx_common_option.h"
void xds_cea608_test();
#include "ccx_mp4.h"
#include "hardsubx.h"
struct lib_ccx_ctx *signal_ctx;
void sigint_handler()
@@ -22,118 +21,54 @@ void sigint_handler()
exit(EXIT_SUCCESS);
}
struct ccx_s_options ccx_options;
int main(int argc, char *argv[])
{
char *c;
struct encoder_ctx enc_ctx[2];
struct cc_subtitle dec_sub;
#ifdef ENABLE_FFMPEG
void *ffmpeg_ctx = NULL;
#endif
struct lib_ccx_ctx *ctx;
struct lib_cc_decode *dec_ctx = NULL;
int ret = 0;
enum ccx_stream_mode_enum stream_mode;
init_options (&ccx_options);
parse_configuration(&ccx_options);
parse_parameters (&ccx_options, argc, argv);
// Initialize libraries
ctx = init_libraries(&ccx_options);
dec_ctx = ctx->dec_ctx;
// Prepare write structures
init_write(&ctx->wbout1,ccx_options.wbout1.filename);
init_write(&ctx->wbout2,ccx_options.wbout2.filename);
int show_myth_banner = 0;
memset (&cea708services[0],0,CCX_DECODERS_708_MAX_SERVICES*sizeof (int)); // Cannot (yet) be moved because it's needed in parse_parameters.
memset (&dec_sub, 0,sizeof(dec_sub));
if (ctx->num_input_files==0 && ccx_options.input_source==CCX_DS_FILE)
ret = parse_parameters (&ccx_options, argc, argv);
if (ret == EXIT_NO_INPUT_FILES)
{
usage ();
fatal (EXIT_NO_INPUT_FILES, "(This help screen was shown because there were no input files)\n");
}
if (ctx->num_input_files>1 && ccx_options.live_stream)
else if (ret == EXIT_WITH_HELP)
{
fatal(EXIT_TOO_MANY_INPUT_FILES, "Live stream mode accepts only one input file.\n");
return EXIT_OK;
}
if (ctx->num_input_files && ccx_options.input_source==CCX_DS_NETWORK)
else if (ret != EXIT_OK)
{
fatal(EXIT_TOO_MANY_INPUT_FILES, "UDP mode is not compatible with input files.\n");
exit(ret);
}
if (ccx_options.input_source==CCX_DS_NETWORK || ccx_options.input_source==CCX_DS_TCP)
#ifdef ENABLE_HARDSUBX
if(ccx_options.hardsubx)
{
ccx_options.buffer_input=1; // Mandatory, because each datagram must be read complete.
}
if (ctx->num_input_files && ccx_options.input_source==CCX_DS_TCP)
{
fatal(EXIT_TOO_MANY_INPUT_FILES, "TCP mode is not compatible with input files.\n");
// Perform burned in subtitle extraction
hardsubx(&ccx_options);
return 0;
}
#endif
// Initialize libraries
ctx = init_libraries(&ccx_options);
if (!ctx && errno == ENOMEM)
fatal (EXIT_NOT_ENOUGH_MEMORY, "Not enough memory\n");
else if (!ctx && errno == EINVAL)
fatal (CCX_COMMON_EXIT_BUG_BUG, "Invalid option to CCextractor Library\n");
else if (!ctx && errno == EPERM)
fatal (CCX_COMMON_EXIT_FILE_CREATION_FAILED, "Unable to create Output File\n");
else if (!ctx && errno == EACCES)
fatal (CCX_COMMON_EXIT_FILE_CREATION_FAILED, "Unable to create Output File\n");
else if (!ctx)
fatal (EXIT_NOT_CLASSIFIED, "Unable to create Library Context %d\n",errno);
if (ctx->num_input_files > 0)
{
ctx->wbout1.multiple_files = 1;
ctx->wbout1.first_input_file = ctx->inputfile[0];
ctx->wbout2.multiple_files = 1;
ctx->wbout2.first_input_file = ctx->inputfile[0];
}
int show_myth_banner = 0;
// teletext page number out of range
if ((tlt_config.page != 0) && ((tlt_config.page < 100) || (tlt_config.page > 899))) {
fatal (EXIT_NOT_CLASSIFIED, "Teletext page number could not be lower than 100 or higher than 899\n");
}
if (ccx_options.output_filename!=NULL)
{
// Use the given output file name for the field specified by
// the -1, -2 switch. If -12 is used, the filename is used for
// field 1.
if (ccx_options.extract==2)
ctx->wbout2.filename=ccx_options.output_filename;
else
ctx->wbout1.filename=ccx_options.output_filename;
}
switch (ccx_options.write_format)
{
case CCX_OF_RAW:
ctx->extension = ".raw";
break;
case CCX_OF_SRT:
ctx->extension = ".srt";
break;
case CCX_OF_SAMI:
ctx->extension = ".smi";
break;
case CCX_OF_SMPTETT:
ctx->extension = ".ttml";
break;
case CCX_OF_TRANSCRIPT:
ctx->extension = ".txt";
break;
case CCX_OF_RCWT:
ctx->extension = ".bin";
break;
case CCX_OF_SPUPNG:
ctx->extension = ".xml";
break;
case CCX_OF_NULL:
ctx->extension = "";
break;
case CCX_OF_DVDRAW:
ctx->extension = ".dvdraw";
break;
default:
fatal (CCX_COMMON_EXIT_BUG_BUG, "write_format doesn't have any legal value, this is a bug.\n");
}
params_dump(ctx);
// default teletext page
@@ -142,225 +77,6 @@ int main(int argc, char *argv[])
tlt_config.page = ((tlt_config.page / 100) << 8) | (((tlt_config.page / 10) % 10) << 4) | (tlt_config.page % 10);
}
if (ctx->auto_stream==CCX_SM_MCPOODLESRAW && ccx_options.write_format==CCX_OF_RAW)
{
fatal (EXIT_INCOMPATIBLE_PARAMETERS, "-in=raw can only be used if the output is a subtitle file.\n");
}
if (ctx->auto_stream==CCX_SM_RCWT && ccx_options.write_format==CCX_OF_RCWT && ccx_options.output_filename==NULL)
{
fatal (EXIT_INCOMPATIBLE_PARAMETERS,
"CCExtractor's binary format can only be used simultaneously for input and\noutput if the output file name is specified given with -o.\n");
}
subline = (unsigned char *) malloc (SUBLINESIZE);
switch (ccx_options.input_source)
{
case CCX_DS_FILE:
ctx->basefilename = (char *) malloc (strlen (ctx->inputfile[0])+1);
break;
case CCX_DS_STDIN:
ctx->basefilename = (char *) malloc (strlen (ctx->basefilename_for_stdin)+1);
break;
case CCX_DS_NETWORK:
case CCX_DS_TCP:
ctx->basefilename = (char *) malloc (strlen (ctx->basefilename_for_network)+1);
break;
}
if (ctx->basefilename == NULL)
fatal (EXIT_NOT_ENOUGH_MEMORY, "Not enough memory\n");
switch (ccx_options.input_source)
{
case CCX_DS_FILE:
strcpy (ctx->basefilename, ctx->inputfile[0]);
break;
case CCX_DS_STDIN:
strcpy (ctx->basefilename, ctx->basefilename_for_stdin);
break;
case CCX_DS_NETWORK:
case CCX_DS_TCP:
strcpy (ctx->basefilename, ctx->basefilename_for_network);
break;
}
for (c=ctx->basefilename+strlen (ctx->basefilename)-1; ctx->basefilename &&
*c!='.'; c--) {;} // Get last .
if (*c=='.')
*c=0;
if (ctx->wbout1.filename==NULL)
{
ctx->wbout1.filename = (char *) malloc (strlen (ctx->basefilename)+3+strlen (ctx->extension));
ctx->wbout1.filename[0]=0;
}
if (ctx->wbout2.filename==NULL)
{
ctx->wbout2.filename = (char *) malloc (strlen (ctx->basefilename)+3+strlen (ctx->extension));
ctx->wbout2.filename[0]=0;
}
if (ctx->buffer == NULL || ctx->pesheaderbuf==NULL ||
ctx->wbout1.filename == NULL || ctx->wbout2.filename == NULL ||
subline==NULL || init_file_buffer() )
{
fatal (EXIT_NOT_ENOUGH_MEMORY, "Not enough memory\n");
}
if (ccx_options.send_to_srv)
{
connect_to_srv(ccx_options.srv_addr, ccx_options.srv_port, ccx_options.tcp_desc);
}
if (ccx_options.write_format!=CCX_OF_NULL)
{
/* # DVD format uses one raw file for both fields, while Broadcast requires 2 */
if (ccx_options.write_format==CCX_OF_DVDRAW)
{
if (ctx->wbout1.filename[0]==0)
{
strcpy (ctx->wbout1.filename,ctx->basefilename);
strcat (ctx->wbout1.filename,".raw");
}
if (ctx->cc_to_stdout)
{
ctx->wbout1.fh=STDOUT_FILENO;
mprint ("Sending captions to stdout.\n");
}
else
{
mprint ("Creating %s\n", ctx->wbout1.filename);
ctx->wbout1.fh=open (ctx->wbout1.filename, O_RDWR | O_CREAT | O_TRUNC | O_BINARY, S_IREAD | S_IWRITE);
if (ctx->wbout1.fh==-1)
{
fatal(CCX_COMMON_EXIT_FILE_CREATION_FAILED, "Failed\n");
}
}
}
else
{
if (ctx->cc_to_stdout && ccx_options.extract==12)
fatal (EXIT_INCOMPATIBLE_PARAMETERS, "You can't extract both fields to stdout at the same time in broadcast mode.");
if (ccx_options.write_format == CCX_OF_SPUPNG && ctx->cc_to_stdout)
fatal (EXIT_INCOMPATIBLE_PARAMETERS, "You cannot use -out=spupng with -stdout.");
if (ccx_options.extract!=2)
{
if (ctx->cc_to_stdout)
{
ctx->wbout1.fh=STDOUT_FILENO;
mprint ("Sending captions to stdout.\n");
}
else if (!ccx_options.send_to_srv)
{
if (ctx->wbout1.filename[0]==0)
{
strcpy (ctx->wbout1.filename,ctx->basefilename);
if (ccx_options.extract==12) // _1 only added if there's two files
strcat (ctx->wbout1.filename,"_1");
strcat (ctx->wbout1.filename,(const char *) ctx->extension);
}
mprint ("Creating %s\n", ctx->wbout1.filename);
ctx->wbout1.fh=open (ctx->wbout1.filename, O_RDWR | O_CREAT | O_TRUNC | O_BINARY, S_IREAD | S_IWRITE);
if (ctx->wbout1.fh==-1)
{
fatal(CCX_COMMON_EXIT_FILE_CREATION_FAILED, "Failed (errno=%d)\n", errno);
}
}
switch (ccx_options.write_format)
{
case CCX_OF_RAW:
writeraw(BROADCAST_HEADER, sizeof(BROADCAST_HEADER), &ctx->wbout1);
break;
case CCX_OF_DVDRAW:
break;
case CCX_OF_RCWT:
if (init_encoder(enc_ctx, &ctx->wbout1))
fatal(EXIT_NOT_ENOUGH_MEMORY, "Not enough memory\n");
set_encoder_subs_delay(enc_ctx, ctx->subs_delay);
set_encoder_last_displayed_subs_ms(enc_ctx, ctx->last_displayed_subs_ms);
set_encoder_startcredits_displayed(enc_ctx, ctx->startcredits_displayed);
break;
default:
if (!ccx_options.no_bom){
if (ccx_options.encoding == CCX_ENC_UTF_8){ // Write BOM
writeraw(UTF8_BOM, sizeof(UTF8_BOM), &ctx->wbout1);
}
if (ccx_options.encoding == CCX_ENC_UNICODE){ // Write BOM
writeraw(LITTLE_ENDIAN_BOM, sizeof(LITTLE_ENDIAN_BOM), &ctx->wbout1);
}
}
if (init_encoder(enc_ctx, &ctx->wbout1)){
fatal(EXIT_NOT_ENOUGH_MEMORY, "Not enough memory\n");
}
set_encoder_subs_delay(enc_ctx, ctx->subs_delay);
set_encoder_last_displayed_subs_ms(enc_ctx, ctx->last_displayed_subs_ms);
set_encoder_startcredits_displayed(enc_ctx, ctx->startcredits_displayed);
}
}
if (ccx_options.extract == 12 && ccx_options.write_format != CCX_OF_RAW)
mprint (" and \n");
if (ccx_options.extract!=1)
{
if (ctx->cc_to_stdout)
{
ctx->wbout1.fh=STDOUT_FILENO;
mprint ("Sending captions to stdout.\n");
}
else if(ccx_options.write_format == CCX_OF_RAW
&& ccx_options.extract == 12)
{
memcpy(&ctx->wbout2, &ctx->wbout1,sizeof(ctx->wbout1));
}
else if (!ccx_options.send_to_srv)
{
if (ctx->wbout2.filename[0]==0)
{
strcpy (ctx->wbout2.filename,ctx->basefilename);
if (ccx_options.extract==12) // _ only added if there's two files
strcat (ctx->wbout2.filename,"_2");
strcat (ctx->wbout2.filename,(const char *) ctx->extension);
}
mprint ("Creating %s\n", ctx->wbout2.filename);
ctx->wbout2.fh=open (ctx->wbout2.filename, O_RDWR | O_CREAT | O_TRUNC | O_BINARY, S_IREAD | S_IWRITE);
if (ctx->wbout2.fh==-1)
{
fatal(CCX_COMMON_EXIT_FILE_CREATION_FAILED, "Failed\n");
}
if(ccx_options.write_format == CCX_OF_RAW)
writeraw (BROADCAST_HEADER,sizeof (BROADCAST_HEADER),&ctx->wbout2);
}
switch (ccx_options.write_format)
{
case CCX_OF_RAW:
case CCX_OF_DVDRAW:
break;
case CCX_OF_RCWT:
if( init_encoder(enc_ctx+1,&ctx->wbout2) )
fatal (EXIT_NOT_ENOUGH_MEMORY, "Not enough memory\n");
set_encoder_subs_delay(enc_ctx+1, ctx->subs_delay);
set_encoder_last_displayed_subs_ms(enc_ctx+1, ctx->last_displayed_subs_ms);
set_encoder_startcredits_displayed(enc_ctx+1, ctx->startcredits_displayed);
break;
default:
if (!ccx_options.no_bom){
if (ccx_options.encoding == CCX_ENC_UTF_8){ // Write BOM
writeraw(UTF8_BOM, sizeof(UTF8_BOM), &ctx->wbout2);
}
if (ccx_options.encoding == CCX_ENC_UNICODE){ // Write BOM
writeraw(LITTLE_ENDIAN_BOM, sizeof(LITTLE_ENDIAN_BOM), &ctx->wbout2);
}
}
if (init_encoder(enc_ctx + 1, &ctx->wbout2)){
fatal(EXIT_NOT_ENOUGH_MEMORY, "Not enough memory\n");
}
set_encoder_subs_delay(enc_ctx+1, ctx->subs_delay);
set_encoder_last_displayed_subs_ms(enc_ctx+1, ctx->last_displayed_subs_ms);
set_encoder_startcredits_displayed(enc_ctx+1, ctx->startcredits_displayed);
}
}
}
}
if (ccx_options.transcript_settings.xds)
{
if (ccx_options.write_format != CCX_OF_TRANSCRIPT)
@@ -370,187 +86,62 @@ int main(int argc, char *argv[])
}
}
if (ccx_options.teletext_mode == CCX_TXT_IN_USE) // Here, it would mean it was forced by user
telxcc_init(ctx);
ctx->fh_out_elementarystream = NULL;
if (ccx_options.out_elementarystream_filename!=NULL)
{
if ((ctx->fh_out_elementarystream = fopen (ccx_options.out_elementarystream_filename,"wb"))==NULL)
{
fatal(CCX_COMMON_EXIT_FILE_CREATION_FAILED, "Unable to open clean file: %s\n", ccx_options.out_elementarystream_filename);
}
}
// Initialize HDTV caption buffer
init_hdcc();
if (ccx_options.line_terminator_lf)
encoded_crlf_length = encode_line(encoded_crlf, (unsigned char *) "\n");
else
encoded_crlf_length = encode_line(encoded_crlf, (unsigned char *) "\r\n");
encoded_br_length = encode_line(encoded_br, (unsigned char *) "<br>");
time_t start, final;
time(&start);
dec_ctx->processed_enough=0;
if (ccx_options.binary_concat)
{
ctx->total_inputsize=gettotalfilessize(ctx);
if (ctx->total_inputsize==-1)
fatal (EXIT_UNABLE_TO_DETERMINE_FILE_SIZE, "Failed to determine total file size.\n");
if (ctx->total_inputsize < 0)
{
switch (ctx->total_inputsize)
{
case -1*ENOENT:
fatal(EXIT_NO_INPUT_FILES, "Failed to open file: File not Exist");
case -1*EACCES:
fatal(EXIT_READ_ERROR, "Failed to open file: Unable to access");
case -1*EINVAL:
fatal(EXIT_READ_ERROR, "Failed to open file: Invalid opening flag.");
case -1*EMFILE:
fatal(EXIT_TOO_MANY_INPUT_FILES, "Failed to open file: Too many files are open.");
default:
fatal(EXIT_READ_ERROR, "Failed to open file: Reason unknown");
}
}
}
#ifndef _WIN32
signal_ctx = ctx;
m_signal(SIGINT, sigint_handler);
create_signal();
#endif
while (switch_to_next_file(ctx, 0) && !dec_ctx->processed_enough)
while (switch_to_next_file(ctx, 0))
{
prepare_for_new_file(ctx);
#ifdef ENABLE_FFMPEG
close_input_file(ctx);
ffmpeg_ctx = init_ffmpeg(ctx->inputfile[0]);
if(ffmpeg_ctx)
{
do
{
int ret = 0;
unsigned char *bptr = ctx->buffer;
int len = ff_get_ccframe(ffmpeg_ctx, bptr, 1024);
int cc_count = 0;
if(len == AVERROR(EAGAIN))
{
continue;
}
else if(len == AVERROR_EOF)
break;
else if(len == 0)
continue;
else if(len < 0 )
{
mprint("Error extracting Frame\n");
break;
}
else
cc_count = len/3;
ret = process_cc_data(dec_ctx, bptr, cc_count, &dec_sub);
if(ret >= 0 && dec_sub.got_output)
{
encode_sub(enc_ctx, &dec_sub);
dec_sub.got_output = 0;
}
}while(1);
continue;
}
else
{
mprint ("\rFailed to initialized ffmpeg falling back to legacy\n");
}
#endif
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;
}
/* -----------------------------------------------------------------
MAIN LOOP
----------------------------------------------------------------- */
// 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) )
{
ctx->stream_mode=CCX_SM_MYTH;
}
break;
default:
// Keep stream_mode
break;
}
break;
}
stream_mode = ctx->demux_ctx->get_stream_mode(ctx->demux_ctx);
// Disable sync check for raw formats - they have the right timeline.
// Also true for bin formats, but -nosync might have created a
// broken timeline for debug purposes.
// Disable too in MP4, specs doesn't say that there can't be a jump
switch (ctx->stream_mode)
switch (stream_mode)
{
case CCX_SM_MCPOODLESRAW:
case CCX_SM_RCWT:
case CCX_SM_MP4:
case CCX_SM_MCPOODLESRAW:
case CCX_SM_RCWT:
case CCX_SM_MP4:
#ifdef WTV_DEBUG
case CCX_SM_HEX_DUMP:
case CCX_SM_HEX_DUMP:
#endif
ccx_common_timing_settings.disable_sync_check = 1;
break;
default:
break;
ccx_common_timing_settings.disable_sync_check = 1;
break;
default:
break;
}
switch (ctx->stream_mode)
/* -----------------------------------------------------------------
MAIN LOOP
----------------------------------------------------------------- */
switch (stream_mode)
{
case CCX_SM_ELEMENTARY_OR_NOT_FOUND:
if (!ccx_options.use_gop_as_pts) // If !0 then the user selected something
@@ -560,28 +151,34 @@ int main(int argc, char *argv[])
case CCX_SM_PROGRAM:
case CCX_SM_ASF:
case CCX_SM_WTV:
case CCX_SM_GXF:
#ifdef ENABLE_FFMPEG
case CCX_SM_FFMPEG:
#endif
if (!ccx_options.use_gop_as_pts) // If !0 then the user selected something
ccx_options.use_gop_as_pts = 0;
mprint ("\rAnalyzing data in general mode\n");
general_loop(ctx, &enc_ctx);
general_loop(ctx);
break;
case CCX_SM_MCPOODLESRAW:
mprint ("\rAnalyzing data in McPoodle raw mode\n");
raw_loop(ctx, &enc_ctx);
raw_loop(ctx);
break;
case CCX_SM_RCWT:
mprint ("\rAnalyzing data in CCExtractor's binary format\n");
rcwt_loop(ctx, &enc_ctx);
rcwt_loop(ctx);
break;
case CCX_SM_MYTH:
mprint ("\rAnalyzing data in MythTV mode\n");
show_myth_banner = 1;
myth_loop(ctx, &enc_ctx);
myth_loop(ctx);
break;
case CCX_SM_MP4:
case CCX_SM_MP4:
mprint ("\rAnalyzing data with GPAC (MP4 library)\n");
close_input_file(ctx); // No need to have it open. GPAC will do it for us
processmp4 (ctx, ctx->inputfile[0],&enc_ctx);
processmp4(ctx, &ctx->mp4_cfg, ctx->inputfile[ctx->current_file]);
if (ccx_options.print_file_reports)
print_file_report(ctx);
break;
#ifdef WTV_DEBUG
case CCX_SM_HEX_DUMP:
@@ -594,168 +191,137 @@ int main(int argc, char *argv[])
break;
}
mprint("\n");
dbg_print(CCX_DMT_DECODER_608, "\nTime stamps after last caption block was written:\n");
dbg_print(CCX_DMT_DECODER_608, "Last time stamps: PTS: %s (%+2dF) ",
print_mstime( (LLONG) (sync_pts/(MPEG_CLOCK_FREQ/1000)
+frames_since_ref_time*1000.0/current_fps) ),
frames_since_ref_time);
dbg_print(CCX_DMT_DECODER_608, "GOP: %s \n", print_mstime(gop_time.ms) );
// Blocks since last PTS/GOP time stamp.
dbg_print(CCX_DMT_DECODER_608, "Calc. difference: PTS: %s (%+3lldms incl.) ",
print_mstime( (LLONG) ((sync_pts-min_pts)/(MPEG_CLOCK_FREQ/1000)
+ fts_offset + frames_since_ref_time*1000.0/current_fps)),
fts_offset + (LLONG) (frames_since_ref_time*1000.0/current_fps) );
dbg_print(CCX_DMT_DECODER_608, "GOP: %s (%+3dms incl.)\n",
print_mstime((LLONG)(gop_time.ms
-first_gop_time.ms
+get_fts_max()-fts_at_gop_start)),
(int)(get_fts_max()-fts_at_gop_start));
// When padding is active the CC block time should be within
// 1000/29.97 us of the differences.
dbg_print(CCX_DMT_DECODER_608, "Max. FTS: %s (without caption blocks since then)\n",
print_mstime(get_fts_max()));
if (ctx->stat_hdtv)
list_for_each_entry(dec_ctx, &ctx->dec_ctx_head, list, struct lib_cc_decode)
{
mprint ("\rCC type 0: %d (%s)\n", dec_ctx->cc_stats[0], cc_types[0]);
mprint ("CC type 1: %d (%s)\n", dec_ctx->cc_stats[1], cc_types[1]);
mprint ("CC type 2: %d (%s)\n", dec_ctx->cc_stats[2], cc_types[2]);
mprint ("CC type 3: %d (%s)\n", dec_ctx->cc_stats[3], cc_types[3]);
}
mprint ("\nTotal frames time: %s (%u frames at %.2ffps)\n",
print_mstime( (LLONG)(total_frames_count*1000/current_fps) ),
total_frames_count, current_fps);
if (ctx->total_pulldownframes)
mprint("\n");
dbg_print(CCX_DMT_DECODER_608, "\nTime stamps after last caption block was written:\n");
dbg_print(CCX_DMT_DECODER_608, "GOP: %s \n", print_mstime(gop_time.ms) );
dbg_print(CCX_DMT_DECODER_608, "GOP: %s (%+3dms incl.)\n",
print_mstime((LLONG)(gop_time.ms
-first_gop_time.ms
+get_fts_max(dec_ctx->timing)-fts_at_gop_start)),
(int)(get_fts_max(dec_ctx->timing)-fts_at_gop_start));
// When padding is active the CC block time should be within
// 1000/29.97 us of the differences.
dbg_print(CCX_DMT_DECODER_608, "Max. FTS: %s (without caption blocks since then)\n",
print_mstime(get_fts_max(dec_ctx->timing)));
if (dec_ctx->codec == CCX_CODEC_ATSC_CC)
{
mprint ("\nTotal frames time: %s (%u frames at %.2ffps)\n",
print_mstime( (LLONG)(total_frames_count*1000/current_fps) ),
total_frames_count, current_fps);
}
if (ctx->stat_hdtv)
{
mprint ("\rCC type 0: %d (%s)\n", dec_ctx->cc_stats[0], cc_types[0]);
mprint ("CC type 1: %d (%s)\n", dec_ctx->cc_stats[1], cc_types[1]);
mprint ("CC type 2: %d (%s)\n", dec_ctx->cc_stats[2], cc_types[2]);
mprint ("CC type 3: %d (%s)\n", dec_ctx->cc_stats[3], cc_types[3]);
}
// Add one frame as fts_max marks the beginning of the last frame,
// but we need the end.
dec_ctx->timing->fts_global += dec_ctx->timing->fts_max + (LLONG) (1000.0/current_fps);
// CFS: At least in Hauppage mode, cb_field can be responsible for ALL the
// timing (cb_fields having a huge number and fts_now and fts_global being 0 all
// the time), so we need to take that into account in fts_global before resetting
// counters.
if (cb_field1!=0)
dec_ctx->timing->fts_global += cb_field1*1001/3;
else if (cb_field2!=0)
dec_ctx->timing->fts_global += cb_field2*1001/3;
else
dec_ctx->timing->fts_global += cb_708*1001/3;
// Reset counters - This is needed if some captions are still buffered
// and need to be written after the last file is processed.
cb_field1 = 0; cb_field2 = 0; cb_708 = 0;
dec_ctx->timing->fts_now = 0;
dec_ctx->timing->fts_max = 0;
if (dec_ctx->total_pulldownframes)
mprint ("incl. pulldown frames: %s (%u frames at %.2ffps)\n",
print_mstime( (LLONG)(ctx->total_pulldownframes*1000/current_fps) ),
ctx->total_pulldownframes, current_fps);
if (pts_set >= 1 && min_pts != 0x01FFFFFFFFLL)
print_mstime( (LLONG)(dec_ctx->total_pulldownframes*1000/current_fps) ),
dec_ctx->total_pulldownframes, current_fps);
if (dec_ctx->timing->pts_set >= 1 && dec_ctx->timing->min_pts != 0x01FFFFFFFFLL)
{
LLONG postsyncms = (LLONG) (ctx->frames_since_last_gop*1000/current_fps);
LLONG postsyncms = (LLONG) (dec_ctx->frames_since_last_gop*1000/current_fps);
mprint ("\nMin PTS: %s\n",
print_mstime( min_pts/(MPEG_CLOCK_FREQ/1000) - fts_offset));
print_mstime( dec_ctx->timing->min_pts/(MPEG_CLOCK_FREQ/1000) - dec_ctx->timing->fts_offset));
if (pts_big_change)
mprint ("(Reference clock was reset at some point, Min PTS is approximated)\n");
mprint ("Max PTS: %s\n",
print_mstime( sync_pts/(MPEG_CLOCK_FREQ/1000) + postsyncms));
print_mstime( dec_ctx->timing->sync_pts/(MPEG_CLOCK_FREQ/1000) + postsyncms));
mprint ("Length: %s\n",
print_mstime( sync_pts/(MPEG_CLOCK_FREQ/1000) + postsyncms
- min_pts/(MPEG_CLOCK_FREQ/1000) + fts_offset ));
print_mstime( dec_ctx->timing->sync_pts/(MPEG_CLOCK_FREQ/1000) + postsyncms
- dec_ctx->timing->min_pts/(MPEG_CLOCK_FREQ/1000) + dec_ctx->timing->fts_offset ));
}
// dvr-ms files have invalid GOPs
if (gop_time.inited && first_gop_time.inited && ctx->stream_mode != CCX_SM_ASF)
if (gop_time.inited && first_gop_time.inited && stream_mode != CCX_SM_ASF)
{
mprint ("\nInitial GOP time: %s\n",
print_mstime(first_gop_time.ms));
mprint ("Final GOP time: %s%+3dF\n",
print_mstime(gop_time.ms),
ctx->frames_since_last_gop);
dec_ctx->frames_since_last_gop);
mprint ("Diff. GOP length: %s%+3dF",
print_mstime(gop_time.ms - first_gop_time.ms),
ctx->frames_since_last_gop);
mprint (" (%s)\n",
dec_ctx->frames_since_last_gop);
mprint (" (%s)\n\n",
print_mstime(gop_time.ms - first_gop_time.ms
+(LLONG) ((ctx->frames_since_last_gop)*1000/29.97)) );
+(LLONG) ((dec_ctx->frames_since_last_gop)*1000/29.97)) );
}
if (ctx->false_pict_header)
mprint ("\nNumber of likely false picture headers (discarded): %d\n",ctx->false_pict_header);
if (dec_ctx->false_pict_header)
mprint ("\nNumber of likely false picture headers (discarded): %d\n",dec_ctx->false_pict_header);
if (ctx->stat_numuserheaders)
mprint("\nTotal user data fields: %d\n", ctx->stat_numuserheaders);
if (ctx->stat_dvdccheaders)
mprint("DVD-type user data fields: %d\n", ctx->stat_dvdccheaders);
if (ctx->stat_scte20ccheaders)
mprint("SCTE-20 type user data fields: %d\n", ctx->stat_scte20ccheaders);
if (ctx->stat_replay4000headers)
mprint("ReplayTV 4000 user data fields: %d\n", ctx->stat_replay4000headers);
if (ctx->stat_replay5000headers)
mprint("ReplayTV 5000 user data fields: %d\n", ctx->stat_replay5000headers);
if (ctx->stat_hdtv)
mprint("HDTV type user data fields: %d\n", ctx->stat_hdtv);
if (ctx->stat_dishheaders)
mprint("Dish Network user data fields: %d\n", ctx->stat_dishheaders);
if (ctx->stat_divicom)
if (dec_ctx->stat_numuserheaders)
mprint("\nTotal user data fields: %d\n", dec_ctx->stat_numuserheaders);
if (dec_ctx->stat_dvdccheaders)
mprint("DVD-type user data fields: %d\n", dec_ctx->stat_dvdccheaders);
if (dec_ctx->stat_scte20ccheaders)
mprint("SCTE-20 type user data fields: %d\n", dec_ctx->stat_scte20ccheaders);
if (dec_ctx->stat_replay4000headers)
mprint("ReplayTV 4000 user data fields: %d\n", dec_ctx->stat_replay4000headers);
if (dec_ctx->stat_replay5000headers)
mprint("ReplayTV 5000 user data fields: %d\n", dec_ctx->stat_replay5000headers);
if (dec_ctx->stat_hdtv)
mprint("HDTV type user data fields: %d\n", dec_ctx->stat_hdtv);
if (dec_ctx->stat_dishheaders)
mprint("Dish Network user data fields: %d\n", dec_ctx->stat_dishheaders);
if (dec_ctx->stat_divicom)
{
mprint("CEA608/Divicom user data fields: %d\n", ctx->stat_divicom);
mprint("CEA608/Divicom user data fields: %d\n", dec_ctx->stat_divicom);
mprint("\n\nNOTE! The CEA 608 / Divicom standard encoding for closed\n");
mprint("caption is not well understood!\n\n");
mprint("Please submit samples to the developers.\n\n\n");
}
// Add one frame as fts_max marks the beginning of the last frame,
// but we need the end.
fts_global += fts_max + (LLONG) (1000.0/current_fps);
// CFS: At least in Hauppage mode, cb_field can be responsible for ALL the
// timing (cb_fields having a huge number and fts_now and fts_global being 0 all
// the time), so we need to take that into account in fts_global before resetting
// counters.
if (cb_field1!=0)
fts_global += cb_field1*1001/3;
else
fts_global += cb_field2*1001/3;
// Reset counters - This is needed if some captions are still buffered
// and need to be written after the last file is processed.
cb_field1 = 0; cb_field2 = 0; cb_708 = 0;
fts_now = 0;
fts_max = 0;
}
if(is_decoder_processed_enough(ctx) == CCX_TRUE)
break;
} // file loop
close_input_file(ctx);
if (ctx->fh_out_elementarystream!=NULL)
fclose (ctx->fh_out_elementarystream);
flushbuffer (ctx, &ctx->wbout1, false);
flushbuffer (ctx, &ctx->wbout2, false);
prepare_for_new_file (ctx); // To reset counters used by handle_end_of_data()
telxcc_close(ctx);
if (ctx->wbout1.fh!=-1)
{
if (ccx_options.write_format==CCX_OF_SMPTETT || ccx_options.write_format==CCX_OF_SAMI ||
ccx_options.write_format==CCX_OF_SRT || ccx_options.write_format==CCX_OF_TRANSCRIPT
|| ccx_options.write_format==CCX_OF_SPUPNG )
{
handle_end_of_data(dec_ctx->context_cc608_field_1, &dec_sub);
if (dec_sub.got_output)
{
encode_sub(enc_ctx,&dec_sub);
dec_sub.got_output = 0;
}
}
else if(ccx_options.write_format==CCX_OF_RCWT)
{
// Write last header and data
writercwtdata (dec_ctx, NULL);
}
dinit_encoder(enc_ctx);
}
if (ctx->wbout2.fh!=-1)
{
if (ccx_options.write_format==CCX_OF_SMPTETT || ccx_options.write_format==CCX_OF_SAMI ||
ccx_options.write_format==CCX_OF_SRT || ccx_options.write_format==CCX_OF_TRANSCRIPT
|| ccx_options.write_format==CCX_OF_SPUPNG )
{
handle_end_of_data(dec_ctx->context_cc608_field_2, &dec_sub);
if (dec_sub.got_output)
{
encode_sub(enc_ctx,&dec_sub);
dec_sub.got_output = 0;
}
}
dinit_encoder(enc_ctx+1);
}
flushbuffer (ctx, &ctx->wbout1,true);
flushbuffer (ctx, &ctx->wbout2,true);
time (&final);
long proc_time=(long) (final-start);
mprint ("\rDone, processing time = %ld seconds\n", proc_time);
#if 0
if (proc_time>0)
{
LLONG ratio=(get_fts_max()/10)/proc_time;
@@ -764,21 +330,13 @@ int main(int argc, char *argv[])
mprint ("Performance (real length/process time) = %u.%02u\n",
s1, s2);
}
dbg_print(CCX_DMT_708, "The 708 decoder was reset [%d] times.\n",resets_708);
if (ccx_options.teletext_mode == CCX_TXT_IN_USE)
mprint ( "Teletext decoder: %"PRIu32" packets processed, %"PRIu32" SRT frames written.\n", tlt_packet_counter, tlt_frames_produced);
#endif
if (dec_ctx->processed_enough)
if (is_decoder_processed_enough(ctx) == CCX_TRUE)
{
mprint ("\rNote: Processing was cancelled before all data was processed because\n");
mprint ("\rone or more user-defined limits were reached.\n");
}
if (ccblocks_in_avc_lost>0)
{
mprint ("Total caption blocks received: %d\n", ccblocks_in_avc_total);
mprint ("Total caption blocks lost: %d\n", ccblocks_in_avc_lost);
}
mprint ("This is beta software. Report issues to carlos at ccextractor org...\n");
if (show_myth_banner)
{

View File

@@ -417,9 +417,18 @@ GF_Err tx3g_Read(GF_Box *s, GF_BitStream *bs)
ptr->size -= 18 + GPP_BOX_SIZE + GPP_STYLE_SIZE;
while (ptr->size) {
if (ptr->size < 8) {
/* Sometimes there are void atoms at the end of an atom and they are not parsed correctecly */
/* So just skip them if we have less than 8 bytes to parse */
/* "The actual size of an atom cannot be less than 8 bytes" from QTFF specs */
ptr->size = 0;
return GF_OK;
}
e = gf_isom_parse_box(&a, bs);
if (e) return e;
if (ptr->size<a->size) return GF_ISOM_INVALID_FILE;
ptr->size -= a->size;
if (a->type==GF_ISOM_BOX_TYPE_FTAB) {
if (ptr->font_table) gf_isom_box_del((GF_Box *) ptr->font_table);

View File

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

@@ -102,7 +102,7 @@ proceed_box:
}
//handle large box
if (size == 1) {
if (size == 1 && type != GF_ISOM_BOX_TYPE_VOID) {
size = gf_bs_read_u64(bs);
hdr_size += 8;
}

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

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

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

@@ -7,9 +7,9 @@
#include "utility.h"
#include "ccx_encoders_common.h"
#include "ccx_common_option.h"
void do_NAL (struct lib_ccx_ctx *ctx, unsigned char *NALstart, LLONG NAL_length, struct cc_subtitle *sub);
void set_fts(void); // From timing.c
#include "ccx_mp4.h"
#include "activity.h"
#include "ccx_dtvcc.h"
static short bswap16(short v)
{
@@ -32,11 +32,12 @@ static int process_avc_sample(struct lib_ccx_ctx *ctx, u32 timescale, GF_AVCConf
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; )
{
@@ -62,7 +63,7 @@ static int process_avc_sample(struct lib_ccx_ctx *ctx, u32 timescale, GF_AVCConf
temp_debug=0;
if (nal_length>0)
do_NAL (ctx, (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);
@@ -72,8 +73,11 @@ static int process_avc_sample(struct lib_ccx_ctx *ctx, u32 timescale, GF_AVCConf
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;
@@ -91,24 +95,22 @@ static int process_xdvb_track(struct lib_ccx_ctx *ctx, const char* basename, GF_
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 (ctx, (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 (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);
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;
@@ -119,6 +121,9 @@ static int process_avc_track(struct lib_ccx_ctx *ctx, const char* basename, GF_I
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)
{
@@ -168,12 +173,12 @@ static int process_avc_track(struct lib_ccx_ctx *ctx, const char* basename, GF_I
int progress = (int) ((i*100) / sample_count);
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);
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)
@@ -185,6 +190,87 @@ static int process_avc_track(struct lib_ccx_ctx *ctx, const char* basename, GF_I
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(){
@@ -198,11 +284,15 @@ static int process_avc_track(struct lib_ccx_ctx *ctx, const char* basename, GF_I
}
*/
int processmp4 (struct lib_ccx_ctx *ctx, 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);
@@ -231,20 +321,23 @@ int processmp4 (struct lib_ccx_ctx *ctx, 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(ctx, file, f, i + 1, &dec_sub) != 0)
{
@@ -259,8 +352,8 @@ int processmp4 (struct lib_ccx_ctx *ctx, 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)
@@ -268,7 +361,7 @@ int processmp4 (struct lib_ccx_ctx *ctx, 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 (ctx, (unsigned char *) seqcnf->data, seqcnf->size, &dec_sub);
do_NAL (dec_ctx, (unsigned char *) seqcnf->data, seqcnf->size, &dec_sub);
}
}
@@ -282,22 +375,21 @@ int processmp4 (struct lib_ccx_ctx *ctx, 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);
@@ -306,7 +398,7 @@ int processmp4 (struct lib_ccx_ctx *ctx, 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)
{
@@ -322,10 +414,8 @@ int processmp4 (struct lib_ccx_ctx *ctx, 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
@@ -333,47 +423,116 @@ int processmp4 (struct lib_ccx_ctx *ctx, 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, ctx->dec_ctx->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 (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);
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);
}
}
@@ -398,8 +557,6 @@ int processmp4 (struct lib_ccx_ctx *ctx, char *file,void *enc_ctx)
mprint ("found no dedicated CC track(s).\n");
ctx->freport.mp4_cc_track_cnt = cc_track_count;
if (ccx_options.print_file_reports)
print_file_report(ctx);
return 0;
}

View File

@@ -1,204 +0,0 @@
#include "lib_ccx.h"
#include "ccx_common_option.h"
#include "ccx_encoders_common.h"
#include "png.h"
#include "spupng_encoder.h"
#include "ocr.h"
#include "utility.h"
void write_stringz_as_sami(char *string, struct encoder_ctx *context, LLONG ms_start, LLONG ms_end)
{
int used;
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_DECODER_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_DECODER_608, "\r");
dbg_print(CCX_DMT_DECODER_608, "%s\n",subline);
}
write(context->out->fh, el, u);
write(context->out->fh, encoded_br, encoded_br_length);
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_DECODER_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_DECODER_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)
{
int ret = 0;
struct cc_bitmap* rect;
LLONG ms_start, ms_end;
if (context->prev_start != -1 && (sub->flags & SUB_EOD_MARKER))
{
ms_start = context->prev_start + context->subs_delay;
ms_end = sub->start_time - 1;
}
else if ( !(sub->flags & SUB_EOD_MARKER))
{
ms_start = sub->start_time + context->subs_delay;
ms_end = sub->end_time - 1;
}
else if ( context->prev_start == -1 && (sub->flags & SUB_EOD_MARKER) )
{
ms_start = 1 + context->subs_delay;
ms_end = sub->start_time - 1;
}
if(sub->nb_data == 0 )
return 0;
rect = sub->data;
if ( sub->flags & SUB_EOD_MARKER )
context->prev_start = sub->start_time;
#if ENABLE_OCR
if (rect[0].ocr_text && *(rect[0].ocr_text))
{
if (context->prev_start != -1 || !(sub->flags & SUB_EOD_MARKER))
{
char *token = NULL;
char *buf = (char*)context->buffer;
sprintf(buf,
"<SYNC start=%llu><P class=\"UNKNOWNCC\">\r\n"
,(unsigned long long)ms_start);
write(context->out->fh, buf, strlen(buf));
token = strtok(rect[0].ocr_text,"\r\n");
while (token)
{
sprintf(buf, "%s", token);
token = strtok(NULL,"\r\n");
if(token)
strcat(buf, "<br>\n");
else
strcat(buf, "\n");
write(context->out->fh, buf, strlen(buf));
}
sprintf(buf,
"<SYNC start=%llu><P class=\"UNKNOWNCC\">&nbsp;</P></SYNC>\r\n\r\n"
,(unsigned long long)ms_end);
write(context->out->fh, buf, strlen(buf));
}
}
#endif
sub->nb_data = 0;
freep(&sub->data);
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+=context->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_DECODER_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_DECODER_608, "\r");
dbg_print(CCX_DMT_DECODER_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_DECODER_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_DECODER_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,225 +0,0 @@
#include "lib_ccx.h"
#include "ccx_common_option.h"
#include "ccx_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_DECODER_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_DECODER_608, "\r");
dbg_print(CCX_DMT_DECODER_608, "%s\n",subline);
}
write(context->out->fh, el, u);
//write (wb->fh, encoded_br, encoded_br_length);
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_DECODER_608, "\r%s\n", str);
}
used = encode_line(context->buffer,(unsigned char *) str);
write(context->out->fh, context->buffer, used);
sprintf ((char *) str,"<p begin=\"%02u:%02u:%02u.%03u\">\n\n",h2,m2,s2,ms2);
if (ccx_options.encoding!=CCX_ENC_UNICODE)
{
dbg_print(CCX_DMT_DECODER_608, "\r%s\n", str);
}
used = encode_line(context->buffer,(unsigned char *) str);
write (context->out->fh, context->buffer, used);
sprintf ((char *) str,"</p>\n");
free(el);
free(unescaped);
}
int write_cc_bitmap_as_smptett(struct cc_subtitle *sub, struct encoder_ctx *context)
{
int ret = 0;
struct cc_bitmap* rect;
LLONG ms_start, ms_end;
//char timeline[128];
int len = 0;
if (context->prev_start != -1 && (sub->flags & SUB_EOD_MARKER))
{
ms_start = context->prev_start + context->subs_delay;
ms_end = sub->start_time - 1;
}
else if ( !(sub->flags & SUB_EOD_MARKER))
{
ms_start = sub->start_time + context->subs_delay;
ms_end = sub->end_time - 1;
}
else if (context->prev_start == -1 && (sub->flags & SUB_EOD_MARKER))
{
ms_start = 1 + context->subs_delay;
ms_end = sub->start_time - 1;
}
if(sub->nb_data == 0 )
return 0;
rect = sub->data;
if ( sub->flags & SUB_EOD_MARKER )
context->prev_start = sub->start_time;
#ifdef ENABLE_OCR
if (rect[0].ocr_text && *(rect[0].ocr_text))
{
if (context->prev_start != -1 || !(sub->flags & SUB_EOD_MARKER))
{
char *buf = (char *) context->buffer;
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); // -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, buf,strlen(buf) );
len = strlen(rect[0].ocr_text);
write (context->out->fh, rect[0].ocr_text, len);
write (context->out->fh, encoded_crlf, encoded_crlf_length);
sprintf ( buf,"</p>\n");
write (context->out->fh, buf,strlen(buf) );
}
}
#endif
sub->nb_data = 0;
freep(&sub->data);
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+=context->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_DECODER_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_DECODER_608, "\r");
dbg_print(CCX_DMT_DECODER_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_DECODER_608, "\r%s\n", str);
}
used = encode_line(context->buffer,(unsigned char *) str);
write (context->out->fh, context->buffer, used);
if (ccx_options.encoding!=CCX_ENC_UNICODE)
{
dbg_print(CCX_DMT_DECODER_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,278 +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 + context->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(CCX_COMMON_EXIT_FILE_CREATION_FAILED, "Cannot open %s: %s\n",
sp->pngfile, strerror(errno));
}
if (!spupng_export_png(sp, data))
{
fatal(CCX_COMMON_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;
}

View File

@@ -1,18 +1,42 @@
cmake_policy(SET CMP0037 NEW)
cmake_policy (SET CMP0037 NEW)
SET (CMAKE_C_FLAGS "-O0 -Wall -g -std=gnu99")
set (CMAKE_C_FLAGS "-O0 -Wall -g -std=gnu99")
if (WITH_FFMPEG)
SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DENABLE_FFMPEG")
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DENABLE_FFMPEG")
endif (WITH_FFMPEG)
AUX_SOURCE_DIRECTORY("${PROJECT_SOURCE_DIR}/lib_ccx/" SOURCEFILE)
AUX_SOURCE_DIRECTORY("${PROJECT_SOURCE_DIR}/gpacmp4/" SOURCEFILE)
#AUX_SOURCE_DIRECTORY("${PROJECT_SOURCE_DIR}/libpng/" SOURCEFILE)
add_library(ccx ${SOURCEFILE})
if (WITH_OCR)
find_package(PkgConfig)
FILE(GLOB HeaderFiles *.h)
file(WRITE ccx.pc "prefix=${CMAKE_INSTALL_PREFIX}\n"
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"
@@ -20,8 +44,9 @@ file(WRITE ccx.pc "prefix=${CMAKE_INSTALL_PREFIX}\n"
"Version: 0.75\n"
"Cflags: -I\${includedir}/\n"
"Libs: -L\${libdir} -lccx -lpng\n"
"Libs.private: -lpng\n" )
"Libs.private: -lpng\n"
)
install (TARGETS ccx DESTINATION lib)
install (FILES ${HeaderFiles} DESTINATION include)
install (FILES ccx.pc DESTINATION lib/pkgconfig )
install (FILES ccx.pc DESTINATION lib/pkgconfig)

View File

@@ -7,53 +7,54 @@ relevant events. */
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)
/* 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 (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);
}
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);
}
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, ...){
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;
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);
@@ -61,65 +62,65 @@ void activity_library_process(enum ccx_common_logging_gui message_type, ...){
}
void activity_video_info (int hor_size,int vert_size,
const char *aspect_ratio, const char *framerate)
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);
}
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);
}
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);
}
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);
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);
}
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);
}
if (ccx_options.gui_mode_reports)
{
fprintf (stderr, "###DATAREAD#%lu\n", net_activity_gui/1000);
fflush (stderr);
}
}
@@ -127,7 +128,7 @@ void activity_header (void)
{
if (!credits_shown)
{
credits_shown=1;
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;

File diff suppressed because it is too large Load Diff

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)

View File

@@ -14,17 +14,17 @@
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;
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)
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!");
mprint ( "init_bitstream: bitstream has negative length!");
return 1;
}
return 0;
@@ -37,70 +37,70 @@ int init_bitstream(struct bitstream *bstr, unsigned char *start, unsigned char *
// there are not enough bits left in the bitstream.
uint64_t next_bits(struct bitstream *bstr, unsigned bnum)
{
uint64_t res = 0;
uint64_t res = 0;
if(bnum > 64)
fatal(CCX_COMMON_EXIT_BUG_BUG, "next_bits: 64 is maximum bit number, argument: %u!", bnum);
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!");
// 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;
}
// 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;
// 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;
// Special case for reading zero bits. Return zero
if(bnum == 0)
return 0;
int vbit = bstr->bpos;
unsigned char *vpos = bstr->pos;
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);
}
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 ...");
}
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--;
res |= (*vpos & (0x01 << (vbit-1)) ? 1 : 0);
vbit--;
bnum--;
if(vbit == 0)
{
vpos++;
vbit = 8;
}
if(vbit == 0)
{
vpos++;
vbit = 8;
}
if(bnum)
{
res <<= 1;
}
else
break;
}
if(bnum)
{
res <<= 1;
}
else
break;
}
// Remember the bitstream position
bstr->_i_bpos = vbit;
bstr->_i_pos = vpos;
// Remember the bitstream position
bstr->_i_bpos = vbit;
bstr->_i_pos = vpos;
return res;
return res;
}
@@ -108,18 +108,18 @@ uint64_t next_bits(struct bitstream *bstr, unsigned bnum)
// 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);
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;
// 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;
// Advance the bitstream
bstr->bpos = bstr->_i_bpos;
bstr->pos = bstr->_i_pos;
return res;
return res;
}
@@ -128,35 +128,35 @@ uint64_t read_bits(struct bitstream *bstr, unsigned bnum)
// 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!");
// 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;
}
// 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;
// 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;
// Special case for reading zero bits. Return zero
if(bnum == 0)
return 1;
bstr->bpos -= bnum%8;
bstr->pos += bnum/8;
bstr->bpos -= bnum%8;
bstr->pos += bnum/8;
if (bstr->bpos < 1)
{
bstr->bpos += 8;
bstr->pos += 1;
}
return 1;
if (bstr->bpos < 1)
{
bstr->bpos += 8;
bstr->pos += 1;
}
return 1;
}
@@ -165,55 +165,55 @@ int skip_bits(struct bitstream *bstr, unsigned bnum)
// 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!");
// 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;
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 == 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;
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!");
// 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;
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);
}
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;
}
// 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;
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;
}
@@ -224,27 +224,27 @@ void make_byte_aligned(struct bitstream *bstr)
// 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!");
// 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;
}
// 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;
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;
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;
// Remember the bitstream position
bstr->_i_bpos = 8;
bstr->_i_pos = bstr->pos + bynum;
return bstr->pos;
return bstr->pos;
}
@@ -255,15 +255,15 @@ unsigned char *next_bytes(struct bitstream *bstr, unsigned bynum)
// This function does advance the bitstream pointer.
unsigned char *read_bytes(struct bitstream *bstr, unsigned bynum)
{
unsigned char *res = next_bytes(bstr, 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;
// Advance the bitstream when a read was possible
if(res)
{
bstr->bpos = bstr->_i_bpos;
bstr->pos = bstr->_i_pos;
}
return res;
}
@@ -275,19 +275,19 @@ unsigned char *read_bytes(struct bitstream *bstr, unsigned bynum)
// little-endian and big-endian CPUs.
uint64_t bitstream_get_num(struct bitstream *bstr, unsigned bytes, int advance)
{
void *bpos;
uint64_t rval=0;
void *bpos;
uint64_t rval=0;
if (advance)
bpos = read_bytes(bstr, bytes);
else
bpos = next_bytes(bstr, bytes);
if (advance)
bpos = read_bytes(bstr, bytes);
else
bpos = next_bytes(bstr, bytes);
if (!bpos)
return 0;
if (!bpos)
return 0;
switch (bytes)
{
switch (bytes)
{
case 1:
case 2:
case 4:
@@ -295,47 +295,47 @@ uint64_t bitstream_get_num(struct bitstream *bstr, unsigned bytes, int advance)
break;
default:
fatal (CCX_COMMON_EXIT_BUG_BUG, "bitstream_get_num: Illegal precision value [%u]!",
bytes);
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;
return rval;
}
// Read unsigned Exp-Golomb code from bitstream
uint64_t ue(struct bitstream *bstr)
{
uint64_t res = 0;
int zeros=0;
uint64_t res = 0;
int zeros=0;
while(!read_bits(bstr,1))
zeros++;
while(!read_bits(bstr,1))
zeros++;
res = (0x01 << zeros) - 1 + read_bits(bstr,zeros);
res = (0x01 << zeros) - 1 + read_bits(bstr,zeros);
return res;
return res;
}
// Read signed Exp-Golomb code from bitstream
int64_t se(struct bitstream *bstr)
{
int64_t res = 0;
int64_t res = 0;
res = ue(bstr);
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);
// 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;
return res;
}
@@ -343,33 +343,33 @@ int64_t se(struct bitstream *bstr)
// alias for read_bits().
uint64_t u(struct bitstream *bstr, unsigned bnum)
{
return read_bits(bstr, 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);
uint64_t res = read_bits(bstr, bnum);
// Special case for reading zero bits. Return zero
if(bnum == 0)
return 0;
// Special case for reading zero bits. Return zero
if(bnum == 0)
return 0;
return (0xFFFFFFFFFFFFFFFFULL << bnum) | res;
return (0xFFFFFFFFFFFFFFFFULL << bnum) | res;
}
// Return the value with the bit order reversed.
uint8_t reverse8(uint8_t data)
{
uint8_t res = 0;
uint8_t res = 0;
for (int k=0;k<8;k++)
{
res <<= 1;
res |= (data & (0x01 << k) ? 1 : 0);
}
for (int k=0;k<8;k++)
{
res <<= 1;
res |= (data & (0x01 << k) ? 1 : 0);
}
return res;
return res;
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,7 @@
#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, ...)
{
@@ -36,7 +38,8 @@ void fdprintf(int fd, const char *fmt, ...)
free(p);
return;
}
else {
else
{
p = np;
}
}
@@ -63,3 +66,63 @@ void freep(void *arg)
*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

@@ -2,12 +2,41 @@
#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
#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
/* 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_WITH_HELP 9
#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, ...);
@@ -15,6 +44,8 @@ void mstotime(LLONG milli, unsigned *hours, unsigned *minutes,unsigned *seconds,
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

@@ -24,104 +24,104 @@ 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
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"
"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"
"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)"
"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"
"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"
"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,
NTSC_CC_f1 = 0,
NTSC_CC_f2 = 1,
DTVCC_PACKET_DATA = 2,
DTVCC_PACKET_START = 3,
};
/**
@@ -130,9 +130,104 @@ enum
*/
const char *language[NB_LANGUAGE] =
{
"und",
"eng",
"fin",
"spa",
/*0*/"und", //Undefined
/*1*/"eng",
/*2*/"afr",
/*3*/"amh",
/*4*/"ara",
/*5*/"asm",
/*6*/"aze",
/*7*/"bel",
/*8*/"ben",
/*9*/"bod",
/*10*/"bos",
/*11*/"bul",
/*12*/"cat",
/*13*/"ceb",
/*14*/"ces",
/*15*/"chs",
/*16*/"chi",
/*17*/"chr",
/*18*/"cym",
/*19*/"dan",
/*20*/"deu",
/*21*/"dzo",
/*22*/"ell",
/*23*/"enm",
/*24*/"epo",
/*25*/"equ",
/*26*/"est",
/*27*/"eus",
/*28*/"fas",
/*29*/"fin",
/*30*/"fra",
/*31*/"frk",
/*32*/"frm",
/*33*/"gle",
/*34*/"glg",
/*35*/"grc",
/*36*/"guj",
/*37*/"hat",
/*38*/"heb",
/*39*/"hin",
/*40*/"hrv",
/*41*/"hun",
/*42*/"iku",
/*43*/"ind",
/*44*/"isl",
/*45*/"ita",
/*46*/"jav",
/*47*/"jpn",
/*48*/"kan",
/*49*/"kat",
/*50*/"kaz",
/*51*/"khm",
/*52*/"kir",
/*53*/"kor",
/*54*/"kur",
/*55*/"lao",
/*56*/"lat",
/*57*/"lav",
/*58*/"lit",
/*59*/"mal",
/*60*/"mar",
/*61*/"mkd",
/*62*/"mlt",
/*63*/"msa",
/*64*/"mya",
/*65*/"nep",
/*66*/"nld",
/*67*/"nor",
/*68*/"ori",
/*69*/"osd",
/*70*/"pan",
/*71*/"pol",
/*72*/"por",
/*73*/"pus",
/*74*/"ron",
/*75*/"rus",
/*76*/"san",
/*77*/"sin",
/*78*/"slk",
/*79*/"slv",
/*80*/"spa",
/*81*/"sqi",
/*82*/"srp",
/*83*/"swa",
/*84*/"swe",
/*85*/"syr",
/*86*/"tam",
/*87*/"tel",
/*88*/"tgk",
/*89*/"tgl",
/*90*/"tha",
/*91*/"tir",
/*92*/"tur",
/*93*/"uig",
/*94*/"ukr",
/*95*/"urd",
/*96*/"uzb",
/*97*/"vie",
/*98*/"yid",
NULL
};

View File

@@ -36,6 +36,7 @@ extern 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()
@@ -56,6 +57,7 @@ enum ccx_debug_message_types
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
@@ -98,12 +100,11 @@ 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,
@@ -113,13 +114,13 @@ enum ccx_stream_type
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
@@ -131,6 +132,7 @@ enum ccx_mpeg_descriptor
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,
};
@@ -152,15 +154,18 @@ 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_DVDRAW = 8, // See -d at http://www.geocities.com/mcpoodle43/SCC_TOOLS/DOCS/SCC_TOOLS.HTML#CCExtract
CCX_OF_SPUPNG = 7,
CCX_OF_DVDRAW = 8, // See -d at http://www.theneitherworld.com/mcpoodle/SCC_TOOLS/DOCS/SCC_TOOLS.HTML#CCExtract
CCX_OF_WEBVTT = 9,
CCX_OF_SIMPLE_XML = 10,
CCX_OF_G608 = 11,
};
enum ccx_output_date_format
@@ -174,47 +179,55 @@ 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,
#ifdef ENABLE_FFMPEG
CCX_SM_FFMPEG = 10,
#endif
CCX_SM_GXF = 11,
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,
/* BUffer where cc data contain 3 byte cc_valid ccdata 1 ccdata 2 */
CCX_RAW_TYPE = 9,
};
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 {
@@ -229,8 +242,17 @@ enum ccx_code_type
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.
@@ -242,15 +264,15 @@ enum ccx_code_type
*/
#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.
@@ -263,10 +285,18 @@ enum ccx_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
#define NB_LANGUAGE 5
#define NB_LANGUAGE 100
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

@@ -1,22 +1,22 @@
#include "ccx_common_option.h"
#include "ccx_encoders_common.h"
#include "ccx_decoders_708.h"
#include "utility.h"
struct ccx_s_options ccx_options;
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
options->no_bom = 0;
#else
options->buffer_input = 0; // In linux, not so much.
options->no_bom = 1;
#endif
options->nofontcolor=0; // 1 = don't put <font color> tags
options->notypesetting=0; // 1 = Don't put <i>, <u>, etc typesetting tags
options->no_rollup = 0;
options->noscte20 = 0;
options->no_bom = 0; // Use BOM by default.
options->settings_608.direct_rollup = 0;
options->settings_608.no_rollup = 0;
@@ -24,22 +24,15 @@ void init_options (struct ccx_s_options *options)
options->settings_608.screens_to_process = -1;
options->settings_608.default_color = COL_TRANSPARENT; // Defaults to transparant/no-color.
/* Select subtitle codec */
options->codec = CCX_CODEC_ANY;
options->nocodec = CCX_CODEC_NONE;
/* Credit stuff */
options->start_credits_text=NULL;
options->end_credits_text=NULL;
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->trim_subs=0; // " Remove spaces at sides? "
options->gui_mode_reports=0; // If 1, output in stderr progress updates so the GUI can grab them
options->no_progress_bar=0; // If 1, suppress the output of the progress to stdout
options->sentence_cap =0 ; // FIX CASE? = Fix case?
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
@@ -58,26 +51,36 @@ void init_options (struct ccx_s_options *options)
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->autodash=0; // Add dashes (-) before each speaker automatically?
options->teletext_mode=CCX_TXT_AUTO_NOT_YET_FOUND; // 0=Disabled, 1 = Not found, 2=Found
options->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->keep_output_closed = 0; // By default just keep the file open.
options->force_flush = 0; // Don't flush whenever content is written.
options->append_mode = 0; //By default, files are overwritten.
options->ucla = 0; // By default, -UCLA not used
options->hardsubx = 0; // By default, don't try to extract hard subtitles
options->dvbcolor = 0; // By default, only text detected in DVB
options->dvblang = NULL; // By default, autodetect DVB language
options->ocrlang = NULL; // By default, autodetect .traineddata file
/*HardsubX related stuff*/
options->hardsubx_ocr_mode = 0;
options->hardsubx_subcolor = 0;
options->hardsubx_min_sub_duration = 0.5;
options->hardsubx_detect_italics = 0;
options->hardsubx_conf_thresh = 0.0;
options->hardsubx_hue = 0.0;
options->hardsubx_lum_thresh = 95.0;
options->transcript_settings = ccx_encoders_default_transcript_settings;
options->millis_separator=',';
options->encoding = CCX_ENC_UTF_8;
options->write_format=CCX_OF_SRT; // 0=Raw, 1=srt, 2=SMI
options->date_format=ODF_NONE;
options->output_filename=NULL;
options->out_elementarystream_filename=NULL;
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
options->ts_autoprogram =0; // Try to find a stream with captions automatically (no -pn needed)
options->ts_cappid = 0; // PID for stream that holds caption information
options->ts_forced_cappid = 0; // If 1, never mess with the selected PID
options->ts_forced_program=0; // Specific program to process in TS files, if ts_forced_program_selected==1
options->ts_forced_program_selected=0;
options->ts_datastreamtype = -1; // User WANTED stream type (i.e. use the stream that has this type)
options->ts_forced_streamtype=CCX_STREAM_TYPE_UNKNOWNSTREAM; // User selected (forced) stream type
/* Networking */
options->udpaddr = NULL;
options->udpport=0; // Non-zero => Listen for UDP packets on this port, no files.
@@ -87,19 +90,63 @@ void init_options (struct ccx_s_options *options)
options->tcp_desc = NULL;
options->srv_addr = NULL;
options->srv_port = NULL;
options->line_terminator_lf=0; // 0 = CRLF
options->noautotimeref=0; // Do NOT set time automatically?
options->input_source=CCX_DS_FILE; // Files, stdin or network
options->auto_stream = CCX_SM_AUTODETECT;
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->enc_cfg.with_semaphore = 0;
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->startcreditsnotbefore);
init_boundary_time (&options->startcreditsnotafter);
init_boundary_time (&options->startcreditsforatleast);
init_boundary_time (&options->startcreditsforatmost);
init_boundary_time (&options->endcreditsforatleast);
init_boundary_time (&options->endcreditsforatmost);
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

@@ -4,36 +4,96 @@
#include "ccx_common_timing.h"
#include "ccx_decoders_608.h"
#include "ccx_encoders_structs.h"
struct ccx_s_options // Options from user parameters
#include "list.h"
struct demuxer_cfg
{
int extract; // Extract 1st, 2nd or both fields
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;
int no_bom; // Set to 1 when no BOM (Byte Order Mark) should be used for files. Note, this might make files unreadable in windows!
ccx_decoder_608_settings settings_608; // Contains the settings for the 608 decoder.
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
int keep_output_closed;
int force_flush; // Force flush on content write
int append_mode; //Append mode for output files
int ucla; // 1 if -UCLA used, 0 if not
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?
int with_semaphore; // Write a .sem file on file open and delete it on close?
/* 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 noscte20;
int cc_channel; // Channel we want to dump in srt mode
int buffer_input;
int nofontcolor;
int nohtmlescape;
int notypesetting;
struct ccx_boundary_time extraction_start, extraction_end; // Segment we actually process
int print_file_reports;
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 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
@@ -44,7 +104,7 @@ struct ccx_s_options // Options from user parameters
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
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
@@ -52,45 +112,55 @@ struct ccx_s_options // Options from user parameters
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
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
int keep_output_closed;
int force_flush; // Force flush on content write
int append_mode; //Append mode for output files
int ucla; // 1 if UCLA used, 0 if not
int hardsubx; // 1 if burned-in subtitles to be extracted
int dvbcolor; // 1 if Color to be detected for DVB
char *dvblang; // The name of the language stream for DVB
char *ocrlang; // The name of the .traineddata file to be loaded with tesseract
/*HardsubX related stuff*/
int hardsubx_ocr_mode;
int hardsubx_subcolor;
float hardsubx_min_sub_duration;
int hardsubx_detect_italics;
float hardsubx_conf_thresh;
float hardsubx_hue;
float hardsubx_lum_thresh;
ccx_encoders_transcript_format transcript_settings; // Keeps the settings for generating transcript output files.
char millis_separator;
enum ccx_encoding_type encoding;
enum ccx_output_format write_format; // 0=Raw, 1=srt, 2=SMI
enum ccx_output_date_format date_format;
char *output_filename;
char *out_elementarystream_filename;
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
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 *tcp_desc;
char *srv_addr;
char *srv_port;
int line_terminator_lf; // 0 = CRLF, 1=LF
int noautotimeref; // Do NOT set time automatically?
enum ccx_datasource input_source; // Files, stdin or network
char *output_filename;
char **inputfile; // List of files to process
int num_input_files; // How many?
enum ccx_stream_mode_enum auto_stream;
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.
// Output structures
struct ccx_s_write wbout1;
struct ccx_s_write wbout2;
int multiprogram;
int out_interval;
};
extern struct ccx_s_options ccx_options;

View File

@@ -14,6 +14,8 @@
#define __STDC_FORMAT_MACROS
#ifdef _WIN32
#define inline _inline
#define typeof decltype
#include <io.h>
#include <ws2tcpip.h>
#include <windows.h>
@@ -110,4 +112,4 @@
typedef int64_t LLONG;
#endif // CCX_PLATFORM_H
#endif // CCX_PLATFORM_H

View File

@@ -1,6 +1,8 @@
#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
@@ -9,7 +11,7 @@ enum ccx_common_logging_gui {
};
struct ccx_common_logging_t {
int debug_mask; // The debug mask that is used to determine if things should be printed or not.
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.
@@ -21,33 +23,52 @@ 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
* 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;
/** 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

@@ -11,32 +11,18 @@
// Count 608 (per field) and 708 blocks since last set_fts() call
int cb_field1, cb_field2, cb_708;
int pts_set; //0 = No, 1 = received, 2 = min_pts set
int MPEG_CLOCK_FREQ = 90000; // This "constant" is part of the standard
LLONG min_pts, max_pts, sync_pts;
LLONG current_pts = 0;
int max_dif = 5;
unsigned pts_big_change;
// PTS timing related stuff
LLONG fts_now; // Time stamp of current file (w/ fts_offset, w/o fts_global)
LLONG fts_offset; // Time before first sync_pts
LLONG fts_fc_offset; // Time before first GOP
LLONG fts_max; // Remember the maximum fts that we saw in current file
LLONG fts_global = 0; // Duration of previous files (-ve mode), see c1global
enum ccx_frame_type current_picture_coding_type = CCX_FRAME_TYPE_RESET_OR_UNKNOWN;
int current_tref = 0; // Store temporal reference of current frame
double current_fps = (double) 30000.0 / 1001; /* 29.97 */ // TODO: Get from framerates_values[] instead
int frames_since_ref_time = 0;
unsigned total_frames_count;
// Remember the current field for 608 decoding
int current_field = 1; // 1 = field 1, 2 = field 2, 3 = 708
struct gop_time_code gop_time, first_gop_time, printed_gop;
LLONG fts_at_gop_start = 0;
int gop_rollover = 0;
@@ -51,263 +37,341 @@ void ccx_common_timing_init(LLONG *file_position,int no_sync)
ccx_common_timing_settings.no_sync = no_sync;
}
void set_fts(void)
void dinit_timing_ctx(struct ccx_common_timing_ctx **arg)
{
int pts_jump = 0;
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;
// ES don't have PTS unless GOP timing is used
if (!pts_set && ccx_common_timing_settings.is_elementary_stream)
return;
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->sync_pts2fts_set = 0;
ctx->sync_pts2fts_fts = 0;
ctx->sync_pts2fts_pts = 0;
// First check for timeline jump (only when min_pts was set (implies sync_pts)).
int dif = 0;
if (pts_set == 2)
{
dif=(int) (current_pts-sync_pts)/MPEG_CLOCK_FREQ;
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",sync_pts);
ccx_common_logging.log_ftn ("Current PTS value: %lld\n",current_pts);
pts_jump = 1;
pts_big_change=1;
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(current_tref != 0 && current_picture_coding_type != CCX_FRAME_TYPE_I_FRAME)
{
fts_now = fts_max;
ccx_common_logging.log_ftn ("Change did not occur on first frame - probably a broken GOP\n");
return;
}
}
}
// 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 (pts_set!=0)
{
pts_set=2;
// 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 (current_pts<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
// 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
min_pts=current_pts;
ctx->min_pts = ctx->current_pts;
// Avoid next async test
sync_pts = (LLONG)(current_pts
-current_tref*1000.0/current_fps
*(MPEG_CLOCK_FREQ/1000));
// Avoid next async test
ctx->sync_pts = (LLONG)(ctx->current_pts
-ctx->current_tref*1000.0/current_fps
*(MPEG_CLOCK_FREQ/1000));
if(current_tref == 0)
{ // Earliest time in GOP.
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.
fts_offset = 0;
}
else
{ // It needs to be "+1" because the current frame is
// not yet counted.
fts_offset = (LLONG)((total_frames_count
-frames_since_ref_time+1)
*1000.0/current_fps);
}
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(min_pts/(MPEG_CLOCK_FREQ/1000)),
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);
}
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.
fts_offset = fts_offset
+ (sync_pts-min_pts)/(MPEG_CLOCK_FREQ/1000)
+ (LLONG) (frames_since_ref_time*1000/current_fps);
fts_max = fts_offset;
// -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
pts_set=1; // Force min to be set again
// Start counting again from here
ctx->pts_set = 1; // Force min to be set again
ctx->sync_pts2fts_set = 0; // Make note of the new conversion values
// Avoid next async test - the gap might have occured on
// current_tref != 0.
sync_pts = (LLONG) (current_pts
-current_tref*1000.0/current_fps
*(MPEG_CLOCK_FREQ/1000));
// Set min_pts = sync_pts as this is used for fts_now
min_pts = sync_pts;
// 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(min_pts/(MPEG_CLOCK_FREQ/1000)),
fts_offset );
}
}
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(current_tref == 0)
sync_pts = current_pts;
// 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;
// Reset counters
cb_field1 = 0;
cb_field2 = 0;
cb_708 = 0;
// Avoid wrong "Calc. difference" and "Asynchronous by" numbers
// for uninitialized min_pts
// Avoid wrong "Calc. difference" and "Asynchronous by" numbers
// for uninitialized min_pts
if (1) // CFS: Remove or think decent condition
{
if ( pts_set )
if ( ctx->pts_set )
{
// If pts_set is TRUE we have min_pts
fts_now = (LLONG)((current_pts-min_pts)/(MPEG_CLOCK_FREQ/1000)
+ fts_offset);
ctx->fts_now = (LLONG)((ctx->current_pts - ctx->min_pts)/(MPEG_CLOCK_FREQ/1000)
+ ctx->fts_offset);
if (!ctx->sync_pts2fts_set)
{
ctx->sync_pts2fts_pts = ctx->current_pts;
ctx->sync_pts2fts_fts = ctx->fts_now;
ctx->sync_pts2fts_set = 1;
}
}
else
{
// No PTS info at all!!
ccx_common_logging.fatal_ftn(CCX_COMMON_EXIT_BUG_BUG,
"No PTS info. Please write bug report.");
ccx_common_logging.log_ftn("Set PTS called without any global timestamp set\n");
return CCX_EINVAL;
}
}
if ( fts_now > fts_max )
{
fts_max = fts_now;
}
if ( ctx->fts_now > ctx->fts_max )
{
ctx->fts_max = ctx->fts_now;
}
return CCX_OK;
}
LLONG get_fts(void)
LLONG get_fts(struct ccx_common_timing_ctx *ctx, int current_field)
{
LLONG fts;
LLONG fts;
switch (current_field)
{
case 1:
fts = fts_now + fts_global + cb_field1*1001/30;
break;
case 2:
fts = fts_now + fts_global + cb_field2*1001/30;
break;
case 3:
fts = fts_now + fts_global + cb_708*1001/30;
break;
default:
ccx_common_logging.fatal_ftn(CCX_COMMON_EXIT_BUG_BUG, "Cannot be reached!");
}
return 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(void)
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 fts_max + fts_global;
// 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. */
to the microsecond value in mstime. */
char *print_mstime2buf( LLONG mstime , char *buf )
{
unsigned hh,mm,ss,ms;
int signoffset = (mstime < 0 ? 1 : 0);
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)));
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);
buf[0]='-';
sprintf (buf+signoffset, "%02u:%02u:%02u:%03u",hh,mm,ss,ms);
return buf;
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. */
to the microsecond value in mstime. */
char *print_mstime( LLONG mstime )
{
static char buf[15]; // 14 should be long enough
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( void )
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 = (min_pts==0x01FFFFFFFFLL ? sync_pts : min_pts);
// 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((sync_pts)/(MPEG_CLOCK_FREQ/1000)) );
ccx_common_logging.log_ftn("GOP: %s \n", print_mstime(gop_time.ms));
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)((sync_pts-tempmin_pts)/(MPEG_CLOCK_FREQ/1000)
+ fts_offset);
// 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()));
ccx_common_logging.log_ftn(" GOP start FTS: %s\n",
print_mstime(fts_at_gop_start));
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()+(LLONG)(1000.0/current_fps)-ptslenms,
get_fts_max()+(LLONG)(1000.0/current_fps)-goplenms);
// 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 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 (! ((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;
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

@@ -1,7 +1,8 @@
#ifndef __Timing_H__
#define __Timing_H__
#include "ccx_common_platform.h"
#include "ccx_common_constants.h"
struct gop_time_code
{
int drop_frame_flag;
@@ -14,7 +15,8 @@ struct gop_time_code
LLONG ms;
};
struct ccx_common_timing_settings_t {
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.
@@ -29,44 +31,58 @@ struct ccx_boundary_time
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)
int sync_pts2fts_set; //0 = No, 1 = Yes
LLONG sync_pts2fts_fts;
LLONG sync_pts2fts_pts;
};
// Count 608 (per field) and 708 blocks since last set_fts() call
extern int cb_field1, cb_field2, cb_708;
extern int pts_set; //0 = No, 1 = received, 2 = min_pts set
extern int MPEG_CLOCK_FREQ; // This is part of the standard
extern LLONG min_pts, max_pts, sync_pts, current_pts;
extern int max_dif;
extern unsigned pts_big_change;
extern LLONG fts_now; // Time stamp of current file (w/ fts_offset, w/o fts_global)
extern LLONG fts_offset; // Time before first sync_pts
extern LLONG fts_fc_offset; // Time before first GOP
extern LLONG fts_max; // Remember the maximum fts that we saw in current file
extern LLONG fts_global; // Duration of previous files (-ve mode)
extern enum ccx_frame_type current_picture_coding_type;
extern int current_tref; // Store temporal reference of current frame
extern double current_fps;
extern int frames_since_ref_time;
extern unsigned total_frames_count;
extern int current_field;
extern struct gop_time_code gop_time, first_gop_time, printed_gop;
extern LLONG fts_at_gop_start;
extern int gop_rollover;
void ccx_common_timing_init(LLONG *file_position, int no_sync);
void set_fts(void);
LLONG get_fts(void);
LLONG get_fts_max(void);
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);
void print_debug_timing(void);
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);
#define __Timing_H__
#endif

View File

@@ -10,7 +10,7 @@ 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
const unsigned char pac2_attribs[][3] = // Color, font, ident
{
@@ -48,8 +48,6 @@ const unsigned char pac2_attribs[][3] = // Color, font, ident
{ COL_WHITE, FONT_UNDERLINED, 28 } // 0x5f || 0x7f
};
unsigned char *subline; // Temp storage for .srt lines
int new_sentence=1; // Capitalize next letter?
static const char *command_type[] =
{
@@ -88,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\">"},
@@ -109,7 +108,7 @@ void clear_eia608_cc_buffer(ccx_decoder_608_context *context, struct eia608_scre
{
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->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;
}
@@ -120,11 +119,10 @@ void ccx_decoder_608_dinit_library(void **ctx)
{
freep(ctx);
}
ccx_decoder_608_context* ccx_decoder_608_init_library(ccx_decoder_608_settings settings, int channel,
int field, int trim_subs,
enum ccx_encoding_type encoding, int *halt,
int cc_to_stdout, LLONG subs_delay,
enum ccx_output_format output_format)
ccx_decoder_608_context* 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;
@@ -148,19 +146,18 @@ ccx_decoder_608_context* ccx_decoder_608_init_library(ccx_decoder_608_settings s
data->bytes_processed_608 = 0;
data->my_field = field;
data->my_channel = channel;
data->out = NULL;
data->have_cursor_position = 0;
data->trim_subs = trim_subs;
data->encoding = encoding;
data->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->cc_to_stdout = cc_to_stdout;
data->subs_delay = subs_delay;
data->output_format = output_format;
data->settings = settings;
data->current_color = data->settings.default_color;
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);
@@ -207,7 +204,7 @@ void delete_to_end_of_row(ccx_decoder_608_context *context)
// 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] = context->settings.default_color;
use_buffer->colors[context->cursor_row][i] = context->settings->default_color;
use_buffer->fonts[context->cursor_row][i] = context->font;
}
}
@@ -229,15 +226,15 @@ void write_char(const unsigned char c, ccx_decoder_608_context *context)
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<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);
}
}
@@ -289,8 +286,8 @@ int write_cc_buffer(ccx_decoder_608_context *context, struct cc_subtitle *sub)
LLONG end_time;
if (context->settings.screens_to_process != -1 &&
context->screenfuls_counter >= context->settings.screens_to_process)
if (context->settings->screens_to_process != -1 &&
context->screenfuls_counter >= context->settings->screens_to_process)
{
// We are done.
*context->halt=1;
@@ -304,7 +301,7 @@ int write_cc_buffer(ccx_decoder_608_context *context, struct cc_subtitle *sub)
context->current_visible_start_ms = context->ts_start_of_current_line;
start_time = context->current_visible_start_ms;
end_time = get_visible_end() + context->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;
@@ -313,7 +310,7 @@ int write_cc_buffer(ccx_decoder_608_context *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)
@@ -357,11 +354,10 @@ int write_cc_line(ccx_decoder_608_context *context, struct cc_subtitle *sub)
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 + context->subs_delay;
end_time = get_fts() + context->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->start_time = 0;
@@ -370,9 +366,7 @@ int write_cc_line(ccx_decoder_608_context *context, struct cc_subtitle *sub)
data->channel = context->channel;
data->my_field = context->my_field;
//TODO need to put below functionality in encoder context
ret = get_decoder_line_basic (subline, context->cursor_row, data,context->trim_subs,context->encoding);
if( ret > 0 )
if (!data->empty)
{
sub->data = (struct eia608_screen *) realloc(sub->data,(sub->nb_data +1) * sizeof(*data));
if (!sub->data)
@@ -534,13 +528,13 @@ int roll_up(ccx_decoder_608_context *context)
for (int j = 0; j<(1 + context->cursor_row - keep_lines); j++)
{
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->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], ' ', CCX_DECODER_608_SCREEN_WIDTH);
memset(use_buffer->colors[lastrow], context->settings.default_color, 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][CCX_DECODER_608_SCREEN_WIDTH] = 0;
@@ -599,7 +593,7 @@ int is_current_row_empty(ccx_decoder_608_context *context)
}
/* Process GLOBAL CODES */
void handle_command(/*const */ unsigned char c1, const unsigned char c2, ccx_decoder_608_context *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;
@@ -646,12 +640,12 @@ void handle_command(/*const */ unsigned char c1, const unsigned char c2, ccx_dec
if ((c1==0x14 || c1==0x1C) && c2==0x2b)
command = COM_RESUMETEXTDISPLAY;
if ((command == COM_ROLLUP2 || command == COM_ROLLUP3 || command == COM_ROLLUP4) && context->settings.force_rollup == 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) && context->settings.force_rollup == 2)
if ((command == COM_ROLLUP3 || command == COM_ROLLUP4) && context->settings->force_rollup == 2)
command=COM_ROLLUP2;
else if (command == COM_ROLLUP4 && context->settings.force_rollup == 3)
else if (command == COM_ROLLUP4 && context->settings->force_rollup == 3)
command=COM_ROLLUP3;
ccx_common_logging.debug_ftn(CCX_DMT_DECODER_608, "\rCommand begin: %02X %02X (%s)\n", c1, c2, command_type[command]);
@@ -756,14 +750,14 @@ void handle_command(/*const */ unsigned char c1, const unsigned char c2, ccx_dec
{
if (write_cc_buffer(context, sub))
context->screenfuls_counter++;
if (context->settings.no_rollup)
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:
@@ -791,7 +785,7 @@ void handle_command(/*const */ unsigned char c1, const unsigned char c2, ccx_dec
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
@@ -799,10 +793,10 @@ void handle_command(/*const */ unsigned char c1, const unsigned char c2, ccx_dec
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->current_color = context->settings.default_color;
context->current_color = context->settings->default_color;
context->font = FONT_REGULAR;
context->mode = MODE_POPON;
break;
@@ -828,7 +822,7 @@ void handle_command(/*const */ unsigned char c1, const unsigned char c2, ccx_dec
}
void handle_end_of_data(ccx_decoder_608_context *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.
@@ -926,7 +920,7 @@ void handle_pac(unsigned char c1, unsigned char c2, ccx_decoder_608_context *con
int indent=pac2_attribs[c2][2];
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))
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)
{
@@ -949,7 +943,7 @@ void handle_pac(unsigned char c1, unsigned char c2, ccx_decoder_608_context *con
if (use_buffer->row_used[j])
{
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->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;
@@ -977,10 +971,10 @@ void erase_both_memories(ccx_decoder_608_context *context, struct cc_subtitle *s
// 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->current_color = context->settings.default_color;
context->current_color = context->settings->default_color;
context->font = FONT_REGULAR;
erase_memory(context, true);
@@ -1075,15 +1069,29 @@ int disCommand(unsigned char hi, unsigned char lo, ccx_decoder_608_context *cont
return wrote_to_screen;
}
/* If wb is NULL, then only XDS will be processed */
int process608(const unsigned char *data, int length, ccx_decoder_608_context *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)
{
struct ccx_decoder_608_report *report = NULL;
static int textprinted = 0;
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;
report = context->report;
context->bytes_processed_608 += length;
}
if (!data)
@@ -1118,35 +1126,37 @@ int process608(const unsigned char *data, int length, ccx_decoder_608_context *c
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;
}
if(report)
report->xds=1;
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;
}
if (hi>=0x10 && hi<=0x1F) // Non-character code or special/extended char
// http://www.geocities.com/mcpoodle43/SCC_TOOLS/DOCS/CC_CODES.HTML
// http://www.geocities.com/mcpoodle43/SCC_TOOLS/DOCS/CC_CHARS.HTML
// http://www.theneitherworld.com/mcpoodle/SCC_TOOLS/DOCS/CC_CODES.HTML
// http://www.theneitherworld.com/mcpoodle/SCC_TOOLS/DOCS/CC_CHARS.HTML
{
// We were writing characters before, start a new line for
// diagnostic output from disCommand()
if (textprinted == 1 )
{
ccx_common_logging.debug_ftn(CCX_DMT_DECODER_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
@@ -1167,7 +1177,7 @@ int process608(const unsigned char *data, int length, ccx_decoder_608_context *c
{
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.
@@ -1182,10 +1192,10 @@ int process608(const unsigned char *data, int length, ccx_decoder_608_context *c
if (context->channel != context->my_channel)
continue;
if( textprinted == 0 )
if( context->textprinted == 0 )
{
ccx_common_logging.debug_ftn(CCX_DMT_DECODER_608, "\n");
textprinted = 1;
context->textprinted = 1;
}
handle_single(hi, context);
@@ -1195,16 +1205,16 @@ int process608(const unsigned char *data, int length, ccx_decoder_608_context *c
context->last_c2 = 0;
}
if (!textprinted && context->channel == context->my_channel)
if (!context->textprinted && context->channel == context->my_channel)
{ // Current FTS information after the characters are shown
ccx_common_logging.debug_ftn(CCX_DMT_DECODER_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 && context->settings.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 ||
@@ -1212,7 +1222,7 @@ int process608(const unsigned char *data, int length, ccx_decoder_608_context *c
{
// 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 && context->cc_to_stdout)

View File

@@ -1,5 +1,5 @@
#ifndef __608_H__
#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"
@@ -7,14 +7,14 @@
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.
*/
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
{
unsigned xds : 1;
unsigned cc_channels[4];
uint8_t xds : 1;
uint8_t cc_channels[4];
};
typedef struct ccx_decoder_608_settings
@@ -24,11 +24,12 @@ typedef struct ccx_decoder_608_settings
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;
ccx_decoder_608_settings *settings;
eia608_screen buffer1;
eia608_screen buffer2;
int cursor_row, cursor_column;
@@ -47,65 +48,60 @@ typedef struct ccx_decoder_608_context
int my_field; // Used for sanity checks
int my_channel; // Used for sanity checks
long bytes_processed_608; // To be written ONLY by process_608
struct ccx_s_write *out;
int have_cursor_position;
int trim_subs;
enum ccx_encoding_type encoding;
int *halt; // Can be used to halt the feeding of caption data. Set to 1 if screens_to_progress != -1 && screenfuls_counter >= screens_to_process
int cc_to_stdout; // If this is set to 1, the stdout will be flushed when data was written to the screen during a process_608 call.
struct ccx_decoder_608_report report;
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;
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];
#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
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
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_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,
@@ -121,18 +117,17 @@ void ccx_decoder_608_dinit_library(void **ctx);
/*
*
*/
ccx_decoder_608_context* ccx_decoder_608_init_library(ccx_decoder_608_settings settings, int channel,
int field, int trim_subs,
enum ccx_encoding_type encoding, int *halt,
int cc_to_stdout, LLONG subs_delay,
enum ccx_output_format output_format);
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 context context of cc608 where important information related to 608
* @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
@@ -140,15 +135,14 @@ ccx_decoder_608_context* ccx_decoder_608_init_library(ccx_decoder_608_settings s
*
* @return number of bytes used from data, -1 when any error is encountered
*/
int process608(const unsigned char *data, int length, ccx_decoder_608_context *context, struct cc_subtitle *sub);
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 handle_end_of_data(ccx_decoder_608_context *context, struct cc_subtitle *sub);
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);
#define __608_H__
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -2,312 +2,371 @@
#define _INCLUDE_708_
#include <sys/stat.h>
#include "ccx_decoders_common.h"
#include "ccx_common_platform.h"
#include "ccx_common_constants.h"
#include "ccx_common_structs.h"
#define MAX_708_PACKET_LENGTH 128
#define CCX_DECODERS_708_MAX_SERVICES 63
#define CCX_DTVCC_MAX_PACKET_LENGTH 128 //According to EIA-708B, part 5
#define CCX_DTVCC_MAX_SERVICES 63
#define I708_MAX_ROWS 15
#define I708_MAX_COLUMNS 42
#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 I708_SCREENGRID_ROWS 75
#define I708_SCREENGRID_COLUMNS 210
#define CCX_DTVCC_SCREENGRID_ROWS 75
#define CCX_DTVCC_SCREENGRID_COLUMNS 210
#define I708_MAX_WINDOWS 8
#define CCX_DTVCC_MAX_WINDOWS 8
/*
This variable (ccx_decoder_708_report) holds data on the cc channels & xds packets that are encountered during file parse.
This can be interesting if you just want to know what kind of data a file holds that has 608 packets. CCExtractor uses it
for the report functionality.
*/
struct ccx_decoder_708_report_t
#define CCX_DTVCC_FILENAME_TEMPLATE ".p%u.svc%02u"
#define CCX_DTVCC_NO_LAST_SEQUENCE -1
enum CCX_DTVCC_COMMANDS_C0_CODES
{
unsigned services[CCX_DECODERS_708_MAX_SERVICES];
};
extern struct ccx_decoder_708_report_t ccx_decoder_708_report;
enum COMMANDS_C0_CODES
{
NUL=0,
ETX=3,
BS=8,
FF=0xC,
CR=0xD,
HCR=0xE,
EXT1=0x10,
P16=0x18
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 COMMANDS_C1_CODES
enum CCX_DTVCC_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
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 S_COMMANDS_C1
struct CCX_DTVCC_S_COMMANDS_C1
{
int code;
const char *name;
const char *description;
int length;
int code;
const char *name;
const char *description;
int length;
};
enum eWindowsAttribJustify
enum ccx_dtvcc_window_justify
{
left=0,
right=1,
center=2,
full=3
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 eWindowsAttribPrintDirection
enum ccx_dtvcc_window_pd //Print Direction
{
pd_left_to_right=0,
pd_right_to_left=1,
pd_top_to_bottom=2,
pd_bottom_to_top=3
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 eWindowsAttribScrollDirection
enum ccx_dtvcc_window_sd //Scroll Direction
{
sd_left_to_right=0,
sd_right_to_left=1,
sd_top_to_bottom=2,
sd_bottom_to_top=3
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 eWindowsAttribScrollDisplayEffect
enum ccx_dtvcc_window_sde //Scroll Display Effect
{
snap=0,
fade=1,
wipe=2
CCX_DTVCC_WINDOW_SDE_SNAP = 0,
CCX_DTVCC_WINDOW_SDE_FADE = 1,
CCX_DTVCC_WINDOW_SDE_WIPE = 2
};
enum eWindowsAttribEffectDirection
enum ccx_dtvcc_window_ed //Effect Direction
{
left_to_right=0,
right_to_left=1,
top_to_bottom=2,
bottom_to_top=3
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 eWindowsAttribFillOpacity
enum ccx_dtvcc_window_fo //Fill Opacity
{
solid=0,
flash=1,
traslucent=2,
transparent=3
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 eWindowsAttribBorderType
enum ccx_dtvcc_window_border
{
none=0,
raised=1,
depressed=2,
uniform=3,
shadow_left=4,
shadow_right=5
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 ePenAttribSize
enum ccx_dtvcc_pen_size
{
pensize_small=0,
pensize_standard=1,
pensize_large=2
CCX_DTVCC_PEN_SIZE_SMALL = 0,
CCX_DTVCC_PEN_SIZE_STANDART = 1,
CCX_DTVCC_PEN_SIZE_LARGE = 2
};
enum ePenAttribFontStyle
enum ccx_dtvcc_pen_font_style
{
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
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 ePanAttribTextTag
enum ccx_dtvcc_pen_text_tag
{
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
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 ePanAttribOffset
enum ccx_dtvcc_pen_offset
{
offset_subscript=0,
offset_normal=1,
offset_superscript=2
CCX_DTVCC_PEN_OFFSET_SUBSCRIPT = 0,
CCX_DTVCC_PEN_OFFSET_NORMAL = 1,
CCX_DTVCC_PEN_OFFSET_SUPERSCRIPT = 2
};
enum ePanAttribEdgeType
enum ccx_dtvcc_pen_edge
{
edgetype_none=0,
edgetype_raised=1,
edgetype_depressed=2,
edgetype_uniform=3,
edgetype_left_drop_shadow=4,
edgetype_right_drop_shadow=5
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 eAnchorPoints
enum ccx_dtvcc_pen_anchor_point
{
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
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 e708Pen_color
typedef struct ccx_dtvcc_pen_color
{
int fg_color;
int fg_opacity;
int bg_color;
int bg_opacity;
int edge_color;
} e708Pen_color;
int fg_color;
int fg_opacity;
int bg_color;
int bg_opacity;
int edge_color;
} ccx_dtvcc_pen_color;
typedef struct e708Pen_attribs
typedef struct ccx_dtvcc_pen_attribs
{
int pen_size;
int offset;
int text_tag;
int font_tag;
int edge_type;
int underline;
int italic;
} e708Pen_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 e708Window_attribs
typedef struct ccx_dtvcc_window_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;
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;
typedef struct e708Window
/**
* 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
{
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;
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;
} e708Window;
LLONG time_ms_show;
LLONG time_ms_hide;
} ccx_dtvcc_window;
typedef struct tvscreen
typedef struct dtvcc_tv_screen
{
unsigned char chars[I708_SCREENGRID_ROWS][I708_SCREENGRID_COLUMNS+1];
}
tvscreen;
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;
typedef struct cc708_service_decoder
/**
* 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
{
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;
enum ccx_output_format output_format; // What kind of output format should be used?
LLONG subs_delay; // ms to delay (or advance) subs
}
cc708_service_decoder;
int reset_count;
unsigned services[CCX_DTVCC_MAX_SERVICES];
} ccx_decoder_dtvcc_report;
extern int do_cea708; // Process 708 data?
extern int cea708services[]; // [] -> 1 for services to be processed
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;
extern int resets_708;
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;
void do_708 (struct lib_cc_decode* ctx, const unsigned char *data, int datalength);
/**
* TODO
* solution requires "sink" or "writer" entity to write captions to output file
* decoders have to know nothing about output files
*/
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);
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);
void ccx_decoders_708_init_library(char *basefilename,const char *extension, int report);
#endif

View File

@@ -12,34 +12,34 @@ EIA-708, SO INTERNALLY WE USE THIS TABLE (FOR CONVENIENCE)
A0-FF -> Group G1 as is - non-English characters and symbols
*/
unsigned char get_internal_from_G0 (unsigned char g0_char)
unsigned char dtvcc_get_internal_from_G0(unsigned char g0_char)
{
return g0_char;
return g0_char;
}
unsigned char get_internal_from_G1 (unsigned char g1_char)
unsigned char dtvcc_get_internal_from_G1(unsigned char g1_char)
{
return 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)
unsigned char dtvcc_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;
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 get_internal_from_G3 (unsigned char g3_char)
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;
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),"%s", (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

@@ -8,96 +8,37 @@ made to reuse, not duplicate, as many functions as possible */
#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;
// Preencoded strings
unsigned char encoded_crlf[16];
unsigned int encoded_crlf_length;
unsigned char encoded_br[16];
unsigned int encoded_br_length;
LLONG minimum_fts = 0; // No screen should start before this FTS
/* This function returns a FTS that is guaranteed to be at least 1 ms later than the end of the previous screen. It shouldn't be needed
obviously but it guarantees there's no timing overlap */
LLONG get_visible_start (void)
LLONG get_visible_start (struct ccx_common_timing_ctx *ctx, int current_field)
{
LLONG fts = get_fts();
if (fts <= minimum_fts)
fts = minimum_fts+1;
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 get_visible_start */
LLONG get_visible_end (void)
/* 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();
if (fts>minimum_fts)
minimum_fts=fts;
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;
}
void find_limit_characters(unsigned char *line, int *first_non_blank, int *last_non_blank)
{
*last_non_blank = -1;
*first_non_blank = -1;
for (int i = 0; i<CCX_DECODER_608_SCREEN_WIDTH; i++)
{
unsigned char c = line[i];
if (c != ' ' && c != 0x89)
{
if (*first_non_blank == -1)
*first_non_blank = i;
*last_non_blank = i;
}
}
}
unsigned get_decoder_line_basic(unsigned char *buffer, int line_num, struct eia608_screen *data, int trim_subs, enum ccx_encoding_type encoding)
{
unsigned char *line = data->characters[line_num];
int last_non_blank = -1;
int first_non_blank = -1;
unsigned char *orig = buffer; // Keep for debugging
find_limit_characters(line, &first_non_blank, &last_non_blank);
if (!trim_subs)
first_non_blank = 0;
if (first_non_blank == -1)
{
*buffer = 0;
return 0;
}
int bytes = 0;
for (int i = first_non_blank; i <= last_non_blank; i++)
{
char c = line[i];
switch (encoding)
{
case CCX_ENC_UTF_8:
bytes = get_char_in_utf_8(buffer, c);
break;
case CCX_ENC_LATIN_1:
get_char_in_latin_1(buffer, c);
bytes = 1;
break;
case CCX_ENC_UNICODE:
get_char_in_unicode(buffer, c);
bytes = 2;
break;
}
buffer += bytes;
}
*buffer = 0;
return (unsigned)(buffer - orig); // Return length
}
int process_cc_data (struct lib_cc_decode *ctx, unsigned char *cc_data, int cc_count, struct cc_subtitle *sub)
{
int ret = -1;
@@ -139,20 +80,20 @@ int validate_cc_data_pair (unsigned char *cc_data_pair)
}
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;
unsigned char cc_valid = (*cc_block & 4) >>2;
unsigned char cc_type = *cc_block & 3;
int timeok = 1;
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->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 &&
@@ -160,116 +101,128 @@ int do_cb (struct lib_cc_decode *ctx, unsigned char *cc_block, struct cc_subtitl
&& (cc_block[1]&0x7F)==0 && (cc_block[2]&0x7F)==0) // CFS: Skip non-data, makes debugging harder.
return 1;
// Print raw data with FTS.
dbg_print(CCX_DMT_CBRAW, "%s %d %02X:%c%c:%02X", print_mstime(fts_now + fts_global),in_xds_mode,
cc_block[0], cc_block[1]&0x7f,cc_block[2]&0x7f, cc_block[2]);
// 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 do_708() must not be called for
* the CCX_OF_RCWT case. */
/* 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]++;
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));
switch (cc_type)
{
case 0:
dbg_print(CCX_DMT_CBRAW, " %s .. ..\n", debug_608toASC( cc_block, 0));
current_field=1;
ctx->saw_caption_block = 1;
ctx->current_field = 1;
ctx->saw_caption_block = 1;
if (ctx->extraction_start.set &&
get_fts() < ctx->extraction_start.time_in_ms)
timeok = 0;
if (ctx->extraction_end.set &&
get_fts() > ctx->extraction_end.time_in_ms)
{
timeok = 0;
ctx->processed_enough=1;
}
if (timeok)
{
if(ctx->write_format!=CCX_OF_RCWT)
printdata (ctx, cc_block+1,2,0,0, sub);
else
writercwtdata(ctx, cc_block);
}
cb_field1++;
break;
case 1:
dbg_print(CCX_DMT_CBRAW, " .. %s ..\n", debug_608toASC( cc_block, 1));
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));
current_field=2;
ctx->saw_caption_block = 1;
ctx->current_field = 2;
ctx->saw_caption_block = 1;
if (ctx->extraction_start.set &&
get_fts() < ctx->extraction_start.time_in_ms)
timeok = 0;
if (ctx->extraction_end.set &&
get_fts() > ctx->extraction_end.time_in_ms)
{
timeok = 0;
ctx->processed_enough=1;
}
if (timeok)
{
if(ctx->write_format!=CCX_OF_RCWT)
printdata (ctx, 0,0,cc_block+1,2, sub);
else
writercwtdata(ctx, cc_block);
}
cb_field2++;
break;
case 2: //EIA-708
// DTVCC packet data
// Fall through
case 3: //EIA-708
dbg_print(CCX_DMT_CBRAW, " .. .. DD\n");
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
current_field=3;
// DTVCC packet start
ctx->current_field = 3;
if (ctx->extraction_start.set &&
get_fts() < ctx->extraction_start.time_in_ms)
timeok = 0;
if (ctx->extraction_end.set &&
get_fts() > ctx->extraction_end.time_in_ms)
{
timeok = 0;
ctx->processed_enough=1;
}
char temp[4];
temp[0]=cc_valid;
temp[1]=cc_type;
temp[2]=cc_block[1];
temp[3]=cc_block[2];
if (timeok)
{
if(ctx->write_format!=CCX_OF_RCWT)
do_708 (ctx,(const unsigned char *) temp, 4);
else
writercwtdata(ctx, cc_block);
}
cb_708++;
// Check for bytes read
// printf ("Warning: Losing EIA-708 data!\n");
break;
default:
fatal(CCX_COMMON_EXIT_BUG_BUG, "Cannot be reached!");
} // switch (cc_type)
} // cc_valid
else
{
dbg_print(CCX_DMT_CBRAW, " .. .. ..\n");
dbg_print(CCX_DMT_VERBOSE, "Found !(cc_valid || cc_type==3) - ignore this block\n");
}
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;
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;
@@ -278,42 +231,177 @@ struct lib_cc_decode* init_cc_decode (struct ccx_decoders_common_settings_t *set
if(!ctx)
return NULL;
// Prepare 608 context
ctx->context_cc608_field_1 = ccx_decoder_608_init_library(
ccx_options.settings_608,
ccx_options.cc_channel,
1,
ccx_options.trim_subs,
ccx_options.encoding,
&ctx->processed_enough,
setting->cc_to_stdout,
setting->subs_delay,
setting->output_format
);
ctx->context_cc608_field_2 = ccx_decoder_608_init_library(
ccx_options.settings_608,
ccx_options.cc_channel,
2,
ccx_options.trim_subs,
ccx_options.encoding,
&ctx->processed_enough,
setting->cc_to_stdout,
setting->subs_delay,
setting->output_format
);
ctx->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->noscte20 = setting->noscte20;
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->wbout1 = setting->wbout1;
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;
ctx->total_pulldownfields = 0;
ctx->total_pulldownframes = 0;
ctx->stat_numuserheaders = 0;
ctx->stat_dvdccheaders = 0;
ctx->stat_scte20ccheaders = 0;
ctx->stat_replay5000headers = 0;
ctx->stat_replay4000headers = 0;
ctx->stat_dishheaders = 0;
ctx->stat_hdtv = 0;
ctx->stat_divicom = 0;
ctx->false_pict_header = 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_G608 ||
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->output_format!=CCX_OF_TRANSCRIPT)
{
setting->xds_write_to_file = 0;
}
ctx->xds_ctx = ccx_decoders_xds_init_library(ctx->timing, setting->xds_write_to_file);
ctx->vbi_decoder = NULL;
return ctx;
}
void dinit_cc_decode(struct lib_cc_decode **ctx)
void flush_cc_decode(struct lib_cc_decode *ctx, struct cc_subtitle *sub)
{
struct lib_cc_decode *lctx = *ctx;
ccx_decoder_608_dinit_library(&lctx->context_cc608_field_1);
ccx_decoder_608_dinit_library(&lctx->context_cc608_field_2);
freep(ctx);
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

@@ -5,22 +5,15 @@
#include "ccx_common_constants.h"
#include "ccx_common_structs.h"
#include "ccx_decoders_structs.h"
extern unsigned char encoded_crlf[16]; // We keep it encoded here so we don't have to do it many times
extern unsigned int encoded_crlf_length;
extern unsigned char encoded_br[16];
extern unsigned int encoded_br_length;
extern LLONG minimum_fts; // No screen should start before this FTS
#include "ccx_common_option.h"
extern uint64_t utc_refvalue; // UTC referential value
// Declarations
LLONG get_visible_start(void);
LLONG get_visible_end(void);
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);
void find_limit_characters(unsigned char *line, int *first_non_blank, int *last_non_blank);
unsigned get_decoder_line_basic(unsigned char *buffer, int line_num, struct eia608_screen *data, int trim_subs, enum ccx_encoding_type encoding);
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);
@@ -31,4 +24,5 @@ void printdata (struct lib_cc_decode *ctx, const unsigned char *data1, int lengt
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

@@ -4,9 +4,14 @@
#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 )
@@ -81,9 +86,22 @@ struct ccx_decoders_common_settings_t
enum ccx_output_format output_format; // What kind of output format should be used?
int fix_padding; // Replace 0000 with 8080 in HDTV (needed for some cards)
struct ccx_boundary_time extraction_start, extraction_end; // Segment we actually process
void *wbout1;
int cc_to_stdout;
int extract; // Extract 1st, 2nd or both fields
int fullbin; // Disable pruning of padding cc blocks
int no_rollup;
int noscte20;
struct ccx_decoder_608_settings *settings_608; // Contains the settings for the 608 decoder.
ccx_decoder_dtvcc_settings *settings_dtvcc; //Same for cea 708 captions decoder (dtvcc)
int cc_channel; // Channel we want to dump in srt mode
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 xds_write_to_file;
void *private_data;
};
struct lib_cc_decode
{
int cc_stats[4];
@@ -95,11 +113,88 @@ struct lib_cc_decode
void *context_cc608_field_1;
void *context_cc608_field_2;
int no_rollup; // If 1, write one line at a time
int noscte20;
int fix_padding; // Replace 0000 with 8080 in HDTV (needed for some cards)
enum ccx_output_format write_format; // 0=Raw, 1=srt, 2=SMI
struct ccx_boundary_time extraction_start, extraction_end; // Segment we actually process
void *wbout1;
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
/* Stats. Modified in es_userdata.c*/
int stat_numuserheaders;
int stat_dvdccheaders;
int stat_scte20ccheaders;
int stat_replay5000headers;
int stat_replay4000headers;
int stat_dishheaders;
int stat_hdtv;
int stat_divicom;
int false_pict_header;
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;
struct ccx_decoder_vbi_ctx *vbi_decoder;
int (*writedata)(const unsigned char *data, int length, void *private_data, struct cc_subtitle *sub);
};
#endif

View File

@@ -0,0 +1,100 @@
#include "ccx_decoders_vbi.h"
#include "ccx_decoders_common.h"
#include "ccx_common_constants.h"
#include "ccx_common_common.h"
#include "utility.h"
#include "stdlib.h"
void delete_decoder_vbi(struct ccx_decoder_vbi_ctx** arg)
{
struct ccx_decoder_vbi_ctx* ctx = *arg;
vbi_raw_decoder_destroy (&ctx->zvbi_decoder);
freep(arg);
}
struct ccx_decoder_vbi_ctx* init_decoder_vbi(struct ccx_decoder_vbi_cfg *cfg)
{
struct ccx_decoder_vbi_ctx *vbi;
vbi = malloc(sizeof(*vbi));
if(!vbi)
return NULL;
#ifdef VBI_DEBUG
vbi->vbi_debug_dump = fopen("dump_720.vbi","w");
#endif
vbi_raw_decoder_init (&vbi->zvbi_decoder);
if(cfg == NULL)
{
/* Specify the image format. */
vbi->zvbi_decoder.scanning = 525;
/* The decoder ignores chroma data. */
vbi->zvbi_decoder.sampling_format = VBI_PIXFMT_YUV420;
/* You may have to adjust this. */
vbi->zvbi_decoder.sampling_rate = 13.5e6; /* Hz */
vbi->zvbi_decoder.bytes_per_line = 720;
/* Sampling starts 9.7 µs from the front edge of the
hor. sync pulse. You may have to adjust this. */
vbi->zvbi_decoder.offset = 9.7e-6 * 13.5e6;
/* Which lines were captured from the first field.
You may have to adjust this. */
vbi->zvbi_decoder.start[0] = 21;
vbi->zvbi_decoder.count[0] = 1;
/* Second field. */
vbi->zvbi_decoder.start[1] = 284;
vbi->zvbi_decoder.count[1] = 1;
/* The image contains all lines of the first field,
followed by all lines of the second field. */
vbi->zvbi_decoder.interlaced = CCX_TRUE;
/* The first field is always first in memory. */
vbi->zvbi_decoder.synchronous = CCX_TRUE;
/* Specify the services you want. */
vbi_raw_decoder_add_services (&vbi->zvbi_decoder, VBI_SLICED_CAPTION_525, /* strict */ 0);
}
return vbi;
}
int decode_vbi(struct lib_cc_decode *dec_ctx, uint8_t field, unsigned char *buffer, size_t len, struct cc_subtitle *sub)
{
int i = 0;
unsigned int n_lines;
vbi_sliced sliced[52];
if(dec_ctx->vbi_decoder == NULL)
{
dec_ctx->vbi_decoder = init_decoder_vbi(NULL);
}
len -= 720;
n_lines = vbi_raw_decode(&dec_ctx->vbi_decoder->zvbi_decoder, buffer, sliced);
//n_lines = vbi3_raw_decoder_decode (&dec_ctx->vbi_decoder->zvbi_decoder, sliced, 2, buffer);
if (n_lines > 0)
{
for (i = 0; i < n_lines; ++i)
{
int index = 0;
//for(index = 0; index < 56; index += 2)
{
unsigned char data[3];
if (field == 1)
data[0] = 0x04;
else
data[0] = 0x05;
data[1] = sliced[i].data[index];
data[2] = sliced[i].data[index+1];
do_cb(dec_ctx, data, sub);
}
}
}
return CCX_OK;
}

View File

@@ -0,0 +1,28 @@
#ifndef CCX_DECODER_VBI
#define CCX_DECODER_VBI
#include <zvbi_decoder.h>
#define VBI_DEBUG
#include "ccx_decoders_structs.h"
struct ccx_decoder_vbi_cfg
{
#ifdef VBI_DEBUG
char *debug_file_name;
#endif
};
struct ccx_decoder_vbi_ctx
{
int vbi_decoder_inited;
vbi_raw_decoder zvbi_decoder;
//vbi3_raw_decoder zvbi_decoder;
#ifdef VBI_DEBUG
FILE *vbi_debug_dump;
#endif
};
int decode_vbi(struct lib_cc_decode *dec_ctx, uint8_t field, unsigned char *buffer, size_t len, struct cc_subtitle *sub);
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -1,15 +1,13 @@
#ifndef _XDS_H
#define _XDS_H
#ifndef CCX_DECODER_XDS_H
#define CCX_DECODER_XDS_H
#include "ccx_decoders_common.h"
#include "ccx_encoders_common.h"
void process_xds_bytes(const unsigned char hi, int lo);
void do_end_of_xds(struct cc_subtitle *sub, unsigned char expected_checksum);
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);
void ccx_decoders_xds_init_library(ccx_encoders_transcript_format *transcriptSettings, LLONG subs_delay, char millis_separator);
void xds_write_transcript_line_suffix (struct ccx_s_write *wb);
void xds_write_transcript_line_prefix (struct ccx_s_write *wb, LLONG start_time, LLONG end_time, int cur_xds_packet_class);
struct ccx_decoders_xds_context *ccx_decoders_xds_init_library(struct ccx_common_timing_ctx *timing, int xds_write_to_file);
void xds_cea608_test();
#endif

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

@@ -0,0 +1,400 @@
#include "ccx_demuxer.h"
#include "activity.h"
#include "lib_ccx.h"
#include "utility.h"
#include "ffmpeg_intgr.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)
{
ctx->past = 0;
ctx->min_global_timestamp = 0;
ctx->global_timestamp_inited = 0;
ctx->last_global_timestamp = 0;
ctx->offset_global_timestamp = 0;
#ifdef ENABLE_FFMPEG
ctx->ffmpeg_ctx = init_ffmpeg(file);
if(ctx->ffmpeg_ctx)
{
ctx->stream_mode = CCX_SM_FFMPEG;
ctx->auto_stream = CCX_SM_FFMPEG;
return 0;
}
else
{
mprint ("\rFailed to initialized ffmpeg falling back to legacy\n");
}
#endif
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;
case CCX_SM_GXF:
mprint ("\rFile seems to be a GXF\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) )
{
ctx->stream_mode=CCX_SM_MYTH;
}
break;
default:
// Keep stream_mode
break;
}
break;
}
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->tb.num = 1;
data->tb.den = 90000;
data->next_stream = 0;
data->next_program = 0;
return data;
}

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

@@ -0,0 +1,182 @@
#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"
#include "utility.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;
#ifdef ENABLE_FFMPEG
void *ffmpeg_ctx;
#endif
void *parent;
//Will contain actual Demuxer Context
void *private_data;
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 ccx_rational tb;
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

File diff suppressed because it is too large Load Diff

View File

@@ -1,17 +1,28 @@
#ifndef _CC_ENCODER_COMMON_H
#define _CC_ENCODER_COMMON_H
#ifdef WIN32
#include "..\\win_iconv\\iconv.h"
#else
#include "iconv.h"
#endif
#include "ccx_common_structs.h"
#include "ccx_decoders_structs.h"
#include "ccx_encoders_structs.h"
#include "ccx_encoders_helpers.h"
#include "ccx_common_option.h"
#define REQUEST_BUFFER_CAPACITY(ctx,length) if (length>ctx->capacity) \
{ctx->capacity = length * 2; ctx->buffer = (unsigned char*)realloc(ctx->buffer, ctx->capacity); \
if (ctx->buffer == NULL) { fatal(EXIT_NOT_ENOUGH_MEMORY, "Not enough memory, bailing out\n"); } \
}
extern ccx_encoders_transcript_format ccx_encoders_default_transcript_settings;
typedef struct ccx_dtvcc_writer_ctx
{
int fd;
char *filename;
iconv_t cd;
} ccx_dtvcc_writer_ctx;
/**
* Context of encoder, This structure gives single interface
@@ -25,14 +36,75 @@ struct encoder_ctx
unsigned int capacity;
/* keep count of srt subtitle*/
unsigned int srt_counter;
/* output context */
/* Did we write the WebVTT sync header already? */
unsigned int wrote_webvtt_sync_header;
/* Input outputs */
/* Flag giving hint that output is send to server through network */
unsigned int send_to_srv;
/* Used only in Spupng output */
int multiple_files;
/* Used only in Spupng output and creating name of output file*/
char *first_input_file;
/* Its array with length of number of languages */
struct ccx_s_write *out;
/* number of member in array of write out array */
int nb_out;
/* Input file format used in Teletext for exceptional output */
unsigned int in_fileformat; //1 =Normal, 2=Teletext
/* Keep output file closed when not actually writing to it and start over each time (add headers, etc) */
unsigned int keep_output_closed;
/* Force a flush on the file buffer whenever content is written */
int force_flush;
/* Keep track of whether -UCLA used */
int ucla;
struct ccx_common_timing_ctx *timing; /* Some encoders need access to PTS, such as WebVTT */
/* Flag saying BOM to be written in each output file */
enum ccx_encoding_type encoding;
enum ccx_output_format write_format; // 0=Raw, 1=srt, 2=SMI
struct ccx_encoders_transcript_format *transcript_settings; // Keeps the settings for generating transcript output files.
int no_bom;
int sentence_cap ; // FIX CASE? = Fix case?
int trim_subs; // " Remove spaces at sides? "
int autodash; // Add dashes (-) before each speaker automatically?
int no_font_color;
int no_type_setting;
int gui_mode_reports; // If 1, output in stderr progress updates so the GUI can grab them
unsigned char *subline; // Temp storage for storing each line
int extract;
int dtvcc_extract; //1 or 0 depending if we have to handle dtvcc
ccx_dtvcc_writer_ctx dtvcc_writers[CCX_DTVCC_MAX_SERVICES];
/* Timing related variables*/
/* start time of previous sub */
LLONG prev_start;
LLONG subs_delay;
LLONG last_displayed_subs_ms;
enum ccx_output_date_format date_format;
char millis_separator;
/* Credit stuff */
int startcredits_displayed;
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;
// Preencoded strings
unsigned char encoded_crlf[16];
unsigned int encoded_crlf_length;
unsigned char encoded_br[16];
unsigned int encoded_br_length;
int new_sentence; // Capitalize next letter?
int program_number;
struct list_head list;
};
#define INITIAL_ENC_BUFFER_CAPACITY 2048
@@ -42,12 +114,11 @@ struct encoder_ctx
* write subtitle header to file refrenced by
* output context
*
* @param ctx preallocated encoder ctx
* @param out output context
* @param cfg Option to initilaize encoder cfg params
*
* @return 0 on SUCESS, -1 on failure
* @return Allocated and properly initilaized Encoder Context, NULL on failure
*/
int init_encoder(struct encoder_ctx *ctx,struct ccx_s_write *out);
struct encoder_ctx *init_encoder(struct encoder_cfg *opt);
/**
* try to add end credits in subtitle file and then write subtitle
@@ -56,9 +127,11 @@ int init_encoder(struct encoder_ctx *ctx,struct ccx_s_write *out);
* 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
* @oaram arg pointer to initialized encoder ctx using init_encoder
*
* @param current_fts to calculate window for end credits
*/
void dinit_encoder(struct encoder_ctx *ctx);
void dinit_encoder(struct encoder_ctx **arg, LLONG current_fts);
/**
* @param ctx encoder context
@@ -66,18 +139,31 @@ void dinit_encoder(struct encoder_ctx *ctx);
*/
int encode_sub(struct encoder_ctx *ctx,struct cc_subtitle *sub);
int write_cc_buffer_as_g608(struct eia608_screen *data, struct encoder_ctx *context);
int write_cc_buffer_as_srt(struct eia608_screen *data, struct encoder_ctx *context);
void write_stringz_as_srt(char *string, struct encoder_ctx *context, LLONG ms_start, LLONG ms_end);
int write_cc_subtitle_as_srt(struct cc_subtitle *sub, struct encoder_ctx *context);
int write_stringz_as_srt(char *string, struct encoder_ctx *context, LLONG ms_start, LLONG ms_end);
int write_cc_buffer_as_webvtt(struct eia608_screen *data, struct encoder_ctx *context);
int write_cc_subtitle_as_webvtt(struct cc_subtitle *sub, struct encoder_ctx *context);
int write_stringz_as_webvtt(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_stringz_as_sami(char *string, struct encoder_ctx *context, LLONG ms_start, LLONG ms_end);
int write_cc_subtitle_as_sami(struct cc_subtitle *sub, struct encoder_ctx *context);
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);
int write_cc_subtitle_as_smptett(struct cc_subtitle *sub, struct encoder_ctx *context);
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_subtitle_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_webvtt(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);
@@ -85,4 +171,9 @@ int write_cc_bitmap_as_smptett(struct cc_subtitle *sub, struct encoder_ctx *cont
void set_encoder_last_displayed_subs_ms(struct encoder_ctx *ctx, LLONG last_displayed_subs_ms);
void set_encoder_subs_delay(struct encoder_ctx *ctx, LLONG subs_delay);
void set_encoder_startcredits_displayed(struct encoder_ctx *ctx, int startcredits_displayed);
void set_encoder_rcwt_fileformat(struct encoder_ctx *ctx, short int format);
void find_limit_characters(unsigned char *line, int *first_non_blank, int *last_non_blank, int max_len);
int get_str_basic(unsigned char *out_buffer, unsigned char *in_buffer, int trim_subs,
enum ccx_encoding_type in_enc, enum ccx_encoding_type out_enc, int max_len);
#endif

View File

@@ -0,0 +1,109 @@
#include "lib_ccx.h"
#include "ccx_encoders_common.h"
#include "ccx_encoders_helpers.h"
static unsigned int get_line_encoded(struct encoder_ctx *ctx, unsigned char *buffer, int line_num, struct eia608_screen *data)
{
unsigned char *orig = buffer; // Keep for debugging
unsigned char *line = data->characters[line_num];
for (int i = 0; i < 32; i++)
{
int bytes = 0;
switch (ctx->encoding)
{
case CCX_ENC_UTF_8:
bytes = get_char_in_utf_8(buffer, line[i]);
break;
case CCX_ENC_LATIN_1:
get_char_in_latin_1(buffer, line[i]);
bytes = 1;
break;
case CCX_ENC_UNICODE:
get_char_in_unicode(buffer, line[i]);
bytes = 2;
case CCX_ENC_ASCII:
*buffer = line[i];
bytes = 1;
break;
}
buffer += bytes;
}
return (unsigned int)(buffer - orig); // Return length
}
static unsigned int get_color_encoded(struct encoder_ctx *ctx, unsigned char *buffer, int line_num, struct eia608_screen *data)
{
unsigned char *orig = buffer; // Keep for debugging
for (int i = 0; i < 32; i++)
{
if (data->colors[line_num][i] < 10)
*buffer++ = data->colors[line_num][i] + '0';
else
*buffer++ = 'E';
}
*buffer = 0;
return (unsigned)(buffer - orig); // Return length
}
static unsigned int get_font_encoded(struct encoder_ctx *ctx, unsigned char *buffer, int line_num, struct eia608_screen *data)
{
unsigned char *orig = buffer; // Keep for debugging
for (int i = 0; i < 32; i++)
{
if(data->fonts[line_num][i] == FONT_REGULAR)
*buffer++ = 'R';
else if(data->fonts[line_num][i] == FONT_UNDERLINED_ITALICS)
*buffer++ = 'B';
else if(data->fonts[line_num][i] == FONT_UNDERLINED)
*buffer++ = 'U';
else if(data->fonts[line_num][i] == FONT_ITALICS)
*buffer++ = 'I';
else
*buffer++ = 'E';
}
return (unsigned)(buffer - orig); // Return length
}
int write_cc_buffer_as_g608(struct eia608_screen *data, struct encoder_ctx *context)
{
int used;
unsigned h1,m1,s1,ms1;
unsigned h2,m2,s2,ms2;
LLONG ms_start, ms_end;
int wrote_something = 0;
ms_start = data->start_time;
ms_start+=context->subs_delay;
if (ms_start<0) // Drop screens that because of subs_delay start too early
return 0;
ms_end = data->end_time;
mstotime (ms_start,&h1,&m1,&s1,&ms1);
mstotime (ms_end-1,&h2,&m2,&s2,&ms2); // -1 To prevent overlapping with next line.
char timeline[128];
context->srt_counter++;
sprintf(timeline, "%u%s", context->srt_counter, context->encoded_crlf);
used = encode_line(context, context->buffer,(unsigned char *) timeline);
write(context->out->fh, context->buffer, used);
sprintf (timeline, "%02u:%02u:%02u,%03u --> %02u:%02u:%02u,%03u%s",
h1, m1, s1, ms1, h2, m2, s2, ms2, context->encoded_crlf);
used = encode_line(context, context->buffer,(unsigned char *) timeline);
write (context->out->fh, context->buffer, used);
for (int i=0;i<15;i++)
{
int length = get_line_encoded (context, context->subline, i, data);
write(context->out->fh, context->subline, length);
length = get_color_encoded (context, context->subline, i, data);
write(context->out->fh, context->subline, length);
length = get_font_encoded (context, context->subline, i, data);
write(context->out->fh, context->subline, length);
write(context->out->fh, context->encoded_crlf, context->encoded_crlf_length);
wrote_something=1;
}
write (context->out->fh, context->encoded_crlf, context->encoded_crlf_length);
return wrote_something;
}

View File

@@ -3,6 +3,7 @@
#include "ccx_common_constants.h"
#include "ccx_common_structs.h"
#include "ccx_decoders_common.h"
#include "ccx_encoders_common.h"
#ifdef _MSC_VER
#define strcasecmp stricmp
@@ -17,7 +18,6 @@ char **spell_lower = NULL;
char **spell_correct = NULL;
int spell_words = 0;
int spell_capacity = 0;
struct ccx_encoders_helpers_settings_t ccx_encoders_helpers_settings;
// Some basic English words, so user-defined doesn't have to
// include the common stuff
static const char *spell_builtin[] =
@@ -40,7 +40,7 @@ int string_cmp(const void *p1, const void *p2)
return string_cmp2(p1, p2, NULL);
}
void correct_case(int line_num, struct eia608_screen *data)
void correct_case_with_dictionary(int line_num, struct eia608_screen *data)
{
char delim[64] = {
' ', '\n', '\r', 0x89, 0x99,
@@ -54,6 +54,11 @@ void correct_case(int line_num, struct eia608_screen *data)
char *line = strdup(((char*)data->characters[line_num]));
char *oline = (char*)data->characters[line_num];
char *c = strtok(line, delim);
if (c == NULL)
{
free(line);
return;
}
do
{
char **index = bsearch(&c, spell_lower, spell_words, sizeof(*spell_lower), string_cmp);
@@ -68,9 +73,62 @@ void correct_case(int line_num, struct eia608_screen *data)
free(line);
}
void capitalize(int line_num, struct eia608_screen *data)
void telx_correct_case(char *sub_line)
{
for (int i = 0; i<CCX_DECODER_608_SCREEN_WIDTH; i++)
char delim[64] = {
' ', '\n', '\r', 0x89, 0x99,
'!', '"', '#', '%', '&',
'\'', '(', ')', ';', '<',
'=', '>', '?', '[', '\\',
']', '*', '+', ',', '-',
'.', '/', ':', '^', '_',
'{', '|', '}', '~', '\0' };
char *line = strdup(((char*)sub_line));
char *oline = (char*)sub_line;
char *c = strtok(line, delim);
if (c == NULL)
{
free(line);
return;
}
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);
}
int is_all_caps(struct encoder_ctx *context, int line_num, struct eia608_screen *data)
{
int saw_upper = 0, saw_lower = 0;
for (int i = 0; i < CCX_DECODER_608_SCREEN_WIDTH; i++)
{
if (islower(data->characters[line_num][i]))
saw_lower = 1;
else if (isupper(data->characters[line_num][i]))
saw_upper = 1;
}
return (saw_upper && !saw_lower); // 1 if we've seen upper and not lower, 0 otherwise
}
int clever_capitalize(struct encoder_ctx *context, int line_num, struct eia608_screen *data)
{
// CFS: Tried doing to clever (see below) but some channels do all uppercase except for
// notes for deaf people (such as "(narrator)" which messes things up.
// First find out if we actually need to do it, don't mess with lines that come OK
//int doit = is_all_caps(context, line_num, data);
int doit = 1;
for (int i = 0; i < CCX_DECODER_608_SCREEN_WIDTH; i++)
{
switch (data->characters[line_num][i])
{
@@ -82,28 +140,32 @@ void capitalize(int line_num, struct eia608_screen *data)
case '?': // Fallthrough
case '!':
case ':':
new_sentence = 1;
context->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;
if (doit)
{
if (context->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]);
}
context->new_sentence = 0;
break;
}
}
return doit;
}
// 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 encode_line(struct encoder_ctx *ctx, unsigned char *buffer, unsigned char *text)
{
unsigned bytes = 0;
while (*text)
{
switch (ccx_encoders_helpers_settings.encoding)
switch (ctx->encoding)
{
case CCX_ENC_UTF_8:
case CCX_ENC_LATIN_1:
@@ -120,6 +182,7 @@ unsigned encode_line(unsigned char *buffer, unsigned char *text)
}
text++;
}
*buffer = 0;
return bytes;
}
@@ -128,7 +191,7 @@ unsigned get_decoder_line_encoded_for_gui(unsigned char *buffer, int line_num, s
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);
find_limit_characters(line, &first, &last, CCX_DECODER_608_SCREEN_WIDTH);
for (int i = first; i <= last; i++)
{
get_char_in_latin_1(buffer, line[i]);
@@ -139,7 +202,7 @@ unsigned get_decoder_line_encoded_for_gui(unsigned char *buffer, int line_num, s
}
unsigned char *close_tag(unsigned char *buffer, char *tagstack, char tagtype, int *punderlined, int *pitalics, int *pchanged_font)
unsigned char *close_tag(struct encoder_ctx *ctx, unsigned char *buffer, char *tagstack, char tagtype, int *punderlined, int *pitalics, int *pchanged_font)
{
for (int l = strlen(tagstack) - 1; l >= 0; l--)
{
@@ -147,15 +210,15 @@ unsigned char *close_tag(unsigned char *buffer, char *tagstack, char tagtype, in
switch (cur)
{
case 'F':
buffer += encode_line(buffer, (unsigned char *) "</font>");
buffer += encode_line(ctx, buffer, (unsigned char *) "</font>");
(*pchanged_font)--;
break;
case 'U':
buffer += encode_line(buffer, (unsigned char *) "</u>");
buffer += encode_line(ctx, buffer, (unsigned char *) "</u>");
(*punderlined)--;
break;
case 'I':
buffer += encode_line(buffer, (unsigned char *) "</i>");
buffer += encode_line(ctx, buffer, (unsigned char *) "</i>");
(*pitalics)--;
break;
}
@@ -168,7 +231,7 @@ unsigned char *close_tag(unsigned char *buffer, char *tagstack, char tagtype, in
return buffer;
}
unsigned get_decoder_line_encoded(unsigned char *buffer, int line_num, struct eia608_screen *data)
unsigned get_decoder_line_encoded(struct encoder_ctx *ctx, unsigned char *buffer, int line_num, struct eia608_screen *data)
{
int col = COL_WHITE;
int underlined = 0;
@@ -179,25 +242,33 @@ unsigned get_decoder_line_encoded(unsigned char *buffer, int line_num, struct ei
unsigned char *line = data->characters[line_num];
unsigned char *orig = buffer; // Keep for debugging
int first = 0, last = 31;
if (ccx_encoders_helpers_settings.trim_subs)
find_limit_characters(line, &first, &last);
if (ctx->trim_subs)
find_limit_characters(line, &first, &last, CCX_DECODER_608_SCREEN_WIDTH);
for (int i = first; i <= last; i++)
{
// Handle color
int its_col = data->colors[line_num][i];
if (its_col != col && !ccx_encoders_helpers_settings.no_font_color &&
if (its_col != col && !ctx->no_font_color &&
!(col == COL_USERDEFINED && its_col == COL_WHITE)) // Don't replace user defined with white
{
if (changed_font)
buffer = close_tag(buffer, tagstack, 'F', &underlined, &italics, &changed_font);
buffer = close_tag(ctx, buffer, tagstack, 'F', &underlined, &italics, &changed_font);
// Add new font tag
buffer += encode_line(buffer, (unsigned char*)color_text[its_col][1]);
if ( MAX_COLOR > its_col)
buffer += encode_line(ctx, buffer, (unsigned char*)color_text[its_col][1]);
else
{
ccx_common_logging.log_ftn("WARNING:get_decoder_line_encoded:Invalid Color index Selected %d\n", its_col);
its_col = COL_WHITE;
}
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*) "\">");
buffer += encode_line(ctx, buffer, (unsigned char*)usercolor_rgb);
buffer += encode_line(ctx, buffer, (unsigned char*) "\">");
}
if (color_text[its_col][1][0]) // That means a <font> was added to the buffer
{
@@ -208,30 +279,30 @@ unsigned get_decoder_line_encoded(unsigned char *buffer, int line_num, struct ei
}
// Handle underlined
int is_underlined = data->fonts[line_num][i] & FONT_UNDERLINED;
if (is_underlined && underlined == 0 && !ccx_encoders_helpers_settings.no_type_setting) // Open underline
if (is_underlined && underlined == 0 && !ctx->no_type_setting) // Open underline
{
buffer += encode_line(buffer, (unsigned char *) "<u>");
buffer += encode_line(ctx, buffer, (unsigned char *) "<u>");
strcat(tagstack, "U");
underlined++;
}
if (is_underlined == 0 && underlined && !ccx_encoders_helpers_settings.no_type_setting) // Close underline
if (is_underlined == 0 && underlined && !ctx->no_type_setting) // Close underline
{
buffer = close_tag(buffer, tagstack, 'U', &underlined, &italics, &changed_font);
buffer = close_tag(ctx, buffer, tagstack, 'U', &underlined, &italics, &changed_font);
}
// Handle italics
int has_ita = data->fonts[line_num][i] & FONT_ITALICS;
if (has_ita && italics == 0 && !ccx_encoders_helpers_settings.no_type_setting) // Open italics
if (has_ita && italics == 0 && !ctx->no_type_setting) // Open italics
{
buffer += encode_line(buffer, (unsigned char *) "<i>");
buffer += encode_line(ctx, buffer, (unsigned char *) "<i>");
strcat(tagstack, "I");
italics++;
}
if (has_ita == 0 && italics && !ccx_encoders_helpers_settings.no_type_setting) // Close italics
if (has_ita == 0 && italics && !ctx->no_type_setting) // Close italics
{
buffer = close_tag(buffer, tagstack, 'I', &underlined, &italics, &changed_font);
buffer = close_tag(ctx, buffer, tagstack, 'I', &underlined, &italics, &changed_font);
}
int bytes = 0;
switch (ccx_encoders_helpers_settings.encoding)
switch (ctx->encoding)
{
case CCX_ENC_UTF_8:
bytes = get_char_in_utf_8(buffer, line[i]);
@@ -247,7 +318,7 @@ unsigned get_decoder_line_encoded(unsigned char *buffer, int line_num, struct ei
}
buffer += bytes;
}
buffer = close_tag(buffer, tagstack, 'A', &underlined, &italics, &changed_font);
buffer = close_tag(ctx, buffer, tagstack, 'A', &underlined, &italics, &changed_font);
if (underlined || italics || changed_font)
ccx_common_logging.fatal_ftn(CCX_COMMON_EXIT_BUG_BUG, "Not all tags closed in encoding, this is a bug, please report.\n");
*buffer = 0;
@@ -293,6 +364,11 @@ int add_word(const char *word)
ptr_correct = (char **)realloc(spell_correct, sizeof (char *)*
spell_capacity);
}
else
{
ptr_lower = spell_lower;
ptr_correct = spell_correct;
}
size_t len = strlen(word);
new_lower = (char *)malloc(len + 1);
new_correct = (char *)malloc(len + 1);
@@ -356,6 +432,9 @@ int add_built_in_words(void)
* @param size size of each element
* @param compar Comparison function, which is called with three argument
* that point to the objects being compared and arg.
* compare Funtion should return an integer less than, equal to,
* or greater than zero if p1 is found, respectively, to be less than,
* to match, or be greater than p2.
* @param arg argument passed as it is, to compare function
*/
void shell_sort(void *base, int nb, size_t size, int(*compar)(const void*p1, const void *p2, void*arg), void *arg)
@@ -384,9 +463,3 @@ void ccx_encoders_helpers_perform_shellsort_words(void)
shell_sort(spell_correct, spell_words, sizeof(*spell_correct), string_cmp2, NULL);
}
void ccx_encoders_helpers_setup(enum ccx_encoding_type encoding,int no_font_color,int no_type_setting,int trim_subs){
ccx_encoders_helpers_settings.encoding = encoding;
ccx_encoders_helpers_settings.no_font_color = no_font_color;
ccx_encoders_helpers_settings.no_type_setting = no_type_setting;
ccx_encoders_helpers_settings.trim_subs = trim_subs;
}

View File

@@ -5,6 +5,7 @@
#include "ccx_common_constants.h"
#include "ccx_decoders_structs.h"
#include "ccx_decoders_608.h"
#include "ccx_encoders_common.h"
extern char **spell_lower;
extern char **spell_correct;
@@ -19,18 +20,20 @@ struct ccx_encoders_helpers_settings_t {
int no_type_setting;
enum ccx_encoding_type encoding;
};
extern struct ccx_encoders_helpers_settings_t ccx_encoders_helpers_settings;
// Helper functions
void correct_case(int line_num, struct eia608_screen *data);
void capitalize(int line_num, struct eia608_screen *data);
void correct_case_with_dictionary(int line_num, struct eia608_screen *data);
int is_all_caps(struct encoder_ctx *context, int line_num, struct eia608_screen *data);
int clever_capitalize(struct encoder_ctx *context, int line_num, struct eia608_screen *data);
void telx_correct_case(char *sub_line);
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);
unsigned get_decoder_line_encoded(struct encoder_ctx *ctx, unsigned char *buffer, int line_num, struct eia608_screen *data);
int string_cmp(const void *p1, const void *p2);
int string_cmp2(const void *p1, const void *p2, void *arg);
int add_built_in_words(void);
int add_word(const char *word);
unsigned encode_line (struct encoder_ctx *ctx, unsigned char *buffer, unsigned char *text);
void shell_sort(void *base, int nb, size_t size, int(*compar)(const void*p1, const void *p2, void*arg), void *arg);

View File

@@ -0,0 +1,270 @@
#include "lib_ccx.h"
#include "ccx_common_option.h"
#include "ccx_encoders_common.h"
#include "png.h"
#include "spupng_encoder.h"
#include "ocr.h"
#include "utility.h"
#include "ccx_encoders_helpers.h"
int write_stringz_as_sami(char *string, struct encoder_ctx *context, LLONG ms_start, LLONG ms_end)
{
int used;
int len = 0;
int ret = 0;
unsigned char *unescaped = NULL;
unsigned char *el = NULL;
char str[1024];
sprintf (str,"<SYNC start=%llu><P class=\"UNKNOWNCC\">\r\n",(unsigned long long)ms_start);
if (context->encoding != CCX_ENC_UNICODE)
{
dbg_print(CCX_DMT_DECODER_608, "\r%s\n", str);
}
used = encode_line(context, context->buffer, (unsigned char *) str);
ret = write (context->out->fh, context->buffer, used);
if(ret != used)
{
return ret;
}
len = strlen (string);
unescaped= (unsigned char *) malloc (len+1);
if(!unescaped)
{
mprint ("In write_stringz_as_sami() - not enough memory for len %d.\n", len);
ret = -1;
goto end;
}
el = (unsigned char *) malloc (len*3+1); // Be generous
if (el == NULL)
{
mprint ("In write_stringz_as_sami() - not enough memory for len %d.\n", len);
ret = -1;
goto end;
}
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 (context, el, begin);
if (context->encoding != CCX_ENC_UNICODE)
{
dbg_print(CCX_DMT_DECODER_608, "\r");
dbg_print(CCX_DMT_DECODER_608, "%s\n",context->subline);
}
ret = write(context->out->fh, el, u);
if(ret != u)
goto end;
ret = write(context->out->fh, context->encoded_br, context->encoded_br_length);
if(ret != context->encoded_br_length)
goto end;
ret = write(context->out->fh, context->encoded_crlf, context->encoded_crlf_length);
if(ret != context->encoded_crlf_length)
goto end;
begin += strlen ((const char *) begin) + 1;
}
sprintf ((char *) str, "</P></SYNC>\r\n");
if (context->encoding != CCX_ENC_UNICODE)
{
dbg_print(CCX_DMT_DECODER_608, "\r%s\n", str);
}
used = encode_line (context, context->buffer,(unsigned char *) str);
ret = write(context->out->fh, context->buffer, used);
if(ret != used)
goto end;
sprintf ((char *) str,
"<SYNC start=%llu><P class=\"UNKNOWNCC\">&nbsp;</P></SYNC>\r\n\r\n",
(unsigned long long)ms_end);
if (context->encoding != CCX_ENC_UNICODE)
{
dbg_print(CCX_DMT_DECODER_608, "\r%s\n", str);
}
ret = write(context->out->fh, context->buffer, used);
if(ret != used)
goto end;
end:
free(el);
free(unescaped);
return ret;
}
int write_cc_bitmap_as_sami(struct cc_subtitle *sub, struct encoder_ctx *context)
{
int ret = 0;
#ifdef ENABLE_OCR
struct cc_bitmap* rect;
LLONG ms_start, ms_end;
if (context->prev_start != -1 && (sub->flags & SUB_EOD_MARKER))
{
ms_start = context->prev_start + context->subs_delay;
ms_end = sub->start_time - 1;
}
else if ( !(sub->flags & SUB_EOD_MARKER))
{
ms_start = sub->start_time + context->subs_delay;
ms_end = sub->end_time - 1;
}
else if ( context->prev_start == -1 && (sub->flags & SUB_EOD_MARKER) )
{
ms_start = 1 + context->subs_delay;
ms_end = sub->start_time - 1;
}
if(sub->nb_data == 0 )
return 0;
rect = sub->data;
if ( sub->flags & SUB_EOD_MARKER )
context->prev_start = sub->start_time;
if (rect[0].ocr_text && *(rect[0].ocr_text))
{
if (context->prev_start != -1 || !(sub->flags & SUB_EOD_MARKER))
{
char *token = NULL;
char *buf = (char*)context->buffer;
sprintf(buf,
"<SYNC start=%llu><P class=\"UNKNOWNCC\">\r\n"
,(unsigned long long)ms_start);
write(context->out->fh, buf, strlen(buf));
token = strtok(rect[0].ocr_text,"\r\n");
while (token)
{
sprintf(buf, "%s", token);
token = strtok(NULL,"\r\n");
if(token)
strcat(buf, "<br>\n");
else
strcat(buf, "\n");
write(context->out->fh, buf, strlen(buf));
}
sprintf(buf,
"<SYNC start=%llu><P class=\"UNKNOWNCC\">&nbsp;</P></SYNC>\r\n\r\n"
,(unsigned long long)ms_end);
write(context->out->fh, buf, strlen(buf));
}
}
#endif
sub->nb_data = 0;
freep(&sub->data);
return ret;
}
int write_cc_subtitle_as_sami(struct cc_subtitle *sub, struct encoder_ctx *context)
{
int ret = 0;
struct cc_subtitle *osub = sub;
struct cc_subtitle *lsub = sub;
while(sub)
{
if(sub->type == CC_TEXT)
{
ret = write_stringz_as_sami(sub->data, context, sub->start_time, sub->end_time);
freep(&sub->data);
sub->nb_data = 0;
}
lsub = sub;
sub = sub->next;
}
while(lsub != osub)
{
sub = lsub->prev;
freep(&lsub);
lsub = sub;
}
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;
char str[1024];
startms = data->start_time;
startms+=context->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 (str,"<SYNC start=%llu><P class=\"UNKNOWNCC\">\r\n",
(unsigned long long)startms);
if (context->encoding != CCX_ENC_UNICODE)
{
dbg_print(CCX_DMT_DECODER_608, "\r%s\n", str);
}
used = encode_line(context, 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 (context, context->subline, i, data);
if (context->encoding != CCX_ENC_UNICODE)
{
dbg_print(CCX_DMT_DECODER_608, "\r");
dbg_print(CCX_DMT_DECODER_608, "%s\n",context->subline);
}
write (context->out->fh, context->subline, length);
wrote_something = 1;
if (i!=14)
write (context->out->fh, context->encoded_br, context->encoded_br_length);
write (context->out->fh, context->encoded_crlf, context->encoded_crlf_length);
}
}
sprintf ((char *) str,"</P></SYNC>\r\n");
if (context->encoding != CCX_ENC_UNICODE)
{
dbg_print(CCX_DMT_DECODER_608, "\r%s\n", str);
}
used = encode_line(context, 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 (context->encoding!=CCX_ENC_UNICODE)
{
dbg_print(CCX_DMT_DECODER_608, "\r%s\n", str);
}
used = encode_line(context, context->buffer,(unsigned char *) str);
write (context->out->fh, context->buffer, used);
return wrote_something;
}

View File

@@ -0,0 +1,258 @@
/*
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.
*/
#include "lib_ccx.h"
#include "ccx_common_option.h"
#include "ccx_encoders_common.h"
#include "png.h"
#include "spupng_encoder.h"
#include "ocr.h"
#include "utility.h"
#include "ccx_encoders_helpers.h"
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;
int len = strlen (string);
unsigned char *unescaped= (unsigned char *) malloc (len+1);
unsigned char *el = (unsigned char *) malloc (len*3+1); // Be generous
int pos_r = 0;
int pos_w = 0;
char str[1024];
if (el == NULL || unescaped == NULL)
fatal (EXIT_NOT_ENOUGH_MEMORY, "In write_stringz_as_sami() - not enough memory.\n");
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 (context->encoding!=CCX_ENC_UNICODE)
{
dbg_print(CCX_DMT_DECODER_608, "\r%s\n", str);
}
used = encode_line(context, context->buffer, (unsigned char *) str);
write (context->out->fh, context->buffer, used);
// 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 (context, el, begin);
if (context->encoding != CCX_ENC_UNICODE)
{
dbg_print(CCX_DMT_DECODER_608, "\r");
dbg_print(CCX_DMT_DECODER_608, "%s\n", context->subline);
}
write(context->out->fh, el, u);
//write (wb->fh, encoded_br, encoded_br_length);
write(context->out->fh, context->encoded_crlf, context->encoded_crlf_length);
begin += strlen ((const char *) begin)+1;
}
sprintf ((char *) str, "</p>\n");
if (context->encoding != CCX_ENC_UNICODE)
{
dbg_print(CCX_DMT_DECODER_608, "\r%s\n", str);
}
used = encode_line(context, 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 (context->encoding != CCX_ENC_UNICODE)
{
dbg_print(CCX_DMT_DECODER_608, "\r%s\n", str);
}
used = encode_line(context, 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)
{
int ret = 0;
#ifdef ENABLE_OCR
struct cc_bitmap* rect;
LLONG ms_start, ms_end;
//char timeline[128];
int len = 0;
if (context->prev_start != -1 && (sub->flags & SUB_EOD_MARKER))
{
ms_start = context->prev_start + context->subs_delay;
ms_end = sub->start_time - 1;
}
else if ( !(sub->flags & SUB_EOD_MARKER))
{
ms_start = sub->start_time + context->subs_delay;
ms_end = sub->end_time - 1;
}
else if (context->prev_start == -1 && (sub->flags & SUB_EOD_MARKER))
{
ms_start = 1 + context->subs_delay;
ms_end = sub->start_time - 1;
}
if(sub->nb_data == 0 )
return 0;
rect = sub->data;
if ( sub->flags & SUB_EOD_MARKER )
context->prev_start = sub->start_time;
if (rect[0].ocr_text && *(rect[0].ocr_text))
{
if (context->prev_start != -1 || !(sub->flags & SUB_EOD_MARKER))
{
char *buf = (char *) context->buffer;
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); // -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, buf,strlen(buf) );
len = strlen(rect[0].ocr_text);
write (context->out->fh, rect[0].ocr_text, len);
write (context->out->fh, context->encoded_crlf, context->encoded_crlf_length);
sprintf ( buf,"</p>\n");
write (context->out->fh, buf,strlen(buf) );
}
}
#endif
sub->nb_data = 0;
freep(&sub->data);
return ret;
}
int write_cc_subtitle_as_smptett(struct cc_subtitle *sub, struct encoder_ctx *context)
{
int ret = 0;
struct cc_subtitle *osub = sub;
struct cc_subtitle *lsub = sub;
while(sub)
{
if(sub->type == CC_TEXT)
{
write_stringz_as_smptett(sub->data, context, sub->start_time, sub->end_time);
freep(&sub->data);
sub->nb_data = 0;
}
lsub = sub;
sub = sub->next;
}
while(lsub != osub)
{
sub = lsub->prev;
freep(&lsub);
lsub = sub;
}
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;
char str[1024];
startms+=context->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 (context->encoding!=CCX_ENC_UNICODE)
{
dbg_print(CCX_DMT_DECODER_608, "\r%s\n", str);
}
used = encode_line(context, 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 (context, context->subline, i, data);
if (context->encoding!=CCX_ENC_UNICODE)
{
dbg_print(CCX_DMT_DECODER_608, "\r");
dbg_print(CCX_DMT_DECODER_608, "%s\n",context->subline);
}
write(context->out->fh, context->subline, length);
wrote_something=1;
write(context->out->fh, context->encoded_crlf, context->encoded_crlf_length);
}
}
sprintf ((char *) str,"</p>\n");
if (context->encoding!=CCX_ENC_UNICODE)
{
dbg_print(CCX_DMT_DECODER_608, "\r%s\n", str);
}
used = encode_line(context, context->buffer,(unsigned char *) str);
write (context->out->fh, context->buffer, used);
if (context->encoding!=CCX_ENC_UNICODE)
{
dbg_print(CCX_DMT_DECODER_608, "\r%s\n", str);
}
used = encode_line(context, context->buffer,(unsigned char *) str);
//write (wb->fh, enc_buffer,enc_buffer_used);
return wrote_something;
}

View File

@@ -0,0 +1,416 @@
#include <assert.h>
#include <sys/stat.h>
#include "ccx_encoders_spupng.h"
#include "ccx_encoders_helpers.h"
void draw_str(char *str, uint8_t * canvas, int rowstride)
{
char *ptr;
uint8_t* cell;
uint8_t pen[2];
int i = 0;
pen[0] = COL_BLACK;
pen[1] = COL_WHITE;
for(ptr = str; ptr != '\0';ptr++)
{
cell = canvas + ((i+1) * CCW);
draw_char_indexed(cell, rowstride, pen, 0, 0, 0);
i++;
}
}
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_export_string2png(struct spupng_t *sp, char *str)
{
png_structp png_ptr;
png_infop info_ptr;
png_bytep *row_pointer;
png_bytep image;
int ww, wh, rowstride, row_adv;
int row = 0;
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 */
draw_str(str, 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 0
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;
}
#endif
png_destroy_write_struct (&png_ptr, &info_ptr);
free (row_pointer);
free (image);
return 1;
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)
{
int row;
int empty_buf = 1;
char str[256] = "";
int str_len = 0;
LLONG ms_start = data->start_time + context->subs_delay;
if (ms_start < 0)
{
dbg_print(CCX_DMT_VERBOSE, "Negative start\n");
return 0;
}
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(CCX_COMMON_EXIT_FILE_CREATION_FAILED, "Cannot open %s: %s\n",
sp->pngfile, strerror(errno));
}
if (!spupng_export_png(sp, data))
{
fatal(CCX_COMMON_EXIT_FILE_CREATION_FAILED, "Cannot write %s: %s\n",
sp->pngfile, strerror(errno));
}
fclose(sp->fppng);
write_sputag_open(sp,ms_start,ms_end);
for (row = 0; row < ROWS; row++)
{
if (data->row_used[row])
{
int len = get_decoder_line_encoded(context, context->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 = context->subline; ptr < context->subline+len; ptr++)
{
switch (*ptr)
{
case 0:
*ptr = ' ';
break;
case '-':
if (*(ptr+1) == '-')
{
*ptr++ = '_';
*ptr = '_';
}
break;
}
}
if (str_len + len + 3 > 256 )
{
mprint("WARNING: Possible Loss of data\n");
break;
}
strncat(str, (const char*)context->subline, len);
strncat(str,"\n",3);
str_len = str_len + len + 2;
}
}
write_spucomment(sp,str);
write_sputag_close(sp);
return 1;
}
int spupng_write_string(struct spupng_t *sp, char *string, LLONG start_time, LLONG end_time,
struct encoder_ctx *context)
{
char str[256] = "";
LLONG ms_start = start_time + context->subs_delay;
if (ms_start < 0)
{
dbg_print(CCX_DMT_VERBOSE, "Negative start\n");
return 0;
}
LLONG ms_end = end_time;
sprintf(sp->pngfile, "%s/sub%04d.png", sp->dirname, sp->fileIndex++);
if ((sp->fppng = fopen(sp->pngfile, "wb")) == NULL)
{
fatal(CCX_COMMON_EXIT_FILE_CREATION_FAILED, "Cannot open %s: %s\n",
sp->pngfile, strerror(errno));
}
if (!spupng_export_string2png(sp, str))
{
fatal(CCX_COMMON_EXIT_FILE_CREATION_FAILED, "Cannot write %s: %s\n",
sp->pngfile, strerror(errno));
}
fclose(sp->fppng);
write_sputag_open(sp,ms_start,ms_end);
write_spucomment(sp,str);
write_sputag_close(sp);
return 1;
}
int write_cc_subtitle_as_spupng(struct cc_subtitle *sub, struct encoder_ctx *context)
{
struct spupng_t *sp = (struct spupng_t *) context->out->spupng_data;
if (!sp)
return -1;
if(sub->type == CC_TEXT)
{
spupng_write_string(sp, sub->data, sub->start_time, sub->end_time, context);
}
return 0;
}
int write_cc_buffer_as_spupng(struct eia608_screen *data,struct encoder_ctx *context)
{
struct spupng_t *sp = (struct spupng_t *) context->out->spupng_data;
if (NULL != sp)
{
return spupng_write_ccbuffer(sp, data, context);
}
return 0;
}

View File

@@ -1,4 +1,5 @@
#ifndef __608_SPUPNG_H__
#define __608_SPUPNG_H__
#include "lib_ccx.h"
#include "spupng_encoder.h"

View File

@@ -2,25 +2,30 @@
#include "ccx_common_option.h"
#include "ccx_encoders_common.h"
#include "utility.h"
#include "ccx_encoders_helpers.h"
#include "ocr.h"
/* The timing here is not PTS based, but output based, i.e. user delay must be accounted for
if there is any */
void write_stringz_as_srt(char *string, struct encoder_ctx *context, LLONG ms_start, LLONG ms_end)
int write_stringz_as_srt(char *string, struct encoder_ctx *context, LLONG ms_start, LLONG ms_end)
{
int used;
unsigned h1,m1,s1,ms1;
unsigned h2,m2,s2,ms2;
char timeline[128];
if(!string || !string[0])
return 0;
mstotime (ms_start,&h1,&m1,&s1,&ms1);
mstotime (ms_end-1,&h2,&m2,&s2,&ms2); // -1 To prevent overlapping with next line.
char timeline[128];
context->srt_counter++;
sprintf(timeline, "%u%s", context->srt_counter, encoded_crlf);
used = encode_line(context->buffer,(unsigned char *) timeline);
sprintf(timeline, "%u%s", context->srt_counter, context->encoded_crlf);
used = encode_line(context, context->buffer,(unsigned char *) timeline);
write(context->out->fh, context->buffer, used);
sprintf (timeline, "%02u:%02u:%02u,%03u --> %02u:%02u:%02u,%03u%s",
h1, m1, s1, ms1, h2, m2, s2, ms2, encoded_crlf);
used = encode_line(context->buffer,(unsigned char *) timeline);
h1, m1, s1, ms1, h2, m2, s2, ms2, context->encoded_crlf);
used = encode_line(context, context->buffer,(unsigned char *) timeline);
dbg_print(CCX_DMT_DECODER_608, "\n- - - SRT caption - - -\n");
dbg_print(CCX_DMT_DECODER_608, "%s",timeline);
@@ -52,36 +57,39 @@ void write_stringz_as_srt(char *string, struct encoder_ctx *context, LLONG ms_st
unsigned char *begin=unescaped;
while (begin<unescaped+len)
{
unsigned int u = encode_line (el, begin);
if (ccx_options.encoding!=CCX_ENC_UNICODE)
unsigned int u = encode_line (context, el, begin);
if (context->encoding != CCX_ENC_UNICODE)
{
dbg_print(CCX_DMT_DECODER_608, "\r");
dbg_print(CCX_DMT_DECODER_608, "%s\n",subline);
dbg_print(CCX_DMT_DECODER_608, "%s\n",context->subline);
}
write(context->out->fh, el, u);
write(context->out->fh, encoded_crlf, encoded_crlf_length);
write(context->out->fh, context->encoded_crlf, context->encoded_crlf_length);
begin+= strlen ((const char *) begin)+1;
}
dbg_print(CCX_DMT_DECODER_608, "- - - - - - - - - - - -\r\n");
write(context->out->fh, encoded_crlf, encoded_crlf_length);
write(context->out->fh, context->encoded_crlf, context->encoded_crlf_length);
free(el);
free(unescaped);
return 0;
}
int write_cc_bitmap_as_srt(struct cc_subtitle *sub, struct encoder_ctx *context)
{
int ret = 0;
#ifdef ENABLE_OCR
struct cc_bitmap* rect;
LLONG ms_start, ms_end;
#ifdef ENABLE_OCR
unsigned h1,m1,s1,ms1;
unsigned h2,m2,s2,ms2;
char timeline[128];
int len = 0;
int used;
#endif
int i = 0;
char *str;
if (context->prev_start != -1 && (sub->flags & SUB_EOD_MARKER))
{
@@ -105,9 +113,8 @@ int write_cc_bitmap_as_srt(struct cc_subtitle *sub, struct encoder_ctx *context)
if(sub->flags & SUB_EOD_MARKER)
context->prev_start = sub->start_time;
rect = sub->data;
#ifdef ENABLE_OCR
if (rect[0].ocr_text && *(rect[0].ocr_text))
str = paraof_ocrtext(sub, context->encoded_crlf, context->encoded_crlf_length);
if (str)
{
if (context->prev_start != -1 || !(sub->flags & SUB_EOD_MARKER))
{
@@ -115,16 +122,22 @@ int write_cc_bitmap_as_srt(struct cc_subtitle *sub, struct encoder_ctx *context)
mstotime (ms_end-1,&h2,&m2,&s2,&ms2); // -1 To prevent overlapping with next line.
context->srt_counter++;
sprintf(timeline, "%u\r\n", context->srt_counter);
used = encode_line(context->buffer,(unsigned char *) timeline);
used = encode_line(context, context->buffer,(unsigned char *) timeline);
write(context->out->fh, context->buffer, used);
sprintf (timeline, "%02u:%02u:%02u,%03u --> %02u:%02u:%02u,%03u\r\n",
h1,m1,s1,ms1, h2,m2,s2,ms2);
used = encode_line(context->buffer,(unsigned char *) timeline);
used = encode_line(context, context->buffer,(unsigned char *) timeline);
write (context->out->fh, context->buffer, used);
len = strlen(rect[0].ocr_text);
write (context->out->fh, rect[0].ocr_text, len);
write (context->out->fh, encoded_crlf, encoded_crlf_length);
len = strlen(str);
write (context->out->fh, str, len);
write (context->out->fh, context->encoded_crlf, context->encoded_crlf_length);
}
freep(&str);
}
for(i = 0, rect = sub->data; i < sub->nb_data; i++, rect++)
{
freep(rect->data);
freep(rect->data+1);
}
#endif
sub->nb_data = 0;
@@ -132,6 +145,34 @@ int write_cc_bitmap_as_srt(struct cc_subtitle *sub, struct encoder_ctx *context)
return ret;
}
int write_cc_subtitle_as_srt(struct cc_subtitle *sub,struct encoder_ctx *context)
{
int ret = 0;
struct cc_subtitle *osub = sub;
struct cc_subtitle *lsub = sub;
while(sub)
{
if(sub->type == CC_TEXT)
{
ret = write_stringz_as_srt(sub->data, context, sub->start_time, sub->end_time);
freep(&sub->data);
sub->nb_data = 0;
ret = 1;
}
lsub = sub;
sub = sub->next;
}
while(lsub != osub)
{
sub = lsub->prev;
freep(&lsub);
lsub = sub;
}
return ret;
}
int write_cc_buffer_as_srt(struct eia608_screen *data, struct encoder_ctx *context)
{
int used;
@@ -165,12 +206,12 @@ int write_cc_buffer_as_srt(struct eia608_screen *data, struct encoder_ctx *conte
mstotime (ms_end-1,&h2,&m2,&s2,&ms2); // -1 To prevent overlapping with next line.
char timeline[128];
context->srt_counter++;
sprintf(timeline, "%u%s", context->srt_counter, encoded_crlf);
used = encode_line(context->buffer,(unsigned char *) timeline);
sprintf(timeline, "%u%s", context->srt_counter, context->encoded_crlf);
used = encode_line(context, context->buffer,(unsigned char *) timeline);
write(context->out->fh, context->buffer, used);
sprintf (timeline, "%02u:%02u:%02u,%03u --> %02u:%02u:%02u,%03u%s",
h1, m1, s1, ms1, h2, m2, s2, ms2, encoded_crlf);
used = encode_line(context->buffer,(unsigned char *) timeline);
h1, m1, s1, ms1, h2, m2, s2, ms2, context->encoded_crlf);
used = encode_line(context, context->buffer,(unsigned char *) timeline);
dbg_print(CCX_DMT_DECODER_608, "\n- - - SRT caption ( %d) - - -\n", context->srt_counter);
dbg_print(CCX_DMT_DECODER_608, "%s",timeline);
@@ -180,17 +221,17 @@ int write_cc_buffer_as_srt(struct eia608_screen *data, struct encoder_ctx *conte
{
if (data->row_used[i])
{
if (ccx_options.sentence_cap)
if (context->sentence_cap)
{
capitalize (i,data);
correct_case(i,data);
if (clever_capitalize (context, i, data))
correct_case_with_dictionary(i, data);
}
if (ccx_options.autodash && ccx_options.trim_subs)
if (context->autodash && context->trim_subs)
{
int first=0, last=31, center1=-1, center2=-1;
unsigned char *line = data->characters[i];
int do_dash=1, colon_pos=-1;
find_limit_characters(line,&first,&last);
find_limit_characters(line, &first, &last, CCX_DECODER_608_SCREEN_WIDTH);
if (first==-1 || last==-1) // Probably a bug somewhere though
break;
// Is there a speaker named, for example: TOM: What are you doing?
@@ -242,21 +283,21 @@ int write_cc_buffer_as_srt(struct eia608_screen *data, struct encoder_ctx *conte
prev_line_center2=center2;
}
int length = get_decoder_line_encoded (subline, i, data);
if (ccx_options.encoding!=CCX_ENC_UNICODE)
int length = get_decoder_line_encoded (context, context->subline, i, data);
if (context->encoding!=CCX_ENC_UNICODE)
{
dbg_print(CCX_DMT_DECODER_608, "\r");
dbg_print(CCX_DMT_DECODER_608, "%s\n",subline);
dbg_print(CCX_DMT_DECODER_608, "%s\n",context->subline);
}
write(context->out->fh, subline, length);
write(context->out->fh, encoded_crlf, encoded_crlf_length);
write(context->out->fh, context->subline, length);
write(context->out->fh, context->encoded_crlf, context->encoded_crlf_length);
wrote_something=1;
// fprintf (wb->fh,encoded_crlf);
// fprintf (wb->fh,context->encoded_crlf);
}
}
dbg_print(CCX_DMT_DECODER_608, "- - - - - - - - - - - -\r\n");
// fprintf (wb->fh, encoded_crlf);
write (context->out->fh, encoded_crlf, encoded_crlf_length);
// fprintf (wb->fh, context->encoded_crlf);
write (context->out->fh, context->encoded_crlf, context->encoded_crlf_length);
return wrote_something;
}

View File

@@ -1,4 +1,5 @@
#ifndef CCX_ENCODERS_STRUCTS_H
#define CCX_ENCODERS_STRUCTS_H
typedef struct ccx_encoders_transcript_format {
// TODO: add more options, and (perhaps) reduce other ccextractor options?
@@ -14,12 +15,17 @@ typedef struct ccx_encoders_transcript_format {
struct ccx_s_write
{
int multiple_files;
char *first_input_file;
int fh;
int temporarily_closed; // 1 means the file was created OK before but we released the handle
char *filename;
void* spupng_data;
int with_semaphore; // 1 means create a .sem file when the file is open and delete it when it's closed
char *semaphore_filename;
int with_playlist; // For m3u8 /webvtt: If 1, we'll generate a playlist and segments
char *playlist_filename;
int renaming_extension; //Used for file rotations
int append_mode; /* Append the file. Prevent overwriting of files */
};
#define CCX_ENCODERS_STRUCTS_H
#endif

View File

@@ -0,0 +1,356 @@
#include "lib_ccx.h"
#include "ccx_common_option.h"
#include "ccx_encoders_common.h"
#include "ccx_encoders_helpers.h"
#include "utility.h"
#include "ocr.h"
/* The timing here is not PTS based, but output based, i.e. user delay must be accounted for
if there is any */
int write_stringz_as_webvtt(char *string, struct encoder_ctx *context, LLONG ms_start, LLONG ms_end)
{
int used;
unsigned h1, m1, s1, ms1;
unsigned h2, m2, s2, ms2;
int written;
char timeline[128];
mstotime(ms_start, &h1, &m1, &s1, &ms1);
mstotime(ms_end - 1, &h2, &m2, &s2, &ms2); // -1 To prevent overlapping with next line.
used = encode_line(context, context->buffer, (unsigned char *)timeline);
written = write(context->out->fh, context->buffer, used);
if (written != used)
return -1;
sprintf(timeline, "%02u:%02u:%02u.%03u --> %02u:%02u:%02u.%03u%s",
h1, m1, s1, ms1, h2, m2, s2, ms2, context->encoded_crlf);
used = encode_line(context, context->buffer, (unsigned char *)timeline);
dbg_print(CCX_DMT_DECODER_608, "\n- - - WEBVTT caption - - -\n");
dbg_print(CCX_DMT_DECODER_608, "%s", timeline);
written = write(context->out->fh, context->buffer, used);
if (written != used)
return -1;
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_webvtt() - 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(context, el, begin);
if (context->encoding != CCX_ENC_UNICODE)
{
dbg_print(CCX_DMT_DECODER_608, "\r");
dbg_print(CCX_DMT_DECODER_608, "%s\n", context->subline);
}
written = write(context->out->fh, el, u);
if (written != u)
{
free(el);
free(unescaped);
return -1;
}
written = write(context->out->fh, context->encoded_crlf, context->encoded_crlf_length);
if (written != context->encoded_crlf_length)
{
return -1;
}
begin += strlen((const char *)begin) + 1;
}
dbg_print(CCX_DMT_DECODER_608, "- - - - - - - - - - - -\r\n");
written = write(context->out->fh, context->encoded_crlf, context->encoded_crlf_length);
free(el);
free(unescaped);
if (written != context->encoded_crlf_length)
{
return -1;
}
return 0;
}
int write_xtimestamp_header(struct encoder_ctx *context)
{
if (context->wrote_webvtt_sync_header) // Already done
return 1;
if (context->timing->sync_pts2fts_set)
{
char header_string[200];
int used;
unsigned h1, m1, s1, ms1;
mstotime(context->timing->sync_pts2fts_fts, &h1, &m1, &s1, &ms1);
sprintf(header_string, "X-TIMESTAMP-MAP=MPEGTS:%ld, LOCAL %02u:%02u:%02u.%03u\r\n",
context->timing->sync_pts2fts_pts,
h1, m1, s1, ms1);
used = encode_line(context, context->buffer, (unsigned char *)header_string);
write(context->out->fh, context->buffer, used);
}
// Add the additional CRLF to finish the header
write(context->out->fh, context->encoded_crlf, context->encoded_crlf_length);
context->wrote_webvtt_sync_header = 1; // Do it even if couldn't write the header, because it won't be possible anyway
}
int write_cc_bitmap_as_webvtt(struct cc_subtitle *sub, struct encoder_ctx *context)
{
int ret = 0;
#ifdef ENABLE_OCR
struct cc_bitmap* rect;
LLONG ms_start, ms_end;
unsigned h1, m1, s1, ms1;
unsigned h2, m2, s2, ms2;
char timeline[128];
int len = 0;
int used;
int i = 0;
char *str;
if (context->prev_start != -1 && (sub->flags & SUB_EOD_MARKER))
{
ms_start = context->prev_start;
ms_end = sub->start_time;
}
else if (!(sub->flags & SUB_EOD_MARKER))
{
ms_start = sub->start_time;
ms_end = sub->end_time;
}
else if (context->prev_start == -1 && (sub->flags & SUB_EOD_MARKER))
{
ms_start = 1;
ms_end = sub->start_time;
}
if (sub->nb_data == 0)
return 0;
write_xtimestamp_header(context);
if (sub->flags & SUB_EOD_MARKER)
context->prev_start = sub->start_time;
str = paraof_ocrtext(sub, context->encoded_crlf, context->encoded_crlf_length);
if (str)
{
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.
context->srt_counter++; // Not needed for WebVTT but let's keep it around for now
sprintf(timeline, "%02u:%02u:%02u.%03u --> %02u:%02u:%02u.%03u%s",
h1, m1, s1, ms1, h2, m2, s2, ms2, context->encoded_crlf);
used = encode_line(context, context->buffer, (unsigned char *)timeline);
write(context->out->fh, context->buffer, used);
len = strlen(str);
write(context->out->fh, str, len);
write(context->out->fh, context->encoded_crlf, context->encoded_crlf_length);
}
freep(&str);
}
for (i = 0, rect = sub->data; i < sub->nb_data; i++, rect++)
{
freep(rect->data);
freep(rect->data + 1);
}
#endif
sub->nb_data = 0;
freep(&sub->data);
return ret;
}
int write_cc_subtitle_as_webvtt(struct cc_subtitle *sub, struct encoder_ctx *context)
{
int ret = 0;
struct cc_subtitle *osub = sub;
struct cc_subtitle *lsub = sub;
while (sub)
{
if (sub->type == CC_TEXT)
{
ret = write_stringz_as_webvtt(sub->data, context, sub->start_time, sub->end_time);
freep(&sub->data);
sub->nb_data = 0;
}
lsub = sub;
sub = sub->next;
}
while (lsub != osub)
{
sub = lsub->prev;
freep(&lsub);
lsub = sub;
}
return ret;
}
int write_cc_buffer_as_webvtt(struct eia608_screen *data, struct encoder_ctx *context)
{
int used;
int written;
unsigned h1, m1, s1, ms1;
unsigned h2, m2, s2, ms2;
LLONG ms_start, ms_end;
int wrote_something = 0;
ms_start = data->start_time;
int prev_line_start = -1, prev_line_end = -1; // Column in which the previous line started and ended, for autodash
int prev_line_center1 = -1, prev_line_center2 = -1; // Center column of previous line text
int empty_buf = 1;
char timeline[128] = "";
for (int i = 0; i<15; i++)
{
if (data->row_used[i])
{
empty_buf = 0;
break;
}
}
if (empty_buf) // Prevent writing empty screens. Not needed in .vtt
return 0;
ms_start += context->subs_delay;
if (ms_start<0) // Drop screens that because of subs_delay start too early
return 0;
write_xtimestamp_header(context);
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.
sprintf(timeline, "%02u:%02u:%02u.%03u --> %02u:%02u:%02u.%03u%s",
h1, m1, s1, ms1, h2, m2, s2, ms2, context->encoded_crlf);
used = encode_line(context, context->buffer, (unsigned char *)timeline);
dbg_print(CCX_DMT_DECODER_608, "\n- - - WEBVTT caption - - -\n");
dbg_print(CCX_DMT_DECODER_608, "%s", timeline);
written = write(context->out->fh, context->buffer, used);
if (written != used)
return -1;
for (int i = 0; i<15; i++)
{
if (data->row_used[i])
{
if (context->sentence_cap)
{
if (clever_capitalize(context, i, data))
correct_case_with_dictionary(i, data);
}
if (context->autodash && context->trim_subs)
{
int first = 0, last = 31, center1 = -1, center2 = -1;
unsigned char *line = data->characters[i];
int do_dash = 1, colon_pos = -1;
find_limit_characters(line, &first, &last, CCX_DECODER_608_SCREEN_WIDTH);
if (first == -1 || last == -1) // Probably a bug somewhere though
break;
// Is there a speaker named, for example: TOM: What are you doing?
for (int j = first; j <= last; j++)
{
if (line[j] == ':')
{
colon_pos = j;
break;
}
if (!isupper(line[j]))
break;
}
if (prev_line_start == -1)
do_dash = 0;
if (first == prev_line_start) // Case of left alignment
do_dash = 0;
if (last == prev_line_end) // Right align
do_dash = 0;
if (first>prev_line_start && last<prev_line_end) // Fully contained
do_dash = 0;
if ((first>prev_line_start && first<prev_line_end) || // Overlap
(last>prev_line_start && last<prev_line_end))
do_dash = 0;
center1 = (first + last) / 2;
if (colon_pos != -1)
{
while (colon_pos<CCX_DECODER_608_SCREEN_WIDTH &&
(line[colon_pos] == ':' ||
line[colon_pos] == ' ' ||
line[colon_pos] == 0x89))
colon_pos++; // Find actual text
center2 = (colon_pos + last) / 2;
}
else
center2 = center1;
if (center1 >= prev_line_center1 - 1 && center1 <= prev_line_center1 + 1 && center1 != -1) // Center align
do_dash = 0;
if (center2 >= prev_line_center2 - 2 && center1 <= prev_line_center2 + 2 && center1 != -1) // Center align
do_dash = 0;
if (do_dash)
{
written = write(context->out->fh, "- ", 2);
if (written != 2)
return -1;
}
prev_line_start = first;
prev_line_end = last;
prev_line_center1 = center1;
prev_line_center2 = center2;
}
int length = get_decoder_line_encoded(context, context->subline, i, data);
if (context->encoding != CCX_ENC_UNICODE)
{
dbg_print(CCX_DMT_DECODER_608, "\r");
dbg_print(CCX_DMT_DECODER_608, "%s\n", context->subline);
}
written = write(context->out->fh, context->subline, length);
if (written != length)
return -1;
written = write(context->out->fh,
context->encoded_crlf, context->encoded_crlf_length);
if (written != context->encoded_crlf_length)
return -1;
wrote_something = 1;
// fprintf (wb->fh,encoded_crlf);
}
}
dbg_print(CCX_DMT_DECODER_608, "- - - - - - - - - - - -\r\n");
// fprintf (wb->fh, encoded_crlf);
written = write(context->out->fh, context->encoded_crlf, context->encoded_crlf_length);
if (written != context->encoded_crlf_length)
return -1;
return wrote_something;
}

View File

@@ -0,0 +1,95 @@
#include "ccx_common_platform.h"
#include "ccx_common_common.h"
#include "ccx_encoders_common.h"
#include "ccx_decoders_common.h"
static const char *XDSclasses_short[]=
{
"CUR",
"FUT",
"CHN",
"MIS",
"PUB",
"RES",
"PRV",
"END"
};
void xds_write_transcript_line_prefix (struct encoder_ctx *context, struct ccx_s_write *wb, LLONG start_time, LLONG end_time, int cur_xds_packet_class)
{
unsigned h1,m1,s1,ms1;
unsigned h2,m2,s2,ms2;
if (!wb || wb->fh==-1)
return;
if (start_time == -1)
{
// Means we entered XDS mode without making a note of the XDS start time. This is a bug.
ccx_common_logging.fatal_ftn(CCX_COMMON_EXIT_BUG_BUG, "Bug in timedtranscript (XDS). Please report.");
}
if (context->transcript_settings->showStartTime)
{
char buffer[80];
if (context->transcript_settings->relativeTimestamp)
{
if (utc_refvalue == UINT64_MAX)
{
mstotime(start_time + context->subs_delay, &h1, &m1, &s1, &ms1);
fdprintf(wb->fh, "%02u:%02u:%02u%c%03u|", h1, m1, s1, context->millis_separator, ms1);
}
else
{
fdprintf(wb->fh, "%lld%c%03d|", (start_time + context->subs_delay) / 1000,
context->millis_separator, (start_time + context->subs_delay) % 1000);
}
}
else
{
mstotime(start_time + context->subs_delay, &h1, &m1, &s1, &ms1);
time_t start_time_int = (start_time + context->subs_delay) / 1000;
int start_time_dec = (start_time + context->subs_delay) % 1000;
struct tm *start_time_struct = gmtime(&start_time_int);
strftime(buffer, sizeof(buffer), "%Y%m%d%H%M%S", start_time_struct);
fdprintf(wb->fh, "%s%c%03d|", buffer, context->millis_separator, start_time_dec);
}
}
if (context->transcript_settings->showEndTime)
{
char buffer[80];
if (context->transcript_settings->relativeTimestamp)
{
if (utc_refvalue == UINT64_MAX)
{
mstotime(end_time, &h2, &m2, &s2, &ms2);
fdprintf(wb->fh, "%02u:%02u:%02u%c%03u|", h2, m2, s2, context->millis_separator, ms2);
}
else
{
fdprintf(wb->fh, "%lld%s%03d|", end_time / 1000, context->millis_separator, end_time% 1000);
}
}
else
{
mstotime(end_time, &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(buffer, sizeof(buffer), "%Y%m%d%H%M%S", end_time_struct);
fdprintf(wb->fh, "%s%c%03d|", buffer, context->millis_separator, end_time_dec);
}
}
if (context->transcript_settings->showMode)
{
const char *mode = "XDS";
fdprintf(wb->fh, "%s|", mode);
}
if (context->transcript_settings->showCC)
{
fdprintf(wb->fh, "%s|", XDSclasses_short[cur_xds_packet_class]);
}
}

View File

@@ -0,0 +1,5 @@
#ifndef _CCX_ENCODER_XDS_H
#define _CCX_ENCODER_XDS_H
void xds_write_transcript_line_prefix (struct encoder_ctx *context, struct ccx_s_write *wb, LLONG start_time, LLONG end_time, int cur_xds_packet_class);
#endif

1734
src/lib_ccx/ccx_gxf.c Normal file

File diff suppressed because it is too large Load Diff

9
src/lib_ccx/ccx_gxf.h Normal file
View File

@@ -0,0 +1,9 @@
#ifndef CCX_GXF
#define CCX_GXF
#include "ccx_demuxer.h"
int ccx_gxf_probe(unsigned char *buf, int len);
int ccx_gxf_getmoredata(struct ccx_demuxer *ctx, struct demuxer_data **data);
struct ccx_gxf *ccx_gxf_init(struct ccx_demuxer *arg);
#endif

7
src/lib_ccx/ccx_mp4.h Normal file
View File

@@ -0,0 +1,7 @@
#ifndef CXX_MP4_H
#define CXX_MP4_H
int processmp4 (struct lib_ccx_ctx *ctx,struct ccx_s_mp4Cfg *cfg, char *file);
#endif

View File

@@ -0,0 +1,9 @@
#ifndef CCX_CCEXTRACTOR_COMPILE_H
#define CCX_CCEXTRACTOR_COMPILE_H
#ifndef VERSION_FILE_PRESENT
#define GIT_COMMIT "Unknown"
#define COMPILE_DATE "Unknown"
#else
#include "compile_info_real.h"
#endif
#endif

View File

@@ -47,28 +47,13 @@ struct conf_map configuration_map[] = {
{"BUFFER_INPUT",offsetof(struct ccx_s_options,buffer_input),set_int},
{"NOFONT_COLOR",offsetof(struct ccx_s_options,nofontcolor),set_int},
{"NOTYPE_SETTING",offsetof(struct ccx_s_options,notypesetting),set_int},
{"CODEC",offsetof(struct ccx_s_options,codec),set_int},
{"NOCODEC",offsetof(struct ccx_s_options,nocodec),set_int},
{"OUTPUT_FORMAT",offsetof(struct ccx_s_options,write_format),set_int},
{"START_CREDIT_TEXT",offsetof(struct ccx_s_options,start_credits_text),set_string},
{"START_CREDIT_NOT_BEFORE",offsetof(struct ccx_s_options,startcreditsnotbefore),set_time},
{"START_CREDIT_NOT_AFTER",offsetof(struct ccx_s_options,startcreditsnotafter),set_time},
{"START_CREDIT_FOR_ATLEAST",offsetof(struct ccx_s_options,startcreditsforatleast),set_time},
{"START_CREDIT_FOR_ATMOST",offsetof(struct ccx_s_options,startcreditsforatmost),set_time},
{"END_CREDITS_TEXT",offsetof(struct ccx_s_options,end_credits_text),set_string},
{"END_CREDITS_FOR_ATLEAST",offsetof(struct ccx_s_options,endcreditsforatleast),set_time},
{"END_CREDITS_FOR_ATMOST",offsetof(struct ccx_s_options,endcreditsforatmost),set_time},
{"VIDEO_EDITED",offsetof(struct ccx_s_options,binary_concat),set_int},
{"GOP_TIME",offsetof(struct ccx_s_options,use_gop_as_pts),set_int},
{"FIX_PADDINDG",offsetof(struct ccx_s_options,fix_padding),set_int},
{"TRIM",offsetof(struct ccx_s_options,trim_subs),set_int},
{"GUI_MODE_REPORTS",offsetof(struct ccx_s_options,gui_mode_reports),set_int},
{"NO_PROGRESS_BAR",offsetof(struct ccx_s_options,no_progress_bar),set_int},
{"SENTENCE_CAP",offsetof(struct ccx_s_options,sentence_cap),set_int},
{"CAP_FILE",offsetof(struct ccx_s_options,sentence_cap_file),set_string},
{"PROGRAM_NUMBER",offsetof(struct ccx_s_options,ts_forced_program),set_int},
{"AUTO_PROGRAM",offsetof(struct ccx_s_options,ts_autoprogram),set_int},
{"STREAM",offsetof(struct ccx_s_options,live_stream),set_int},
{"START_AT",offsetof(struct ccx_s_options,extraction_start),set_time},
{"END_AT",offsetof(struct ccx_s_options,extraction_end),set_time},
{"INVASTIGATE_PACKET",offsetof(struct ccx_s_options,investigate_packets),set_int},
@@ -76,15 +61,9 @@ struct conf_map configuration_map[] = {
{"NO_SYNC",offsetof(struct ccx_s_options,nosync),set_int},
{"HAUPPAUGE_MODE",offsetof(struct ccx_s_options,hauppauge_mode),set_int},
{"MP4_VIDEO_TRACK",offsetof(struct ccx_s_options,mp4vidtrack),set_int},
{"ENCODING",offsetof(struct ccx_s_options,encoding),set_int},
{"USE_PIC_ORDER",offsetof(struct ccx_s_options,usepicorder),set_int},
{"AUTO_MYTH",offsetof(struct ccx_s_options,auto_myth),set_int},
{"WTV_MPEG2",offsetof(struct ccx_s_options,wtvmpeg2),set_int},
{"OUTPUT_FILENAME",offsetof(struct ccx_s_options,output_filename),set_string},
{"OUT_ELEMENTRY_STREAM_FILENAME",offsetof(struct ccx_s_options,out_elementarystream_filename),set_string},
{"DATA_PID",offsetof(struct ccx_s_options,ts_cappid),set_int},
{"STREAM_TYPE",offsetof(struct ccx_s_options,ts_datastreamtype),set_int},
{"TS_FORCED_STREAM_TYPE",offsetof(struct ccx_s_options,ts_forced_streamtype),set_int},
{"DATE_FORMAT",offsetof(struct ccx_s_options,date_format),set_int},
// Settings for 608 decoder
{ "NO_ROLL_UP", offsetof(struct ccx_s_options, settings_608.no_rollup), set_int },

View File

@@ -429,17 +429,21 @@ void* dvbsub_init_decoder(struct dvb_config* cfg)
DVBSubContext *ctx = (DVBSubContext*) malloc(sizeof(DVBSubContext));
memset(ctx, 0, sizeof(DVBSubContext));
ctx->composition_id = cfg->composition_id[0];
ctx->ancillary_id = cfg->ancillary_id[0];
ctx->lang_index = cfg->lang_index[0];
if(cfg)
{
ctx->composition_id = cfg->composition_id[0];
ctx->ancillary_id = cfg->ancillary_id[0];
ctx->lang_index = cfg->lang_index[0];
}
else
{
ctx->composition_id = 1;
ctx->ancillary_id = 1;
ctx->lang_index = 1;
}
#ifdef ENABLE_OCR
ctx->ocr_ctx = init_ocr(ctx->lang_index);
if(!ctx->ocr_ctx)
{
freep(&ctx);
return NULL;
}
#endif
ctx->version = -1;
@@ -522,9 +526,9 @@ void* dvbsub_init_decoder(struct dvb_config* cfg)
return (void*) ctx;
}
int dvbsub_close_decoder(void *dvb_ctx)
int dvbsub_close_decoder(void **dvb_ctx)
{
DVBSubContext *ctx = (DVBSubContext *) dvb_ctx;
DVBSubContext *ctx = (DVBSubContext *) *dvb_ctx;
DVBSubRegionDisplay *display;
delete_regions(ctx);
@@ -542,6 +546,11 @@ int dvbsub_close_decoder(void *dvb_ctx)
free(display);
}
#ifdef ENABLE_OCR
if (ctx->ocr_ctx)
delete_ocr(&ctx->ocr_ctx);
#endif
freep(dvb_ctx);
return 0;
}
@@ -1427,20 +1436,29 @@ static void dvbsub_parse_display_definition_segment(void *dvb_ctx,
}
}
static int write_dvb_sub(void *dvb_ctx, struct cc_subtitle *sub)
/**
* Write Subtitle in cc_subtitle structure in CC_BITMAP format
* when OCR subsystem is present then it also write recognised text in
* cc_bitmap ocr_text variable.
*/
static int write_dvb_sub(struct lib_cc_decode *dec_ctx, struct cc_subtitle *sub)
{
DVBSubContext *ctx = (DVBSubContext *) dvb_ctx;
DVBSubContext *ctx;
DVBSubRegion *region;
DVBSubRegionDisplay *display;
DVBSubCLUT *clut;
DVBSubDisplayDefinition *display_def = ctx->display_definition;
DVBSubDisplayDefinition *display_def;
struct cc_bitmap *rect = NULL;
uint32_t *clut_table;
int offset_x=0, offset_y=0;
int ret = 0;
ctx = (DVBSubContext *) dec_ctx->private_data;
display_def = ctx->display_definition;
sub->type = CC_BITMAP;
sub->lang_index = ctx->lang_index;
if (display_def)
{
offset_x = display_def->x;
@@ -1464,7 +1482,8 @@ static int write_dvb_sub(void *dvb_ctx, struct cc_subtitle *sub)
return -1;
}
sub->start_time = get_visible_start();
/* USE PTS and convert here in required time */
sub->start_time = get_visible_start(dec_ctx->timing, 1);
sub->end_time = sub->start_time + ( ctx->time_out * 1000 );
sub->flags |= SUB_EOD_MARKER;
sub->got_output = 1;
@@ -1514,19 +1533,22 @@ static int write_dvb_sub(void *dvb_ctx, struct cc_subtitle *sub)
rect->data[0] = malloc(region->buf_size);
memcpy(rect->data[0], region->pbuf, region->buf_size);
#ifdef ENABLE_OCR
ret = ocr_rect(ctx->ocr_ctx, rect, &ocr_str);
if(ret >= 0)
rect->ocr_text = ocr_str;
if (ctx->ocr_ctx)
{
ret = ocr_rect(ctx->ocr_ctx, rect, &ocr_str,region->bgcolor);
if(ret >= 0)
rect->ocr_text = ocr_str;
else
rect->ocr_text = NULL;
}
else
{
rect->ocr_text = NULL;
}
#endif
rect++;
}
#ifdef DeBUG
if (ctx->object_list)
{
//save_display_set(ctx);
}
#endif
return 0;
}
@@ -1539,9 +1561,9 @@ static int write_dvb_sub(void *dvb_ctx, struct cc_subtitle *sub)
*
* @return -1 on error
*/
int dvbsub_decode(void *dvb_ctx, const unsigned char *buf, int buf_size, struct cc_subtitle *sub)
int dvbsub_decode(struct lib_cc_decode *dec_ctx, const unsigned char *buf, int buf_size, struct cc_subtitle *sub)
{
DVBSubContext *ctx = (DVBSubContext *) dvb_ctx;
DVBSubContext *ctx = (DVBSubContext *) dec_ctx->private_data;
const uint8_t *p, *p_end;
int segment_type;
int page_id;
@@ -1551,14 +1573,16 @@ int dvbsub_decode(void *dvb_ctx, const unsigned char *buf, int buf_size, struct
if (buf_size <= 6 || *buf != 0x0f)
{
mprint("incomplete or broken packet\n");
mprint("dvbsub_decode: incomplete, broken or empty packet\n");
return -1;
}
p = buf;
p_end = buf + buf_size;
set_fts();
dec_ctx->timing->current_tref = 0;
set_fts(dec_ctx->timing);
while (p_end - p >= 6 && *p == 0x0f)
{
p += 1;
@@ -1570,7 +1594,7 @@ int dvbsub_decode(void *dvb_ctx, const unsigned char *buf, int buf_size, struct
if (p_end - p < segment_length)
{
mprint("incomplete or broken packet\n");
mprint("dvbsub_decode: incomplete, broken or empty packet\n");
return -1;
}
@@ -1580,29 +1604,29 @@ int dvbsub_decode(void *dvb_ctx, const unsigned char *buf, int buf_size, struct
switch (segment_type)
{
case DVBSUB_PAGE_SEGMENT:
dvbsub_parse_page_segment(dvb_ctx, p, segment_length);
dvbsub_parse_page_segment(ctx, p, segment_length);
got_segment |= 1;
break;
case DVBSUB_REGION_SEGMENT:
dvbsub_parse_region_segment(dvb_ctx, p, segment_length);
dvbsub_parse_region_segment(ctx, p, segment_length);
got_segment |= 2;
break;
case DVBSUB_CLUT_SEGMENT:
ret = dvbsub_parse_clut_segment(dvb_ctx, p, segment_length);
ret = dvbsub_parse_clut_segment(ctx, p, segment_length);
if (ret < 0)
goto end;
got_segment |= 4;
break;
case DVBSUB_OBJECT_SEGMENT:
dvbsub_parse_object_segment(dvb_ctx, p, segment_length);
dvbsub_parse_object_segment(ctx, p, segment_length);
got_segment |= 8;
break;
case DVBSUB_DISPLAYDEFINITION_SEGMENT:
dvbsub_parse_display_definition_segment(dvb_ctx, p,
dvbsub_parse_display_definition_segment(ctx, p,
segment_length);
break;
case DVBSUB_DISPLAY_SEGMENT:
write_dvb_sub(dvb_ctx,sub);
write_dvb_sub(dec_ctx, sub);
got_segment |= 16;
break;
default:
@@ -1618,7 +1642,7 @@ int dvbsub_decode(void *dvb_ctx, const unsigned char *buf, int buf_size, struct
// segments then we need no further data.
if (got_segment == 15)
{
write_dvb_sub(dvb_ctx,sub);
write_dvb_sub(dec_ctx, sub);
}
@@ -1671,9 +1695,15 @@ int parse_dvb_description(struct dvb_config* cfg, unsigned char*data,
for (i = 0; i < cfg->n_language; i++, data += i * 8)
{
/* setting language to undefined if not found in language lkup table */
char lang_name[4];
for(int char_index = 0; char_index < 3; char_index++)
{
lang_name[char_index] = cctolower(data[char_index]);
}
for (j = 0, cfg->lang_index[i] = 0; language[j] != NULL; j++)
{
if (!strncmp((const char*) (data), language[j], 3))
if (!strncmp(lang_name, language[j], 3))
cfg->lang_index[i] = j;
}
cfg->sub_type[i] = data[3];
@@ -1682,5 +1712,21 @@ int parse_dvb_description(struct dvb_config* cfg, unsigned char*data,
}
/*
Abhinav95: The way this function is called right now, only cfg->lang_index[0]
gets populated. E.g. for 3 stream languages, it will be called 3 times, and
set the language index in only the first element each time. This works with the
current state of the DVB code.
*/
if(ccx_options.dvblang)
{
if(strcmp(ccx_options.dvblang, language[cfg->lang_index[0]])!=0)
{
mprint("Ignoring stream language '%s' not equal to dvblang '%s'\n",
language[cfg->lang_index[0]], ccx_options.dvblang);
return -1;
}
}
return 0;
}

View File

@@ -44,7 +44,7 @@ struct dvb_config
*/
void* dvbsub_init_decoder(struct dvb_config* cfg);
int dvbsub_close_decoder(void *dvb_ctx);
int dvbsub_close_decoder(void **dvb_ctx);
/**
* @param dvb_ctx PreInitialized DVB context using DVB
@@ -55,7 +55,7 @@ int dvbsub_close_decoder(void *dvb_ctx);
*
* @return -1 on error
*/
int dvbsub_decode(void *dvb_ctx, const unsigned char *buf, int buf_size, struct cc_subtitle *sub);
int dvbsub_decode(struct lib_cc_decode *dec_ctx, const unsigned char *buf, int buf_size, struct cc_subtitle *sub);
/**
* @func parse_dvb_description

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,5 @@
#include "lib_ccx.h"
#include "ccx_decoders_vbi.h"
// Parse the user data for captions. The udtype variable denotes
@@ -9,473 +10,498 @@
// 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 lib_ccx_ctx *ctx, struct bitstream *ustream, int udtype, struct cc_subtitle *sub)
int user_data(struct lib_cc_decode *ctx, struct bitstream *ustream, int udtype, struct cc_subtitle *sub)
{
struct lib_cc_decode *dec_ctx = NULL;
dec_ctx = ctx->dec_ctx;
dbg_print(CCX_DMT_VERBOSE, "user_data(%d)\n", udtype);
dbg_print(CCX_DMT_VERBOSE, "user_data(%d)\n", udtype);
// Shall not happen
if (ustream->error || ustream->bitsleft <= 0)
// 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(CCX_COMMON_EXIT_BUG_BUG, "user_data: Impossible!");
// fatal(CCX_COMMON_EXIT_BUG_BUG, "user_data: Impossible!");
}
// Do something
ctx->stat_numuserheaders++;
//header+=4;
// Do something
ctx->stat_numuserheaders++;
//header+=4;
unsigned char *ud_header = next_bytes(ustream, 4);
if (ustream->error || ustream->bitsleft <= 0)
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(CCX_COMMON_EXIT_BUG_BUG, "user_data: Impossible!");
// fatal(CCX_COMMON_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 ) )
{
ctx->stat_dvdccheaders++;
// DVD CC header, see
// <http://www.theneitherworld.com/mcpoodle/SCC_TOOLS/DOCS/SCC_FORMAT.HTML>
if ( !memcmp(ud_header,"\x43\x43", 2 ) )
{
ctx->stat_dvdccheaders++;
// Probably unneeded, but keep looking for extra caption blocks
int maybeextracb = 1;
// Probably unneeded, but keep looking for extra caption blocks
int maybeextracb = 1;
read_bytes(ustream, 4); // "43 43 01 F8"
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
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
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":""));
dbg_print(CCX_DMT_VERBOSE, "Reading %d%s DVD CC segments\n",
capcount, (truncate_flag?"+1":""));
capcount += truncate_flag;
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);
// 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 (ctx->timing->fts_max > 0)
ctx->timing->fts_now = ctx->timing->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);
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(dec_ctx, 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(dec_ctx, data, sub);
ecbcount++;
}
else
{
dbg_print(CCX_DMT_VERBOSE, "Illegal (extra) caption segment - stop here.\n");
maybeextracb = 0;
break;
}
}
}
// 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(ctx, 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(ctx, 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
dbg_print(CCX_DMT_VERBOSE, "Read %d/%d DVD CC blocks\n", rcbcount, ecbcount);
}
// SCTE 20 user data
else if (!ctx->noscte20 && ud_header[0] == 0x03)
{
if ((ud_header[1]&0x7F) == 0x01)
{
unsigned char cc_data[3*31+1]; // Maximum cc_count is 31
ctx->stat_scte20ccheaders++;
read_bytes(ustream, 2); // "03 01"
ctx->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 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 */
unsigned field_number;
unsigned cc_data1;
unsigned cc_data2;
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);
read_bits(ustream,1); // TODO: Add syntax check */
if (ustream->bitsleft < 0)
fatal(CCX_COMMON_EXIT_BUG_BUG, "Oops!");
if (ustream->bitsleft < 0)
fatal(CCX_COMMON_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(ctx, cc_data, cc_count, current_tref, fts_now, sub);
// 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(!ctx->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(ctx, cc_data, cc_count, ctx->timing->current_tref, ctx->timing->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)
ctx->stat_replay4000headers++;
else
ctx->stat_replay5000headers++;
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];
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(dec_ctx, data, sub);
read_bytes(ustream, 2); // Skip "CC 02" for R4000 or "AA 02" for R5000
data[0]=0x04; // Field 1
data[1]=read_u8(ustream);
data[2]=read_u8(ustream);
do_cb(dec_ctx, data, sub);
}
// HDTV - see A/53 Part 4 (Video)
else if ( !memcmp(ud_header,"\x47\x41\x39\x34", 4 ) )
{
ctx->stat_hdtv++;
if (ud_header[0]==0xbb)
ctx->stat_replay4000headers++;
else
ctx->stat_replay5000headers++;
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);
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(ctx, data, sub);
read_bytes(ustream, 2); // Skip "CC 02" for R4000 or "AA 02" for R5000
data[0]=0x04; // Field 1
data[1]=read_u8(ustream);
data[2]=read_u8(ustream);
do_cb(ctx, data, sub);
}
// HDTV - see A/53 Part 4 (Video)
else if ( !memcmp(ud_header,"\x47\x41\x39\x34", 4 ) )
{
ctx->stat_hdtv++;
int proceed = 1;
unsigned char *cc_data = read_bytes(ustream, cc_count*3);
if (ustream->bitsleft < 0)
fatal(CCX_COMMON_EXIT_BUG_BUG, "Not enough for CC captions!");
read_bytes(ustream, 4); // "47 41 39 34"
// 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;
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);
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);
int proceed = 1;
unsigned char *cc_data = read_bytes(ustream, cc_count*3);
if (ustream->bitsleft < 0)
fatal(CCX_COMMON_EXIT_BUG_BUG, "Not enough for CC captions!");
// 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(ctx, cc_data, cc_count, current_tref, fts_now, sub);
// 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;
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;
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);
dbg_print(CCX_DMT_VERBOSE, "Reading Dish Network user data\n");
// 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(ctx, cc_data, cc_count, ctx->timing->current_tref, ctx->timing->fts_now, sub);
ctx->stat_dishheaders++;
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;
read_bytes(ustream, 2); // "05 02"
dbg_print(CCX_DMT_VERBOSE, "Reading Dish Network user data\n");
// 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);
ctx->stat_dishheaders++;
unsigned char hi;
read_bytes(ustream, 2); // "05 02"
// 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]);
// 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);
cc_count = 1;
dishdata[1]=dcd[1];
dishdata[2]=dcd[2];
unsigned char hi;
dbg_print(CCX_DMT_PARSE, "%s", debug_608toASC( dishdata, 0) );
// 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]);
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];
cc_count = 1;
dishdata[1]=dcd[1];
dishdata[2]=dcd[2];
dbg_print(CCX_DMT_PARSE, "%s:\n", debug_608toASC( dishdata+3, 0) );
}
else
{
dbg_print(CCX_DMT_PARSE, ":\n");
}
dbg_print(CCX_DMT_PARSE, "%s", debug_608toASC( dishdata, 0) );
dishdata[cc_count*3] = 0xFF; // Set end marker
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];
store_hdcc(ctx, dishdata, cc_count, current_tref, fts_now, sub);
dbg_print(CCX_DMT_PARSE, "%s:\n", debug_608toASC( dishdata+3, 0) );
}
else
{
dbg_print(CCX_DMT_PARSE, ":\n");
}
// 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]);
dishdata[cc_count*3] = 0xFF; // Set end marker
cc_count = 2;
dishdata[1]=dcd[1];
dishdata[2]=dcd[2];
store_hdcc(ctx, dishdata, cc_count, ctx->timing->current_tref, ctx->timing->fts_now, sub);
dishdata[3]=0x04; // Field 1
dishdata[4]=dcd[3];
dishdata[5]=dcd[4];
dishdata[6] = 0xFF; // Set end marker
// 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]);
dbg_print(CCX_DMT_PARSE, "%s", debug_608toASC( dishdata, 0) );
dbg_print(CCX_DMT_PARSE, "%s:\n", debug_608toASC( dishdata+3, 0) );
cc_count = 2;
dishdata[1]=dcd[1];
dishdata[2]=dcd[2];
store_hdcc(ctx, dishdata, cc_count, current_tref, fts_now, sub);
dishdata[3]=0x04; // Field 1
dishdata[4]=dcd[3];
dishdata[5]=dcd[4];
dishdata[6] = 0xFF; // Set end marker
// 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
dbg_print(CCX_DMT_PARSE, "%s", debug_608toASC( dishdata, 0) );
dbg_print(CCX_DMT_PARSE, "%s:\n", debug_608toASC( dishdata+3, 0) );
// 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]);
store_hdcc(ctx, dishdata, cc_count, ctx->timing->current_tref, ctx->timing->fts_now, sub);
type=dcd[0]; // Number of caption bytes (0x02 or 0x04)
// 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
cc_count = 1;
dishdata[1]=dcd[2];
dishdata[2]=dcd[3];
// 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]);
dcd+=4; // Skip the first 4 bytes.
if (type==0x02)
{
type=dcd[0]; // repeater (0x02 or 0x04)
dcd++; // Skip the repeater byte.
type=dcd[0]; // Number of caption bytes (0x02 or 0x04)
dbg_print(CCX_DMT_PARSE, " - R:%02X :%s", type, debug_608toASC( dishdata, 0) );
cc_count = 1;
dishdata[1]=dcd[2];
dishdata[2]=dcd[3];
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
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, ":%s", debug_608toASC( dishdata, 0) );
dbg_print(CCX_DMT_PARSE, "%s:\n", debug_608toASC( dishdata+3, 0) );
}
dbg_print(CCX_DMT_PARSE, " - R:%02X :%s", type, debug_608toASC( dishdata, 0) );
store_hdcc(ctx, dishdata, cc_count, current_tref, fts_now, sub);
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
// Ignore 3 (0x0A, followed by 2 unknown) bytes.
break;
default:
// printf ("Unknown?\n");
break;
} // switch
dbg_print(CCX_DMT_PARSE, ":%s", debug_608toASC( dishdata, 0) );
dbg_print(CCX_DMT_PARSE, "%s:\n", debug_608toASC( dishdata+3, 0) );
}
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.
ctx->stat_divicom++;
store_hdcc(ctx, dishdata, cc_count, ctx->timing->current_tref, ctx->timing->fts_now, sub);
unsigned char data[3];
// Ignore 3 (0x0A, followed by 2 unknown) bytes.
break;
default:
// printf ("Unknown?\n");
break;
} // switch
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(dec_ctx, 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, "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.
ctx->stat_divicom++;
dbg_print(CCX_DMT_VERBOSE, "User data - processed\n");
unsigned char data[3];
// Read complete
return 1;
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(ctx, data, sub);
// This is probably incomplete!
}
// GXF vbi OEM code
else if ( !memcmp(ud_header,"\x73\x52\x21\x06", 4 ) )
{
int udatalen = ustream->end - ustream->pos;
uint16_t line_nb;
uint8_t line_type;
uint8_t field = 1;
read_bytes(ustream, 4); //skip header code
read_bytes(ustream, 2); //skip data length
line_nb = read_bits(ustream, 16);
line_type = read_u8(ustream);
field = (line_type & 0x03);
if(field == 0)
mprint("MPEG:VBI: Invalid field\n");
line_type = line_type >> 2;
if(line_type != 1)
mprint("MPEG:VBI: only support Luma line\n");
if (udatalen < 720)
mprint("MPEG:VBI: Minimum 720 bytes in luma line required\n");
decode_vbi(ctx, field, ustream->pos, 720, sub);
dbg_print(CCX_DMT_VERBOSE, "GXF (vbi line %d) user data:\n", line_nb);
}
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

@@ -21,6 +21,7 @@ struct ffmpeg_ctx
AVFrame *frame;
int stream_index;
};
/**
* call back function to be registered for avlog
*/
@@ -52,13 +53,14 @@ static void log_cb(void* ptr, int level, const char* fmt, va_list vl)
vfprintf(flog, fmt, vl);
}
/**
* @path this path could be relative or absolute path of static file
* this path could be path of device
*
* @return ctx Context of ffmpeg
*/
void *init_ffmpeg(char *path)
void *init_ffmpeg(const char *path)
{
int ret = 0;
int stream_index = 0;
@@ -120,6 +122,7 @@ void *init_ffmpeg(char *path)
fail:
return ctx;
}
/**
* @param ctx context of ffmpeg
* @param data preallocated buffer where data will be recieved
@@ -158,10 +161,10 @@ int ff_get_ccframe(void *arg, unsigned char*data, int maxlen)
{
return AVERROR(EAGAIN);
}
current_pts = av_frame_get_best_effort_timestamp(ctx->frame);
if(!pts_set)
pts_set = 1;
set_fts();
// current_pts = av_frame_get_best_effort_timestamp(ctx->frame);
// if(!pts_set)
// pts_set = 1;
// set_fts();
for(int i = 0;i< ctx->frame->nb_side_data;i++)
{
if(ctx->frame->side_data[i]->type == AV_FRAME_DATA_A53_CC)
@@ -184,4 +187,56 @@ int ff_get_ccframe(void *arg, unsigned char*data, int maxlen)
return len;
}
int ffmpeg_getmoredata(struct ccx_demuxer *ctx, struct demuxer_data **ppdata)
{
struct demuxer_data *data;
int ret = 0;
if(!*ppdata)
{
*ppdata = alloc_demuxer_data();
if(!*ppdata)
return -1;
data = *ppdata;
//TODO Set to dummy, find and set actual value
data->program_number = 1;
data->stream_pid = 1;
data->codec = CCX_CODEC_ATSC_CC;
data->bufferdatatype = CCX_RAW_TYPE;
}
else
{
data = *ppdata;
}
do
{
int len = ff_get_ccframe(ctx->ffmpeg_ctx, data->buffer, BUFSIZE);
if(len == AVERROR(EAGAIN))
{
continue;
}
else if(len == AVERROR_EOF)
{
ret = CCX_EOF;
break;
}
else if(len == 0)
continue;
else if(len < 0 )
{
mprint("Error extracting Frame\n");
break;
}
else
{
data->len = len;
break;
}
}while(1);
return ret;
}
#endif

View File

@@ -5,19 +5,14 @@
#include "libavutil/common.h"
#include "libavutil/error.h"
#endif
#include "ccx_demuxer.h"
/**
* @path this path could be relative or absolute path of static file
* this path could be path of device
*
* @return ctx Context of ffmpeg
*/
void *init_ffmpeg(char *path);
void *init_ffmpeg(const char *path);
/**
* @param ctx context of ffmpeg
* @param data preallocated buffer where data will be recieved
* @param maxlen length of buffer, where data will be copied
* @return number of bytes recieved as data
*/
int ff_get_ccframe(void *arg, unsigned char*data, int maxlen);
int ffmpeg_getmoredata(struct ccx_demuxer *ctx, struct demuxer_data **ppdata);
#endif

94
src/lib_ccx/file_buffer.h Normal file
View File

@@ -0,0 +1,94 @@
#ifndef FILE_BUFFER_H
#define FILE_BUFFER_H
/**
* Read from buffer if there is insufficient data then cache the buffer
*
* @param ctx ccx_demuxer context properly initilaized ccx_demuxer with some input
* Not to be NULL, since ctx is derefrenced inside this function
*
* @param buffer if buffer then it must be allocated to at;east bytes len as
* passed in third argument, If buffer is NULL then those number of bytes
* are skipped from input.
* @param bytes number of bytes to be read from file buffer.
*
* @return 0 or number of bytes, if returned 0 then op should check error number to know
* details of error
*/
size_t buffered_read_opt (struct ccx_demuxer *ctx, unsigned char *buffer, size_t bytes);
/**
* Skip bytes from file buffer and if needed also seek file for number of bytes.
*
*/
static size_t inline buffered_skip(struct ccx_demuxer *ctx, unsigned int bytes)
{
size_t result;
if (bytes <= ctx->bytesinbuffer - ctx->filebuffer_pos)
{
ctx->filebuffer_pos += bytes;
result = bytes;
}
else
{
result = buffered_read_opt (ctx, NULL, bytes);
}
return result;
}
/**
* Read bytes from file buffer and if needed also read file for number of bytes.
*
*/
static size_t inline buffered_read(struct ccx_demuxer *ctx, unsigned char *buffer, size_t bytes)
{
size_t result;
if (bytes <= ctx->bytesinbuffer - ctx->filebuffer_pos)
{
if (buffer != NULL)
memcpy (buffer, ctx->filebuffer + ctx->filebuffer_pos, bytes);
ctx->filebuffer_pos+=bytes;
result = bytes;
}
else
{
result = buffered_read_opt (ctx, 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();
}
}
return result;
}
/**
* Read single byte from file buffer and if needed also read file for number of bytes.
*
*/
static size_t inline buffered_read_byte(struct ccx_demuxer *ctx, unsigned char *buffer)
{
size_t result;
if (ctx->bytesinbuffer - ctx->filebuffer_pos)
{
if (buffer)
{
*buffer=ctx->filebuffer[ctx->filebuffer_pos];
ctx->filebuffer_pos++;
result = 1;
}
}
else
result = buffered_read_opt (ctx, buffer, 1);
return result;
}
unsigned short buffered_get_be16(struct ccx_demuxer *ctx);
unsigned char buffered_get_byte (struct ccx_demuxer *ctx);
unsigned int buffered_get_be32(struct ccx_demuxer *ctx);
unsigned short buffered_get_le16(struct ccx_demuxer *ctx);
unsigned int buffered_get_le32(struct ccx_demuxer *ctx);
#endif

View File

@@ -1,22 +1,23 @@
#include "lib_ccx.h"
#include "ccx_common_option.h"
#include "activity.h"
#include "file_buffer.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;
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);
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);
ret = LSEEK (in, current, SEEK_SET);
if (ret < 0)
return -1;
@@ -25,77 +26,84 @@ LLONG getfilesize (int in)
LLONG gettotalfilessize (struct lib_ccx_ctx *ctx) // -1 if one or more files failed to open
{
LLONG ts=0;
int h;
for (int i=0;i<ctx->num_input_files;i++)
{
if (0 == strcmp(ctx->inputfile[i],"-")) // Skip stdin
LLONG ts=0;
int h;
for (int i = 0; i < ctx->num_input_files; i++)
{
if (0 == strcmp(ctx->inputfile[i], "-")) // Skip stdin
continue;
#ifdef _WIN32
h=OPEN (ctx->inputfile[i],O_RDONLY | O_BINARY);
h = OPEN (ctx->inputfile[i], O_RDONLY | O_BINARY);
#else
h=OPEN (ctx->inputfile[i],O_RDONLY);
h = OPEN (ctx->inputfile[i], O_RDONLY);
#endif
if (h==-1)
{
mprint ("\rUnable to open %s\r\n",ctx->inputfile[i]);
return -1;
}
if (!ccx_options.live_stream)
ts+=getfilesize (h);
close (h);
}
return ts;
if (h == -1) {
switch (errno)
{
case ENOENT:
return -1 * ENOENT;
case EACCES:
return -1 * EACCES;
case EINVAL:
return -1 * EINVAL;
case EMFILE:
return -1 * EMFILE;
default:
return -1;
}
}
if (!ccx_options.live_stream)
ts += getfilesize (h);
close (h);
}
return ts;
}
void prepare_for_new_file (struct lib_ccx_ctx *ctx)
{
struct lib_cc_decode *dec_ctx = NULL;
dec_ctx = ctx->dec_ctx;
// Init per file variables
min_pts=0x01FFFFFFFFLL; // 33 bit
sync_pts=0;
pts_set = 0;
// inputsize=0; Now responsibility of switch_to_next_file()
ctx->last_reported_progress=-1;
ctx->stat_numuserheaders = 0;
ctx->stat_dvdccheaders = 0;
ctx->stat_scte20ccheaders = 0;
ctx->stat_replay5000headers = 0;
ctx->stat_replay4000headers = 0;
ctx->stat_dishheaders = 0;
ctx->stat_hdtv = 0;
ctx->stat_divicom = 0;
total_frames_count = 0;
ctx->total_pulldownfields = 0;
ctx->total_pulldownframes = 0;
dec_ctx->cc_stats[0]=0; dec_ctx->cc_stats[1]=0; dec_ctx->cc_stats[2]=0; dec_ctx->cc_stats[3]=0;
ctx->false_pict_header=0;
ctx->frames_since_last_gop=0;
frames_since_ref_time=0;
gop_time.inited=0;
first_gop_time.inited=0;
gop_rollover=0;
printed_gop.inited=0;
dec_ctx->saw_caption_block=0;
ctx->past=0;
pts_big_change=0;
ctx->startbytes_pos=0;
ctx->startbytes_avail=0;
init_file_buffer();
anchor_hdcc(-1);
firstcall = 1;
ctx->last_reported_progress =-1;
ctx->stat_numuserheaders = 0;
ctx->stat_dvdccheaders = 0;
ctx->stat_scte20ccheaders = 0;
ctx->stat_replay5000headers = 0;
ctx->stat_replay4000headers = 0;
ctx->stat_dishheaders = 0;
ctx->stat_hdtv = 0;
ctx->stat_divicom = 0;
total_frames_count = 0;
ctx->false_pict_header = 0;
frames_since_ref_time = 0;
gop_time.inited = 0;
first_gop_time.inited = 0;
gop_rollover = 0;
printed_gop.inited = 0;
pts_big_change = 0;
firstcall = 1;
if(ctx->epg_inited)
{
for(int x = 0; x < 0xfff; x++)
{
ctx->epg_buffers[x].buffer = NULL;
ctx->epg_buffers[x].ccounter = 0;
}
for (int i = 0; i < TS_PMT_MAP_SIZE; i++)
{
ctx->eit_programs[i].array_len = 0;
ctx->eit_current_events[i] = -1;
}
ctx->epg_last_output = -1;
ctx->epg_last_live_output = -1;
}
}
/* Close input file if there is one and let the GUI know */
void close_input_file (struct lib_ccx_ctx *ctx)
{
if (ctx->infd!=-1 && ccx_options.input_source==CCX_DS_FILE)
{
close (ctx->infd);
ctx->infd=-1;
activity_input_file_closed();
}
ctx->demux_ctx->close(ctx->demux_ctx);
}
/* Close current file and open next one in list -if any- */
@@ -105,368 +113,411 @@ can be done */
int switch_to_next_file (struct lib_ccx_ctx *ctx, LLONG bytesinbuffer)
{
struct lib_cc_decode *dec_ctx = NULL;
dec_ctx = ctx->dec_ctx;
if (ctx->current_file==-1 || !ccx_options.binary_concat)
int ret = 0;
if (ctx->current_file == -1 || !ccx_options.binary_concat)
{
memset (ctx->PIDs_seen,0,65536*sizeof (int));
memset (ctx->PIDs_programs,0,65536*sizeof (struct PMT_entry *));
ctx->demux_ctx->reset(ctx->demux_ctx);
}
if (ccx_options.input_source==CCX_DS_STDIN)
switch(ccx_options.input_source)
{
if (ctx->infd!=-1) // Means we had already processed stdin. So we're done.
{
if (ccx_options.print_file_reports)
print_file_report(ctx);
return 0;
}
ctx->infd=0;
mprint ("\n\r-----------------------------------------------------------------\n");
mprint ("\rReading from standard input\n");
return 1;
case CCX_DS_STDIN:
case CCX_DS_NETWORK:
case CCX_DS_TCP:
ret = ctx->demux_ctx->open(ctx->demux_ctx, NULL);
if (ret < 0)
return 0;
else if (ret)
return ret;
else
return 1;
break;
default:
break;
}
if (ccx_options.input_source==CCX_DS_NETWORK)
/* Close current and make sure things are still sane */
if (ctx->demux_ctx->is_open(ctx->demux_ctx))
{
if (ctx->infd!=-1) // Means we have already bound a socket.
{
if (ccx_options.print_file_reports)
print_file_report(ctx);
return 0;
}
ctx->infd = start_upd_srv(ccx_options.udpaddr, ccx_options.udpport);
return 1;
if(ctx->infd < 0)
fatal (CCX_COMMON_EXIT_BUG_BUG, "socket() failed.");
}
if (ccx_options.input_source==CCX_DS_TCP)
{
if (ctx->infd != -1)
{
if (ccx_options.print_file_reports)
print_file_report(ctx);
return 0;
}
ctx->infd = start_tcp_srv(ccx_options.tcpport, ccx_options.tcp_password);
return 1;
}
/* Close current and make sure things are still sane */
if (ctx->infd!=-1)
{
dbg_print(CCX_DMT_708, "[CEA-708] The 708 decoder was reset [%d] times.\n", ctx->freport.data_from_708->reset_count);
if (ccx_options.print_file_reports)
print_file_report(ctx);
close_input_file (ctx);
if (ctx->inputsize>0 && ((ctx->past+bytesinbuffer) < ctx->inputsize) && !dec_ctx->processed_enough)
{
mprint("\n\n\n\nATTENTION!!!!!!\n");
mprint("In switch_to_next_file(): Processing of %s %d ended prematurely %lld < %lld, please send bug report.\n\n",
ctx->inputfile[ctx->current_file], ctx->current_file, ctx->past, ctx->inputsize);
}
if (ccx_options.binary_concat)
{
ctx->total_past+=ctx->inputsize;
ctx->past=0; // Reset always or at the end we'll have double the size
}
}
for (;;)
{
ctx->current_file++;
if (ctx->current_file>=ctx->num_input_files)
break;
// The following \n keeps the progress percentage from being overwritten.
mprint ("\n\r-----------------------------------------------------------------\n");
if (ctx->inputsize > 0 && ((ctx->demux_ctx->past+bytesinbuffer) < ctx->inputsize) && is_decoder_processed_enough(ctx) == CCX_FALSE)
{
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",
ctx->inputfile[ctx->current_file], ctx->current_file, ctx->demux_ctx->past, ctx->inputsize);
}
close_input_file (ctx);
if (ccx_options.binary_concat)
{
ctx->total_past += ctx->inputsize;
ctx->demux_ctx->past = 0; // Reset always or at the end we'll have double the size
}
}
for (;;)
{
ctx->current_file++;
if (ctx->current_file >= ctx->num_input_files)
break;
// The following \n keeps the progress percentage from being overwritten.
mprint ("\n\r-----------------------------------------------------------------\n");
mprint ("\rOpening file: %s\n", ctx->inputfile[ctx->current_file]);
#ifdef _WIN32
ctx->infd=OPEN (ctx->inputfile[ctx->current_file],O_RDONLY | O_BINARY);
#else
ctx->infd=OPEN (ctx->inputfile[ctx->current_file],O_RDONLY);
#endif
if (ctx->infd == -1)
mprint ("\rWarning: Unable to open input file [%s]\n", ctx->inputfile[ctx->current_file]);
else
{
activity_input_file_open (ctx->inputfile[ctx->current_file]);
if (!ccx_options.live_stream)
{
ctx->inputsize = getfilesize (ctx->infd);
if (!ccx_options.binary_concat)
ctx->total_inputsize=ctx->inputsize;
}
return 1; // Succeeded
}
}
return 0;
ret = ctx->demux_ctx->open(ctx->demux_ctx, ctx->inputfile[ctx->current_file]);
if (ret < 0)
mprint ("\rWarning: Unable to open input file [%s]\n", ctx->inputfile[ctx->current_file]);
else
{
activity_input_file_open (ctx->inputfile[ctx->current_file]);
if (!ccx_options.live_stream)
{
ctx->inputsize = ctx->demux_ctx->get_filesize (ctx->demux_ctx);
if (!ccx_options.binary_concat)
ctx->total_inputsize = ctx->inputsize;
}
return 1; // Succeeded
}
}
return 0;
}
void position_sanity_check (void)
void position_sanity_check (int in)
{
#ifdef SANITY_CHECK
if (in!=-1)
{
LLONG realpos=LSEEK (in,0,SEEK_CUR);
if (realpos!=ctx->past-filebuffer_pos+bytesinbuffer)
{
fatal (CCX_COMMON_EXIT_BUG_BUG, "Position desync, THIS IS A BUG. Real pos =%lld, past=%lld.\n",realpos,ctx->past);
}
}
if (in!=-1)
{
LLONG realpos = LSEEK (in,0,SEEK_CUR);
if (realpos != ctx->demux_ctx->past - filebuffer_pos + bytesinbuffer)
{
fatal (CCX_COMMON_EXIT_BUG_BUG, "Position desync, THIS IS A BUG. Real pos =%lld, past=%lld.\n", realpos, ctx->demux_ctx->past);
}
}
#endif
}
int init_file_buffer(void)
int init_file_buffer(struct ccx_demuxer *ctx)
{
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;
ctx->filebuffer_start = 0;
ctx->filebuffer_pos = 0;
if (ctx->filebuffer == NULL)
{
ctx->filebuffer = (unsigned char *) malloc (FILEBUFFERSIZE);
ctx->bytesinbuffer = 0;
}
if (ctx->filebuffer == NULL)
{
return -1;
}
return 0;
}
void buffered_seek (struct lib_ccx_ctx *ctx, int offset)
void buffered_seek (struct ccx_demuxer *ctx, int offset)
{
position_sanity_check();
if (offset<0)
{
filebuffer_pos+=offset;
if (filebuffer_pos<0)
{
// We got into the start buffer (hopefully)
if (ctx->startbytes_pos+filebuffer_pos < 0)
{
fatal (CCX_COMMON_EXIT_BUG_BUG, "PANIC: Attempt to seek before buffer start, this is a bug!");
}
ctx->startbytes_pos+=filebuffer_pos;
filebuffer_pos=0;
}
}
else
{
buffered_read_opt (ctx, NULL, offset);
position_sanity_check();
}
position_sanity_check(ctx->infd);
if (offset < 0)
{
ctx->filebuffer_pos += offset;
if (ctx->filebuffer_pos < 0)
{
// We got into the start buffer (hopefully)
if ((ctx->filebuffer_pos + ctx->startbytes_pos) < 0)
{
fatal (CCX_COMMON_EXIT_BUG_BUG, "PANIC: Attempt to seek before buffer start, this is a bug!");
}
ctx->startbytes_pos += ctx->filebuffer_pos;
ctx->filebuffer_pos = 0;
}
}
else
{
buffered_read_opt (ctx, NULL, offset);
position_sanity_check(ctx->infd);
}
}
void sleepandchecktimeout (time_t start)
{
if (ccx_options.input_source==CCX_DS_STDIN)
{
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;
}
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);
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)
void return_to_buffer (struct ccx_demuxer *ctx, unsigned char *buffer, unsigned int bytes)
{
if (bytes == filebuffer_pos)
if (bytes == ctx->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;
memcpy (ctx->filebuffer, buffer, bytes);
ctx->filebuffer_pos = 0;
return;
}
if (filebuffer_pos>0) // Discard old bytes, because we may need the space
if (ctx->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;
memmove (ctx->filebuffer, ctx->filebuffer + ctx->filebuffer_pos, ctx->bytesinbuffer-ctx->filebuffer_pos);
ctx->bytesinbuffer -= ctx->filebuffer_pos;
ctx->bytesinbuffer = 0;
ctx->filebuffer_pos = 0;
}
if (bytesinbuffer + bytes > FILEBUFFERSIZE)
if (ctx->bytesinbuffer + bytes > FILEBUFFERSIZE)
fatal (CCX_COMMON_EXIT_BUG_BUG, "Invalid return_to_buffer() - please submit a bug report.");
memmove (filebuffer+bytes,filebuffer,bytesinbuffer);
memcpy (filebuffer,buffer,bytes);
bytesinbuffer+=bytes;
memmove (ctx->filebuffer + bytes, ctx->filebuffer, ctx->bytesinbuffer);
memcpy (ctx->filebuffer, buffer, bytes);
ctx->bytesinbuffer += bytes;
}
LLONG buffered_read_opt (struct lib_ccx_ctx *ctx, unsigned char *buffer, unsigned int bytes)
/**
* @param buffer can be NULL, in case when user want to just buffer it or skip some data.
*
* Global options that have efffect on this function are following
* 1) ccx_options.live_stream
* 2) ccx_options.buffer_input
* 3) ccx_options.input_source
* 4) ccx_options.binary_concat
*
* TODO instead of using global ccx_options move them to ccx_demuxer
*/
size_t buffered_read_opt (struct ccx_demuxer *ctx, unsigned char *buffer, size_t 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 = (ctx->infd==-1);
size_t origin_buffer_size = bytes;
size_t copied = 0;
time_t seconds = 0;
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
{
position_sanity_check(ctx->infd);
if (ccx_options.live_stream > 0)
time (&seconds);
if (ccx_options.buffer_input || ctx->filebuffer_pos < ctx->bytesinbuffer)
{
// Needs to return data from filebuffer_start+pos to filebuffer_start+pos+bytes-1;
int eof = (ctx->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 = ctx->bytesinbuffer - ctx->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 (ctx->infd,buffer,bytes);
if( i == -1)
fatal (EXIT_READ_ERROR, "Error reading input file!\n");
buffer+=i;
}
else // Seek
{
if (buffer != NULL) // Read
{
i = read (ctx->infd, buffer, bytes);
if( i == -1)
fatal (EXIT_READ_ERROR, "Error reading input file!\n");
buffer += i;
}
else // Seek
{
LLONG op, np;
op =LSEEK (ctx->infd,0,SEEK_CUR); // Get current pos
if (op+bytes<0) // Would mean moving beyond start of file: Not supported
return 0;
np =LSEEK (ctx->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;
}
op = LSEEK (ctx->infd, 0, SEEK_CUR); // Get current pos
if (op + bytes < 0) // Would mean moving beyond start of file: Not supported
return 0;
np = LSEEK (ctx->infd, bytes, SEEK_CUR); // Pos after moving
i = (int) (np - op);
}
// if both above lseek returned -1 (error); i would be 0 here and
// in case when its not live stream copied would decrease and bytes would...
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(ctx, 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);
}
while ((i || ccx_options.live_stream ||
(ccx_options.binary_concat && switch_to_next_file(ctx->parent, copied))) && bytes);
return copied;
}
// Keep the last 8 bytes, so we have a guaranteed
// working seek (-8) - needed by mythtv.
int keep = ctx->bytesinbuffer > 8 ? 8 : ctx->bytesinbuffer;
memmove (ctx->filebuffer, ctx->filebuffer+(FILEBUFFERSIZE-keep),keep);
int i;
if (ccx_options.input_source==CCX_DS_FILE || ccx_options.input_source==CCX_DS_STDIN)
i=read (ctx->infd, filebuffer+keep,FILEBUFFERSIZE-keep);
if (ccx_options.input_source == CCX_DS_FILE || ccx_options.input_source == CCX_DS_STDIN)
i = read (ctx->infd, ctx->filebuffer + keep, FILEBUFFERSIZE-keep);
else if (ccx_options.input_source == CCX_DS_TCP)
i = net_tcp_read(ctx->infd, (char *) ctx->filebuffer + keep, FILEBUFFERSIZE - keep);
else
i = recvfrom(ctx->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(ctx, 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
{
i = recvfrom(ctx->infd,(char *) ctx->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 || ((struct lib_ccx_ctx *)ctx->parent)->inputsize <= origin_buffer_size || !(ccx_options.binary_concat && switch_to_next_file(ctx->parent, copied)))
eof = 1;
}
ctx->filebuffer_pos = keep;
ctx->bytesinbuffer = (int) i + keep;
ready = i;
}
int copy = (int) (ready>=bytes ? bytes:ready);
if (copy)
{
if (buffer != NULL)
{
memcpy (buffer, ctx->filebuffer + ctx->filebuffer_pos, copy);
buffer += copy;
}
ctx->filebuffer_pos += copy;
bytes -= copy;
copied += copy;
}
}
}
else // Read without buffering
{
if (buffer!=NULL)
{
int i;
while (bytes>0 && ctx->infd!=-1 &&
((i=read(ctx->infd,buffer,bytes))!=0 || ccx_options.live_stream ||
(ccx_options.binary_concat && switch_to_next_file(ctx, 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 && ctx->infd!=-1)
{
if (buffer != NULL)
{
int i;
while (bytes > 0 && ctx->infd != -1 &&
((i = read(ctx->infd, buffer, bytes)) != 0 || ccx_options.live_stream ||
(ccx_options.binary_concat && switch_to_next_file(ctx->parent, 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;
}
while (bytes != 0 && ctx->infd != -1)
{
LLONG op, np;
op =LSEEK (ctx->infd,0,SEEK_CUR); // Get current pos
if (op+bytes<0) // Would mean moving beyond start of file: Not supported
return 0;
np =LSEEK (ctx->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(ctx, 0);
else
break;
}
}
}
return copied;
}
op = LSEEK (ctx->infd, 0, SEEK_CUR); // Get current pos
if (op + bytes < 0) // Would mean moving beyond start of file: Not supported
return 0;
np = LSEEK (ctx->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(ctx->parent, 0);
else
break;
}
}
}
}
return copied;
}
unsigned short buffered_get_be16(struct ccx_demuxer *ctx)
{
unsigned char a,b;
unsigned char *a_p = &a; // Just to suppress warnings
unsigned char *b_p = &b;
buffered_read_byte(ctx, a_p);
ctx->past++;
buffered_read_byte(ctx, b_p);
ctx->past++;
return ( (unsigned short) (a<<8) )| ( (unsigned short) b);
}
unsigned char buffered_get_byte (struct ccx_demuxer *ctx)
{
unsigned char b;
unsigned char *b_p = &b;
size_t result;
result = buffered_read_byte(ctx, b_p);
if (result == 1)
{
ctx->past++;
return b;
}
else
return 0;
}
unsigned int buffered_get_be32(struct ccx_demuxer *ctx)
{
unsigned int val;
val = buffered_get_be16(ctx) << 16;
val |= buffered_get_be16(ctx);
return val;
}
unsigned short buffered_get_le16(struct ccx_demuxer *ctx)
{
unsigned char a,b;
unsigned char *a_p = &a; // Just to suppress warnings
unsigned char *b_p = &b;
buffered_read_byte(ctx, a_p);
ctx->past++;
buffered_read_byte(ctx, b_p);
ctx->past++;
return ( (unsigned short) (b<<8) )| ( (unsigned short) a);
}
unsigned int buffered_get_le32(struct ccx_demuxer *ctx)
{
unsigned int val;
val = buffered_get_le16(ctx);
val |= buffered_get_le16(ctx) << 16;
return val;
}

File diff suppressed because it is too large Load Diff

291
src/lib_ccx/hardsubx.c Normal file
View File

@@ -0,0 +1,291 @@
#ifdef ENABLE_HARDSUBX
#include "hardsubx.h"
#include "capi.h"
#include "allheaders.h"
#include "ocr.h"
#include "utility.h"
//TODO: Correct FFMpeg integration
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libavutil/imgutils.h>
#include <libswscale/swscale.h>
int hardsubx_process_data(struct lib_hardsubx_ctx *ctx)
{
// Get the required media attributes and initialize structures
av_register_all();
if(avformat_open_input(&ctx->format_ctx, ctx->inputfile[0], NULL, NULL)!=0)
{
fatal (EXIT_READ_ERROR, "Error reading input file!\n");
}
if(avformat_find_stream_info(ctx->format_ctx, NULL)<0)
{
fatal (EXIT_READ_ERROR, "Error reading input stream!\n");
}
// Important call in order to determine media information using ffmpeg
// TODO: Handle multiple inputs
av_dump_format(ctx->format_ctx, 0, ctx->inputfile[0], 0);
ctx->video_stream_id = -1;
for(int i = 0; i < ctx->format_ctx->nb_streams; i++)
{
if(ctx->format_ctx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO)
{
ctx->video_stream_id = i;
break;
}
}
if(ctx->video_stream_id == -1)
{
fatal (EXIT_READ_ERROR, "Video Stream not found!\n");
}
ctx->codec_ctx = ctx->format_ctx->streams[ctx->video_stream_id]->codec;
ctx->codec = avcodec_find_decoder(ctx->codec_ctx->codec_id);
if(ctx->codec == NULL)
{
fatal (EXIT_READ_ERROR, "Input codec is not supported!\n");
}
if(avcodec_open2(ctx->codec_ctx, ctx->codec, &ctx->options_dict) < 0)
{
fatal (EXIT_READ_ERROR, "Error opening input codec!\n");
}
ctx->frame = av_frame_alloc();
ctx->rgb_frame = av_frame_alloc();
if(!ctx->frame || !ctx->rgb_frame)
{
fatal(EXIT_NOT_ENOUGH_MEMORY, "Not enough memory to initialize frame!");
}
int frame_bytes = av_image_get_buffer_size(AV_PIX_FMT_RGB24, ctx->codec_ctx->width, ctx->codec_ctx->height, 16);
ctx->rgb_buffer = (uint8_t *)av_malloc(frame_bytes*sizeof(uint8_t));
ctx->sws_ctx = sws_getContext(
ctx->codec_ctx->width,
ctx->codec_ctx->height,
ctx->codec_ctx->pix_fmt,
ctx->codec_ctx->width,
ctx->codec_ctx->height,
AV_PIX_FMT_RGB24,
SWS_BILINEAR,
NULL,NULL,NULL
);
av_image_fill_arrays(ctx->rgb_frame->data, ctx->rgb_frame->linesize, ctx->rgb_buffer, AV_PIX_FMT_RGB24, ctx->codec_ctx->width, ctx->codec_ctx->height, 1);
// int frame_bytes = av_image_get_buffer_size(AV_PIX_FMT_RGB24, 1280, 720, 16);
// ctx->rgb_buffer = (uint8_t *)av_malloc(frame_bytes*sizeof(uint8_t));
// ctx->sws_ctx = sws_getContext(
// ctx->codec_ctx->width,
// ctx->codec_ctx->height,
// ctx->codec_ctx->pix_fmt,
// 1280,
// 720,
// AV_PIX_FMT_RGB24,
// SWS_BILINEAR,
// NULL,NULL,NULL
// );
// avpicture_fill((AVPicture*)ctx->rgb_frame, ctx->rgb_buffer, AV_PIX_FMT_RGB24, 1280, 720);
// av_image_fill_arrays(ctx->rgb_frame->data, ctx->rgb_frame->linesize, ctx->rgb_buffer, AV_PIX_FMT_RGB24, 1280, 720, 1);
// Pass on the processing context to the appropriate functions
struct encoder_ctx *enc_ctx;
enc_ctx = init_encoder(&ccx_options.enc_cfg);
mprint("Beginning burned-in subtitle detection...\n");
hardsubx_process_frames_linear(ctx, enc_ctx);
dinit_encoder(&enc_ctx, 0); //TODO: Replace 0 with end timestamp
// Free the allocated memory for frame processing
av_free(ctx->rgb_buffer);
av_free(ctx->rgb_frame);
av_free(ctx->frame);
avcodec_close(ctx->codec_ctx);
avformat_close_input(&ctx->format_ctx);
}
void _hardsubx_params_dump(struct ccx_s_options *options, struct lib_hardsubx_ctx *ctx)
{
// Print the relevant passed parameters onto the screen
mprint("Input : %s\n", ctx->inputfile[0]);
switch(ctx->subcolor)
{
case HARDSUBX_COLOR_WHITE:
mprint("Subtitle Color : White\n");
break;
case HARDSUBX_COLOR_YELLOW:
mprint("Subtitle Color : Yellow\n");
break;
case HARDSUBX_COLOR_GREEN:
mprint("Subtitle Color : Green\n");
break;
case HARDSUBX_COLOR_CYAN:
mprint("Subtitle Color : Cyan\n");
break;
case HARDSUBX_COLOR_BLUE:
mprint("Subtitle Color : Blue\n");
break;
case HARDSUBX_COLOR_MAGENTA:
mprint("Subtitle Color : Magenta\n");
break;
case HARDSUBX_COLOR_RED:
mprint("Subtitle Color : Red\n");
break;
case HARDSUBX_COLOR_CUSTOM:
mprint("Subtitle Color : Custom Hue - %0.2f\n",ctx->hue);
break;
default:
fatal(EXIT_MALFORMED_PARAMETER,"Invalid Subtitle Color");
}
switch(ctx->ocr_mode)
{
case HARDSUBX_OCRMODE_WORD:
mprint("OCR Mode : Word-wise\n");
break;
case HARDSUBX_OCRMODE_LETTER:
mprint("OCR Mode : Letter-wise\n");
break;
case HARDSUBX_OCRMODE_FRAME:
mprint("OCR Mode : Frame-wise (simple)\n");
break;
default:
fatal(EXIT_MALFORMED_PARAMETER,"Invalid OCR Mode");
}
if(ctx->conf_thresh > 0)
{
mprint("OCR Confidence Threshold : %.2f\n",ctx->conf_thresh);
}
else
{
mprint("OCR Confidence Threshold : %.2f (Default)\n",ctx->conf_thresh);
}
if(ctx->subcolor == HARDSUBX_COLOR_WHITE)
{
if(ctx->lum_thresh != 95.0)
{
mprint("OCR Luminance Threshold : %.2f\n",ctx->lum_thresh);
}
else
{
mprint("OCR Luminance Threshold : %.2f (Default)\n",ctx->lum_thresh);
}
}
if(ctx->detect_italics == 1)
{
mprint("OCR Italic Detection : On\n");
}
else
{
mprint("OCR Italic Detection : Off\n");
}
if(ctx->min_sub_duration == 0.5)
{
mprint("Minimum subtitle duration : 0.5 seconds (Default)\n");
}
else
{
mprint("Minimum subtitle duration : %0.2f seconds (Default)\n",ctx->min_sub_duration);
}
mprint("FFMpeg Media Information:-\n");
}
struct lib_hardsubx_ctx* _init_hardsubx(struct ccx_s_options *options)
{
// Initialize HardsubX data structures
struct lib_hardsubx_ctx *ctx = (struct lib_hardsubx_ctx *)malloc(sizeof(struct lib_hardsubx_ctx));
if(!ctx)
fatal(EXIT_NOT_ENOUGH_MEMORY, "lib_hardsubx_ctx");
memset(ctx, 0, sizeof(struct lib_hardsubx_ctx));
ctx->tess_handle = TessBaseAPICreate();
if(TessBaseAPIInit3(ctx->tess_handle, NULL, "eng") != 0)
{
fatal(EXIT_NOT_ENOUGH_MEMORY, "Not enough memory to initialize Tesseract!");
}
//Initialize attributes common to lib_ccx context
ctx->basefilename = get_basename(options->output_filename);//TODO: Check validity, add stdin, network
ctx->current_file = -1;
ctx->inputfile = options->inputfile;
ctx->num_input_files = options->num_input_files;
ctx->extension = get_file_extension(options->write_format);
ctx->write_format = options->write_format;
ctx->subs_delay = options->subs_delay;
ctx->cc_to_stdout = options->cc_to_stdout;
//Initialize subtitle text parameters
ctx->ocr_mode = options->hardsubx_ocr_mode;
ctx->subcolor = options->hardsubx_subcolor;
ctx->min_sub_duration = options->hardsubx_min_sub_duration;
ctx->detect_italics = options->hardsubx_detect_italics;
ctx->conf_thresh = options->hardsubx_conf_thresh;
ctx->hue = options->hardsubx_hue;
ctx->lum_thresh = options->hardsubx_lum_thresh;
//Initialize subtitle structure memory
ctx->dec_sub = (struct cc_subtitle *)malloc(sizeof(struct cc_subtitle));
memset (ctx->dec_sub, 0,sizeof(struct cc_subtitle));
return ctx;
}
void _dinit_hardsubx(struct lib_hardsubx_ctx **ctx)
{
struct lib_hardsubx_ctx *lctx = *ctx;
// Free all memory allocated to everything in the context
// Free OCR
TessBaseAPIEnd(lctx->tess_handle);
TessBaseAPIDelete(lctx->tess_handle);
//Free subtitle
freep(lctx->dec_sub);
freep(ctx);
}
void hardsubx(struct ccx_s_options *options)
{
// This is similar to the 'main' function in ccextractor.c, but for hard subs
mprint("HardsubX (Hard Subtitle Extractor) - Burned-in subtitle extraction subsystem\n");
// Initialize HardsubX data structures
struct lib_hardsubx_ctx *ctx;
ctx = _init_hardsubx(options);
// Dump parameters (Not using params_dump since completely different parameters)
_hardsubx_params_dump(options, ctx);
// Configure output settings
// Data processing loop
time_t start, end;
time(&start);
hardsubx_process_data(ctx);
// Show statistics (time taken, frames processed, mode etc)
time(&end);
long processing_time=(long) (end-start);
mprint ("\rDone, processing time = %ld seconds\n", processing_time);
// Free all allocated memory for the data structures
_dinit_hardsubx(&ctx);
}
#endif

107
src/lib_ccx/hardsubx.h Normal file
View File

@@ -0,0 +1,107 @@
#ifndef HARDSUBX_H
#define HARDSUBX_H
#include "lib_ccx.h"
#include "utility.h"
#ifdef ENABLE_HARDSUBX
//TODO: Correct FFMpeg integration
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libswscale/swscale.h>
#include "allheaders.h"
#include "capi.h"
enum hardsubx_color_type
{
HARDSUBX_COLOR_WHITE = 0,
HARDSUBX_COLOR_YELLOW = 1,
HARDSUBX_COLOR_GREEN = 2,
HARDSUBX_COLOR_CYAN = 3,
HARDSUBX_COLOR_BLUE = 4,
HARDSUBX_COLOR_MAGENTA = 5,
HARDSUBX_COLOR_RED = 6,
HARDSUBX_COLOR_CUSTOM = 7,
};
enum hardsubx_ocr_mode
{
HARDSUBX_OCRMODE_FRAME = 0,
HARDSUBX_OCRMODE_WORD = 1,
HARDSUBX_OCRMODE_LETTER = 2,
};
struct lib_hardsubx_ctx
{
// The main context for hard subtitle extraction
// Attributes common to the lib_ccx context
int cc_to_stdout;
LLONG subs_delay;
LLONG last_displayed_subs_ms;
char *basefilename;
const char *extension;
int current_file;
char **inputfile;
int num_input_files;
LLONG system_start_time;
enum ccx_output_format write_format;
// Media file context
AVFormatContext *format_ctx;
AVCodecContext *codec_ctx;
AVCodec *codec;
AVFrame *frame;
AVFrame *rgb_frame;
AVPacket packet;
AVDictionary *options_dict;
struct SwsContext *sws_ctx;
uint8_t *rgb_buffer;
int video_stream_id;
// Leptonica Image and Tesseract Context
PIX *im;
TessBaseAPI *tess_handle;
// Classifier parameters
// Subtitle text parameters
struct cc_subtitle *dec_sub;
int ocr_mode;
int subcolor;
float min_sub_duration;
int detect_italics;
float conf_thresh;
float hue;
float lum_thresh;
};
struct lib_hardsubx_ctx* _init_hardsubx(struct ccx_s_options *options);
void _hardsubx_params_dump(struct ccx_s_options *options, struct lib_hardsubx_ctx *ctx);
void hardsubx(struct ccx_s_options *options);
//hardsubx_decoder.c
int hardsubx_process_frames_linear(struct lib_hardsubx_ctx *ctx, struct encoder_ctx *enc_ctx);
int hardsubx_process_frames_binary(struct lib_hardsubx_ctx *ctx);
//hardsubx_imgops.c
void rgb2hsv(float R, float G, float B,float *H, float *S, float *V);
void rgb2lab(float R, float G, float B,float *L, float *a, float *b);
//hardsubx_classifier.c
char *get_ocr_text_simple(struct lib_hardsubx_ctx *ctx, PIX *image);
char *get_ocr_text_wordwise(struct lib_hardsubx_ctx *ctx, PIX *image);
char *get_ocr_text_letterwise(struct lib_hardsubx_ctx *ctx, PIX *image);
char *get_ocr_text_simple_threshold(struct lib_hardsubx_ctx *ctx, PIX *image, float threshold);
char *get_ocr_text_wordwise_threshold(struct lib_hardsubx_ctx *ctx, PIX *image, float threshold);
char *get_ocr_text_letterwise_threshold(struct lib_hardsubx_ctx *ctx, PIX *image, float threshold);
//hardsubx_utility.c
int edit_distance(char * word1, char * word2, int len1, int len2);
int64_t convert_pts_to_ms(int64_t pts, AVRational time_base);
int64_t convert_pts_to_ns(int64_t pts, AVRational time_base);
int64_t convert_pts_to_s(int64_t pts, AVRational time_base);
#endif
#endif

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