Compare commits

...

36 Commits
v0.75 ... v0.76

Author SHA1 Message Date
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
24 changed files with 3293 additions and 125 deletions

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:
Extracting subtitles has never been so easy. Just type the following command:
ccextrator "name of input"
Gui lovers please download Sorceforge version of CCExtractor, Git Version is not your cup of tea.
Gui lovers should download the Sorceforge version of CCExtractor, the Git Version is not your cup of tea.
http://ccextractor.sourceforge.net/download-ccextractor.html
For News about release, please find CHANGES.TXT

View File

@@ -1,5 +1,11 @@
0.75
-----------
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 +13,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 +23,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 +45,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 +86,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 +106,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 +121,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 +142,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 +221,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 +240,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 +261,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 +270,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 +293,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 +304,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 +315,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 +344,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 +369,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 +395,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 +409,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 +436,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 +462,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 +486,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 +500,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 +521,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 +533,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 +542,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 +563,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 +604,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 +635,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 +645,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 +697,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 +717,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 +737,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 +746,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 +768,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 +791,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 +806,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 +818,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 +836,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 +848,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 +857,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 +871,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).

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

@@ -1 +1 @@
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')
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' \! -name 'win_*') $(find ../src/ -name '*.c' \! -name 'win_*') -liconv

View File

@@ -182,7 +182,8 @@ int main(int argc, char *argv[])
strcpy (ctx->basefilename, ctx->basefilename_for_network);
break;
}
for (c=ctx->basefilename+strlen (ctx->basefilename)-1; ctx->basefilename &&
for (c = ctx->basefilename + strlen(ctx->basefilename) - 1; c>ctx->basefilename &&
*c!='.'; c--) {;} // Get last .
if (*c=='.')
*c=0;
@@ -268,6 +269,7 @@ int main(int argc, char *argv[])
switch (ccx_options.write_format)
{
case CCX_OF_RAW:
init_encoder(enc_ctx, &ctx->wbout1);
writeraw(BROADCAST_HEADER, sizeof(BROADCAST_HEADER), &ctx->wbout1);
break;
case CCX_OF_DVDRAW:

View File

@@ -259,8 +259,8 @@ spupng_write_ccbuffer(struct spupng_t *sp, struct eia608_screen* data,
break;
}
}
strncat(str,(const char*)subline,256);
strncat(str,"\n",256);
strncat(str,(const char*)subline,256);
strncat(str,"\n",256);
}
}

View File

@@ -59,6 +59,10 @@ void init_options (struct ccx_s_options *options)
/* 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->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->teletext_mode=CCX_TXT_AUTO_NOT_YET_FOUND; // 0=Disabled, 1 = Not found, 2=Found
options->transcript_settings = ccx_encoders_default_transcript_settings;
@@ -91,6 +95,7 @@ void init_options (struct ccx_s_options *options)
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->m2ts = 0;
// Prepare time structures
init_boundary_time (&options->extraction_start);

View File

@@ -53,6 +53,10 @@ struct ccx_s_options // Options from user parameters
/* 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?
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
unsigned teletext_mode; // 0=Disabled, 1 = Not found, 2=Found
ccx_encoders_transcript_format transcript_settings; // Keeps the settings for generating transcript output files.
char millis_separator;
@@ -86,6 +90,7 @@ struct ccx_s_options // Options from user parameters
char **inputfile; // List of files to process
int num_input_files; // How many?
enum ccx_stream_mode_enum auto_stream;
int m2ts; // Regular TS or M2TS
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

View File

@@ -99,6 +99,7 @@ struct lib_cc_decode
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;
void *wbout2;
LLONG subs_delay; // ms to delay (or advance) subs
};

View File

@@ -427,7 +427,8 @@ static int sequence_header(struct lib_ccx_ctx *ctx, struct bitstream *esstream)
// whole sequence info.
if (vert_size >= 288 && vert_size <= 1088 &&
hor_size >= 352 && hor_size <= 1920 &&
hor_size / vert_size >= 352/576 && hor_size / vert_size <= 2 &&
(hor_size*100) / vert_size >= (352*100)/576 && // The weird *100 is to avoid using floats
hor_size / vert_size <= 2 &&
frame_rate>0 && frame_rate<9 &&
aspect_ratio>0 && aspect_ratio<5)
{

View File

@@ -85,6 +85,16 @@ void prepare_for_new_file (struct lib_ccx_ctx *ctx)
init_file_buffer();
anchor_hdcc(-1);
firstcall = 1;
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 */
@@ -246,7 +256,7 @@ void buffered_seek (struct lib_ccx_ctx *ctx, int offset)
if (filebuffer_pos<0)
{
// We got into the start buffer (hopefully)
if (ctx->startbytes_pos+filebuffer_pos < 0)
if ((filebuffer_pos+ctx->startbytes_pos) < 0)
{
fatal (CCX_COMMON_EXIT_BUG_BUG, "PANIC: Attempt to seek before buffer start, this is a bug!");
}

View File

@@ -538,6 +538,8 @@ void general_loop(struct lib_ccx_ctx *ctx, void *enc_ctx)
struct cc_subtitle dec_sub;
struct lib_cc_decode *dec_ctx = NULL;
dec_ctx = ctx->dec_ctx;
dec_ctx->wbout1 = (struct ccx_s_write*)&ctx->wbout1 ;
dec_ctx->wbout2 = (struct ccx_s_write*)&ctx->wbout2 ;
inbuf = 0; // No data yet
end_of_file = 0;

View File

@@ -50,6 +50,7 @@ struct lib_ccx_ctx* init_libraries(struct ccx_s_options *opt)
ctx->stream_mode = CCX_SM_ELEMENTARY_OR_NOT_FOUND;
ctx->auto_stream = opt->auto_stream;
ctx->m2ts = opt->m2ts;
ctx->screens_to_process = -1;
ctx->current_file = -1;
ctx->infd = -1;//Set to -1 to indicate no file is open.
@@ -116,6 +117,8 @@ void dinit_libraries( struct lib_ccx_ctx **ctx)
if( lctx->PIDs_programs[i])
freep(lctx->PIDs_programs + i);
}
// free EPG memory
EPG_free(lctx);
dinit_ts(lctx);
dinit_cc_decode(&lctx->dec_ctx);
freep(&lctx->buffer);

View File

