Compare commits

...

35 Commits
v0.83 ... v0.84

Author SHA1 Message Date
Carlos Fernandez
19f12038cd Added new stuff to CHANGES.TXT 2016-12-16 10:50:04 -08:00
Carlos Fernandez
ebc7c070f3 Merge branch 'pr/n545_Izaron' 2016-12-16 10:44:14 -08:00
Carlos Fernandez
7acb3c3874 Version bump (to 0.84). Rename target name of the Windows OCR binaries. 2016-12-16 10:41:02 -08:00
Carlos Fernandez
e3ca2c3fbc Merge branch 'pr/n537_maxkoryukov' 2016-12-16 10:06:18 -08:00
Carlos Fernandez
ac1accce96 Merge branch 'pr/n544_Izaron' 2016-12-16 10:04:19 -08:00
Carlos Fernandez
c39185abab Merge branch 'pr/n541_saurabhshri' 2016-12-16 10:03:37 -08:00
Carlos Fernandez
6729c9c33f Merge branch 'pr/n524_DanilaFe' 2016-12-16 10:02:18 -08:00
Carlos Fernandez
4e4a7aa19e Merge branch 'pr/n522_DanilaFe' 2016-12-16 10:01:24 -08:00
Izaron
5d8ce8bfb8 Added configurable curl post url 2016-12-16 15:07:01 +03:00
Izaron
92b811b329 Added myself to credits 2016-12-16 14:02:37 +03:00
Saurabh Shrivastava
8c8a357aa7 Corrected filename. 2016-12-16 11:00:34 +05:30
Saurabh Shrivastava
f2770b4609 Corrected filename. 2016-12-16 10:59:20 +05:30
Danila Fedorin
7c21754b74 Update with upstream changes and fix merge conflict. 2016-12-15 14:05:08 -08:00
Carlos Fernandez
547a9e9fbf Merge branch 'master' of https://github.com/CCExtractor/ccextractor 2016-12-15 13:53:57 -08:00
Carlos Fernandez
fd6a223876 Merge branch 'pr/n520_DanilaFe' 2016-12-15 13:53:37 -08:00
captions
2fd71f00d6 Minor gramatical error 2016-12-15 11:32:17 -08:00
Carlos Fernandez
0301a40560 Merge branch 'pr/n538_Izaron' 2016-12-15 11:31:38 -08:00
Evgeny Shulgin
5bbf27de9c Fixed linux/build script
Last PR #534
2016-12-15 21:07:29 +04:00
maxkoryukov
54f628f7a6 remove debug-files, increase verbosity for tests
fix maxkoryukov/ccextractor#1
2016-12-15 21:23:16 +05:00
maxkoryukov
4743eb46c1 Try to make changes compatible with upstream 2016-12-15 20:25:06 +05:00
maxkoryukov
66393a80f2 Break incoming subs into sentences (through a buffer), and remove duplicates 2016-12-15 20:21:43 +05:00
Danila Fedorin
c6c8de7357 Rename mstotime to millis_to_time in ccx_encoders_ssa. 2016-12-14 17:43:59 -08:00
Danila Fedorin
cbbbb20751 Merge remote-tracking branch 'upstream/master' into cleanup-ccx-common-h 2016-12-14 17:37:55 -08:00
Danila Fedorin
5846093a7f Merge remote-tracking branch 'upstream/master' into refactor-msprint
# Conflicts:
#	src/lib_ccx/general_loop.c
2016-12-11 14:20:15 -08:00
Danila Fedorin
f1d276c988 Merge upstream changes. 2016-12-11 14:13:27 -08:00
Danila Fedorin
0d0cb83ed6 Merge upstream changes 2016-12-11 14:05:49 -08:00
Danila Fedorin
08e9c3d596 Rename previously not renamed function. 2016-12-11 01:16:52 -08:00
Danila Fedorin
edcd2df6bc Fix variable names in asf_functions.c 2016-12-11 01:11:25 -08:00
Danila Fedorin
3f679d72cf Fix typo in asf_cuntions.c. It looks like a typo from the surrounding
code.
2016-12-11 01:05:45 -08:00
Danila Fedorin
2e09541c84 Rename another function. 2016-12-11 01:05:35 -08:00
Danila Fedorin
27417cda70 Rename more mstotime's to millis_to_time. 2016-12-10 23:22:10 -08:00
Danila Fedorin
2959d2a2ae Rename function to new name. 2016-12-10 23:22:03 -08:00
Danila Fedorin
289aecc1ed Refactor code surrounding print_mstime_static.
This should decrease code duplication - print_mstime2buf was doing
the same thing as mstime_sprintf, but with a hardcoded format and
a different return value. print_mstime (renamed to print_mstime_static)
could therefore be reworked into simply calling mstime_sprintf
 (renamed to print_mstime_buff).
2016-12-10 23:20:57 -08:00
Danila Fedorin
ea980a4150 Add underscores to debug_608toASC. 2016-12-10 23:12:37 -08:00
Danila Fedorin
2910b10f99 Rename mstotime to millis_to_time. 2016-12-10 23:11:01 -08:00
41 changed files with 1284 additions and 499 deletions

6
.gitignore vendored
View File

@@ -1,3 +1,9 @@
####
# Ignore tests tmp files and results
tests/runtest
tests/**/*.gcda
tests/**/*.gcno
####
# Ignore CVS related files

View File

@@ -1,3 +1,15 @@
0.84 (2016-12-16)
-----------------
- New: In Windows, both with and without-OCR binaries are bundled, since the OCR one causes problems due to
dependencies in some system. So unless you need the OCR just use the non-OCR version.
- New: Added -sbs (sentence by sentence) for DVB output. Each frame in the output file contains a complete
sentence (experimental).
- New: Added -curlposturl. If used each output frame will be sent with libcurl by doing a POST to that URL.
- Fix: More code consistency checking in function names.
- Fix: linux build script now tries to verify dependencies.
- Fix: Mac build script was missing a directory.
0.83 (2016-12-13)
-----------------
- Fix: Duplicate lines in mp4 (specifically affects itunes).

View File

@@ -30,6 +30,7 @@ Google Summer of Code 2016 students
- Rishabh Garg
Google Code-in 2016 students
- Evgeny Shulgin
(to be listed)

View File

@@ -13,4 +13,33 @@ BLD_SOURCES="../src/ccextractor.c $SRC_CCX $SRC_GPAC $SRC_ZLIB $SRC_ZVBI $SRC_LI
BLD_LINKER="-lm -zmuldefs -l tesseract -l lept"
./pre-build.sh
gcc $BLD_FLAGS $BLD_INCLUDE -o ccextractor $BLD_SOURCES $BLD_LINKER
out=$((LC_ALL=C gcc $BLD_FLAGS $BLD_INCLUDE -o ccextractor $BLD_SOURCES $BLD_LINKER) 2>&1)
res=$?
if [[ $out == *"gcc: command not found"* ]]
then
echo "Error: please install gcc";
exit 1
fi
if [[ $out == *"curl.h: No such file or directory"* ]]
then
echo "Error: please install curl development library (libcurl4-gnutls-dev for Debian/Ubuntu)";
exit 2
fi
if [[ $out == *"capi.h: No such file or directory"* ]]
then
echo "Error: please install tesseract development library (tesseract-ocr-dev for Debian/Ubuntu)";
exit 3
fi
if [[ $out == *"allheaders.h: No such file or directory"* ]]
then
echo "Error: please install leptonica development library (libleptonica-dev for Debian/Ubuntu)";
exit 4
fi
if [[ $res -ne 0 ]] # Unknown error
then
echo "Compiled with errors"
>&2 echo "$out"
exit 5
fi
echo "Compilation successful";

View File

@@ -30,5 +30,5 @@ echo "#define CCX_CCEXTRACTOR_COMPILE_REAL_H" >> ../src/lib_ccx/compile_info_rea
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 "Stored all in compile_info_real.h"
echo "Done."

View File

@@ -30,5 +30,5 @@ echo "#define CCX_CCEXTRACTOR_COMPILE_REAL_H" >> ../src/lib_ccx/compile_info_rea
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 "Stored all in compile_info_real.h"
echo "Done."

View File

@@ -84,8 +84,8 @@ int main(int argc, char *argv[])
#ifdef WITH_LIBCURL
curl_global_init(CURL_GLOBAL_ALL);
/* get a curl handle */
/* get a curl handle */
curl = curl_easy_init();
if (!curl)
{
@@ -205,7 +205,7 @@ int main(int argc, char *argv[])
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;
ccx_options.use_gop_as_pts = 0;
mprint ("\rAnalyzing data in general mode\n");
general_loop(ctx);
break;
@@ -244,22 +244,22 @@ int main(int argc, char *argv[])
{
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 \n", print_mstime_static(gop_time.ms) );
dbg_print(CCX_DMT_DECODER_608, "GOP: %s (%+3dms incl.)\n",
print_mstime((LLONG)(gop_time.ms
print_mstime_static((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)));
print_mstime_static(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) ),
print_mstime_static( (LLONG)(total_frames_count*1000/current_fps) ),
total_frames_count, current_fps);
}
@@ -273,7 +273,7 @@ int main(int argc, char *argv[])
// 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
// 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.
@@ -284,11 +284,11 @@ int main(int argc, char *argv[])
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.
// 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;
#ifdef ENABLE_SHARING
if (ccx_options.sharing_enabled)
{
@@ -299,20 +299,20 @@ int main(int argc, char *argv[])
if (dec_ctx->total_pulldownframes)
mprint ("incl. pulldown frames: %s (%u frames at %.2ffps)\n",
print_mstime( (LLONG)(dec_ctx->total_pulldownframes*1000/current_fps) ),
print_mstime_static( (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) (dec_ctx->frames_since_last_gop*1000/current_fps);
mprint ("\nMin PTS: %s\n",
print_mstime( dec_ctx->timing->min_pts/(MPEG_CLOCK_FREQ/1000) - dec_ctx->timing->fts_offset));
print_mstime_static( 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( dec_ctx->timing->sync_pts/(MPEG_CLOCK_FREQ/1000) + postsyncms));
print_mstime_static( dec_ctx->timing->sync_pts/(MPEG_CLOCK_FREQ/1000) + postsyncms));
mprint ("Length: %s\n",
print_mstime( dec_ctx->timing->sync_pts/(MPEG_CLOCK_FREQ/1000) + postsyncms
print_mstime_static( dec_ctx->timing->sync_pts/(MPEG_CLOCK_FREQ/1000) + postsyncms
- dec_ctx->timing->min_pts/(MPEG_CLOCK_FREQ/1000) + dec_ctx->timing->fts_offset ));
}
@@ -321,15 +321,15 @@ int main(int argc, char *argv[])
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));
print_mstime_static(first_gop_time.ms));
mprint ("Final GOP time: %s%+3dF\n",
print_mstime(gop_time.ms),
print_mstime_static(gop_time.ms),
dec_ctx->frames_since_last_gop);
mprint ("Diff. GOP length: %s%+3dF",
print_mstime(gop_time.ms - first_gop_time.ms),
print_mstime_static(gop_time.ms - first_gop_time.ms),
dec_ctx->frames_since_last_gop);
mprint (" (%s)\n\n",
print_mstime(gop_time.ms - first_gop_time.ms
print_mstime_static(gop_time.ms - first_gop_time.ms
+(LLONG) ((dec_ctx->frames_since_last_gop)*1000/29.97)) );
}
@@ -361,7 +361,7 @@ int main(int argc, char *argv[])
}
if(is_decoder_processed_enough(ctx) == CCX_TRUE)
break;
@@ -381,8 +381,8 @@ int main(int argc, char *argv[])
{
LLONG ratio=(get_fts_max()/10)/proc_time;
unsigned s1=(unsigned) (ratio/100);
unsigned s2=(unsigned) (ratio%100);
mprint ("Performance (real length/process time) = %u.%02u\n",
unsigned s2=(unsigned) (ratio%100);
mprint ("Performance (real length/process time) = %u.%02u\n",
s1, s2);
}
#endif
@@ -391,13 +391,13 @@ int main(int argc, char *argv[])
{
mprint ("\rNote: Processing was canceled before all data was processed because\n");
mprint ("\rone or more user-defined limits were reached.\n");
}
}
mprint ("This is beta software. Report issues to carlos at ccextractor org...\n");
if (show_myth_banner)
{
mprint ("NOTICE: Due to the major rework in 0.49, we needed to change part of the timing\n");
mprint ("code in the MythTV's branch. Please report results to the address above. If\n");
mprint ("something is broken it will be fixed. Thanks\n");
mprint ("something is broken it will be fixed. Thanks\n");
}
#ifdef CURL

View File

