mirror of
https://github.com/CCExtractor/ccextractor.git
synced 2026-02-08 13:34:59 +00:00
Compare commits
35 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
19f12038cd | ||
|
|
ebc7c070f3 | ||
|
|
7acb3c3874 | ||
|
|
e3ca2c3fbc | ||
|
|
ac1accce96 | ||
|
|
c39185abab | ||
|
|
6729c9c33f | ||
|
|
4e4a7aa19e | ||
|
|
5d8ce8bfb8 | ||
|
|
92b811b329 | ||
|
|
8c8a357aa7 | ||
|
|
f2770b4609 | ||
|
|
7c21754b74 | ||
|
|
547a9e9fbf | ||
|
|
fd6a223876 | ||
|
|
2fd71f00d6 | ||
|
|
0301a40560 | ||
|
|
5bbf27de9c | ||
|
|
54f628f7a6 | ||
|
|
4743eb46c1 | ||
|
|
66393a80f2 | ||
|
|
c6c8de7357 | ||
|
|
cbbbb20751 | ||
|
|
5846093a7f | ||
|
|
f1d276c988 | ||
|
|
0d0cb83ed6 | ||
|
|
08e9c3d596 | ||
|
|
edcd2df6bc | ||
|
|
3f679d72cf | ||
|
|
2e09541c84 | ||
|
|
27417cda70 | ||
|
|
2959d2a2ae | ||
|
|
289aecc1ed | ||
|
|
ea980a4150 | ||
|
|
2910b10f99 |
6
.gitignore
vendored
6
.gitignore
vendored
@@ -1,3 +1,9 @@
|
||||
####
|
||||
# Ignore tests tmp files and results
|
||||
tests/runtest
|
||||
tests/**/*.gcda
|
||||
tests/**/*.gcno
|
||||
|
||||
####
|
||||
# Ignore CVS related files
|
||||
|
||||
|
||||
@@ -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).
|
||||
|
||||
@@ -30,6 +30,7 @@ Google Summer of Code 2016 students
|
||||
- Rishabh Garg
|
||||
|
||||
Google Code-in 2016 students
|
||||
- Evgeny Shulgin
|
||||
(to be listed)
|
||||
|
||||
|
||||
|
||||
31
linux/build
31
linux/build
@@ -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";
|
||||
|
||||
@@ -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."
|
||||
|
||||
@@ -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."
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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],
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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];
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
59
tests/Makefile
Normal 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
43
tests/README.md
Normal 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/)
|
||||
305
tests/ccx_encoders_splitbysentence_suite.c
Normal file
305
tests/ccx_encoders_splitbysentence_suite.c
Normal 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;
|
||||
}
|
||||
4
tests/ccx_encoders_splitbysentence_suite.h
Normal file
4
tests/ccx_encoders_splitbysentence_suite.h
Normal file
@@ -0,0 +1,4 @@
|
||||
// -------------------------------------
|
||||
// SUITE
|
||||
// -------------------------------------
|
||||
Suite * ccx_encoders_splitbysentence_suite(void);
|
||||
21
tests/runtest.c
Normal file
21
tests/runtest.c
Normal 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;
|
||||
}
|
||||
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user