@@ -1,7 +1,7 @@
#ifndef CCX_CCEXTRACTOR_H
#define CCX_CCEXTRACTOR_H
#define VERSION "0.75"
#define VERSION "0.76"
// Load common includes and constants for library usage
#include "ccx_common_platform.h"
@@ -56,6 +56,49 @@ struct PMT_entry
unsigned printable_stream_type;
};
struct EIT_buffer
{
uint32_t prev_ccounter;
uint8_t *buffer;
uint32_t buffer_length;
uint32_t ccounter;
};
struct EPG_rating
{
char country_code[4];
uint8_t age;
};
struct EPG_event
{
uint32_t id;
char start_time_string[21]; //"YYYYMMDDHHMMSS +0000" = 20 chars
char end_time_string[21];
uint8_t running_status;
uint8_t free_ca_mode;
char ISO_639_language_code[4];
char *event_name;
char *text;
char extended_ISO_639_language_code[4];
char *extended_text;
uint8_t has_simple;
struct EPG_rating *ratings;
uint32_t num_ratings;
uint8_t *categories;
uint32_t num_categories;
uint16_t service_id;
long long int count; //incremented by one each time the event is updated
uint8_t live_output; //boolean flag, true if this event has been output
};
#define EPG_MAX_EVENTS 60*24*7
struct EIT_program
{
uint32_t array_len;
struct EPG_event epg_events[EPG_MAX_EVENTS];
};
/* Report information */
#define SUB_STREAMS_CNT 10
struct file_report
@@ -135,6 +178,7 @@ struct lib_ccx_ctx
struct lib_cc_decode *dec_ctx;
enum ccx_stream_mode_enum stream_mode;
enum ccx_stream_mode_enum auto_stream;
int m2ts;
int rawmode; // Broadcast or DVD
@@ -172,6 +216,14 @@ struct lib_ccx_ctx
char *basefilename_for_network;
int PIDs_seen[MAX_PID];
struct PMT_entry *PIDs_programs[MAX_PID];
//struct EIT_buffer eit_buffer;
struct EIT_buffer epg_buffers[0xfff+1];
struct EIT_program eit_programs[TS_PMT_MAP_SIZE+1];
int32_t eit_current_events[TS_PMT_MAP_SIZE+1];
int16_t ATSC_source_pg_map[0xffff];
int epg_last_output;
int epg_last_live_output;
struct file_report freport;
long capbufsize;
@@ -311,6 +363,8 @@ LLONG ts_getmoredata(struct lib_ccx_ctx *ctx);
int write_section(struct lib_ccx_ctx *ctx, struct ts_payload *payload, unsigned char*buf, int size, int pos);
int parse_PMT (struct lib_ccx_ctx *ctx, unsigned char *buf, int len, int pos);
int parse_PAT (struct lib_ccx_ctx *ctx);
void parse_EPG_packet (struct lib_ccx_ctx *ctx);
void EPG_free();
// myth.c
void myth_loop(struct lib_ccx_ctx *ctx, void *enc_ctx);

View File