@@ -39,7 +39,7 @@ uint32_t asf_readval(void *val, int ltype)
return rval;
}
char *guidstr(void *val)
char *gui_data_string(void *val)
{
static char sbuf[40];
@@ -75,31 +75,31 @@ int asf_get_more_data(struct lib_ccx_ctx *ctx, struct demuxer_data **ppdata)
int reentry = 1;
// Variables for Header Object
int64_t DataPacketsCount = 0;
int BroadcastFlag = 0;
int SeekableFlag = 0;
uint32_t MinPacketSize = 0;
uint32_t MaxPacketSize = 0;
int64_t data_packets_count = 0;
int broadcast_flag = 0;
int seekable_flag = 0;
uint32_t min_packet_size = 0;
uint32_t max_packet_size = 0;
// Data Object Loop
int datapacketlength = 0; // Collect the read header bytes
int data_packet_length = 0; // Collect the read header bytes
// Payload parsing information
int SequenceType = 0; // ASF
int PaddingLType = 0; // ASF
uint32_t Sequence = 0;
uint32_t SendTime = 0;
int sequence_type = 0; // ASF
int padding_l_type = 0; // ASF
uint32_t sequence = 0;
uint32_t send_time = 0;
int payloadparsersize = 0; // Infered (PacketLType + SequenceType + PaddingLType + 6);
int payload_parser_size = 0; // Infered (PacketLType + sequence_type + padding_l_type + 6);
uint32_t OffsetMediaLength = 0; // ASF
uint32_t ReplicatedLength = 0; // ASF
uint32_t offset_media_length = 0; // ASF
uint32_t replicated_length = 0; // ASF
// Last media number. Used to determine a new PES, mark uninitialized.
uint32_t curmedianumber = 0xFFFFFFFF;
uint32_t current_media_number = 0xFFFFFFFF;
unsigned char *curpos;
int64_t getbytes;
unsigned char *current_position;
int64_t get_bytes;
size_t result = 0;
struct demuxer_data *data;
@@ -194,12 +194,12 @@ int asf_get_more_data(struct lib_ccx_ctx *ctx, struct demuxer_data **ppdata)
asf_data_container.parsebufsize = (long)asf_data_container.HeaderObjectSize;
}
curpos = asf_data_container.parsebuf + 30;
getbytes = asf_data_container.HeaderObjectSize - 30;
current_position = asf_data_container.parsebuf + 30;
get_bytes = asf_data_container.HeaderObjectSize - 30;
result = buffered_read(ctx->demux_ctx, curpos, (int) getbytes);
result = buffered_read(ctx->demux_ctx, current_position, (int) get_bytes);
ctx->demux_ctx->past += result;
if (result!=getbytes)
if (result!=get_bytes)
{
mprint("Premature end of file!\n");
end_of_file=1;
@@ -208,174 +208,174 @@ int asf_get_more_data(struct lib_ccx_ctx *ctx, struct demuxer_data **ppdata)
dbg_print(CCX_DMT_PARSE, "Reading header objects\n");
while (curpos < asf_data_container.parsebuf + asf_data_container.HeaderObjectSize)
while (current_position < asf_data_container.parsebuf + asf_data_container.HeaderObjectSize)
{
int64_t hpobjectsize = *((int64_t*)(curpos+16)); // Local
int64_t hpobjectsize = *((int64_t*)(current_position+16)); // Local
if( !memcmp(curpos, ASF_FILE_PROPERTIES, 16 ) )
if( !memcmp(current_position, ASF_FILE_PROPERTIES, 16 ) )
{
// Mandatory Object, only one.
dbg_print(CCX_DMT_PARSE, "\nFile Properties Object (size: %lld)\n", hpobjectsize);
asf_data_container.FileSize = *((int64_t*)(curpos + 40));
DataPacketsCount = *((int64_t*)(curpos+56));
BroadcastFlag = 0x1 & curpos[88];
SeekableFlag = 0x2 & curpos[88];
MinPacketSize = *((uint32_t*)(curpos+92));
MaxPacketSize = *((uint32_t*)(curpos+96));
asf_data_container.FileSize = *((int64_t*)(current_position + 40));
data_packets_count = *((int64_t*)(current_position+56));
broadcast_flag = 0x1 & current_position[88];
seekable_flag = 0x2 & current_position[88];
min_packet_size = *((uint32_t*)(current_position+92));
max_packet_size = *((uint32_t*)(current_position+96));
dbg_print(CCX_DMT_PARSE, "FileSize: %lld Packet count: %lld\n", asf_data_container.FileSize, DataPacketsCount);
dbg_print(CCX_DMT_PARSE, "Broadcast: %d - Seekable: %d\n", BroadcastFlag, SeekableFlag);
dbg_print(CCX_DMT_PARSE, "MiDPS: %d MaDPS: %d\n", MinPacketSize, MaxPacketSize);
dbg_print(CCX_DMT_PARSE, "FileSize: %lld Packet count: %lld\n", asf_data_container.FileSize, data_packets_count);
dbg_print(CCX_DMT_PARSE, "Broadcast: %d - Seekable: %d\n", broadcast_flag, seekable_flag);
dbg_print(CCX_DMT_PARSE, "MiDPS: %d MaDPS: %d\n", min_packet_size, max_packet_size);
}
else if( !memcmp(curpos,ASF_STREAM_PROPERTIES, 16 ) )
else if( !memcmp(current_position,ASF_STREAM_PROPERTIES, 16 ) )
{
dbg_print(CCX_DMT_PARSE, "\nStream Properties Object (size: %lld)\n", hpobjectsize);
if( !memcmp(curpos+24, ASF_VIDEO_MEDIA, 16 ) )
if( !memcmp(current_position+24, ASF_VIDEO_MEDIA, 16 ) )
{
asf_data_container.StreamProperties.VideoStreamNumber = *(curpos + 72) & 0x7F;
asf_data_container.StreamProperties.VideoStreamNumber = *(current_position + 72) & 0x7F;
dbg_print(CCX_DMT_PARSE, "Stream Type: ASF_Video_Media\n");
dbg_print(CCX_DMT_PARSE, "Video Stream Number: %d\n", asf_data_container.StreamProperties.VideoStreamNumber);
}
else if( !memcmp(curpos+24, ASF_AUDIO_MEDIA, 16 ) )
else if( !memcmp(current_position+24, ASF_AUDIO_MEDIA, 16 ) )
{
asf_data_container.StreamProperties.AudioStreamNumber = *(curpos + 72) & 0x7F;
asf_data_container.StreamProperties.AudioStreamNumber = *(current_position + 72) & 0x7F;
dbg_print(CCX_DMT_PARSE, "Stream Type: ASF_Audio_Media\n");
dbg_print(CCX_DMT_PARSE, "Audio Stream Number: %d\n", asf_data_container.StreamProperties.AudioStreamNumber);
}
else
{
dbg_print(CCX_DMT_PARSE, "Stream Type: %s\n",
guidstr(curpos+24));
dbg_print(CCX_DMT_PARSE, "Stream Number: %d\n", *(curpos+72) & 0x7F );
gui_data_string(current_position+24));
dbg_print(CCX_DMT_PARSE, "Stream Number: %d\n", *(current_position+72) & 0x7F );
}
}
else if( !memcmp(curpos,ASF_HEADER_EXTENSION, 16 ) )
else if( !memcmp(current_position,ASF_HEADER_EXTENSION, 16 ) )
{
dbg_print(CCX_DMT_PARSE, "\nHeader Extension Object (size: %lld)\n", hpobjectsize);
int32_t HeaderExtensionDataSize = *((uint32_t*)(curpos+42));
int32_t header_extension_data_size = *((uint32_t*)(current_position+42));
// Process Header Extension Data
if ( HeaderExtensionDataSize )
if ( header_extension_data_size )
{
unsigned char *hecurpos=curpos+46;
unsigned char *header_current_position=current_position+46;
if ( HeaderExtensionDataSize != hpobjectsize - 46 )
if ( header_extension_data_size != hpobjectsize - 46 )
fatal(EXIT_NOT_CLASSIFIED, "In asf_getmoredata: Incorrect HeaderExtensionDataSize value, cannot continue.");
dbg_print(CCX_DMT_PARSE, "\nReading Header Extension Sub-Objects\n");
while( hecurpos < curpos+46 + HeaderExtensionDataSize )
while( header_current_position < current_position+46 + header_extension_data_size )
{
int64_t heobjectsize = *((int64_t*)(hecurpos+16)); // Local
int64_t header_object_size = *((int64_t*)(header_current_position+16)); // Local
if( !memcmp(hecurpos,ASF_EXTENDED_STREAM_PROPERTIES, 16 ) )
if( !memcmp(header_current_position,ASF_EXTENDED_STREAM_PROPERTIES, 16 ) )
{
dbg_print(CCX_DMT_PARSE, "\nExtended Stream Properties Object (size: %lld)\n", heobjectsize);
int StreamNumber = *((uint16_t*)(hecurpos+72));
int StreamNameCount = *((uint16_t*)(hecurpos+84));
int PayloadExtensionSystemCount = *((uint16_t*)(hecurpos+86));
dbg_print(CCX_DMT_PARSE, "\nExtended Stream Properties Object (size: %lld)\n", header_object_size);
int stream_number = *((uint16_t*)(header_current_position+72));
int stream_name_count = *((uint16_t*)(header_current_position+84));
int payload_ext_system_count = *((uint16_t*)(header_current_position+86));
unsigned char *estreamproppos=hecurpos+88;
unsigned char *stream_prop_position=header_current_position+88;
int streamnamelength;
int stream_name_length;
dbg_print(CCX_DMT_PARSE, "Stream Number: %d NameCount: %d ESCount: %d\n",
StreamNumber, StreamNameCount, PayloadExtensionSystemCount);
stream_number, stream_name_count, payload_ext_system_count);
if ( StreamNumber >= STREAMNUM )
if ( stream_number >= STREAMNUM )
fatal(CCX_COMMON_EXIT_BUG_BUG, "In asf_getmoredata: STREAMNUM too small. Please file a bug report in GitHub.\n");
for(int i=0; i<StreamNameCount; i++)
for(int i=0; i<stream_name_count; i++)
{
dbg_print(CCX_DMT_PARSE,"%2d. Stream Name Field\n",i);
streamnamelength=*((uint16_t*)(estreamproppos+2));
estreamproppos+=4+streamnamelength;
stream_name_length=*((uint16_t*)(stream_prop_position+2));
stream_prop_position+=4+stream_name_length;
}
int extensionsystemdatasize;
int extensionsysteminfolength;
int ext_system_data_size;
int ext_system_info_length;
if ( PayloadExtensionSystemCount > PAYEXTNUM )
if ( payload_ext_system_count > PAYEXTNUM )
fatal(CCX_COMMON_EXIT_BUG_BUG, "In asf_getmoredata: PAYEXTNUM too small. Please file a bug report in GitHub.\n");
for(int i=0; i<PayloadExtensionSystemCount; i++)
for(int i=0; i<payload_ext_system_count; i++)
{
extensionsystemdatasize = *((uint16_t*)(estreamproppos+16));
extensionsysteminfolength = *((uint32_t*)(estreamproppos+18));
ext_system_data_size = *((uint16_t*)(stream_prop_position+16));
ext_system_info_length = *((uint32_t*)(stream_prop_position+18));
asf_data_container.PayloadExtSize[StreamNumber][i] = extensionsystemdatasize;
asf_data_container.PayloadExtSize[stream_number][i] = ext_system_data_size;
dbg_print(CCX_DMT_PARSE,"%2d. Payload Extension GUID: %s Size %d Info Length %d\n",
i,guidstr(estreamproppos+0),
extensionsystemdatasize,
extensionsysteminfolength);
i,gui_data_string(stream_prop_position+0),
ext_system_data_size,
ext_system_info_length);
// For DVR-MS presentation timestamp
if( !memcmp(estreamproppos, DVRMS_PTS, 16 ) )
if( !memcmp(stream_prop_position, DVRMS_PTS, 16 ) )
{
dbg_print(CCX_DMT_PARSE, "Found DVRMS_PTS\n");
asf_data_container.PayloadExtPTSEntry[StreamNumber] = i;
asf_data_container.PayloadExtPTSEntry[stream_number] = i;
}
estreamproppos+=22+extensionsysteminfolength;
stream_prop_position+=22+ext_system_info_length;
}
// Now, there can be a Stream Properties Object. The only way to
// find out is to check if there are bytes left in the current
// object.
if ( (estreamproppos - hecurpos) < heobjectsize )
if ( (stream_prop_position - header_current_position) < header_object_size )
{
int64_t spobjectsize = *((int64_t*)(estreamproppos+16)); // Local
if( memcmp(estreamproppos, ASF_STREAM_PROPERTIES, 16 ) )
int64_t stream_prop_object_size = *((int64_t*)(stream_prop_position+16)); // Local
if( memcmp(stream_prop_position, ASF_STREAM_PROPERTIES, 16 ) )
fatal(EXIT_NOT_CLASSIFIED, "Stream Properties Object expected\n");
if( !memcmp(estreamproppos+24, ASF_VIDEO_MEDIA, 16 ) )
if( !memcmp(stream_prop_position+24, ASF_VIDEO_MEDIA, 16 ) )
{
dbg_print(CCX_DMT_PARSE, "Stream Type: ASF_Video_Media (size: %lld)\n",
spobjectsize);
asf_data_container.StreamProperties.VideoStreamNumber = StreamNumber;
stream_prop_object_size);
asf_data_container.StreamProperties.VideoStreamNumber = stream_number;
}
else if( !memcmp(estreamproppos+24, ASF_AUDIO_MEDIA, 16 ) )
else if( !memcmp(stream_prop_position+24, ASF_AUDIO_MEDIA, 16 ) )
{
dbg_print(CCX_DMT_PARSE, "Stream Type: ASF_Audio_Media (size: %lld)\n",
spobjectsize);
asf_data_container.StreamProperties.AudioStreamNumber = StreamNumber;
stream_prop_object_size);
asf_data_container.StreamProperties.AudioStreamNumber = stream_number;
}
else if( !memcmp(estreamproppos+24, ASF_BINARY_MEDIA, 16 ) )
else if( !memcmp(stream_prop_position+24, ASF_BINARY_MEDIA, 16 ) )
{
// dvr-ms files identify audio streams as binary streams
// but use the "major media type" accordingly to identify
// the steam. (There might be other audio identifiers.)
if( !memcmp(estreamproppos+78, DVRMS_AUDIO, 16 ) ) {
if( !memcmp(stream_prop_position+78, DVRMS_AUDIO, 16 ) ) {
dbg_print(CCX_DMT_PARSE, "Binary media: DVR-MS Audio Stream (size: %lld)\n",
spobjectsize);
stream_prop_object_size);
}
else if( !memcmp(estreamproppos+78, DVRMS_NTSC, 16 ) )
else if( !memcmp(stream_prop_position+78, DVRMS_NTSC, 16 ) )
{
dbg_print(CCX_DMT_PARSE, "Binary media: NTSC captions (size: %lld)\n",
spobjectsize);
asf_data_container.StreamProperties.CaptionStreamNumber = StreamNumber;
stream_prop_object_size);
asf_data_container.StreamProperties.CaptionStreamNumber = stream_number;
asf_data_container.StreamProperties.CaptionStreamStyle = 1;
}
else if( !memcmp(estreamproppos+78, DVRMS_ATSC, 16 ) )
else if( !memcmp(stream_prop_position+78, DVRMS_ATSC, 16 ) )
{
dbg_print(CCX_DMT_PARSE, "Binary media: ATSC captions (size: %lld)\n",
spobjectsize);
asf_data_container.StreamProperties.CaptionStreamNumber = StreamNumber;
stream_prop_object_size);
asf_data_container.StreamProperties.CaptionStreamNumber = stream_number;
asf_data_container.StreamProperties.CaptionStreamStyle = 2;
}
else
{
dbg_print(CCX_DMT_PARSE, "Binary media: Major Media Type GUID: %s (size: %lld)\n",
guidstr(estreamproppos+78), spobjectsize);
gui_data_string(stream_prop_position+78), stream_prop_object_size);
}
}
else
{
dbg_print(CCX_DMT_PARSE, "Unknown Type GUID: %s (size: %lld)\n",
guidstr(estreamproppos+24), spobjectsize);
gui_data_string(stream_prop_position+24), stream_prop_object_size);
}
}
else
@@ -384,122 +384,122 @@ int asf_get_more_data(struct lib_ccx_ctx *ctx, struct demuxer_data **ppdata)
}
}
else if( !memcmp(hecurpos,ASF_METADATA, 16 ) )
else if( !memcmp(header_current_position,ASF_METADATA, 16 ) )
{
dbg_print(CCX_DMT_PARSE, "\nMetadata Object (size: %lld)\n", heobjectsize);
dbg_print(CCX_DMT_PARSE, "\nMetadata Object (size: %lld)\n", header_object_size);
}
else if( !memcmp(hecurpos,ASF_METADATA_LIBRARY, 16 ) )
else if( !memcmp(header_current_position,ASF_METADATA_LIBRARY, 16 ) )
{
dbg_print(CCX_DMT_PARSE, "\nMetadata Library Object (size: %lld)\n", heobjectsize);
dbg_print(CCX_DMT_PARSE, "\nMetadata Library Object (size: %lld)\n", header_object_size);
}
else if( !memcmp(hecurpos,ASF_COMPATIBILITY2, 16 ) )
else if( !memcmp(header_current_position,ASF_COMPATIBILITY2, 16 ) )
{
dbg_print(CCX_DMT_PARSE, "\nCompatibility Object 2 (size: %lld)\n", heobjectsize);
dbg_print(CCX_DMT_PARSE, "\nCompatibility Object 2 (size: %lld)\n", header_object_size);
}
else if( !memcmp(hecurpos,ASF_PADDING, 16 ) )
else if( !memcmp(header_current_position,ASF_PADDING, 16 ) )
{
dbg_print(CCX_DMT_PARSE, "\nPadding Object (size: %lld)\n", heobjectsize);
dbg_print(CCX_DMT_PARSE, "\nPadding Object (size: %lld)\n", header_object_size);
}
else
{
dbg_print(CCX_DMT_PARSE, "\nGUID: %s size: %lld\n",
guidstr(hecurpos), heobjectsize);
dump(CCX_DMT_PARSE, hecurpos, 16, 0, 0);
gui_data_string(header_current_position), header_object_size);
dump(CCX_DMT_PARSE, header_current_position, 16, 0, 0);
}
hecurpos += heobjectsize;
header_current_position += header_object_size;
}
if (hecurpos - (curpos+46) != HeaderExtensionDataSize)
if (header_current_position - (current_position+46) != header_extension_data_size)
fatal(EXIT_NOT_CLASSIFIED, "HE Parsing problem: read bytes %ld != header length %lld\nAbort!\n",
(long)(hecurpos - (curpos+46)), HeaderExtensionDataSize);
(long)(header_current_position - (current_position+46)), header_extension_data_size);
}
dbg_print(CCX_DMT_PARSE, "\nHeader Extension Object - End\n");
}
else if( !memcmp(curpos,ASF_CONTENT_DESCRIPTION, 16 ) )
else if( !memcmp(current_position,ASF_CONTENT_DESCRIPTION, 16 ) )
{
dbg_print(CCX_DMT_PARSE, "\nContend Description Object (size: %lld)\n", hpobjectsize);
}
else if( !memcmp(curpos,ASF_EXTENDED_CONTENT_DESCRIPTION, 16 ) )
else if( !memcmp(current_position,ASF_EXTENDED_CONTENT_DESCRIPTION, 16 ) )
{
dbg_print(CCX_DMT_PARSE, "\nExtended Contend Description Object (size: %lld)\n", hpobjectsize);
dbg_print(CCX_DMT_PARSE, "\nExtended Content Description Object (size: %lld)\n", hpobjectsize);
int ContentDescriptorsCount = *((uint16_t*)(curpos+24));
unsigned char *econtentpos=curpos+26;
int DescriptorNameLength;
int DescriptorValueDataType;
int DescriptorValueLength;
unsigned char *edescval;
int content_descriptor_count = *((uint16_t*)(current_position+24));
unsigned char *ext_content_position=current_position+26;
int descriptor_name_length;
int descriptor_value_data_type;
int descriptor_value_length;
unsigned char *extended_description_value;
for(int i=0; i<ContentDescriptorsCount; i++)
for(int i=0; i<content_descriptor_count; i++)
{
DescriptorNameLength = *((uint16_t*)(econtentpos));
DescriptorValueDataType = *((uint16_t*)(econtentpos+2+DescriptorNameLength));
DescriptorValueLength = *((uint16_t*)(econtentpos+4+DescriptorNameLength));
edescval = econtentpos+6+DescriptorNameLength;
descriptor_name_length = *((uint16_t*)(ext_content_position));
descriptor_value_data_type = *((uint16_t*)(ext_content_position+2+descriptor_name_length));
descriptor_value_length = *((uint16_t*)(ext_content_position+4+descriptor_name_length));
extended_description_value = ext_content_position+6+descriptor_name_length;
dbg_print(CCX_DMT_PARSE, "%3d. %ls = ",i,(wchar_t*)(econtentpos+2));
switch(DescriptorValueDataType)
dbg_print(CCX_DMT_PARSE, "%3d. %ls = ",i,(wchar_t*)(ext_content_position+2));
switch(descriptor_value_data_type)
{
case 0: // Unicode string
dbg_print(CCX_DMT_PARSE, "%ls (Unicode)\n",(wchar_t*)edescval);
dbg_print(CCX_DMT_PARSE, "%ls (Unicode)\n",(wchar_t*)extended_description_value);
break;
case 1: // byte string
dbg_print(CCX_DMT_PARSE, ":");
for(int ii=0; ii<DescriptorValueLength && ii<9; ii++)
for(int ii=0; ii<descriptor_value_length && ii<9; ii++)
{
dbg_print(CCX_DMT_PARSE, "%02X:",*((unsigned char*)(edescval+ii)));
dbg_print(CCX_DMT_PARSE, "%02X:",*((unsigned char*)(extended_description_value+ii)));
}
if (DescriptorValueLength>8)
dbg_print(CCX_DMT_PARSE, "skipped %d more",DescriptorValueLength-8);
if (descriptor_value_length>8)
dbg_print(CCX_DMT_PARSE, "skipped %d more",descriptor_value_length-8);
dbg_print(CCX_DMT_PARSE, " (BYTES)\n");
break;
case 2: // BOOL
dbg_print(CCX_DMT_PARSE, "%d (BOOL)\n",*((int32_t*)edescval));
dbg_print(CCX_DMT_PARSE, "%d (BOOL)\n",*((int32_t*)extended_description_value));
break;
case 3: // DWORD
dbg_print(CCX_DMT_PARSE, "%u (DWORD)\n",*((uint32_t*)edescval));
dbg_print(CCX_DMT_PARSE, "%u (DWORD)\n",*((uint32_t*)extended_description_value));
break;
case 4: // QWORD
dbg_print(CCX_DMT_PARSE, "%llu (QWORD)\n",*((uint64_t*)edescval));
dbg_print(CCX_DMT_PARSE, "%llu (QWORD)\n",*((uint64_t*)extended_description_value));
break;
case 5: // WORD
dbg_print(CCX_DMT_PARSE, "%u (WORD)\n",(int)*((uint16_t*)edescval));
dbg_print(CCX_DMT_PARSE, "%u (WORD)\n",(int)*((uint16_t*)extended_description_value));
break;
default:
fatal(CCX_COMMON_EXIT_BUG_BUG, "In asf_getmoredata: Impossible value for DescriptorValueDataType. Please file a bug report in GitHub.\n");
break;
}
if(!memcmp(econtentpos+2, L"WM/VideoClosedCaptioning"
,DescriptorNameLength))
if(!memcmp(ext_content_position+2, L"WM/VideoClosedCaptioning"
,descriptor_name_length))
{
// This flag would be really usefull if it would be
// reliable - it isn't.
asf_data_container.VideoClosedCaptioningFlag = *((int32_t*)edescval);
asf_data_container.VideoClosedCaptioningFlag = *((int32_t*)extended_description_value);
dbg_print(CCX_DMT_PARSE, "Found WM/VideoClosedCaptioning flag: %d\n",
asf_data_container.VideoClosedCaptioningFlag);
}
econtentpos+=6+DescriptorNameLength+DescriptorValueLength;
ext_content_position+=6+descriptor_name_length+descriptor_value_length;
}
}
else if( !memcmp(curpos,ASF_STREAM_BITRATE_PROPERTIES, 16 ) )
else if( !memcmp(current_position,ASF_STREAM_BITRATE_PROPERTIES, 16 ) )
{
dbg_print(CCX_DMT_PARSE, "\nStream Bitrate Properties Object (size: %lld)\n", hpobjectsize);
}
else
{
dbg_print(CCX_DMT_PARSE, "\nGUID: %s size: %lld\n",
guidstr(curpos), hpobjectsize);
dump(CCX_DMT_PARSE, curpos, 16, 0, 0);
gui_data_string(current_position), hpobjectsize);
dump(CCX_DMT_PARSE, current_position, 16, 0, 0);
}
curpos += hpobjectsize;
current_position += hpobjectsize;
}
if (curpos - asf_data_container.parsebuf != asf_data_container.HeaderObjectSize)
if (current_position - asf_data_container.parsebuf != asf_data_container.HeaderObjectSize)
fatal(EXIT_NOT_CLASSIFIED, "Parsing problem: read bytes %ld != header length %lld\nAbort!\n",
(long)(curpos - asf_data_container.parsebuf), asf_data_container.HeaderObjectSize);
(long)(current_position - asf_data_container.parsebuf), asf_data_container.HeaderObjectSize);
if (asf_data_container.StreamProperties.VideoStreamNumber == 0)
fatal(EXIT_NOT_CLASSIFIED, "No Video Stream Properties Object found. Unable to continue ...\n");
@@ -541,9 +541,9 @@ int asf_get_more_data(struct lib_ccx_ctx *ctx, struct demuxer_data **ppdata)
// When reading "Payload parsing information" it occured that "Packet Lenght"
// was not set (Packet Length Type 00) and for "Single Payloads" this means
// the Payload Data Length cannot be infered. Use MinPacketSize, MaxPacketSize instead.
if ((MinPacketSize > 0) && (MinPacketSize == MaxPacketSize))
asf_data_container.PacketSize = MinPacketSize;
// the Payload Data Length cannot be infered. Use min_packet_size, max_packet_size instead.
if ((min_packet_size > 0) && (min_packet_size == max_packet_size))
asf_data_container.PacketSize = min_packet_size;
// Now the Data Object, except for the packages
result = buffered_read(ctx->demux_ctx, asf_data_container.parsebuf, 50); // No realloc needed.
@@ -583,7 +583,7 @@ int asf_get_more_data(struct lib_ccx_ctx *ctx, struct demuxer_data **ppdata)
{
int ecinfo = 0;
datapacketlength = 0;
data_packet_length = 0;
dbg_print(CCX_DMT_PARSE, "\nReading packet %d/%d\n", asf_data_container.datapacketcur + 1, asf_data_container.TotalDataPackets);
@@ -597,7 +597,7 @@ int asf_get_more_data(struct lib_ccx_ctx *ctx, struct demuxer_data **ppdata)
end_of_file=1;
return payload_read;
}
datapacketlength+=1;
data_packet_length+=1;
if (*asf_data_container.parsebuf & 0x80)
{
int ecdatalength = *asf_data_container.parsebuf & 0x0F; // Small, no realloc needed
@@ -614,7 +614,7 @@ int asf_get_more_data(struct lib_ccx_ctx *ctx, struct demuxer_data **ppdata)
end_of_file=1;
return payload_read;
}
datapacketlength+=ecdatalength;
data_packet_length+=ecdatalength;
if (asf_data_container.parsebuf[1] & 0x0F)
fatal(EXIT_NOT_CLASSIFIED, "Error correction present. Unable to continue ...\n");
}
@@ -635,15 +635,15 @@ int asf_get_more_data(struct lib_ccx_ctx *ctx, struct demuxer_data **ppdata)
end_of_file=1;
return payload_read;
}
datapacketlength+=2;
data_packet_length+=2;
asf_data_container.MultiplePayloads = *asf_data_container.parsebuf & 0x01;
SequenceType = (*asf_data_container.parsebuf >> 1) & 0x03;
SequenceType = ASF_TypeLength(SequenceType);
sequence_type = (*asf_data_container.parsebuf >> 1) & 0x03;
sequence_type = ASF_TypeLength(sequence_type);
PaddingLType = (*asf_data_container.parsebuf >> 3) & 0x03;
PaddingLType = ASF_TypeLength(PaddingLType);
padding_l_type = (*asf_data_container.parsebuf >> 3) & 0x03;
padding_l_type = ASF_TypeLength(padding_l_type);
asf_data_container.PacketLType = (*asf_data_container.parsebuf >> 5) & 0x03;
asf_data_container.PacketLType = ASF_TypeLength(asf_data_container.PacketLType);
@@ -660,24 +660,24 @@ int asf_get_more_data(struct lib_ccx_ctx *ctx, struct demuxer_data **ppdata)
asf_data_container.StreamNumberLType = (asf_data_container.parsebuf[1] >> 6) & 0x03;
asf_data_container.StreamNumberLType = ASF_TypeLength(asf_data_container.StreamNumberLType);
payloadparsersize = asf_data_container.PacketLType + SequenceType + PaddingLType + 6;
payload_parser_size = asf_data_container.PacketLType + sequence_type + padding_l_type + 6;
result = buffered_read(ctx->demux_ctx, asf_data_container.parsebuf + 2, payloadparsersize); // No realloc needed
result = buffered_read(ctx->demux_ctx, asf_data_container.parsebuf + 2, payload_parser_size); // No realloc needed
ctx->demux_ctx->past += result;
asf_data_container.dobjectread += result;
if (result!=payloadparsersize)
if (result!=payload_parser_size)
{
mprint("Premature end of file!\n");
end_of_file=1;
return payload_read;
}
datapacketlength+=payloadparsersize;
data_packet_length+=payload_parser_size;
asf_data_container.PacketLength = asf_readval(asf_data_container.parsebuf + 2, asf_data_container.PacketLType);
Sequence = asf_readval(asf_data_container.parsebuf + 2 + asf_data_container.PacketLType, SequenceType);
asf_data_container.PaddingLength = asf_readval(asf_data_container.parsebuf + 2 + asf_data_container.PacketLType + SequenceType, PaddingLType);
sequence = asf_readval(asf_data_container.parsebuf + 2 + asf_data_container.PacketLType, sequence_type);
asf_data_container.PaddingLength = asf_readval(asf_data_container.parsebuf + 2 + asf_data_container.PacketLType + sequence_type, padding_l_type);
// Data Packet ms time stamp
SendTime = *((uint32_t*)(asf_data_container.parsebuf + 2 + asf_data_container.PacketLType + SequenceType + PaddingLType));
send_time = *((uint32_t*)(asf_data_container.parsebuf + 2 + asf_data_container.PacketLType + sequence_type + padding_l_type));
// If Packet Length is not set use global setting if possible
if (asf_data_container.PacketLength == 0)
@@ -689,8 +689,8 @@ int asf_get_more_data(struct lib_ccx_ctx *ctx, struct demuxer_data **ppdata)
fatal(EXIT_NOT_CLASSIFIED, "In asf_getmoredata: Cannot determine packet length. Unable to continue processing this file.\n");
}
dbg_print(CCX_DMT_PARSE, "Lengths - Packet: %d / Sequence %d / Padding %d\n",
asf_data_container.PacketLength, Sequence, asf_data_container.PaddingLength);
dbg_print(CCX_DMT_PARSE, "Lengths - Packet: %d / sequence %d / Padding %d\n",
asf_data_container.PacketLength, sequence, asf_data_container.PaddingLength);
asf_data_container.PayloadLType = 0; // Payload Length Type. <>0 for multiple payloads
asf_data_container.PayloadLength = 0; // Payload Length (for multiple payloads)
@@ -709,7 +709,7 @@ int asf_get_more_data(struct lib_ccx_ctx *ctx, struct demuxer_data **ppdata)
end_of_file=1;
return payload_read;
}
datapacketlength+=1;
data_packet_length+=1;
asf_data_container.PayloadLType = (*plheader >> 6) & 0x03;
asf_data_container.PayloadLType = ASF_TypeLength(asf_data_container.PayloadLType);
@@ -737,49 +737,49 @@ int asf_get_more_data(struct lib_ccx_ctx *ctx, struct demuxer_data **ppdata)
else
dbg_print(CCX_DMT_PARSE, "\nMultiple payloads %d/%d\n", asf_data_container.payloadcur + 1, asf_data_container.NumberOfPayloads);
int payloadheadersize = 1 + asf_data_container.MediaNumberLType + asf_data_container.OffsetMediaLType + asf_data_container.ReplicatedLType;
int payload_header_size = 1 + asf_data_container.MediaNumberLType + asf_data_container.OffsetMediaLType + asf_data_container.ReplicatedLType;
result = buffered_read(ctx->demux_ctx, asf_data_container.parsebuf, payloadheadersize); // No realloc needed
result = buffered_read(ctx->demux_ctx, asf_data_container.parsebuf, payload_header_size); // No realloc needed
ctx->demux_ctx->past += result;
asf_data_container.dobjectread += result;
if (result!=payloadheadersize)
if (result!=payload_header_size)
{
mprint("Premature end of file!\n");
end_of_file=1;
return payload_read;
}
datapacketlength+=payloadheadersize;
data_packet_length+=payload_header_size;
asf_data_container.PayloadStreamNumber = *asf_data_container.parsebuf & 0x7F;
asf_data_container.KeyFrame = (*asf_data_container.parsebuf & 0x80) && 1;
asf_data_container.PayloadMediaNumber = asf_readval(asf_data_container.parsebuf + 1, asf_data_container.MediaNumberLType);
OffsetMediaLength = asf_readval(asf_data_container.parsebuf + 1 + asf_data_container.MediaNumberLType, asf_data_container.OffsetMediaLType);
ReplicatedLength = asf_readval(asf_data_container.parsebuf + 1 + asf_data_container.MediaNumberLType + asf_data_container.OffsetMediaLType, asf_data_container.ReplicatedLType);
offset_media_length = asf_readval(asf_data_container.parsebuf + 1 + asf_data_container.MediaNumberLType, asf_data_container.OffsetMediaLType);
replicated_length = asf_readval(asf_data_container.parsebuf + 1 + asf_data_container.MediaNumberLType + asf_data_container.OffsetMediaLType, asf_data_container.ReplicatedLType);
if (ReplicatedLength == 1)
if (replicated_length == 1)
fatal(EXIT_NOT_CLASSIFIED, "Cannot handle compressed data...\n");
if ((long)ReplicatedLength > asf_data_container.parsebufsize)
if ((long)replicated_length > asf_data_container.parsebufsize)
{
asf_data_container.parsebuf = (unsigned char*)realloc(asf_data_container.parsebuf, ReplicatedLength);
asf_data_container.parsebuf = (unsigned char*)realloc(asf_data_container.parsebuf, replicated_length);
if (!asf_data_container.parsebuf)
fatal(EXIT_NOT_ENOUGH_MEMORY, "In asf_getmoredata: Not enough memory for buffer, unable to continue.\n");
asf_data_container.parsebufsize = ReplicatedLength;
asf_data_container.parsebufsize = replicated_length;
}
result = buffered_read(ctx->demux_ctx, asf_data_container.parsebuf, (long)ReplicatedLength);
result = buffered_read(ctx->demux_ctx, asf_data_container.parsebuf, (long)replicated_length);
ctx->demux_ctx->past += result;
asf_data_container.dobjectread += result;
if (result!=ReplicatedLength)
if (result!=replicated_length)
{
mprint("Premature end of file!\n");
end_of_file=1;
return payload_read;
}
// Parse Replicated data
unsigned char *reppos = asf_data_container.parsebuf;
int MediaObjectSize = 0;
int PresentationTimems = 0; //Payload ms time stamp
unsigned char *replicate_position = asf_data_container.parsebuf;
int media_object_size = 0;
int presentation_time_millis = 0; //Payload ms time stamp
int extsize = 0;
// int32_t dwVersion = 0;
// int32_t unknown = 0;
@@ -787,35 +787,35 @@ int asf_get_more_data(struct lib_ccx_ctx *ctx, struct demuxer_data **ppdata)
int64_t rtEnd = 0; // dvr-ms 100ns time stamp end
// Always at least 8 bytes long, see 7.3.1
MediaObjectSize = *((uint16_t*)(asf_data_container.parsebuf));
PresentationTimems = *((uint16_t*)(asf_data_container.parsebuf + 4));
reppos += 8;
media_object_size = *((uint16_t*)(asf_data_container.parsebuf));
presentation_time_millis = *((uint16_t*)(asf_data_container.parsebuf + 4));
replicate_position += 8;
dbg_print(CCX_DMT_PARSE, "Stream# %d[%d] Media# %d Offset/Size: %d/%d\n",
asf_data_container.PayloadStreamNumber, asf_data_container.KeyFrame, asf_data_container.PayloadMediaNumber,
OffsetMediaLength, MediaObjectSize);
offset_media_length, media_object_size);
// Loop over Payload Extension Systems
for (int i = 0; i<asf_data_container.PayloadExtPTSEntry[asf_data_container.PayloadStreamNumber]; i++)
{
if (asf_data_container.PayloadExtSize[asf_data_container.PayloadStreamNumber][i] == 0xffff)
{
extsize = *((uint16_t*)(reppos+0));
reppos += 2;
extsize = *((uint16_t*)(replicate_position+0));
replicate_position += 2;
}
else
{
extsize = asf_data_container.PayloadExtSize[asf_data_container.PayloadStreamNumber][i];
}
reppos += extsize;
replicate_position += extsize;
//printf("%2d. Ext. System - size: %d\n", i, extsize);
}
if (asf_data_container.PayloadExtPTSEntry[asf_data_container.PayloadStreamNumber] > 0)
{
// dwVersion = *((uint32_t*)(reppos+0));
// unknown = *((uint32_t*)(reppos+4));
rtStart = *((int64_t*)(reppos+8));
rtEnd = *((int64_t*)(reppos+16));
// dwVersion = *((uint32_t*)(replicate_position+0));
// unknown = *((uint32_t*)(replicate_position+4));
rtStart = *((int64_t*)(replicate_position+8));
rtEnd = *((int64_t*)(replicate_position+16));
//printf("dwVersion: %d unknown: 0x%04X\n", dwVersion, unknown);
}
@@ -830,13 +830,13 @@ int asf_get_more_data(struct lib_ccx_ctx *ctx, struct demuxer_data **ppdata)
// print_mstime uses a static buffer
dbg_print(CCX_DMT_PARSE, "Stream #%d PacketTime: %s",
asf_data_container.PayloadStreamNumber, print_mstime(SendTime));
asf_data_container.PayloadStreamNumber, print_mstime_static(send_time));
dbg_print(CCX_DMT_PARSE," PayloadTime: %s",
print_mstime(PresentationTimems));
print_mstime_static(presentation_time_millis));
dbg_print(CCX_DMT_PARSE," dvr-ms PTS: %s+%lld\n",
print_mstime(rtStart/10000), (rtEnd-rtStart)/10000);
print_mstime_static(rtStart/10000), (rtEnd-rtStart)/10000);
datapacketlength+=ReplicatedLength;
data_packet_length+=replicated_length;
// Only multiple payload packages have this value
if (asf_data_container.MultiplePayloads != 0)
@@ -856,21 +856,21 @@ int asf_get_more_data(struct lib_ccx_ctx *ctx, struct demuxer_data **ppdata)
}
else
{
asf_data_container.PayloadLength = asf_data_container.PacketLength - datapacketlength - asf_data_container.PaddingLength;
asf_data_container.PayloadLength = asf_data_container.PacketLength - data_packet_length - asf_data_container.PaddingLength;
}
dbg_print(CCX_DMT_PARSE, "Size - Replicated %d + Payload %d = %d\n",
ReplicatedLength, asf_data_container.PayloadLength, ReplicatedLength + asf_data_container.PayloadLength);
replicated_length, asf_data_container.PayloadLength, replicated_length + asf_data_container.PayloadLength);
// Remember the last video time stamp - only when captions are separate
// from video stream.
if (asf_data_container.PayloadStreamNumber == asf_data_container.StreamProperties.VideoStreamNumber
&& asf_data_container.StreamProperties.DecodeStreamNumber != asf_data_container.StreamProperties.VideoStreamNumber
&& OffsetMediaLength == 0)
&& offset_media_length == 0)
{
asf_data_container.StreamProperties.prevVideoStreamMS = asf_data_container.StreamProperties.currVideoStreamMS;
asf_data_container.StreamProperties.currVideoStreamMS = asf_data_container.StreamProperties.VideoStreamMS;
// Use PresentationTimems (SendTime might also work) when the
// Use presentation_time_millis (send_time might also work) when the
// dvr-ms time stamp is not present.
if (asf_data_container.PayloadExtPTSEntry[asf_data_container.PayloadStreamNumber] > 0)
{
@@ -881,7 +881,7 @@ int asf_get_more_data(struct lib_ccx_ctx *ctx, struct demuxer_data **ppdata)
else
{
// Add 1ms to avoid 0ms start times getting rejected
asf_data_container.StreamProperties.VideoStreamMS = PresentationTimems + 1;
asf_data_container.StreamProperties.VideoStreamMS = presentation_time_millis + 1;
}
// This checks if there is a video time jump in the timeline
// between caption information.
@@ -896,12 +896,12 @@ int asf_get_more_data(struct lib_ccx_ctx *ctx, struct demuxer_data **ppdata)
// Remember the PTS values
if (asf_data_container.PayloadStreamNumber == asf_data_container.StreamProperties.DecodeStreamNumber
&& OffsetMediaLength == 0)
&& offset_media_length == 0)
{
asf_data_container.StreamProperties.prevDecodeStreamPTS = asf_data_container.StreamProperties.currDecodeStreamPTS;
asf_data_container.StreamProperties.currDecodeStreamPTS = asf_data_container.StreamProperties.DecodeStreamPTS;
// Use PresentationTimems (SendTime might also work) when the
// Use presentation_time_millis (send_time might also work) when the
// dvr-ms time stamp is not present.
if (asf_data_container.PayloadExtPTSEntry[asf_data_container.PayloadStreamNumber] > 0)
{
@@ -912,7 +912,7 @@ int asf_get_more_data(struct lib_ccx_ctx *ctx, struct demuxer_data **ppdata)
else
{
// Add 1ms to avoid 0ms start times getting rejected
asf_data_container.StreamProperties.DecodeStreamPTS = PresentationTimems + 1;
asf_data_container.StreamProperties.DecodeStreamPTS = presentation_time_millis + 1;
}
// Check the caption stream for jumps in the timeline. This
@@ -955,16 +955,16 @@ int asf_get_more_data(struct lib_ccx_ctx *ctx, struct demuxer_data **ppdata)
// Video streams need several packages to complete a PES. Leave
// the loop when the next package starts a new Media Object.
if ( curmedianumber != 0xFFFFFFFF // Is initialized
if ( current_media_number != 0xFFFFFFFF // Is initialized
&& asf_data_container.PayloadStreamNumber == asf_data_container.StreamProperties.DecodeStreamNumber
&& asf_data_container.PayloadMediaNumber != curmedianumber)
&& asf_data_container.PayloadMediaNumber != current_media_number)
{
if (asf_data_container.StreamProperties.DecodeStreamNumber == asf_data_container.StreamProperties.CaptionStreamNumber)
dbg_print(CCX_DMT_PARSE, "\nCaption stream object");
else
dbg_print(CCX_DMT_PARSE, "\nVideo stream object");
dbg_print(CCX_DMT_PARSE, " read with PTS: %s\n",
print_mstime(asf_data_container.StreamProperties.currDecodeStreamPTS));
print_mstime_static(asf_data_container.StreamProperties.currDecodeStreamPTS));
// Enough for now
@@ -975,7 +975,7 @@ int asf_get_more_data(struct lib_ccx_ctx *ctx, struct demuxer_data **ppdata)
// Read it!!
if (asf_data_container.PayloadStreamNumber == asf_data_container.StreamProperties.DecodeStreamNumber)
{
curmedianumber = asf_data_container.PayloadMediaNumber; // Remember current value
current_media_number = asf_data_container.PayloadMediaNumber; // Remember current value
// Read the data
dbg_print(CCX_DMT_PARSE, "Reading Stream #%d data ...\n", asf_data_container.PayloadStreamNumber);

View File

@@ -1155,7 +1155,7 @@ void slice_header (struct lib_cc_decode *ctx, unsigned char *heabuf, unsigned ch
pic_order_cnt_lsb, ctx->timing->current_tref,
current_index, ctx->avc_ctx->currref, ctx->avc_ctx->lastmaxidx, ctx->avc_ctx->maxtref);
dbg_print(CCX_DMT_TIME, " sync_pts:%s (%8u)",
print_mstime(ctx->timing->sync_pts/(MPEG_CLOCK_FREQ/1000)),
print_mstime_static(ctx->timing->sync_pts/(MPEG_CLOCK_FREQ/1000)),
(unsigned) (ctx->timing->sync_pts));
dbg_print(CCX_DMT_TIME, " - %s since GOP: %2u",
slice_types[slice_type],

View File

@@ -38,14 +38,14 @@ void fdprintf(int fd, const char *fmt, ...)
free(p);
return;
}
else
else
{
p = np;
}
}
}
/* Converts the given milli to separate hours,minutes,seconds and ms variables */
void mstotime(LLONG milli, unsigned *hours, unsigned *minutes,
void millis_to_time(LLONG milli, unsigned *hours, unsigned *minutes,
unsigned *seconds, unsigned *ms)
{
// LLONG milli = (LLONG) ((ccblock*1000)/29.97);

View File

@@ -40,10 +40,10 @@
// Declarations
void fdprintf(int fd, const char *fmt, ...);
void mstotime(LLONG milli, unsigned *hours, unsigned *minutes,unsigned *seconds, unsigned *ms);
void millis_to_time(LLONG milli, unsigned *hours, unsigned *minutes,unsigned *seconds, unsigned *ms);
void freep(void *arg);
void dbg_print(LLONG mask, const char *fmt, ...);
unsigned char *debug_608toASC(unsigned char *ccdata, int channel);
unsigned char *debug_608_to_ASC(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);

View File

@@ -46,7 +46,9 @@ struct encoder_cfg
int trim_subs; // " Remove spaces at sides? "
int sentence_cap ; // FIX CASE? = Fix case?
int splitbysentence; // Split text into complete sentences and prorate time?
#ifdef WITH_LIBCURL
char *curlposturl; // If out=curl, where do we send the data to?
#endif
int with_semaphore; // Write a .sem file on file open and delete it on close?
/* Credit stuff */

View File

@@ -53,7 +53,7 @@ struct ccx_common_timing_ctx *init_timing_ctx(struct ccx_common_timing_settings_
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->sync_pts = 0;
ctx->minimum_fts = 0;
ctx->sync_pts2fts_set = 0;
ctx->sync_pts2fts_fts = 0;
@@ -78,9 +78,9 @@ 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)),
dbg_print(CCX_DMT_VIDES, "PTS: %s (%8u)", print_mstime_static(ctx->current_pts/(MPEG_CLOCK_FREQ/1000)),
(unsigned) (ctx->current_pts));
dbg_print(CCX_DMT_VIDES, " FTS: %s \n",print_mstime(ctx->fts_now));
dbg_print(CCX_DMT_VIDES, " FTS: %s \n",print_mstime_static(ctx->fts_now));
}
int set_fts(struct ccx_common_timing_ctx *ctx)
@@ -159,7 +159,7 @@ int set_fts(struct ccx_common_timing_ctx *ctx)
*1000.0/current_fps);
}
ccx_common_logging.debug_ftn(CCX_DMT_TIME, "\nFirst sync time PTS: %s %+lldms (time before this PTS)\n",
print_mstime(ctx->min_pts/(MPEG_CLOCK_FREQ/1000)),
print_mstime_static(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);
@@ -189,7 +189,7 @@ int set_fts(struct ccx_common_timing_ctx *ctx)
ctx->min_pts = ctx->sync_pts;
ccx_common_logging.debug_ftn(CCX_DMT_TIME, "\nNew min PTS time: %s %+lldms (time before this PTS)\n",
print_mstime(ctx->min_pts/(MPEG_CLOCK_FREQ/1000)),
print_mstime_static(ctx->min_pts/(MPEG_CLOCK_FREQ/1000)),
ctx->fts_offset );
}
}
@@ -265,32 +265,11 @@ LLONG get_fts_max(struct ccx_common_timing_ctx *ctx)
return ctx->fts_max + ctx->fts_global;
}
/* Fill a static buffer with a time string (hh:mm:ss:ms) corresponding
to the microsecond value in mstime. */
char *print_mstime2buf( LLONG mstime , char *buf )
{
unsigned hh,mm,ss,ms;
int signoffset = (mstime < 0 ? 1 : 0);
if (mstime<0) // Avoid loss of data warning with abs()
mstime=-mstime;
hh = (unsigned) (mstime/1000/60/60);
mm = (unsigned) (mstime/1000/60 - 60*hh);
ss = (unsigned) (mstime/1000 - 60*(mm + 60*hh));
ms = (int) (mstime - 1000*(ss + 60*(mm + 60*hh)));
buf[0]='-';
sprintf (buf+signoffset, "%02u:%02u:%02u:%03u",hh,mm,ss,ms);
return buf;
}
/**
* Fill buffer with a time string using specified format
* @param fmt has to contain 4 format specifiers for h, m, s and ms respectively
*/
size_t mstime_sprintf(LLONG mstime, char *fmt, char *buf)
{
size_t print_mstime_buff(LLONG mstime, char* fmt, char* buf){
unsigned hh, mm, ss, ms;
int signoffset = (mstime < 0 ? 1 : 0);
@@ -303,16 +282,17 @@ size_t mstime_sprintf(LLONG mstime, char *fmt, char *buf)
ms = (unsigned) (mstime - 1000 * (ss + 60 * (mm + 60 * hh)));
buf[0] = '-';
return (size_t) sprintf(buf + signoffset, fmt, hh, mm, ss, ms);
}
/* Fill a static buffer with a time string (hh:mm:ss:ms) corresponding
to the microsecond value in mstime. */
char *print_mstime( LLONG mstime )
char *print_mstime_static( LLONG mstime )
{
static char buf[15]; // 14 should be long enough
return print_mstime2buf (mstime, buf);
print_mstime_buff(mstime, "%02u:%02u:%02u:%03u", buf);
return buf;
}
/* Helper function for to display debug timing info. */
@@ -323,8 +303,8 @@ void print_debug_timing(struct ccx_common_timing_ctx *ctx)
LLONG tempmin_pts = (ctx->min_pts==0x01FFFFFFFFLL ? ctx->sync_pts : ctx->min_pts);
ccx_common_logging.log_ftn("Sync time stamps: PTS: %s ",
print_mstime((ctx->sync_pts)/(MPEG_CLOCK_FREQ/1000)) );
ccx_common_logging.log_ftn("GOP: %s \n", print_mstime(gop_time.ms));
print_mstime_static((ctx->sync_pts)/(MPEG_CLOCK_FREQ/1000)) );
ccx_common_logging.log_ftn("GOP: %s \n", print_mstime_static(gop_time.ms));
// Length first GOP to last GOP
LLONG goplenms = (LLONG) (gop_time.ms - first_gop_time.ms);
@@ -333,9 +313,9 @@ void print_debug_timing(struct ccx_common_timing_ctx *ctx)
+ ctx->fts_offset);
ccx_common_logging.log_ftn("Last FTS: %s",
print_mstime(get_fts_max(ctx)));
print_mstime_static(get_fts_max(ctx)));
ccx_common_logging.log_ftn(" GOP start FTS: %s\n",
print_mstime(fts_at_gop_start));
print_mstime_static(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",

View File

@@ -47,7 +47,7 @@ struct ccx_common_timing_ctx
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_fts;
LLONG sync_pts2fts_pts;
};
// Count 608 (per field) and 708 blocks since last set_fts() call
@@ -78,9 +78,8 @@ void add_current_pts(struct ccx_common_timing_ctx *ctx, LLONG pts);
int set_fts(struct ccx_common_timing_ctx *ctx);
LLONG get_fts(struct ccx_common_timing_ctx *ctx, int current_field);
LLONG get_fts_max(struct ccx_common_timing_ctx *ctx);
char *print_mstime(LLONG mstime);
char *print_mstime2buf(LLONG mstime, char *buf);
size_t mstime_sprintf(LLONG mstime, char *fmt, char *buf);
char *print_mstime_static(LLONG mstime);
size_t print_mstime_buff(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);

View File

@@ -1210,7 +1210,7 @@ int process608(const unsigned char *data, int length, void *private_data, struct
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(dec_ctx->timing, context->my_field)));
ccx_common_logging.debug_ftn(CCX_DMT_DECODER_608, "Current FTS: %s\n", print_mstime_static(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",
@@ -1237,7 +1237,7 @@ int process608(const unsigned char *data, int length, void *private_data, struct
/* Return a pointer to a string that holds the printable characters
* of the caption data block. FOR DEBUG PURPOSES ONLY! */
unsigned char *debug_608toASC (unsigned char *cc_data, int channel)
unsigned char *debug_608_to_ASC (unsigned char *cc_data, int channel)
{
static unsigned char output[3];

View File

@@ -105,7 +105,7 @@ ccx_dtvcc_pen_attribs ccx_dtvcc_default_pen_attribs =
};
ccx_dtvcc_window_attribs ccx_dtvcc_predefined_window_styles[] =
{
{
{0,0,0,0,0,0,0,0,0,0, 0}, // Dummy, unused (position 0 doesn't use the table)
{//1 - NTSC Style PopUp Captions
CCX_DTVCC_WINDOW_JUSTIFY_LEFT,
@@ -296,8 +296,8 @@ void _dtvcc_window_dump(ccx_dtvcc_service_decoder *decoder, ccx_dtvcc_window *wi
char tbuf1[SUBLINESIZE],
tbuf2[SUBLINESIZE];
print_mstime2buf(window->time_ms_show, tbuf1);
print_mstime2buf(window->time_ms_hide, tbuf2);
print_mstime_buff(window->time_ms_show, "%02u:%02u:%02u:%03u", tbuf1);
print_mstime_buff(window->time_ms_hide, "%02u:%02u:%02u:%03u", tbuf2);
ccx_common_logging.debug_ftn(CCX_DMT_GENERIC_NOTICES, "\r%s --> %s\n", tbuf1, tbuf2);
for (int i = 0; i < CCX_DTVCC_MAX_ROWS; i++)
@@ -366,7 +366,7 @@ void _dtvcc_window_update_time_show(ccx_dtvcc_window *window, struct ccx_common_
{
char buf[128];
window->time_ms_show = get_visible_start(timing, 3);
print_mstime2buf(window->time_ms_show, buf);
print_mstime_buff(window->time_ms_show, "%02u:%02u:%02u:%03u", buf);
ccx_common_logging.debug_ftn(CCX_DMT_708, "[CEA-708] "
"[W-%d] show time updated to %s\n", window->number, buf);
}
@@ -375,7 +375,7 @@ void _dtvcc_window_update_time_hide(ccx_dtvcc_window *window, struct ccx_common_
{
char buf[128];
window->time_ms_hide = get_visible_end(timing, 3);
print_mstime2buf(window->time_ms_hide, buf);
print_mstime_buff(window->time_ms_hide, "%02u:%02u:%02u:%03u", buf);
ccx_common_logging.debug_ftn(CCX_DMT_708, "[CEA-708] "
"[W-%d] hide time updated to %s\n", window->number, buf);
}
@@ -383,8 +383,8 @@ void _dtvcc_window_update_time_hide(ccx_dtvcc_window *window, struct ccx_common_
void _dtvcc_screen_update_time_show(dtvcc_tv_screen *tv, LLONG time)
{
char buf1[128], buf2[128];
print_mstime2buf(tv->time_ms_show, buf1);
print_mstime2buf(time, buf2);
print_mstime_buff(tv->time_ms_show, "%02u:%02u:%02u:%03u", buf1);
print_mstime_buff(time, "%02u:%02u:%02u:%03u", buf2);
ccx_common_logging.debug_ftn(CCX_DMT_708, "[CEA-708] "
"Screen show time: %s -> %s\n", buf1, buf2);
@@ -397,8 +397,8 @@ void _dtvcc_screen_update_time_show(dtvcc_tv_screen *tv, LLONG time)
void _dtvcc_screen_update_time_hide(dtvcc_tv_screen *tv, LLONG time)
{
char buf1[128], buf2[128];
print_mstime2buf(tv->time_ms_hide, buf1);
print_mstime2buf(time, buf2);
print_mstime_buff(tv->time_ms_hide, "%02u:%02u:%02u:%03u", buf1);
print_mstime_buff(time, "%02u:%02u:%02u:%03u", buf2);
ccx_common_logging.debug_ftn(CCX_DMT_708, "[CEA-708] "
"Screen hide time: %s -> %s\n", buf1, buf2);
@@ -897,9 +897,9 @@ void dtvcc_handle_DFx_DefineWindow(ccx_dtvcc_service_decoder *decoder, int windo
pen_style = 1;
}
//Apply windows attribute presets
//Apply windows attribute presets
if (win_style > 0 && win_style < 8)
window->win_style = win_style; {
window->attribs.border_color = ccx_dtvcc_predefined_window_styles[win_style].border_color;
window->attribs.border_type = ccx_dtvcc_predefined_window_styles[win_style].border_type;
@@ -913,7 +913,7 @@ void dtvcc_handle_DFx_DefineWindow(ccx_dtvcc_service_decoder *decoder, int windo
window->attribs.scroll_direction = ccx_dtvcc_predefined_window_styles[win_style].scroll_direction;
window->attribs.word_wrap = ccx_dtvcc_predefined_window_styles[win_style].word_wrap;
}
if (pen_style > 0)
{
//TODO apply static pen_style preset
@@ -955,7 +955,7 @@ void dtvcc_handle_DFx_DefineWindow(ccx_dtvcc_service_decoder *decoder, int windo
_dtvcc_window_apply_style(window, &ccx_dtvcc_predefined_window_styles[0]);
}
}
else
else
{
if (do_clear_window)
_dtvcc_window_clear_text(window);
@@ -1312,7 +1312,7 @@ int _dtvcc_handle_C1(ccx_dtvcc_ctx *dtvcc,
{
struct CCX_DTVCC_S_COMMANDS_C1 com = DTVCC_COMMANDS_C1[data[0] - 0x80];
ccx_common_logging.debug_ftn(CCX_DMT_708, "[CEA-708] C1: %s | [%02X] [%s] [%s] (%d)\n",
print_mstime(get_fts(dtvcc->timing, 3)),
print_mstime_static(get_fts(dtvcc->timing, 3)),
data[0], com.name, com.description, com.length);
if (com.length > data_length)

View File

@@ -144,10 +144,10 @@ void ccx_dtvcc_write_srt(ccx_dtvcc_writer_ctx *writer, dtvcc_tv_screen *tv, stru
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,
print_mstime_buff(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,
print_mstime_buff(tv->time_ms_hide + encoder->subs_delay,
"%02u:%02u:%02u,%03u", buf + strlen(buf));
sprintf(buf + strlen(buf),"%s", (char *) encoder->encoded_crlf);
@@ -173,8 +173,8 @@ 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);
print_mstime_buff(tv->time_ms_show, "%02u:%02u:%02u:%03u", tbuf1);
print_mstime_buff(tv->time_ms_hide, "%02u:%02u:%02u:%03u", 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++)
@@ -207,11 +207,11 @@ void ccx_dtvcc_write_transcript(ccx_dtvcc_writer_ctx *writer, dtvcc_tv_screen *t
buf[0] = 0;
if (encoder->transcript_settings->showStartTime)
mstime_sprintf(tv->time_ms_show + encoder->subs_delay,
print_mstime_buff(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,
print_mstime_buff(tv->time_ms_hide + encoder->subs_delay,
"%02u:%02u:%02u,%03u|", buf + strlen(buf));
if (encoder->transcript_settings->showCC)

View File

@@ -25,7 +25,7 @@ LLONG get_visible_start (struct ccx_common_timing_ctx *ctx, int current_field)
LLONG fts = get_fts(ctx, current_field);
if (fts <= ctx->minimum_fts)
fts = ctx->minimum_fts + 1;
ccx_common_logging.debug_ftn(CCX_DMT_DECODER_608, "Visible Start time=%s\n", print_mstime(fts));
ccx_common_logging.debug_ftn(CCX_DMT_DECODER_608, "Visible Start time=%s\n", print_mstime_static(fts));
return fts;
}
@@ -35,7 +35,7 @@ LLONG get_visible_end (struct ccx_common_timing_ctx *ctx, int current_field)
LLONG fts = get_fts(ctx, current_field);
if (fts > ctx->minimum_fts)
ctx->minimum_fts = fts;
ccx_common_logging.debug_ftn(CCX_DMT_DECODER_608, "Visible End time=%s\n", print_mstime(fts));
ccx_common_logging.debug_ftn(CCX_DMT_DECODER_608, "Visible End time=%s\n", print_mstime_static(fts));
return fts;
}
@@ -102,7 +102,7 @@ int do_cb (struct lib_cc_decode *ctx, unsigned char *cc_block, struct cc_subtitl
return 1;
// Print raw data with FTS.
dbg_print(CCX_DMT_CBRAW, "%s %d %02X:%c%c:%02X", print_mstime(ctx->timing->fts_now + ctx->timing->fts_global),in_xds_mode,
dbg_print(CCX_DMT_CBRAW, "%s %d %02X:%c%c:%02X", print_mstime_static(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
@@ -118,7 +118,7 @@ int do_cb (struct lib_cc_decode *ctx, unsigned char *cc_block, struct cc_subtitl
switch (cc_type)
{
case 0:
dbg_print(CCX_DMT_CBRAW, " %s .. ..\n", debug_608toASC( cc_block, 0));
dbg_print(CCX_DMT_CBRAW, " %s .. ..\n", debug_608_to_ASC( cc_block, 0));
ctx->current_field = 1;
ctx->saw_caption_block = 1;
@@ -142,7 +142,7 @@ int do_cb (struct lib_cc_decode *ctx, unsigned char *cc_block, struct cc_subtitl
cb_field1++;
break;
case 1:
dbg_print(CCX_DMT_CBRAW, " .. %s ..\n", debug_608toASC( cc_block, 1));
dbg_print(CCX_DMT_CBRAW, " .. %s ..\n", debug_608_to_ASC( cc_block, 1));
ctx->current_field = 2;
ctx->saw_caption_block = 1;
@@ -350,7 +350,7 @@ struct lib_cc_decode* init_cc_decode (struct ccx_decoders_common_settings_t *set
ctx->pulldownfields = 0;
//es parser related variable ends here
memset(ctx->cc_stats, 0, 4 * sizeof(int));
memset(ctx->cc_stats, 0, 4 * sizeof(int));
ctx->anchor_seq_number = -1;
// Init XDS buffers

View File

@@ -385,7 +385,7 @@ static int write_bom(struct encoder_ctx *ctx, struct ccx_s_write *out)
mprint("WARNING: Unable tp write UTF BOM\n");
return -1;
}
}
if (ctx->encoding == CCX_ENC_UNICODE){ // Write BOM
ret = write(out->fh, LITTLE_ENDIAN_BOM, sizeof(LITTLE_ENDIAN_BOM));
@@ -946,7 +946,7 @@ struct encoder_ctx *init_encoder(struct encoder_cfg *opt)
ctx->transcript_settings = &opt->transcript_settings;
ctx->no_bom = opt->no_bom;
ctx->sentence_cap = opt->sentence_cap;
ctx->sentence_cap = opt->sentence_cap;
ctx->trim_subs = opt->trim_subs;
ctx->autodash = opt->autodash;
ctx->no_font_color = opt->no_font_color;
@@ -957,14 +957,10 @@ struct encoder_ctx *init_encoder(struct encoder_cfg *opt)
ctx->force_flush = opt->force_flush;
ctx->ucla = opt->ucla;
ctx->splitbysentence = opt->splitbysentence;
ctx->sbs_newblock_start_time = -1;
ctx->sbs_newblock_end_time = -1;
ctx->sbs_newblock = NULL;
ctx->sbs_newblock_capacity = 0;
ctx->sbs_newblock_size = 0;
ctx->sbs_time_from = -1;
ctx->sbs_time_trim = -1;
ctx->sbs_capacity = 0;
ctx->sbs_buffer = NULL;
ctx->sbs_buffer_capacity = 0;
ctx->sbs_buffer_size = 0;
ctx->subline = (unsigned char *) malloc (SUBLINESIZE);
if(!ctx->subline)
@@ -1045,11 +1041,13 @@ int encode_sub(struct encoder_ctx *context, struct cc_subtitle *sub)
// Write to a buffer that is later s+plit to generate split
// in sentences
if (sub->type == CC_BITMAP)
wrote_something = write_cc_bitmap_to_sentence_buffer(sub, context);
sub = reformat_cc_bitmap_through_sentence_buffer(sub, context);
if (NULL==sub)
return wrote_something;
}
else
{
// Write subtitles as they come
// Write subtitles as they come
if (sub->type == CC_608)
{
struct eia608_screen *data = NULL;
@@ -1249,7 +1247,7 @@ int encode_sub(struct encoder_ctx *context, struct cc_subtitle *sub)
}
sub->nb_data = 0;
}
}
if (!sub->nb_data)
freep(&sub->data);
if (wrote_something && context->force_flush)
@@ -1286,8 +1284,8 @@ void write_cc_buffer_to_gui(struct eia608_screen *data, struct encoder_ctx *cont
if (!time_reported)
{
LLONG ms_end = data->end_time;
mstotime(ms_start, &h1, &m1, &s1, &ms1);
mstotime(ms_end - 1, &h2, &m2, &s2, &ms2); // -1 To prevent overlapping with next line.
millis_to_time(ms_start, &h1, &m1, &s1, &ms1);
millis_to_time(ms_end - 1, &h2, &m2, &s2, &ms2); // -1 To prevent overlapping with next line.
// Note, only MM:SS here as we need to save space in the preview window
fprintf(stderr, "%02u:%02u#%02u:%02u#",
h1 * 60 + m1, s1, h2 * 60 + m2, s2);

View File

@@ -62,7 +62,7 @@ struct encoder_ctx
/* 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;
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 */
@@ -118,15 +118,14 @@ struct encoder_ctx
/* split-by-sentence stuff */
int splitbysentence;
LLONG sbs_newblock_start_time; // Used by the split-by-sentence code to know when the current block starts...
LLONG sbs_newblock_end_time; // ... and ends
ccx_sbs_utf8_character *sbs_newblock;
int sbs_newblock_capacity;
int sbs_newblock_size;
ccx_sbs_utf8_character *sbs_buffer;
int sbs_buffer_capacity;
int sbs_buffer_size;
unsigned char * sbs_buffer; /// Storage for sentence-split buffer
size_t sbs_handled_len; /// The length of the string in the SBS-buffer, already handled, but preserved for DUP-detection.
//ccx_sbs_utf8_character *sbs_newblock;
LLONG sbs_time_from; // Used by the split-by-sentence code to know when the current block starts...
LLONG sbs_time_trim; // ... and ends
size_t sbs_capacity;
};
#define INITIAL_ENC_BUFFER_CAPACITY 2048
@@ -196,10 +195,9 @@ int write_cc_bitmap_as_sami (struct cc_subtitle *sub, struct encoder_
int write_cc_bitmap_as_smptett (struct cc_subtitle *sub, struct encoder_ctx *context);
int write_cc_bitmap_as_spupng (struct cc_subtitle *sub, struct encoder_ctx *context);
int write_cc_bitmap_as_transcript (struct cc_subtitle *sub, struct encoder_ctx *context);
int write_cc_bitmap_to_sentence_buffer (struct cc_subtitle *sub, struct encoder_ctx *context);
int write_cc_bitmap_as_libcurl (struct cc_subtitle *sub, struct encoder_ctx *context);
struct cc_subtitle * reformat_cc_bitmap_through_sentence_buffer (struct cc_subtitle *sub, struct encoder_ctx *context);
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);

View File

@@ -56,8 +56,8 @@ int write_cc_bitmap_as_libcurl(struct cc_subtitle *sub, struct encoder_ctx *cont
{
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.
millis_to_time(ms_start, &h1, &m1, &s1, &ms1);
millis_to_time(ms_end - 1, &h2, &m2, &s2, &ms2); // -1 To prevent overlapping with next line.
context->srt_counter++;
sprintf(timeline, "group_id=ccextractordev&start_time=%" PRIu64 "&end_time=%" PRIu64 "&lang=en", ms_start, ms_end);
char *curlline = NULL;
@@ -68,8 +68,12 @@ int write_cc_bitmap_as_libcurl(struct cc_subtitle *sub, struct encoder_ctx *cont
curl_free (urlencoded);
mprint("%s", curlline);
curl_easy_setopt(curl, CURLOPT_URL, "127.0.0.1:3000/frame/");
char *result = malloc(strlen(ccx_options.curlposturl) + strlen("/frame/") + 1);
strcpy(result, ccx_options.curlposturl);
strcat(result, "/frame/");
curl_easy_setopt(curl, CURLOPT_URL, result);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, curlline);
free(result);
res = curl_easy_perform(curl);
/* Check for errors */

View File

@@ -76,8 +76,8 @@ int write_cc_buffer_as_g608(struct eia608_screen *data, struct encoder_ctx *cont
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.
millis_to_time (ms_start,&h1,&m1,&s1,&ms1);
millis_to_time (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);

View File

@@ -46,8 +46,8 @@ void write_stringz_as_smptett(char *string, struct encoder_ctx *context, LLONG m
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);
millis_to_time (ms_start, &h1, &m1, &s1, &ms1);
millis_to_time (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)
@@ -149,8 +149,8 @@ int write_cc_bitmap_as_smptett(struct cc_subtitle *sub, struct encoder_ctx *cont
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.
millis_to_time (ms_start,&h1,&m1,&s1,&ms1);
millis_to_time (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);
@@ -212,8 +212,8 @@ int write_cc_buffer_as_smptett(struct eia608_screen *data, struct encoder_ctx *c
endms = data->end_time;
endms--; // To prevent overlapping with next line.
mstotime (startms,&h1,&m1,&s1,&ms1);
mstotime (endms-1,&h2,&m2,&s2,&ms2);
millis_to_time (startms,&h1,&m1,&s1,&ms1);
millis_to_time (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);

View File

@@ -1,135 +1,462 @@
#include "ccx_decoders_common.h"
#include "ccx_common_platform.h"
#include "ccx_encoders_common.h"
#include "spupng_encoder.h"
#include "ccx_encoders_spupng.h"
#include "utility.h"
#include "lib_ccx.h"
#include "ocr.h"
#include "ccx_decoders_608.h"
#include "ccx_decoders_708.h"
#include "ccx_decoders_708_output.h"
#include "ccx_encoders_xds.h"
#include "ccx_encoders_helpers.h"
#include "utf8proc.h"
#ifdef DEBUG
#define LOG_DEBUG(...) printf(__VA_ARGS__)
#else
#define LOG_DEBUG ;
#endif
#ifdef ENABLE_SHARING
#include "ccx_share.h"
#endif //ENABLE_SHARING
void lbl_start_block(LLONG start_time, struct encoder_ctx *context)
int sbs_is_pointer_on_sentence_breaker(char * start, char * current)
{
context->sbs_newblock_start_time = start_time;
}
char c = *current;
char n = *(current + 1);
char p = *(current - 1);
void lbl_add_character(struct encoder_ctx *context, ccx_sbs_utf8_character ch)
{
if (context->sbs_newblock_capacity == context->sbs_newblock_size)
if (0 == c) n = 0;
if (current == start) p = 0;
if (0 == c) return 1;
if ('.' == c
|| '!' == c
|| '?' == c
)
{
int newcapacity = (context->sbs_newblock_capacity < 512) ? 1024 : context->sbs_newblock_capacity * 2;
context->sbs_newblock = (ccx_sbs_utf8_character *)realloc(context->sbs_newblock, newcapacity*sizeof(ccx_sbs_utf8_character));
if (!context->sbs_newblock)
fatal(EXIT_NOT_ENOUGH_MEMORY, "Not enough memory in lbl_add_character");
context->sbs_newblock_capacity = newcapacity;
if ('.' == n
|| '!' == n
|| '?' == n
)
{
return 0;
}
return 1;
}
memcpy(&context->sbs_newblock[context->sbs_newblock_size++], &ch, sizeof ch);
return 0;
}
void lbl_end_block(LLONG end_time, struct encoder_ctx *context)
int sbs_fuzzy_strncmp(const char * a, const char * b, size_t n, const size_t maxerr)
{
context->sbs_newblock_end_time = end_time;
// TODO: implement fuzzy comparing
// Error counter DOES NOT WORK!!!
int i;
//int err;
char A, B;
i = -1;
do
{
i++;
// Bound check (compare to N)
if (i == n) return 0;
A = a[i];
B = b[i];
// bound check (line endings)
if (A == 0)
{
if (B == 0) return 0;
return 1;
}
else
{
if (B == 0) return -1;
}
if (A == B) continue;
if (isspace(A) && isspace(B)) continue;
if (A > B) return 1;
return -1;
} while(1);
}
int write_cc_bitmap_to_sentence_buffer(struct cc_subtitle *sub, struct encoder_ctx *context)
void sbs_strcpy_without_dup(const unsigned char * str, struct encoder_ctx * context)
{
int intersect_len;
unsigned char * suffix;
const unsigned char * prefix = str;
unsigned long sbs_len;
unsigned long str_len;
str_len = strlen(str);
sbs_len = strlen(context->sbs_buffer);
intersect_len = str_len;
if (sbs_len < intersect_len)
intersect_len = sbs_len;
while (intersect_len>0)
{
suffix = context->sbs_buffer + sbs_len - intersect_len;
if (0 == sbs_fuzzy_strncmp(prefix, suffix, intersect_len, 1))
{
break;
}
intersect_len--;
}
LOG_DEBUG("Sentence Buffer: sbs_strcpy_without_dup, intersection len [%4d]\n", intersect_len);
// check, that new string does not contain data, from
// already handled sentence:
LOG_DEBUG("Sentence Buffer: sbs_strcpy_without_dup, sbslen [%4d] handled len [%4d]\n", sbs_len, context->sbs_handled_len);
if ( (sbs_len - intersect_len) >= context->sbs_handled_len)
{
// there is no intersection.
// It is time to clean the buffer. Excepting the last uncomplete sentence
strcpy(context->sbs_buffer, context->sbs_buffer + context->sbs_handled_len);
context->sbs_handled_len = 0;
sbs_len = strlen(context->sbs_buffer);
LOG_DEBUG("Sentence Buffer: Clean buffer, after BUF [%s]\n\n\n", context->sbs_buffer);
}
if (intersect_len > 0)
{
// there is a common part (suffix of old sentence equals to prefix of new str)
//
// remove dup from buffer
// we will use an appropriate part from the new string
context->sbs_buffer[sbs_len-intersect_len] = 0;
}
sbs_len = strlen(context->sbs_buffer);
// whitespace control. Add space between subs
if (
!isspace(str[0]) // not a space char in the beginning of new str
&& context->sbs_handled_len >0 // buffer is not empty (there is uncomplete sentence)
&& !isspace(context->sbs_buffer[sbs_len-1]) // not a space char at the end of existing buf
)
{
//strcat(context->sbs_buffer, " ");
}
strcat(context->sbs_buffer, str);
}
void sbs_str_autofix(unsigned char * str)
{
int i;
// replace all whitespaces with spaces:
for (i = 0; str[i] != 0; i++)
{
if (isspace(str[i]))
{
str[i] = ' ';
}
if (
str[i] == '|'
&& (i==0 || isspace(str[i-1]))
&& (str[i+1] == 0 || isspace(str[i+1]) || str[i+1]=='\'')
)
{
// try to convert to "I"
str[i] = 'I';
}
}
}
/**
* Appends the function to the sentence buffer, and returns a list of full sentences (if there are any), or NULL
*
* @param str Partial (or full) sub to append.
* @param time_from Starting timestamp
* @param time_trim Ending timestamp
* @param context Encoder context
* @return New <struct cc_subtitle *> subtitle, or NULL, if <str> doesn't contain the ending part of the sentence. If there are more than one sentence, the remaining sentences will be chained using <result->next> reference.
*/
struct cc_subtitle * sbs_append_string(unsigned char * str, const LLONG time_from, const LLONG time_trim, struct encoder_ctx * context)
{
struct cc_subtitle * resub;
struct cc_subtitle * tmpsub;
unsigned char * bp_current;
unsigned char * bp_last_break;
unsigned char * sbs_undone_start;
int is_buf_initialized;
int required_capacity;
int new_capacity;
LLONG alphanum_total;
LLONG alphanum_cur;
LLONG anychar_total;
LLONG anychar_cur;
LLONG duration;
LLONG available_time;
int use_alphanum_counters;
if (! str)
return NULL;
sbs_str_autofix(str);
is_buf_initialized = (NULL == context->sbs_buffer || context->sbs_capacity == 0)
? 0
: 1;
// ===============================
// grow sentence buffer
// ===============================
required_capacity =
(is_buf_initialized ? strlen(context->sbs_buffer) : 0) // existing data in buf
+ strlen(str) // length of new string
+ 1 // trailing \0
+ 1 // space control (will add one space , if required)
;
if (required_capacity >= context->sbs_capacity)
{
new_capacity = context->sbs_capacity;
if (! is_buf_initialized) new_capacity = 16;
while (new_capacity < required_capacity)
{
// increase NEW_capacity, and check, that increment
// is less than 8 Mb. Because 8Mb - it is a lot
// for a TEXT buffer. It is weird...
new_capacity += (new_capacity > 1048576 * 8)
? 1048576 * 8
: new_capacity;
}
context->sbs_buffer = (unsigned char *)realloc(
context->sbs_buffer,
new_capacity * sizeof(/*unsigned char*/ context->sbs_buffer[0] )
);
if (!context->sbs_buffer)
fatal(EXIT_NOT_ENOUGH_MEMORY, "Not enough memory in sbs_append_string");
context->sbs_capacity = new_capacity;
// if buffer wasn't initialized, we will se trash in buffer.
// but we need just empty string, so here we will get it:
if (! is_buf_initialized)
{
// INIT SBS
context->sbs_buffer[0] = 0;
context->sbs_handled_len = 0;
}
}
// ===============================
// append to buffer
//
// will update sbs_buffer, sbs_handled_len
// ===============================
sbs_strcpy_without_dup(str, context);
// ===============================
// break to sentences
// ===============================
resub = NULL;
tmpsub = NULL;
alphanum_total = 0;
alphanum_cur = 0;
anychar_total = 0;
anychar_cur = 0;
sbs_undone_start = context->sbs_buffer + context->sbs_handled_len;
bp_last_break = sbs_undone_start;
LOG_DEBUG("Sentence Buffer: BEFORE sentence break. Last break: [%s] sbs_undone_start: [%d], sbs_undone: [%s]\n",
bp_last_break, context->sbs_handled_len, sbs_undone_start
);
for (bp_current = sbs_undone_start; bp_current && *bp_current; bp_current++)
{
if (
0 < anychar_cur // skip empty!
&& sbs_is_pointer_on_sentence_breaker(bp_last_break, bp_current) )
{
// it is new sentence!
tmpsub = malloc(sizeof(struct cc_subtitle));
tmpsub->type = CC_TEXT;
// length of new string:
tmpsub->nb_data =
bp_current - bp_last_break
+ 1 // terminating '\0'
+ 1 // skip '.'
;
tmpsub->data = strndup(bp_last_break, tmpsub->nb_data - 1);
tmpsub->got_output = 1;
tmpsub->start_time = alphanum_cur;
alphanum_cur = 0;
tmpsub->end_time = anychar_cur;
anychar_cur = 0;
bp_last_break = bp_current + 1;
// tune last break:
while (
*bp_last_break
&& isspace(*bp_last_break)
)
{
bp_last_break++;
}
// ???
// tmpsub->info = NULL;
// tmpsub->mode = NULL;
// link with prev sub:
tmpsub->next = NULL;
tmpsub->prev = resub;
if (NULL != resub)
{
resub->next = tmpsub;
}
resub = tmpsub;
}
if (*bp_current && isalnum(*bp_current))
{
alphanum_total++;
alphanum_cur++;
}
anychar_total++;
anychar_cur++;
}
// ===============================
// okay, we have extracted several sentences, now we should
// save the position of the "remainder" - start of the last
// incomplete sentece
// ===============================
if (bp_last_break != sbs_undone_start)
{
context->sbs_handled_len = bp_last_break - sbs_undone_start;
}
LOG_DEBUG("Sentence Buffer: AFTER sentence break: Handled Len [%4d]\n", context->sbs_handled_len);
LOG_DEBUG("Sentence Buffer: Alphanum Total: [%4d] Overall chars: [%4d] STRING:[%20s] BUFFER:[%20s]\n", alphanum_total, anychar_total, str, context->sbs_buffer);
// ===============================
// Calculate time spans
// ===============================
if (!is_buf_initialized)
{
context->sbs_time_from = time_from;
context->sbs_time_trim = time_trim;
}
available_time = time_trim - context->sbs_time_from;
use_alphanum_counters = alphanum_total > 0 ? 1 : 0;
tmpsub = resub;
while (tmpsub)
{
alphanum_cur = tmpsub->start_time;
anychar_cur = tmpsub->end_time;
if (use_alphanum_counters)
{
duration = available_time * alphanum_cur / alphanum_total;
}
else
{
duration = available_time * anychar_cur / anychar_total;
}
tmpsub->start_time = context->sbs_time_from;
tmpsub->end_time = tmpsub->start_time + duration;
context->sbs_time_from = tmpsub->end_time + 1;
tmpsub = tmpsub->next;
}
return resub;
}
struct cc_subtitle * reformat_cc_bitmap_through_sentence_buffer(struct cc_subtitle *sub, struct encoder_ctx *context)
{
int ret = 0;
#ifdef ENABLE_OCR
struct cc_bitmap* rect;
LLONG ms_start, ms_end;
int used;
int i = 0;
char *str;
if (context->prev_start != -1 && (sub->flags & SUB_EOD_MARKER))
// this is a sub with a full sentence (or chain of such subs)
struct cc_subtitle * resub = NULL;
#ifdef ENABLE_OCR
if (sub->flags & SUB_EOD_MARKER)
{
ms_start = context->prev_start;
ms_end = sub->start_time;
// the last sub from input
if (context->prev_start == -1)
{
ms_start = 1;
ms_end = sub->start_time;
}
else
{
ms_start = context->prev_start;
ms_end = sub->start_time;
}
}
else if (!(sub->flags & SUB_EOD_MARKER))
else
{
// not the last sub from input
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 ret;
rect = sub->data;
return 0;
if (sub->flags & SUB_EOD_MARKER)
context->prev_start = sub->start_time;
if (rect[0].ocr_text && *(rect[0].ocr_text))
str = paraof_ocrtext(sub, " ", 1);
if (str)
{
lbl_start_block(ms_start, context);
if (context->prev_start != -1 || !(sub->flags & SUB_EOD_MARKER))
{
char *token = NULL;
token = paraof_ocrtext(sub, " ", 1); // Get text with spaces instead of newlines
uint32_t offset=0;
utf8proc_ssize_t ls; // Last size
char *s = token;
int32_t uc;
while ((ls=utf8proc_iterate(s, -1, &uc)))
{
ccx_sbs_utf8_character sbsc;
// Note: We don't care about uc here, since we will be writing the encoded bytes, not the code points in binary.
//TODO: Deal with ls < 0
if (!uc) // End of string
break;
printf("%3ld | %08X | %c %c %c %c\n", ls, uc, ((uc & 0xFF000000) >> 24), ((uc & 0xFF0000) >> 16),
((uc & 0xFF00) >> 8), ( uc & 0xFF));
sbsc.ch = uc;
sbsc.encoded[0] = 0; sbsc.encoded[1] = 0; sbsc.encoded[2] = 0; sbsc.encoded[3] = 0;
memcpy(sbsc.encoded, s, ls);
sbsc.enc_len = ls;
sbsc.ts = 0; // We don't know yet
lbl_add_character(context, sbsc);
s += ls;
// TO-DO: Add each of these characters to the buffer, splitting the timestamps. Remember to add character length to the array
}
printf("-------\n");
/*
while (token)
{
char *newline_pos = strstr(token, context->encoded_crlf);
if (!newline_pos)
{
fdprintf(context->out->fh, "%s", token);
break;
}
else
{
while (token != newline_pos)
{
fdprintf(context->out->fh, "%c", *token);
token++;
}
token += context->encoded_crlf_length;
fdprintf(context->out->fh, "%c", ' ');
}
}*/
resub = sbs_append_string(str, ms_start, ms_end, context);
}
lbl_end_block(ms_end, context);
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;
return resub;
}

View File

@@ -17,8 +17,8 @@ int write_stringz_as_srt(char *string, struct encoder_ctx *context, LLONG ms_sta
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.
millis_to_time (ms_start,&h1,&m1,&s1,&ms1);
millis_to_time (ms_end-1,&h2,&m2,&s2,&ms2); // -1 To prevent overlapping with next line.
context->srt_counter++;
sprintf(timeline, "%u%s", context->srt_counter, context->encoded_crlf);
used = encode_line(context, context->buffer,(unsigned char *) timeline);
@@ -118,8 +118,8 @@ int write_cc_bitmap_as_srt(struct cc_subtitle *sub, struct encoder_ctx *context)
{
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.
millis_to_time (ms_start,&h1,&m1,&s1,&ms1);
millis_to_time (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, context->buffer,(unsigned char *) timeline);
@@ -202,8 +202,8 @@ int write_cc_buffer_as_srt(struct eia608_screen *data, struct encoder_ctx *conte
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.
millis_to_time (ms_start,&h1,&m1,&s1,&ms1);
millis_to_time (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);

View File

@@ -15,8 +15,8 @@ int write_stringz_as_ssa(char *string, struct encoder_ctx *context, LLONG ms_sta
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.
millis_to_time (ms_start,&h1,&m1,&s1,&ms1);
millis_to_time (ms_end-1,&h2,&m2,&s2,&ms2); // -1 To prevent overlapping with next line.
sprintf (timeline, "Dialogue: 0,%02u:%02u:%02u.%01u,%02u:%02u:%02u.%02u,Default,,0000,0000,0000,,",
h1, m1, s1, ms1 / 10, h2, m2, s2, ms2 / 10);
@@ -113,8 +113,8 @@ int write_cc_bitmap_as_ssa(struct cc_subtitle *sub, struct encoder_ctx *context)
{
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.
millis_to_time (ms_start,&h1,&m1,&s1,&ms1);
millis_to_time (ms_end-1,&h2,&m2,&s2,&ms2); // -1 To prevent overlapping with next line.
sprintf (timeline, "Dialogue: 0,%02u:%02u:%02u.%01u,%02u:%02u:%02u.%02u,Default,,0000,0000,0000,,",
h1,m1,s1,ms1/10, h2,m2,s2,ms2/10);
@@ -193,8 +193,8 @@ int write_cc_buffer_as_ssa(struct eia608_screen *data, struct encoder_ctx *conte
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.
millis_to_time (ms_start,&h1,&m1,&s1,&ms1);
millis_to_time (ms_end-1,&h2,&m2,&s2,&ms2); // -1 To prevent overlapping with next line.
char timeline[128];
sprintf (timeline, "Dialogue: 0,%02u:%02u:%02u.%01u,%02u:%02u:%02u.%02u,Default,,0000,0000,0000,,",
h1, m1, s1, ms1 / 10, h2, m2, s2, ms2 / 10);
@@ -291,4 +291,3 @@ int write_cc_buffer_as_ssa(struct eia608_screen *data, struct encoder_ctx *conte
write (context->out->fh, context->encoded_crlf, context->encoded_crlf_length);
return wrote_something;
}

View File

@@ -59,7 +59,7 @@ int write_cc_bitmap_as_transcript(struct cc_subtitle *sub, struct encoder_ctx *c
}
else
{
mstotime(start_time + context->subs_delay, &h1, &m1, &s1, &ms1);
millis_to_time(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);
@@ -375,4 +375,3 @@ int write_cc_buffer_as_transcript2(struct eia608_screen *data, struct encoder_ct
dbg_print(CCX_DMT_DECODER_608, "- - - - - - - - - - - -\r\n");
return wrote_something;
}

View File

@@ -16,8 +16,8 @@ int write_stringz_as_webvtt(char *string, struct encoder_ctx *context, LLONG ms_
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.
millis_to_time(ms_start, &h1, &m1, &s1, &ms1);
millis_to_time(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);
@@ -98,9 +98,9 @@ int write_xtimestamp_header(struct encoder_ctx *context)
char header_string[200];
int used;
unsigned h1, m1, s1, ms1;
mstotime(context->timing->sync_pts2fts_fts, &h1, &m1, &s1, &ms1);
millis_to_time(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,
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);
@@ -155,8 +155,8 @@ int write_cc_bitmap_as_webvtt(struct cc_subtitle *sub, struct encoder_ctx *conte
{
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.
millis_to_time(ms_start, &h1, &m1, &s1, &ms1);
millis_to_time(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);
@@ -239,8 +239,8 @@ int write_cc_buffer_as_webvtt(struct eia608_screen *data, struct encoder_ctx *co
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.
millis_to_time(ms_start, &h1, &m1, &s1, &ms1);
millis_to_time(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);
@@ -332,7 +332,7 @@ int write_cc_buffer_as_webvtt(struct eia608_screen *data, struct encoder_ctx *co
written = write(context->out->fh, context->subline, length);
if (written != length)
return -1;
written = write(context->out->fh,
written = write(context->out->fh,
context->encoded_crlf, context->encoded_crlf_length);
if (written != context->encoded_crlf_length)
return -1;

View File

@@ -35,7 +35,7 @@ void xds_write_transcript_line_prefix (struct encoder_ctx *context, struct ccx_s
{
if (utc_refvalue == UINT64_MAX)
{
mstotime(start_time + context->subs_delay, &h1, &m1, &s1, &ms1);
millis_to_time(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
@@ -46,7 +46,7 @@ void xds_write_transcript_line_prefix (struct encoder_ctx *context, struct ccx_s
}
else
{
mstotime(start_time + context->subs_delay, &h1, &m1, &s1, &ms1);
millis_to_time(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);
@@ -62,7 +62,7 @@ void xds_write_transcript_line_prefix (struct encoder_ctx *context, struct ccx_s
{
if (utc_refvalue == UINT64_MAX)
{
mstotime(end_time, &h2, &m2, &s2, &ms2);
millis_to_time(end_time, &h2, &m2, &s2, &ms2);
fdprintf(wb->fh, "%02u:%02u:%02u%c%03u|", h2, m2, s2, context->millis_separator, ms2);
}
else
@@ -72,7 +72,7 @@ void xds_write_transcript_line_prefix (struct encoder_ctx *context, struct ccx_s
}
else
{
mstotime(end_time, &h2, &m2, &s2, &ms2);
millis_to_time(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);
@@ -92,4 +92,3 @@ void xds_write_transcript_line_prefix (struct encoder_ctx *context, struct ccx_s
fdprintf(wb->fh, "%s|", XDSclasses_short[cur_xds_packet_class]);
}
}

View File

@@ -601,13 +601,13 @@ static int gop_header(struct lib_cc_decode *ctx, struct bitstream *esstream, str
{
mprint("\rWarning: Jump in GOP timing.\n");
mprint(" (old) %s",
print_mstime(gop_time.ms));
print_mstime_static(gop_time.ms));
mprint(" + %s (%uF)",
print_mstime((LLONG) (ctx->frames_since_last_gop
print_mstime_static((LLONG) (ctx->frames_since_last_gop
*1000.0/current_fps)),
ctx->frames_since_last_gop);
mprint(" != (new) %s\n",
print_mstime(gtc.ms));
print_mstime_static(gtc.ms));
}
if (first_gop_time.inited == 0)
@@ -731,7 +731,7 @@ static int read_pic_info(struct lib_cc_decode *ctx, struct bitstream *esstream,
dbg_print(CCX_DMT_VIDES, " t:%d r:%d p:%d", ctx->top_field_first,
ctx->repeat_first_field, ctx->progressive_frame);
dbg_print(CCX_DMT_VIDES, " FTS: %s\n", print_mstime(get_fts(ctx->timing, ctx->current_field)));
dbg_print(CCX_DMT_VIDES, " FTS: %s\n", print_mstime_static(get_fts(ctx->timing, ctx->current_field)));
// Set min_pts/sync_pts according to the current time stamp.
// Use fts_at_gop_start as reference when a GOP header was seen

View File

@@ -154,7 +154,7 @@ int user_data(struct lib_cc_decode *ctx, struct bitstream *ustream, int udtype,
unsigned field_number;
unsigned cc_data1;
unsigned cc_data2;
for (unsigned j=0;j<cc_count;j++)
{
skip_bits(ustream,2); // priority - unused
@@ -327,7 +327,7 @@ int user_data(struct lib_cc_decode *ctx, struct bitstream *ustream, int udtype,
dishdata[1]=dcd[1];
dishdata[2]=dcd[2];
dbg_print(CCX_DMT_PARSE, "%s", debug_608toASC( dishdata, 0) );
dbg_print(CCX_DMT_PARSE, "%s", debug_608_to_ASC( dishdata, 0) );
type=dcd[3]; // repeater (0x02 or 0x04)
hi = dishdata[1] & 0x7f; // Get only the 7 low bits
@@ -338,7 +338,7 @@ int user_data(struct lib_cc_decode *ctx, struct bitstream *ustream, int udtype,
dishdata[4]=dishdata[1];
dishdata[5]=dishdata[2];
dbg_print(CCX_DMT_PARSE, "%s:\n", debug_608toASC( dishdata+3, 0) );
dbg_print(CCX_DMT_PARSE, "%s:\n", debug_608_to_ASC( dishdata+3, 0) );
}
else
{
@@ -369,8 +369,8 @@ int user_data(struct lib_cc_decode *ctx, struct bitstream *ustream, int udtype,
dishdata[5]=dcd[4];
dishdata[6] = 0xFF; // Set end marker
dbg_print(CCX_DMT_PARSE, "%s", debug_608toASC( dishdata, 0) );
dbg_print(CCX_DMT_PARSE, "%s:\n", debug_608toASC( dishdata+3, 0) );
dbg_print(CCX_DMT_PARSE, "%s", debug_608_to_ASC( dishdata, 0) );
dbg_print(CCX_DMT_PARSE, "%s:\n", debug_608_to_ASC( dishdata+3, 0) );
store_hdcc(ctx, dishdata, cc_count, ctx->timing->current_tref, ctx->timing->fts_now, sub);
@@ -406,7 +406,7 @@ int user_data(struct lib_cc_decode *ctx, struct bitstream *ustream, int udtype,
type=dcd[0]; // repeater (0x02 or 0x04)
dcd++; // Skip the repeater byte.
dbg_print(CCX_DMT_PARSE, " - R:%02X :%s", type, debug_608toASC( dishdata, 0) );
dbg_print(CCX_DMT_PARSE, " - R:%02X :%s", type, debug_608_to_ASC( dishdata, 0) );
hi = dishdata[1] & 0x7f; // Get only the 7 low bits
if (type==0x04 && hi<32)
@@ -415,7 +415,7 @@ int user_data(struct lib_cc_decode *ctx, struct bitstream *ustream, int udtype,
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) );
dbg_print(CCX_DMT_PARSE, "%s:\n", debug_608_to_ASC( dishdata+3, 0) );
}
else
{
@@ -433,8 +433,8 @@ int user_data(struct lib_cc_decode *ctx, struct bitstream *ustream, int udtype,
dishdata[5]=dcd[1];
dishdata[6] = 0xFF; // Set end marker
dbg_print(CCX_DMT_PARSE, ":%s", debug_608toASC( dishdata, 0) );
dbg_print(CCX_DMT_PARSE, "%s:\n", debug_608toASC( dishdata+3, 0) );
dbg_print(CCX_DMT_PARSE, ":%s", debug_608_to_ASC( dishdata, 0) );
dbg_print(CCX_DMT_PARSE, "%s:\n", debug_608_to_ASC( dishdata+3, 0) );
}
store_hdcc(ctx, dishdata, cc_count, ctx->timing->current_tref, ctx->timing->fts_now, sub);
@@ -474,7 +474,7 @@ int user_data(struct lib_cc_decode *ctx, struct bitstream *ustream, int udtype,
uint8_t line_type;
uint8_t field = 1;
read_bytes(ustream, 4); //skip header code
read_bytes(ustream, 2); //skip data length
read_bytes(ustream, 2); //skip data length
line_nb = read_bits(ustream, 16);
line_type = read_u8(ustream);
field = (line_type & 0x03);
@@ -488,7 +488,7 @@ int user_data(struct lib_cc_decode *ctx, struct bitstream *ustream, int udtype,
if (udatalen < 720)
mprint("MPEG:VBI: Minimum 720 bytes in luma line required\n");
decode_vbi(ctx, field, ustream->pos, 720, sub);
decode_vbi(ctx, field, ustream->pos, 720, sub);
dbg_print(CCX_DMT_VERBOSE, "GXF (vbi line %d) user data:\n", line_nb);
}
else

View File

@@ -159,7 +159,7 @@ int ps_get_more_data(struct lib_ccx_ctx *ctx, struct demuxer_data ** ppdata)
continue;
}
//PES Header
//Private Stream 1 (non MPEG audio , subpictures)
//Private Stream 1 (non MPEG audio , subpictures)
else if (nextheader[3] == 0xBD)
{
uint16_t packetlength = (nextheader[4] << 8) | nextheader[5];
@@ -178,19 +178,19 @@ int ps_get_more_data(struct lib_ccx_ctx *ctx, struct demuxer_data ** ppdata)
buffered_skip(ctx->demux_ctx, (int)nextheader[6]);
ctx->demux_ctx->past += (int)nextheader[6];
//Substream ID
//Substream ID
ret = buffered_read(ctx->demux_ctx, nextheader+7, 1);
ctx->demux_ctx->past += 1;
if(ret != 1)
{
end_of_file = 1;
break;
break;
}
datalen = packetlength - 4 - nextheader[6];
// dbg_print(CCX_DMT_VERBOSE, "datalen :%d packetlen :%" PRIu16 " pes header ext :%d\n", datalen, packetlength, nextheader[6]);
//Subtitle substream ID 0x20 - 0x39 (32 possible)
//Subtitle substream ID 0x20 - 0x39 (32 possible)
if( nextheader[7] >= 0x20 && nextheader[7] < 0x40)
{
dbg_print(CCX_DMT_VERBOSE, "Subtitle found Stream id:%02x\n", nextheader[7]);
@@ -201,7 +201,7 @@ int ps_get_more_data(struct lib_ccx_ctx *ctx, struct demuxer_data ** ppdata)
end_of_file = 1;
break;
}
if (result>0)
if (result>0)
{
payload_read+=(int) result;
}
@@ -291,7 +291,7 @@ int ps_get_more_data(struct lib_ccx_ctx *ctx, struct demuxer_data ** ppdata)
{
continue;
}
data->bufferdatatype = CCX_PES;
result = buffered_read (ctx->demux_ctx, data->buffer+data->len, want);
@@ -655,7 +655,7 @@ int process_data(struct encoder_ctx *enc_ctx, struct lib_cc_decode *dec_ctx, str
got = process_m2v (dec_ctx, data_node->buffer, data_node->len, dec_sub);
}
else if (data_node->bufferdatatype == CCX_DVD_SUBTITLE)
{
{
if(dec_ctx-> is_alloc == 0)
{
dec_ctx->private_data = init_dvdsub_decode();
@@ -710,9 +710,9 @@ int process_data(struct encoder_ctx *enc_ctx, struct lib_cc_decode *dec_ctx, str
}
dbg_print(CCX_DMT_VIDES, "PTS: %s (%8u)",
print_mstime(dec_ctx->timing->current_pts/(MPEG_CLOCK_FREQ/1000)),
print_mstime_static(dec_ctx->timing->current_pts/(MPEG_CLOCK_FREQ/1000)),
(unsigned) (dec_ctx->timing->current_pts));
dbg_print(CCX_DMT_VIDES, " FTS: %s\n", print_mstime(get_fts(dec_ctx->timing, dec_ctx->current_field)));
dbg_print(CCX_DMT_VIDES, " FTS: %s\n", print_mstime_static(get_fts(dec_ctx->timing, dec_ctx->current_field)));
got = process_raw(dec_ctx, dec_sub, data_node->buffer, data_node->len);
}
@@ -876,7 +876,7 @@ void general_loop(struct lib_ccx_ctx *ctx)
dec_ctx->dtvcc->encoder = (void *)enc_ctx; //WARN: otherwise cea-708 will not work
if (enc_ctx)
enc_ctx->timing = dec_ctx->timing;
if(data_node->pts != CCX_NOPTS)
{
struct ccx_rational tb = {1,MPEG_CLOCK_FREQ};
@@ -979,7 +979,7 @@ void general_loop(struct lib_ccx_ctx *ctx)
// Flush remaining HD captions
if (dec_ctx->has_ccdata_buffered)
process_hdcc(dec_ctx, &dec_ctx->dec_sub);
mprint ("\nNumber of NAL_type_7: %ld\n",dec_ctx->avc_ctx->num_nal_unit_type_7);
mprint ("Number of VCL_HRD: %ld\n",dec_ctx->avc_ctx->num_vcl_hrd);
mprint ("Number of NAL HRD: %ld\n",dec_ctx->avc_ctx->num_nal_hrd);
@@ -1010,7 +1010,7 @@ void rcwt_loop(struct lib_ccx_ctx *ctx)
int bread = 0; // Bytes read
LLONG result;
struct encoder_ctx *enc_ctx = update_encoder_list(ctx);
// As BUFSIZE is a macro this is just a reminder
if (BUFSIZE < (3*0xFFFF + 10))
fatal (CCX_COMMON_EXIT_BUG_BUG, "BUFSIZE too small for RCWT caption block.\n");
@@ -1093,7 +1093,7 @@ void rcwt_loop(struct lib_ccx_ctx *ctx)
cbcount = *((uint16_t*)(parsebuf+8));
dbg_print(CCX_DMT_PARSE, "RCWT data header FTS: %s blocks: %u\n",
print_mstime(currfts), cbcount);
print_mstime_static(currfts), cbcount);
if ( cbcount > 0 )
{
@@ -1118,7 +1118,7 @@ void rcwt_loop(struct lib_ccx_ctx *ctx)
set_fts(dec_ctx->timing); // Now set the FTS related variables
for (int j=0; j<cbcount*3; j=j+3)
{
{
do_cb(dec_ctx, parsebuf+j, dec_sub);
}
}

View File

@@ -1,7 +1,7 @@
#ifndef CCX_CCEXTRACTOR_H
#define CCX_CCEXTRACTOR_H
#define VERSION "0.83"
#define VERSION "0.84"
// Load common includes and constants for library usage
#include "ccx_common_platform.h"

View File

@@ -10,7 +10,7 @@ void dinit_write(struct ccx_s_write *wb)
{
if (wb->fh > 0)
close(wb->fh);
freep(&wb->filename);
freep(&wb->filename);
if (wb->with_semaphore && wb->semaphore_filename)
unlink(wb->semaphore_filename);
freep(&wb->semaphore_filename);
@@ -49,7 +49,7 @@ int init_write (struct ccx_s_write *wb, char *filename, int with_semaphore)
{
memset(wb, 0, sizeof(struct ccx_s_write));
wb->fh=-1;
wb->temporarily_closed = 0;
wb->temporarily_closed = 0;
wb->filename = filename;
wb->with_semaphore = with_semaphore;
wb->append_mode = ccx_options.enc_cfg.append_mode;
@@ -223,7 +223,7 @@ void writercwtdata (struct lib_cc_decode *ctx, const unsigned char *data, struct
}
}
dbg_print(CCX_DMT_CBRAW, "%s Write %d RCWT blocks - skipped %d padding / %d unused blocks.\n",
print_mstime(prevfts), cbcount, storecbcount - cbcount, cbempty);
print_mstime_static(prevfts), cbcount, storecbcount - cbcount, cbempty);
}
// New FTS, write data header
@@ -287,7 +287,7 @@ void writercwtdata (struct lib_cc_decode *ctx, const unsigned char *data, struct
cbempty = 0;
dbg_print(CCX_DMT_CBRAW, "%s Write final padding RCWT blocks.\n",
print_mstime(currfts));
print_mstime_static(currfts));
}
prevfts = currfts;

View File

@@ -68,7 +68,7 @@ void store_hdcc(struct lib_cc_decode *ctx, unsigned char *cc_data, int cc_count,
printf("\nCC blocks, channel 0:\n");
for ( int i=0; i < cc_count*3; i+=3)
{
printf("%s", debug_608toASC( cc_data+i, 0) );
printf("%s", debug_608_to_ASC( cc_data+i, 0) );
}
printf("\n");
*/

59
tests/Makefile Normal file
View File

@@ -0,0 +1,59 @@
SHELL = /bin/sh
CC=gcc
# SYS := $(shell gcc -dumpmachine)
CFLAGS=-O0 -std=gnu99 -D ENABLE_OCR -g -ggdb -rdynamic
#-Q -da -v
# enable COVERAGE
# CFLAGS+=-fprofile-arcs -ftest-coverage
# add debug flag
ifdef DEBUG
CFLAGS+=-DDEBUG
endif
#ALL_FLAGS = -Wno-write-strings -D_FILE_OFFSET_BITS=64 -DVERSION_FILE_PRESENT
LDFLAGS=-lm -g
CFLAGS+=$(shell pkg-config --cflags check)
LDFLAGS+=$(shell pkg-config --libs check)
# TODO: need to rewrite this. Need new way to load sources for testing
SRC=$(wildcard ../src/lib_ccx/ccx_encoders_splitbysentence.c)
OBJS=
SRC_SUITE=$(wildcard *_suite.c)
OBJ_SUITE=$(patsubst %_suite.c, %_suite.o, $(SRC_SUITE))
OBJS+=$(OBJ_SUITE)
all: clean test
%.o: %.c
# explicit output name : -o $@
$(CC) -c $(ALL_FLAGS) $(CFLAGS) $<
runtest: $(OBJS)
@echo "+----------------------------------------------+"
@echo "| BUILD TESTS |"
@echo "+----------------------------------------------+"
$(CC) -c $(ALL_FLAGS) $(CFLAGS) $@.c
$(CC) $(SRC) $@.o $^ $(ALL_FLAGS) $(CFLAGS) $(LDFLAGS) -o $@
.PHONY: test
test: runtest
@echo "+----------------------------------------------+"
@echo "| START TESTS |"
@echo "+----------------------------------------------+"
./runtest
.PHONY: clean
clean:
rm runtest || true
rm *.o || true
# coverage info
rm *.gcda || true
rm *.gcno || true
# debug info
rm *.c.* || true

43
tests/README.md Normal file
View File

@@ -0,0 +1,43 @@
# UNIT TESTING
This folder contains a archetype and several unit-tests for CCExtractor
## RUN TESTS
```shell
cd tests
make
```
This will build and run all test-suite.
If you want MORE output:
```shell
DEBUG=1 make
```
Where `DEBUG` is just an environment variable.
## DEBUGGING
If tests failed after your changes, you could debug them (almost all flags for this are set in the `tests/Makefile`.
Run:
```shell
# build test runner
make
# load test runner to the debgger:
gdb runner
# run under debugger:
(gdb) run
# on segfault:
(gdb) where
```
## DEPENDENCIES
Tests are built around this library: [**libcheck**](https://github.com/libcheck/check), here is [**documentation**](https://libcheck.github.io/check/)

View File

@@ -0,0 +1,305 @@
#include <check.h>
#include "ccx_encoders_splitbysentence_suite.h"
// -------------------------------------
// MOCKS
// -------------------------------------
typedef int64_t LLONG;
#include "../src/lib_ccx/ccx_encoders_common.h"
// -------------------------------------
// Private SBS-functions (for testing only)
// -------------------------------------
struct cc_subtitle * sbs_append_string(unsigned char * str, LLONG time_from, LLONG time_trim, struct encoder_ctx * context);
// -------------------------------------
// Helpers
// -------------------------------------
struct cc_subtitle * helper_create_sub(char * str, LLONG time_from, LLONG time_trim)
{
struct cc_subtitle * sub = (struct cc_subtitle *)malloc(sizeof(struct cc_subtitle));
sub->type = CC_BITMAP;
sub->start_time = 1;
sub->end_time = 100;
sub->data = strdup(str);
sub->nb_data = strlen(sub->data);
return sub;
}
struct cc_subtitle * helper_sbs_append_string(char * str, LLONG time_from, LLONG time_trim, struct encoder_ctx * context)
{
char * str1;
struct cc_subtitle * sub;
str1 = strdup(str);
sub = sbs_append_string(str1, time_from, time_trim, context);
free(str1);
return sub;
}
// -------------------------------------
// MOCKS
// -------------------------------------
struct encoder_ctx * context;
void freep(void * obj){
}
void fatal(int x, void * obj){
}
unsigned char * paraof_ocrtext(void * sub) {
// this is OCR -> text converter.
// now, in our test cases, we will pass TEXT instead of OCR.
// and will return passed text as result
return ((struct cc_subtitle *)sub)->data;
}
// -------------------------------------
// TEST preparations
// -------------------------------------
void setup(void)
{
context = (struct encoder_ctx *)malloc(sizeof(struct encoder_ctx));
context->sbs_buffer = NULL;
context->sbs_capacity = 0;
}
void teardown(void)
{
free(context);
}
// -------------------------------------
// TESTS
// -------------------------------------
START_TEST(test_sbs_one_simple_sentence)
{
struct cc_subtitle * sub = helper_create_sub("Simple sentence.", 1, 100);
struct cc_subtitle * out = reformat_cc_bitmap_through_sentence_buffer(sub, context);
ck_assert_ptr_ne(out, NULL);
ck_assert_str_eq(out->data, "Simple sentence.");
ck_assert_ptr_eq(out->next, NULL);
ck_assert_ptr_eq(out->prev, NULL);
}
END_TEST
START_TEST(test_sbs_two_sentences_with_rep)
{
struct cc_subtitle * sub1 = helper_create_sub("asdf", 1, 100);
struct cc_subtitle * out1 = reformat_cc_bitmap_through_sentence_buffer(sub1, context);
ck_assert_ptr_eq(out1, NULL);
// second sub:
struct cc_subtitle * sub2 = helper_create_sub("asdf Hello.", 101, 200);
struct cc_subtitle * out2 = reformat_cc_bitmap_through_sentence_buffer(sub2, context);
ck_assert_ptr_ne(out2, NULL);
ck_assert_str_eq(out2->data, "asdf Hello.");
ck_assert_ptr_eq(out2->next, NULL);
ck_assert_ptr_eq(out2->prev, NULL);}
END_TEST
START_TEST(test_sbs_append_string_two_separate)
{
unsigned char * test_strings[] = {
"First string.",
"Second string."
};
struct cc_subtitle * sub;
unsigned char * str;
// first string
str = strdup(test_strings[0]);
sub = NULL;
sub = sbs_append_string(str, 1, 20, context);
ck_assert_ptr_ne(sub, NULL);
ck_assert_str_eq(sub->data, test_strings[0]);
ck_assert_int_eq(sub->start_time, 1);
ck_assert_int_eq(sub->end_time, 20);
// second string:
str = strdup(test_strings[1]);
sub = NULL;
sub = sbs_append_string(str, 21, 40, context);
ck_assert_ptr_ne(sub, NULL);
ck_assert_str_eq(sub->data, test_strings[1]);
ck_assert_int_eq(sub->start_time, 21);
ck_assert_int_eq(sub->end_time, 40);
}
END_TEST
START_TEST(test_sbs_append_string_two_with_broken_sentence)
{
// important !!
// summary len == 32
char * test_strings[] = {
"First string",
" ends here, deabbea."
};
struct cc_subtitle * sub;
char * str;
// first string
str = strdup(test_strings[0]);
sub = sbs_append_string(str, 1, 3, context);
ck_assert_ptr_eq(sub, NULL);
// second string:
str = strdup(test_strings[1]);
sub = sbs_append_string(str, 4, 5, context);
ck_assert_ptr_ne(sub, NULL);
ck_assert_str_eq(sub->data, "First string ends here, deabbea.");
ck_assert_int_eq(sub->start_time, 1);
ck_assert_int_eq(sub->end_time, 5);
}
END_TEST
START_TEST(test_sbs_append_string_two_intersecting)
{
char * test_strings[] = {
"First string",
"First string ends here."
};
struct cc_subtitle * sub;
char * str;
// first string
str = strdup(test_strings[0]);
sub = sbs_append_string(str, 1, 20, context);
ck_assert_ptr_eq(sub, NULL);
free(sub);
// second string:
str = strdup(test_strings[1]);
//printf("second string: [%s]\n", str);
sub = sbs_append_string(str, 21, 40, context);
ck_assert_ptr_ne(sub, NULL);
ck_assert_str_eq(sub->data, "First string ends here.");
ck_assert_int_eq(sub->start_time, 1);
ck_assert_int_eq(sub->end_time, 40);
}
END_TEST
START_TEST(test_sbs_append_string_real_data_1)
{
struct cc_subtitle * sub;
// 1
sub = helper_sbs_append_string("Oleon",
1, 0, context);
ck_assert_ptr_eq(sub, NULL);
// 2
sub = helper_sbs_append_string("Oleon costs.",
1, 189, context);
ck_assert_ptr_ne(sub, NULL);
ck_assert_str_eq(sub->data, "Oleon costs.");
// 3
sub = helper_sbs_append_string("buried in the annex, 95 Oleon costs.\n\
Didn't",
190, 889, context);
ck_assert_ptr_ne(sub, NULL);
ck_assert_str_eq(sub->data, "buried in the annex, 95 Oleon costs.");
ck_assert_int_eq(sub->start_time, 190); // = <sub start>
ck_assert_int_eq(sub->end_time, 783); // = <sub start> + <available time,889-190=699 > * <sentence alphanum, 28> / <sub alphanum, 33>
ck_assert_ptr_eq(sub->next, NULL);
// 4
sub = helper_sbs_append_string("buried in the annex, 95 Oleon costs.\n\
Didn't want",
890, 1129, context);
ck_assert_ptr_eq(sub, NULL);
// 5
sub = helper_sbs_append_string("buried in the annex, 95 Oleon costs.\n\
Didn't want to",
1130, 1359, context);
ck_assert_ptr_eq(sub, NULL);
// 6
sub = helper_sbs_append_string("buried in the annex, 95 Oleon costs.\n\
Didn't want to acknowledge",
1360, 2059, context);
ck_assert_ptr_eq(sub, NULL);
// 7
sub = helper_sbs_append_string("buried in the annex, 95 Oleon costs.\n\
Didn't want to acknowledge the",
2060, 2299, context);
ck_assert_ptr_eq(sub, NULL);
// 9
sub = helper_sbs_append_string("Didn't want to acknowledge the\n\
pressures on hospitals, schools and",
2300, 5019, context);
ck_assert_ptr_eq(sub, NULL);
// 13
sub = helper_sbs_append_string("pressures on hospitals, schools and\n\
infrastructure.",
5020, 5159, context);
ck_assert_ptr_ne(sub, NULL);
ck_assert_str_eq(sub->data, "Didn't want to acknowledge the pressures on hospitals, schools and infrastructure.");
ck_assert_int_eq(sub->start_time, 784);
ck_assert_int_eq(sub->end_time, 5159);
ck_assert_ptr_eq(sub->next, NULL);
// 14
sub = helper_sbs_append_string("pressures on hospitals, schools and\n\
infrastructure. If",
5160, 5529, context);
ck_assert_ptr_eq(sub, NULL);
// 16
sub = helper_sbs_append_string("pressures on hospitals, schools and\n\
infrastructure. If we go",
5530, 6559, context);
ck_assert_ptr_eq(sub, NULL);
// ck_assert_int_eq(sub->start_time, 1);
// ck_assert_int_eq(sub->end_time, 40);
}
END_TEST
Suite * ccx_encoders_splitbysentence_suite(void)
{
Suite *s;
TCase *tc_core;
s = suite_create("Sentence Buffer");
/* Overall tests */
tc_core = tcase_create("SB: Overall");
tcase_add_checked_fixture(tc_core, setup, teardown);
tcase_add_test(tc_core, test_sbs_one_simple_sentence);
tcase_add_test(tc_core, test_sbs_two_sentences_with_rep);
suite_add_tcase(s, tc_core);
/**/
TCase *tc_append_string;
tc_append_string = tcase_create("SB: append_string");
tcase_add_checked_fixture(tc_append_string, setup, teardown);
tcase_add_test(tc_append_string, test_sbs_append_string_two_separate);
tcase_add_test(tc_append_string, test_sbs_append_string_two_with_broken_sentence);
tcase_add_test(tc_append_string, test_sbs_append_string_two_intersecting);
tcase_add_test(tc_append_string, test_sbs_append_string_real_data_1);
suite_add_tcase(s, tc_append_string);
return s;
}

View File

@@ -0,0 +1,4 @@
// -------------------------------------
// SUITE
// -------------------------------------
Suite * ccx_encoders_splitbysentence_suite(void);

21
tests/runtest.c Normal file
View File

@@ -0,0 +1,21 @@
#include <check.h>
// TESTS:
#include "ccx_encoders_splitbysentence_suite.h"
int main(void)
{
int number_failed;
Suite *s;
SRunner *sr;
s = ccx_encoders_splitbysentence_suite();
sr = srunner_create(s);
srunner_set_fork_status(sr, CK_NOFORK);
srunner_run_all(sr, CK_VERBOSE);
number_failed = srunner_ntests_failed(sr);
srunner_free(sr);
return (number_failed == 0) ? 0 : 1;
}

View File

@@ -352,7 +352,7 @@
<OutDir>Debug-OCR\</OutDir>
<IntDir>Debug-OCR\</IntDir>
<LinkIncremental>true</LinkIncremental>
<TargetName>ccextractorwin</TargetName>
<TargetName>ccextractorwinocr</TargetName>
<IncludePath>$(ProjectDir)\libs\include;$(IncludePath)</IncludePath>
<LibraryPath>$(ProjectDir)\libs\lib;$(VC_LibraryPath_x86);$(WindowsSDK_LibraryPath_x86)</LibraryPath>
</PropertyGroup>
@@ -366,7 +366,7 @@
<OutDir>Release-OCR\</OutDir>
<IntDir>Release-OCR\</IntDir>
<LinkIncremental>false</LinkIncremental>
<TargetName>ccextractorwin</TargetName>
<TargetName>ccextractorwinocr</TargetName>
<IncludePath>$(ProjectDir)\libs\include;$(IncludePath)</IncludePath>
<LibraryPath>$(ProjectDir)\libs\lib;$(VC_LibraryPath_x86);$(WindowsSDK_LibraryPath_x86)</LibraryPath>
</PropertyGroup>
@@ -485,7 +485,7 @@ xcopy /y $(ProjectDir)libs\lib\libtesseract304d.dll $(ProjectDir)$(OutDir)</Comm
</ClCompile>
<Link>
<AdditionalDependencies>WS2_32.Lib;liblept172.lib;libtesseract304.lib;%(AdditionalDependencies)</AdditionalDependencies>
<GenerateDebugInformation>true</GenerateDebugInformation>
<GenerateDebugInformation>false</GenerateDebugInformation>
<SubSystem>Console</SubSystem>
<OptimizeReferences>true</OptimizeReferences>
<EnableCOMDATFolding>true</EnableCOMDATFolding>