@@ -905,7 +905,7 @@ int start_upd_srv(const char *addr_str, unsigned port)
if (bind(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) != 0)
{
#if _WIN32
wprintf(L"bind() eror: %ld\n", WSAGetLastError());
wprintf(L"bind() error: %ld\n", WSAGetLastError());
exit(EXIT_FAILURE);
#else
fatal(CCX_COMMON_EXIT_BUG_BUG, "bind() error: %s\n", strerror(errno));

View File

@@ -110,6 +110,8 @@ void printdata (struct lib_cc_decode *ctx, const unsigned char *data1, int lengt
struct ccx_decoder_608_context *field_1 = ctx->context_cc608_field_1;
struct ccx_decoder_608_context *field_2 = ctx->context_cc608_field_2;
struct ccx_s_write *wbout1 = ctx->wbout1;
field_1->out = ctx->wbout1 ;
field_2->out = ctx->wbout2 ;
if (ctx->write_format==CCX_OF_DVDRAW)
writeDVDraw (data1, length1, data2, length2, wbout1);
else /* Broadcast raw or any non-raw */

View File

@@ -129,7 +129,7 @@ int parsedelay (struct ccx_s_options *opt, char *par)
c++;
}
if (sign)
opt->subs_delay =- opt->subs_delay;
opt->subs_delay = -opt->subs_delay;
return 0;
}
@@ -272,8 +272,16 @@ void set_input_format (struct ccx_s_options *opt, const char *format)
format++;
if (strcmp (format,"es")==0) // Does this actually do anything?
opt->auto_stream = CCX_SM_ELEMENTARY_OR_NOT_FOUND;
else if (strcmp (format,"ts")==0)
else if (strcmp(format, "ts") == 0)
{
opt->auto_stream = CCX_SM_TRANSPORT;
opt->m2ts = 0;
}
else if (strcmp(format, "m2ts") == 0)
{
opt->auto_stream = CCX_SM_TRANSPORT;
opt->m2ts = 1;
}
else if (strcmp (format,"ps")==0 || strcmp (format,"nots")==0)
opt->auto_stream = CCX_SM_PROGRAM;
else if (strcmp (format,"asf")==0 || strcmp (format,"dvr-ms")==0)
@@ -525,6 +533,8 @@ void usage (void)
mprint (" -autodash: Based on position on screen, attempt to determine\n");
mprint (" the different speakers and a dash (-) when each\n");
mprint (" of them talks (.srt only, -trim required).");
mprint (" -xmltv: produce an XMLTV file containing the EPG data from\n");
mprint (" the source TS file.");
mprint ("Options that affect how ccextractor reads and writes (buffering):\n");
@@ -1465,6 +1475,51 @@ void parse_parameters (struct ccx_s_options *opt, int argc, char *argv[])
ccx_options.autodash = 1;
continue;
}
if (strcmp (argv[i],"-xmltv")==0)
{
if (i==argc-1 // Means no following argument
|| !isanumber (argv[i+1])) // Means is not a number
ccx_options.xmltv = 1;
else
{
ccx_options.xmltv=atoi_hex (argv[i+1]);
i++;
}
continue;
}
if (strcmp (argv[i],"-xmltvliveinterval")==0)
{
if (i==argc-1 // Means no following argument
|| !isanumber (argv[i+1])) // Means is not a number
ccx_options.xmltvliveinterval = 10;
else
{
ccx_options.xmltvliveinterval=atoi_hex (argv[i+1]);
i++;
}
continue;
}
if (strcmp (argv[i],"-xmltvoutputinterval")==0)
{
if (i==argc-1 // Means no following argument
|| !isanumber (argv[i+1])) // Means is not a number
ccx_options.xmltvoutputinterval = 0;
else
{
ccx_options.xmltvoutputinterval=atoi_hex (argv[i+1]);
i++;
}
continue;
}
if (strcmp (argv[i],"-xmltvonlycurrent")==0)
{
ccx_options.xmltvonlycurrent=1;
i++;
continue;
}
if (strcmp (argv[i],"-unixts")==0 && i<argc-1)
{
uint64_t t = 0;

View File

@@ -73,9 +73,26 @@ void detect_stream_type (struct lib_ccx_ctx *ctx)
// Eight sync bytes, that's good enough
ctx->startbytes_pos=i;
ctx->stream_mode=CCX_SM_TRANSPORT;
ctx->m2ts = 0;
break;
}
}
// Check for M2TS
for (unsigned i = 0; i<192; i++)
{
if (ctx->startbytes[i+4] == 0x47 && ctx->startbytes[i + 4 + 192] == 0x47 &&
ctx->startbytes[i + 192 * 2+4] == 0x47 && ctx->startbytes[i + 192 * 3+4] == 0x47 &&
ctx->startbytes[i + 192 * 4+4] == 0x47 && ctx->startbytes[i + 192 * 5+4] == 0x47 &&
ctx->startbytes[i + 192 * 6+4] == 0x47 && ctx->startbytes[i + 192 * 7+4] == 0x47
)
{
// Eight sync bytes, that's good enough
ctx->startbytes_pos = i;
ctx->stream_mode = CCX_SM_TRANSPORT;
ctx->m2ts = 1;
break;
}
}
// Now check for PS (Needs PACK header)
for (unsigned i=0;
i < (unsigned) (ctx->startbytes_avail<50000?ctx->startbytes_avail-3:49997);

View File

@@ -503,7 +503,7 @@ void process_page(struct lib_ccx_ctx *ctx, teletext_page_t *page) {
page_buffer_add_string("<br/>");
break;
default:
page_buffer_add_string(encoded_crlf);
page_buffer_add_string((const char *) encoded_crlf);
}
}
@@ -656,8 +656,8 @@ void process_page(struct lib_ccx_ctx *ctx, teletext_page_t *page) {
}
break;
default: // Yes, this means everything else is .srt for now
page_buffer_add_string (encoded_crlf);
page_buffer_add_string (encoded_crlf);
page_buffer_add_string ((const char *) encoded_crlf);
page_buffer_add_string((const char *) encoded_crlf);
if (ctx->wbout1.fh!=-1) {
fdprintf(ctx->wbout1.fh,"%"PRIu32"%s%s --> %s%s", tlt_frames_produced, encoded_crlf, timecode_show, timecode_hide, encoded_crlf);
fdprintf(ctx->wbout1.fh, "%s",page_buffer_cur);

View File

@@ -57,6 +57,25 @@ void init_ts(struct lib_ccx_ctx *ctx)
// Return 1 for sucessfully read ts packet
int ts_readpacket(struct lib_ccx_ctx* ctx)
{
if (ctx->m2ts)
{
/* M2TS just adds 4 bytes to each packet (so size goes from 188 to 192)
The 4 bytes are not important to us, so just skip
// TP_extra_header {
Copy_permission_indicator 2 unimsbf
Arrival_time_stamp 30 unimsbf
} */
char tp_extra_header[4];
buffered_read(ctx, tp_extra_header, 4);
ctx->past += result;
if (result != 4)
{
if (result>0)
mprint("Premature end of file!\n");
end_of_file = 1;
return 0;
}
}
buffered_read(ctx, tspacket, 188);
ctx->past+=result;
if (result!=188)
@@ -261,6 +280,11 @@ long ts_readstream(struct lib_ccx_ctx *ctx)
ctx->capbuflen = 0;
continue;
}
if( ccx_options.xmltv>=1 && payload.pid == 0x12) // This is DVB EIT
parse_EPG_packet(ctx);
if( ccx_options.xmltv>=1 && payload.pid >= 0x1000) // This may be ATSC EPG packet
parse_EPG_packet(ctx);
// PID != 0 but no PMT selected yet, ignore the rest of the current
// package and continue searching, UNLESS we are in -autoprogram, which requires us

View File

@@ -600,7 +600,18 @@ int parse_PAT (struct lib_ccx_ctx *ctx)
if (!ccx_options.ts_forced_program_selected)
{
if (!ccx_options.ts_autoprogram)
fatal(CCX_COMMON_EXIT_BUG_BUG, "Run ccextractor again with --program-number specifying which program\nto process.");
{
if (ccx_options.xmltv >= 1)
{
mprint("Processing EPG only. If you want to extract subtitles use --program-number to select a program.");
ccx_options.ts_forced_program_selected = 1;
warning_program_not_found_shown = 1;
ccx_options.write_format = CCX_OF_NULL;
}
else
fatal(CCX_COMMON_EXIT_BUG_BUG, "Run ccextractor again with --program-number specifying which program\nto process.");
}
else
mprint ("\nThe first program with a suitable CC stream will be selected.\n");
}

896
src/lib_ccx/ts_tables_epg.c Normal file
View File

@@ -0,0 +1,896 @@
#include "lib_ccx.h"
#include "ccx_common_option.h"
#include "dvb_subtitle_decoder.h"
#include "utility.h"
#include <stdbool.h>
#ifdef WIN32
#include "..\\win_iconv\\win_iconv.h"
#else
#include "iconv.h"
#endif
//Prints a string to a file pointer, escaping XML special chars
//Works with UTF-8
void EPG_fprintxml(FILE *f, char *string) {
char *p = string;
char *start = p;
while(*p!='\0') {
switch(*p) {
case '<':
fwrite(start, 1, p-start, f);
fprintf(f, "&lt;");
start = p+1;
break;
case '>':
fwrite(start, 1, p-start, f);
fprintf(f, "&gt;");
start = p+1;
break;
case '"':
fwrite(start, 1, p-start, f);
fprintf(f, "&quot;");
start = p+1;
break;
case '&':
fwrite(start, 1, p-start, f);
fprintf(f, "&amp;");
start = p+1;
break;
case '\'':
fwrite(start, 1, p-start, f);
fprintf(f, "&apos;");
start = p+1;
break;
}
p++;
}
fwrite(start, 1, p-start, f);
}
// Fills given string with given (event.*_time_string) ATSC time converted to XMLTV style time string
void EPG_ATSC_calc_time(char *output, uint32_t time) {
struct tm timeinfo;
timeinfo.tm_year = 1980-1900;
timeinfo.tm_mon = 0;
timeinfo.tm_mday = 6;
timeinfo.tm_sec = 0+time;
timeinfo.tm_min = 0;
timeinfo.tm_hour = 0;
timeinfo.tm_isdst = -1;
mktime(&timeinfo);
sprintf(output, "%02d%02d%02d%02d%02d%02d +0000", timeinfo.tm_year+1900, timeinfo.tm_mon+1, timeinfo.tm_mday, timeinfo.tm_hour, timeinfo.tm_min, timeinfo.tm_sec);
}
// Fills event.start_time_string in XMLTV format with passed DVB time
void EPG_DVB_calc_start_time(struct EPG_event *event, uint64_t time) {
uint64_t mjd = time>>24;
event->start_time_string[0]='\0';
if (mjd > 0) {
long y,m,d ,k;
// algo: ETSI EN 300 468 - ANNEX C
y = (long) ((mjd - 15078.2) / 365.25);
m = (long) ((mjd - 14956.1 - (long)(y * 365.25) ) / 30.6001);
d = (long) (mjd - 14956 - (long)(y * 365.25) - (long)(m * 30.6001));
k = (m == 14 || m == 15) ? 1 : 0;
y = y + k + 1900;
m = m - 1 - k*12;
sprintf(event->start_time_string, "%02d%02d%02d%06x +0000",y,m,d,time&0xffffff);
}
}
// Fills event.end_time_string in XMLTV with passed DVB time + duration
void EPG_DVB_calc_end_time(struct EPG_event *event, uint64_t time, uint32_t duration) {
uint64_t mjd = time>>24;
event->end_time_string[0]='\0';
if (mjd > 0) {
long y,m,d ,k;
struct tm timeinfo;
// algo: ETSI EN 300 468 - ANNEX C
y = (long) ((mjd - 15078.2) / 365.25);
m = (long) ((mjd - 14956.1 - (long)(y * 365.25) ) / 30.6001);
d = (long) (mjd - 14956 - (long)(y * 365.25) - (long)(m * 30.6001));
k = (m == 14 || m == 15) ? 1 : 0;
y = y + k + 1900;
m = m - 1 - k*12;
timeinfo.tm_year = y-1900;
timeinfo.tm_mon = m-1;
timeinfo.tm_mday = d;
timeinfo.tm_sec = (time&0x0f) + (10*((time&0xf0)>>4)) + (duration&0x0f) + (10*((duration&0xf0)>>4));
timeinfo.tm_min = ((time&0x0f00)>>8) + (10*((time&0xf000)>>4)>>8) + ((duration&0x0f00)>>8) + (10*((duration&0xf000)>>4)>>8);
timeinfo.tm_hour = ((time&0x0f0000)>>16) + (10*((time&0xf00000)>>4)>>16) + ((duration&0x0f0000)>>16) + (10*((duration&0xf00000)>>4)>>16);
timeinfo.tm_isdst = -1;
mktime(&timeinfo);
sprintf(event->end_time_string, "%02d%02d%02d%02d%02d%02d +0000", timeinfo.tm_year+1900, timeinfo.tm_mon+1, timeinfo.tm_mday, timeinfo.tm_hour, timeinfo.tm_min, timeinfo.tm_sec);
}
}
// returns english string description of the passed DVB category ID
char *EPG_DVB_content_type_to_string(uint8_t cat) {
struct table {
uint8_t cat;
char *name;
};
struct table t[] = {
{0x00, "reserved"}, { 0x10, "movie/drama (general)" }, { 0x11, "detective/thriller" }, { 0x12, "adventure/western/war" }, { 0x13, "science fiction/fantasy/horror" },{ 0x14, "comedy" },
{ 0x15, "soap/melodram/folkloric" }, { 0x16, "romance" }, { 0x17, "serious/classical/religious/historical movie/drama" }, { 0x18, "adult movie/drama" }, { 0x1E, "reserved" },
{ 0x1F, "user defined" }, { 0x20, "news/current affairs (general)" }, { 0x21, "news/weather report" }, { 0x22, "news magazine" }, { 0x23, "documentary" }, { 0x24, "discussion/interview/debate" },
{ 0x2E, "reserved" }, { 0x2F, "user defined" }, { 0x30, "show/game show (general)" }, { 0x31, "game show/quiz/contest" }, { 0x32, "variety show" }, { 0x33, "talk show" }, { 0x3E, "reserved" },
{ 0x3F, "user defined" }, { 0x40, "sports (general)" }, { 0x41, "special events" }, { 0x42, "sports magazine" }, { 0x43, "football/soccer" }, { 0x44, "tennis/squash" }, { 0x45, "team sports" },
{ 0x46, "athletics" }, { 0x47, "motor sport" }, { 0x48, "water sport" }, { 0x49, "winter sport" }, { 0x4A, "equestrian" }, { 0x4B, "martial sports" }, { 0x4E, "reserved" }, { 0x4F, "user defined" },
{ 0x50, "childrens's/youth program (general)" }, { 0x51, "pre-school children's program" }, { 0x52, "entertainment (6-14 year old)" }, { 0x53, "entertainment (10-16 year old)" },
{ 0x54, "information/education/school program" }, { 0x55, "cartoon/puppets" }, { 0x5E, "reserved" }, { 0x5F, "user defined" }, { 0x60, "music/ballet/dance (general)" }, { 0x61, "rock/pop" },
{ 0x62, "serious music/classic music" }, { 0x63, "folk/traditional music" }, { 0x64, "jazz" }, { 0x65, "musical/opera" }, { 0x66, "ballet" }, { 0x6E, "reserved" }, { 0x6F, "user defined" },
{ 0x70, "arts/culture (without music, general)" },{ 0x71, "performing arts" }, { 0x72, "fine arts" }, { 0x73, "religion" }, { 0x74, "popular culture/traditional arts" }, { 0x75, "literature" },
{ 0x76, "film/cinema" }, { 0x77, "experimental film/video" }, { 0x78, "broadcasting/press" }, { 0x79, "new media" }, { 0x7A, "arts/culture magazine" }, { 0x7B, "fashion" }, { 0x7E, "reserved" },
{ 0x7F, "user defined" }, { 0x80, "social/political issues/economics (general)" }, { 0x81, "magazines/reports/documentary" }, { 0x82, "economics/social advisory" }, { 0x83, "remarkable people" },
{ 0x8E, "reserved" }, { 0x8F, "user defined" }, { 0x90, "education/science/factual topics (general)" }, { 0x91, "nature/animals/environment" }, { 0x92, "technology/natural science" },
{ 0x93, "medicine/physiology/psychology" }, { 0x94, "foreign countries/expeditions" }, { 0x95, "social/spiritual science" }, { 0x96, "further education" }, { 0x97, "languages" },
{ 0x9E, "reserved" }, { 0x9F, "user defined" }, { 0xA0, "leisure hobbies (general)" }, { 0xA1, "tourism/travel" }, { 0xA2, "handicraft" }, { 0xA3, "motoring" }, { 0xA4, "fitness & health" },
{ 0xA5, "cooking" }, { 0xA6, "advertisement/shopping" }, { 0xA7, "gardening" }, { 0xAE, "reserved" }, { 0xAF, "user defined" }, { 0xB0, "original language" }, { 0xB1, "black & white" },
{ 0xB2, "unpublished" }, { 0xB3, "live broadcast" }, { 0xBE, "reserved" }, { 0xBF, "user defined" }, { 0xEF, "reserved" }, { 0xFF, "user defined" }, {0x00, NULL},
};
struct table *p = t;
while(p->name!=NULL) {
if(cat==p->cat)
return p->name;
p++;
}
return "undefined content";
}
// Prints given event to already opened XMLTV file.
void EPG_print_event(struct EPG_event *event, uint32_t channel, FILE *f) {
int i;
fprintf(f, " <program ");
fprintf(f, "start=\"");
fprintf(f, "%s", event->start_time_string);
fprintf(f, "\" ");
fprintf(f, "stop=\"");
fprintf(f, "%s", event->end_time_string);
fprintf(f, "\" ");
fprintf(f, "channel=\"%i\">\n", channel);
if(event->has_simple) {
fprintf(f, " <title lang=\"%s\">", event->ISO_639_language_code);
EPG_fprintxml(f, event->event_name);
fprintf(f, "</title>\n");
fprintf(f, " <sub-title lang=\"%s\">", event->ISO_639_language_code);
EPG_fprintxml(f, event->text);
fprintf(f, "</sub-title>\n");
}
if(event->extended_text!=NULL) {
fprintf(f, " <desc lang=\"%s\">", event->extended_ISO_639_language_code);
EPG_fprintxml(f, event->extended_text);
fprintf(f, "</desc>\n");
}
for(i=0; i<event->num_ratings; i++)
if(event->ratings[i].age>0 && event->ratings[i].age<0x10)
fprintf(f, " <rating system=\"dvb:%s\">%i</rating>\n", event->ratings[i].country_code, event->ratings[i].age+3);
for(i=0; i<event->num_categories; i++) {
fprintf(f, " <category lang=\"en\">");
EPG_fprintxml(f, EPG_DVB_content_type_to_string(event->categories[i]));
fprintf(f, "</category>\n");
}
fprintf(f, " <ts-meta-id>%i</ts-meta-id>\n", event->id);
fprintf(f, " </program>\n");
}
// Creates fills and closes a new XMLTV file for live mode output.
// File should include only events not previously output.
void EPG_output_live(struct lib_ccx_ctx *ctx) {
int c=false, i, j;
FILE *f;
char *filename, *finalfilename;
for(i=0; i<pmt_array_length; i++) {
for(j=0; j<ctx->eit_programs[i].array_len; j++)
if(ctx->eit_programs[i].epg_events[j].live_output==false) {
c=true;
}
}
if(!c)
return;
filename = malloc(strlen(ctx->basefilename)+30);
sprintf(filename, "%s_%i.xml.part", ctx->basefilename, ctx->epg_last_live_output);
f = fopen(filename, "w");
fprintf(f, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE tv SYSTEM \"xmltv.dtd\">\n\n<tv>\n");
for(i=0; i<pmt_array_length; i++) {
fprintf(f, " <channel id=\"%i\">\n", pmt_array[i].program_number);
fprintf(f, " <display-name>%i</display-name>\n", pmt_array[i].program_number);
fprintf(f, " </channel>\n");
}
for(i=0; i<pmt_array_length; i++) {
for(j=0; j<ctx->eit_programs[i].array_len; j++)
if(ctx->eit_programs[i].epg_events[j].live_output==false) {
ctx->eit_programs[i].epg_events[j].live_output=true;
EPG_print_event(&ctx->eit_programs[i].epg_events[j], pmt_array[i].program_number, f);
}
}
fprintf(f, "</tv>");
fclose(f);
finalfilename = malloc(strlen(ctx->wbout1.filename)+30);
memcpy(finalfilename, filename, strlen(filename)-5);
finalfilename[strlen(filename)-5]='\0';
rename(filename, finalfilename);
free(filename);
free(finalfilename);
}
// Creates fills and closes a new XMLTV file for full output mode.
// File should include all events in memory.
void EPG_output(struct lib_ccx_ctx *ctx) {
FILE *f;
char *filename;
int i,j, ce;
filename = malloc(strlen(ctx->basefilename) + 9);
memcpy(filename, ctx->basefilename, strlen(ctx->basefilename)+1);
strcat(filename, "_epg.xml");
f = fopen(filename, "w");
free(filename);
fprintf(f, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE tv SYSTEM \"xmltv.dtd\">\n\n<tv>\n");
for(i=0; i<pmt_array_length; i++) {
fprintf(f, " <channel id=\"%i\">\n", pmt_array[i].program_number);
fprintf(f, " <display-name>%i</display-name>\n", pmt_array[i].program_number);
fprintf(f, " </channel>\n");
}
if(ccx_options.xmltvonlycurrent==0) { // print all events
for(i=0; i<pmt_array_length; i++) {
for(j=0; j<ctx->eit_programs[i].array_len; j++)
EPG_print_event(&ctx->eit_programs[i].epg_events[j], pmt_array[i].program_number, f);
}
if(pmt_array_length==0) //Stream has no PMT, fall back to unordered events
for(j=0; j<ctx->eit_programs[TS_PMT_MAP_SIZE].array_len; j++)
EPG_print_event(&ctx->eit_programs[TS_PMT_MAP_SIZE].epg_events[j], ctx->eit_programs[TS_PMT_MAP_SIZE].epg_events[j].service_id, f);
}
else { // print current events only
for(i=0; i<pmt_array_length; i++) {
ce = ctx->eit_current_events[i];
for(j=0; j<ctx->eit_programs[i].array_len; j++) {
if(ce==ctx->eit_programs[i].epg_events[j].id)
EPG_print_event(&ctx->eit_programs[i].epg_events[j], pmt_array[i].program_number, f);
}
}
}
fprintf(f, "</tv>");
fclose(f);
}
// Free all memory allocated for given event
void EPG_free_event(struct EPG_event *event) {
if(event->has_simple) {
free(event->event_name);
free(event->text);
}
if(event->extended_text!=NULL)
free(event->extended_text);
if(event->num_ratings>0)
free(event->ratings);
if(event->num_categories>0)
free(event->categories);
}
//compare 2 events. Return false if they are different.
int EPG_event_cmp(struct EPG_event *e1, struct EPG_event *e2) {
if(e1->id != e2->id || (strcmp(e1->start_time_string, e2->start_time_string)!=0) || (strcmp(e1->end_time_string, e2->end_time_string)!=0))
return false;
// could add full checking of strings here if desired.
return true;
}
// Add given event to array of events.
// Return FALSE if nothing changed, TRUE if this is a new or updated event.
int EPG_add_event(struct lib_ccx_ctx *ctx, int32_t pmt_map, struct EPG_event *event) {
int isnew=true, j;
for(j=0; j<ctx->eit_programs[pmt_map].array_len; j++) {
if(ctx->eit_programs[pmt_map].epg_events[j].id==event->id) {
if(EPG_event_cmp(event, &ctx->eit_programs[pmt_map].epg_events[j]))
return false; //event already in array, nothing to do
else { //event with this id is already in the array but something has changed. Update it.
event->count=ctx->eit_programs[pmt_map].epg_events[j].count;
EPG_free_event(&ctx->eit_programs[pmt_map].epg_events[j]);
memcpy(&ctx->eit_programs[pmt_map].epg_events[j], event, sizeof(struct EPG_event));
return true;
}
}
}
// id not in array. Add new event;
event->count=0;
memcpy(&ctx->eit_programs[pmt_map].epg_events[ctx->eit_programs[pmt_map].array_len], event, sizeof(struct EPG_event));
ctx->eit_programs[pmt_map].array_len++;
return true;
}
//EN 300 468 V1.3.1 (1998-02)
//6.2.4 Content descriptor
void EPG_decode_content_descriptor(uint8_t *offset, uint32_t descriptor_length, struct EPG_event *event) {
int i;
int num_items = descriptor_length/2;
if(num_items == 0) {
dbg_print (CCX_DMT_GENERIC_NOTICES, "\rWarning: Invalid EIT content_descriptor length detected.\n");
return;
}
event->categories = malloc(1*num_items);
event->num_categories = num_items;
for(i=0; i<num_items; i++) {
event->categories[i] = offset[0];
offset+=2;
}
}
//EN 300 468 V1.3.1 (1998-02)
//6.2.20 Parental rating descripto
void EPG_decode_parental_rating_descriptor(uint8_t *offset, uint32_t descriptor_length, struct EPG_event *event) {
int i;
int num_items = descriptor_length/4;
struct EPG_rating *ratings;
if(num_items == 0) {
dbg_print (CCX_DMT_GENERIC_NOTICES, "\rWarning: Invalid EIT parental_rating length detected.\n");
return;
}
event->ratings = malloc(sizeof(struct EPG_rating)*num_items);
ratings = event->ratings;
event->num_ratings = num_items;
for(i=0; i<descriptor_length/4; i++) {
ratings[i].country_code[0] = offset[0];
ratings[i].country_code[1] = offset[1];
ratings[i].country_code[2] = offset[2];
ratings[i].country_code[3] = '\0';
if(offset[3] == 0x00 || offset[3] >=0x10)
ratings[i].age = 0;
else
ratings[i].age = offset[3];
offset+=4;
}
}
// an ungly function to convert from dvb codepages to UTF-8859-9 using iconv
// returns a null terminated UTF8-strings
// EN 300 468 V1.7.1 (2006-05)
// A.2 Selection of Character table
char* EPG_DVB_decode_string(uint8_t *in, size_t size) {
uint8_t *out;
uint16_t decode_buffer_size = (size*4)+1;
uint8_t *decode_buffer = malloc(decode_buffer_size);
char *dp = &decode_buffer[0];
size_t obl=decode_buffer_size;
uint16_t osize=0;
iconv_t cd=(iconv_t)(-1);
int skipiconv = false;
int ret=-1;
int x;
if(size==0) { // 0 length strings are valid
decode_buffer[0]='\0';
return decode_buffer;
}
if(in[0]>=0x20) {
skipiconv=true;
}
else if(in[0]==0x01) {
size--; in++;
cd = iconv_open("UTF-8", "ISO8859-5"); //tested
}
else if(in[0]==0x02) {
size--; in++;
cd = iconv_open("UTF-8", "ISO8859-6");
}
else if(in[0]==0x03) {
size--; in++;
cd = iconv_open("UTF-8", "ISO8859-7");
}
else if(in[0]==0x04) {
size--; in++;
cd = iconv_open("UTF-8", "ISO8859-8");
}
else if(in[0]==0x05) {
size--; in++;
cd = iconv_open("UTF-8", "ISO8859-9");
}
else if(in[0]==0x06) {
size--; in++;
cd = iconv_open("UTF-8", "ISO8859-10");
}
else if(in[0]==0x07) {
size--; in++;
cd = iconv_open("UTF-8", "ISO8859-11");
}
else if(in[0]==0x08) {
size--; in++;
cd = iconv_open("UTF-8", "ISO8859-12"); //This doesn't even exist?
}
else if(in[0]==0x09) {
size--; in++;
cd = iconv_open("UTF-8", "ISO8859-13");
}
else if(in[0]==0x0a) {
size--; in++;
cd = iconv_open("UTF-8", "ISO8859-14");
}
else if(in[0]==0x0b) {
size--; in++;
cd = iconv_open("UTF-8", "ISO8859-15"); //tested, german
}
else if(in[0]==0x10) {
char from[14];
uint16_t cpn = (in[1] << 8) | in[2];
size-=3; in+=3;
snprintf(from, sizeof(from), "ISO8859-%d", cpn);
cd = iconv_open("UTF-8", from);
}
else if(in[0]==0x11) {
size--; in++;
cd = iconv_open("UTF-8", "ISO-10646/UTF8");
}
else if(in[0]==0x12) {
size--; in++;
cd = iconv_open("UTF-8", "KS_C_5601-1987");
}
else if(in[0]==0x13) {
size--; in++;
cd = iconv_open("UTF-8", "GB2312");
}
else if(in[0]==0x14) {
size--; in++;
cd = iconv_open("UTF-8", "BIG-5");
}
else if(in[0]==0x15) {
size--; in++;
cd = iconv_open("UTF-8", "UTF-8");
}
else {
dbg_print (CCX_DMT_GENERIC_NOTICES, "\rWarning: EPG_DVB_decode_string(): Reserved encoding detected: %02x.\n", in[0]);
size--; in++;
cd = iconv_open("UTF-8", "ISO8859-9");
}
if((long)cd != -1 && !skipiconv) {
ret = iconv(cd, (char **)&in, &size, &dp, &obl);
obl=decode_buffer_size-obl;
decode_buffer[obl]=0x00;
}
else {
uint16_t newsize=0;
if(!skipiconv)
dbg_print (CCX_DMT_GENERIC_NOTICES, "\rWarning: EPG_DVB_decode_string(): Failed to convert codepage.\n");
/*
http://dvbstreamer.sourcearchive.com/documentation/2.1.0-2/dvbtext_8c_source.html
libiconv doesn't support ISO 6937, but glibc does?!
so fall back to ISO8859-1 and strip out the non spacing
diacritical mark/graphical characters etc.
ALSO: http://lists.gnu.org/archive/html/bug-gnu-libiconv/2009-09/msg00000.html
*/
for(x=0; x<size; x++) {
if(in[x]<=(uint8_t)127) {
decode_buffer[newsize]=in[x];
newsize++;
}
}
size=newsize;
decode_buffer[size]=0x00;
}
osize=strlen(decode_buffer);
out = malloc(osize+1);
memcpy(out, decode_buffer, osize);
out[osize]=0x00;
free(decode_buffer);
if (cd != (iconv_t)-1)
iconv_close(cd);
return out;
}
//EN 300 468 V1.3.1 (1998-02)
//6.2.27 Short event descriptor
void EPG_decode_short_event_descriptor(uint8_t *offset, uint32_t descriptor_length, struct EPG_event *event) {
uint8_t text_length;
uint8_t event_name_length;
event->has_simple=true;
event->ISO_639_language_code[0] = offset[0];
event->ISO_639_language_code[1] = offset[1];
event->ISO_639_language_code[2] = offset[2];
event->ISO_639_language_code[3] = 0x00;
event_name_length = offset[3];
if(event_name_length+4>descriptor_length) {
dbg_print (CCX_DMT_GENERIC_NOTICES, "\rWarning: Invalid short_event_descriptor size detected.\n");
return;
}
event->event_name = EPG_DVB_decode_string(&offset[4], event_name_length);
text_length = offset[4+event_name_length];
if(text_length+event_name_length+4>descriptor_length) {
dbg_print (CCX_DMT_GENERIC_NOTICES, "\rWarning: Invalid short_event_descriptor size detected.\n");
return;
}
event->text = EPG_DVB_decode_string(&offset[5+event_name_length], text_length);
}
//EN 300 468 V1.3.1 (1998-02)
//6.2.9 Extended event descriptor
void EPG_decode_extended_event_descriptor(uint8_t *offset, uint32_t descriptor_length, struct EPG_event *event) {
uint8_t descriptor_number=offset[0]>>4;
uint8_t last_descriptor_number=(offset[0]&0x0f);
uint32_t text_length;
uint32_t oldlen=0;
uint8_t length_of_items = offset[4];
event->extended_ISO_639_language_code[0] = offset[1];
event->extended_ISO_639_language_code[1] = offset[2];
event->extended_ISO_639_language_code[2] = offset[3];
event->extended_ISO_639_language_code[3] = 0x00;
offset=offset+length_of_items+5;
if(length_of_items>descriptor_length-5) {
dbg_print (CCX_DMT_GENERIC_NOTICES, "\rWarning: Invalid extended_event_descriptor size detected.\n");
return;
}
text_length = offset[0];
if(text_length>descriptor_length-5-length_of_items-1) {
dbg_print (CCX_DMT_GENERIC_NOTICES, "\rWarning: Invalid extended_event_text_length size detected.\n");
return;
}
//TODO: can this leak memory with a malformed descriptor?
if(descriptor_number>0) {
if(offset[1]<0x20) {
offset++;
text_length--;
}
uint8_t *net = malloc(strlen(event->extended_text)+text_length+1);
oldlen=strlen(event->extended_text);
memcpy(net, event->extended_text, strlen(event->extended_text));
free(event->extended_text);
event->extended_text=net;
}
else
event->extended_text = malloc(text_length+1);
memcpy(&event->extended_text[oldlen], &offset[1], text_length);
event->extended_text[oldlen + text_length] = '\0';
if(descriptor_number==last_descriptor_number) {
uint8_t *old = event->extended_text;
event->extended_text = EPG_DVB_decode_string(event->extended_text, strlen(event->extended_text));
free(old);
}
}
// decode an ATSC multiple_string
// extremly basic implementation
// only handles single segment, single language ANSI string!
void EPG_ATSC_decode_multiple_string(uint8_t *offset, uint32_t length, struct EPG_event *event) {
uint8_t number_strings = offset[0];
int i, j;
char ISO_639_language_code[4];
offset++;
for(i=0; i<number_strings; i++) {
uint8_t number_segments = offset[3];
ISO_639_language_code[0] = offset[0];
ISO_639_language_code[1] = offset[1];
ISO_639_language_code[2] = offset[2];
ISO_639_language_code[3] = 0x00;
offset+=4;
for (j=0; j< number_segments; j++) {
uint8_t compression_type = offset[0];
uint8_t mode = offset[1];
uint8_t number_bytes = offset[2];
offset+=3;
if(mode==0 && compression_type==0 && j==0) {
event->has_simple=true;
event->ISO_639_language_code[0]=ISO_639_language_code[0];
event->ISO_639_language_code[1]=ISO_639_language_code[1];
event->ISO_639_language_code[2]=ISO_639_language_code[2];
event->ISO_639_language_code[3]=0x00;
event->event_name = malloc(number_bytes+1);
memcpy(event->event_name, &offset[0], number_bytes);
event->event_name[number_bytes]='\0';
event->text = malloc(number_bytes+1);
memcpy(event->text, &offset[0], number_bytes);
event->text[number_bytes]='\0';
}
else {
dbg_print (CCX_DMT_GENERIC_NOTICES, "\rWarning: Unsupported ATSC multiple_string encoding detected!.\n");
}
offset+=number_bytes;
}
}
}
// decode ATSC EIT table.
void EPG_ATSC_decode_EIT(struct lib_ccx_ctx *ctx, uint8_t *payload_start, uint32_t size) {
uint8_t table_id = payload_start[0];
struct EPG_event event;
uint8_t num_events_in_section;
uint8_t *offset;
int hasnew=false;
int i, j;
uint16_t source_id = ((payload_start[3]) << 8) | payload_start[4];
int32_t pmt_map = -1;
event.has_simple=false;
event.extended_text=NULL;
event.num_ratings=0;
event.num_categories=0;
event.live_output=false;
for (i = 0; i < pmt_array_length; i++)
{
if (pmt_array[i].program_number == ctx->ATSC_source_pg_map[source_id])
pmt_map=i;
}
//Don't know how to stroe EPG until we know the programs. Ignore it.
if(pmt_map==-1)
pmt_map=TS_PMT_MAP_SIZE;
num_events_in_section = payload_start[9];
offset=&payload_start[10];
for(j=0; j<num_events_in_section; j++) {
uint16_t descriptors_loop_length;
uint8_t title_length, emt_location;
uint32_t length_in_seconds, start_time, full_id;
uint16_t event_id = ((offset[0]&0x3F) << 8) | offset[1];
full_id = (source_id << 16) | event_id;
event.id=full_id;
event.service_id=source_id;
start_time = (offset[2] << 24) | (offset[3] << 16) | (offset[4] << 8)| (offset[5] << 0);
EPG_ATSC_calc_time(event.start_time_string, start_time);
emt_location = (offset[6]&0x30)>>4;
length_in_seconds = (((offset[6]&0x0F) << 16) | (offset[7] << 8) | (offset[8] << 0));
EPG_ATSC_calc_time(event.end_time_string, start_time+length_in_seconds);
title_length = offset[9];
EPG_ATSC_decode_multiple_string(&offset[10], title_length, &event);
descriptors_loop_length = ((offset[10+title_length] & 0x0f) << 8) | offset[10+title_length+1];
hasnew |= EPG_add_event(ctx, pmt_map, &event);
offset+=12+descriptors_loop_length+title_length;
}
if((ccx_options.xmltv==1 || ccx_options.xmltv==3) && ccx_options.xmltvoutputinterval==0 && hasnew)
EPG_output(ctx);
}
// decode ATSC VCT table.
void EPG_ATSC_decode_VCT(struct lib_ccx_ctx *ctx, uint8_t *payload_start, uint32_t size) {
uint8_t table_id = payload_start[0];
uint8_t num_channels_in_section = payload_start[9];
uint8_t *offset = &payload_start[10];
int i;
for (i=0; i< num_channels_in_section; i++) {
char short_name[7*2];
uint16_t program_number = offset[24]<<8 | offset[25];
uint16_t source_id = offset[28]<<8 | offset[29];
uint16_t descriptors_loop_length = ((offset[30] & 0x03) << 8) | offset[31];
memcpy(short_name, &offset[0], 7*2);
offset+=32+descriptors_loop_length;
ctx->ATSC_source_pg_map[source_id]=program_number;
}
}
void EPG_DVB_decode_EIT(struct lib_ccx_ctx *ctx, uint8_t *payload_start, uint32_t size) {
uint8_t table_id = payload_start[0];
//uint8_t section_syntax_indicator = (0xf1&0x80)>>7;
uint16_t section_length = (payload_start[1]&0x0F)<<8 | payload_start[2];
uint16_t service_id = (payload_start[3] << 8) | payload_start[4];
int32_t pmt_map = -1;
int i;
int hasnew=false;
struct EPG_event event;
uint8_t section_number = payload_start[6];
uint8_t last_section_number = payload_start[7];
uint8_t segment_last_section_number = payload_start[12];
uint32_t events_length = section_length - 11;
uint8_t *offset=payload_start;
uint32_t remaining=events_length;
for (i = 0; i < pmt_array_length; i++)
{
if (pmt_array[i].program_number == service_id)
pmt_map=i;
}
//For any service we don't have an PMT for (yet), store it in the special last array pos.
if(pmt_map==-1)
pmt_map=TS_PMT_MAP_SIZE;
if(events_length>size-14) {
dbg_print (CCX_DMT_GENERIC_NOTICES, "\rWarning: Invalid EIT packet size detected.\n");
}
while(remaining>4) {
uint16_t descriptors_loop_length;
uint8_t *descp;
uint32_t duration;
uint64_t start_time;
event.id=(offset[14] << 8) | offset[15];
event.has_simple=false;
event.extended_text=NULL;
event.num_ratings=0;
event.num_categories=0;
event.live_output=false;
event.service_id=service_id;
//40 bits
start_time = ((uint64_t)offset[16] << 32) | ((uint64_t)offset[17] << 24) | ((uint64_t)offset[18] << 16) | ((uint64_t)offset[19] << 8)| ((uint64_t)offset[20] << 0);
EPG_DVB_calc_start_time(&event, start_time);
//24 bits
duration = (offset[21] << 16 ) | (offset[22] << 8 ) | (offset[23] << 0 );
EPG_DVB_calc_end_time(&event, start_time, duration);
event.running_status = (offset[24] & 0xE0) >> 5;
event.free_ca_mode = (offset[24] & 0x10) >> 4;
//12 bits
descriptors_loop_length = ((offset[24] & 0x0f) << 8) | offset[25];
descp = &offset[26];
if(descriptors_loop_length > remaining-16) {
dbg_print (CCX_DMT_GENERIC_NOTICES, "\rWarning: Invalid EIT descriptors_loop_length detected.\n");
return;
}
while(descp<&(offset[26])+descriptors_loop_length) {
if(descp+descp[1]+2>payload_start+size) {
dbg_print (CCX_DMT_GENERIC_NOTICES, "\rWarning: Invalid EIT descriptor_loop_length detected.\n");
EPG_free_event(&event);
return;
}
if(descp[0]==0x4d)
EPG_decode_short_event_descriptor(descp+2, descp[1], &event);
if(descp[0]==0x4e)
EPG_decode_extended_event_descriptor(descp+2, descp[1], &event);
if(descp[0]==0x54)
EPG_decode_content_descriptor(descp+2, descp[1], &event);
if(descp[0]==0x55)
EPG_decode_parental_rating_descriptor(descp+2, descp[1], &event);
if(descp[1]+2==0) {
dbg_print (CCX_DMT_GENERIC_NOTICES, "\rWarning: Invalid EIT descriptor_length detected.\n");
return;
}
descp=descp+(descp[1]+2);
}
remaining=remaining-(descriptors_loop_length+12);
offset=offset+descriptors_loop_length+12;
hasnew |= EPG_add_event(ctx, pmt_map, &event);
if(hasnew && section_number==0 && table_id==0x4e)
ctx->eit_current_events[pmt_map]=event.id;
}
if((ccx_options.xmltv==1 || ccx_options.xmltv==3) && ccx_options.xmltvoutputinterval==0 && hasnew)
EPG_output(ctx);
}
//handle outputing to xml files
void EPG_handle_output(struct lib_ccx_ctx *ctx) {
int cur_sec = (int) ((ctx->global_timestamp-ctx->min_global_timestamp) / 1000);
if(ccx_options.xmltv==1 || ccx_options.xmltv==3) { //full outout
if(ccx_options.xmltvoutputinterval!=0 && cur_sec>ctx->epg_last_output+ccx_options.xmltvliveinterval) {
ctx->epg_last_output=cur_sec;
EPG_output(ctx);
}
}
if(ccx_options.xmltv==2 || ccx_options.xmltv==3) { //live output
if(cur_sec>ctx->epg_last_live_output+ccx_options.xmltvliveinterval) {
ctx->epg_last_live_output=cur_sec;
EPG_output_live(ctx);
}
}
}
//determin table type and call the correct function to handle it
void EPG_parse_table(struct lib_ccx_ctx *ctx, uint8_t *b, uint32_t size) {
uint8_t pointer_field=b[0];
uint8_t *payload_start = &b[pointer_field + 1];
uint8_t table_id = payload_start[0];
switch (table_id) {
case 0x0cb:
EPG_ATSC_decode_EIT(ctx, payload_start, size);
break;
case 0xc8:
EPG_ATSC_decode_VCT(ctx, payload_start, size);
break;
default:
if (table_id>=0x4e && table_id<=0x6f)
EPG_DVB_decode_EIT(ctx, payload_start, size);
break;
}
EPG_handle_output(ctx);
}
// recounsructs DVB EIT and ATSC tables
void parse_EPG_packet(struct lib_ccx_ctx *ctx) {
unsigned char *payload_start = tspacket + 4;
unsigned payload_length = 188 - 4;
unsigned transport_error_indicator = (tspacket[1]&0x80)>>7;
unsigned payload_start_indicator = (tspacket[1]&0x40)>>6;
// unsigned transport_priority = (tspacket[1]&0x20)>>5;
unsigned pid = (((tspacket[1] & 0x1F) << 8) | tspacket[2]) & 0x1FFF;
// unsigned transport_scrambling_control = (tspacket[3]&0xC0)>>6;
unsigned adaptation_field_control = (tspacket[3]&0x30)>>4;
unsigned ccounter = tspacket[3] & 0xF;
unsigned adaptation_field_length = 0;
int buffer_map = 0xfff;
if ( adaptation_field_control & 2 )
{
adaptation_field_length = tspacket[4];
payload_start = payload_start + adaptation_field_length + 1;
payload_length = tspacket+188-payload_start;
}
if((pid!=0x12 && pid!=0x1ffb && pid<0x1000) || pid==0x1fff)
return;
if(pid!=0x12)
buffer_map = pid-0x1000;
if(payload_start_indicator) {
if(ctx->epg_buffers[buffer_map].ccounter>0) {
ctx->epg_buffers[buffer_map].ccounter=0;
EPG_parse_table(ctx, ctx->epg_buffers[buffer_map].buffer, ctx->epg_buffers[buffer_map].buffer_length);
}
ctx->epg_buffers[buffer_map].prev_ccounter = ccounter;
if(ctx->epg_buffers[buffer_map].buffer!=NULL)
free(ctx->epg_buffers[buffer_map].buffer);
else {
// must be first EIT packet
}
ctx->epg_buffers[buffer_map].buffer = (uint8_t *)malloc(payload_length);
memcpy(ctx->epg_buffers[buffer_map].buffer, payload_start, payload_length);
ctx->epg_buffers[buffer_map].buffer_length=payload_length;
ctx->epg_buffers[buffer_map].ccounter++;
}
else if(ccounter==ctx->epg_buffers[buffer_map].prev_ccounter+1 || (ctx->epg_buffers[buffer_map].prev_ccounter==0x0f && ccounter==0)) {
ctx->epg_buffers[buffer_map].prev_ccounter = ccounter;
ctx->epg_buffers[buffer_map].buffer = (uint8_t *)realloc(ctx->epg_buffers[buffer_map].buffer, ctx->epg_buffers[buffer_map].buffer_length+payload_length);
memcpy(ctx->epg_buffers[buffer_map].buffer+ctx->epg_buffers[buffer_map].buffer_length, payload_start, payload_length);
ctx->epg_buffers[buffer_map].ccounter++;
ctx->epg_buffers[buffer_map].buffer_length+=payload_length;
}
else {
dbg_print (CCX_DMT_GENERIC_NOTICES, "\rWarning: Out of order EPG packets detected.\n");
}
}
// Free all memory used for EPG parsing
void EPG_free(struct lib_ccx_ctx *ctx) {
int i = 0, j;
if(ccx_options.xmltv==2 || ccx_options.xmltv==3) {
EPG_output_live(ctx);
}
for (i = 0; i < TS_PMT_MAP_SIZE; i++)
{
for(j = 0; j < ctx->eit_programs[i].array_len; j++)
{
if(ctx->eit_programs[i].epg_events[j].has_simple) {
free(ctx->eit_programs[i].epg_events[j].event_name);
free(ctx->eit_programs[i].epg_events[j].text);
}
if(ctx->eit_programs[i].epg_events[j].extended_text!=NULL)
free(ctx->eit_programs[i].epg_events[j].extended_text);
if(ctx->eit_programs[i].epg_events[j].num_ratings>0)
free(ctx->eit_programs[i].epg_events[j].ratings);
if(ctx->eit_programs[i].epg_events[j].num_categories>0)
free(ctx->eit_programs[i].epg_events[j].categories);
}
ctx->eit_programs[i].array_len=0;
}
for (i = 0; i < 0xfff; i++) {
if(ctx->epg_buffers[i].buffer!=NULL)
free(ctx->epg_buffers[i].buffer);
}
}

2074
src/win_iconv/win_iconv.h Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -22,7 +22,7 @@
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* $Id: dirent.h,v 1.20 2014/03/19 17:52:23 tronkko Exp $
* $Id: dirent.h,v 1.1 2015/01/16 07:40:15 cfsmp3 Exp $
*/
#ifndef DIRENT_H
#define DIRENT_H

View File

@@ -173,6 +173,7 @@
<ClCompile Include="..\src\lib_ccx\telxcc.c" />
<ClCompile Include="..\src\lib_ccx\ts_functions.c" />
<ClCompile Include="..\src\lib_ccx\ts_tables.c" />
<ClCompile Include="..\src\lib_ccx\ts_tables_epg.c" />
<ClCompile Include="..\src\lib_ccx\utility.c" />
<ClCompile Include="..\src\lib_ccx\wtv_functions.c" />
<ClCompile Include="..\src\zlib\adler32.c" />