mirror of
https://github.com/CCExtractor/ccextractor.git
synced 2026-02-11 21:22:22 +00:00
Compare commits
16 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1bd3a43dbe | ||
|
|
5fa83394a0 | ||
|
|
51537e8725 | ||
|
|
071386d552 | ||
|
|
ec9a0985ce | ||
|
|
71dffd6eb3 | ||
|
|
560a88b0b9 | ||
|
|
8dc1964f8c | ||
|
|
d72e946213 | ||
|
|
24edbff859 | ||
|
|
77da2dc873 | ||
|
|
d9414782b2 | ||
|
|
d1b127164e | ||
|
|
db8d9c67b6 | ||
|
|
c9a3a0c7f2 | ||
|
|
0e4d211eaf |
@@ -1,3 +1,7 @@
|
||||
0.85b (2017-1-26)
|
||||
-----------------
|
||||
- Fix: Base Windows binary (without OCR) compiled without DLL dependencies.
|
||||
|
||||
0.85 (2017-01-23)
|
||||
-----------------
|
||||
- New: Added FFMPEG 3.0 to Windows build - last one that is XP compatible.
|
||||
|
||||
@@ -27,6 +27,13 @@ struct lib_ccx_ctx *signal_ctx;
|
||||
|
||||
volatile int terminate_asap = 0;
|
||||
|
||||
void sigusr1_handler(int sig)
|
||||
{
|
||||
mprint("Caught SIGUSR1. Filename Change Requested\n");
|
||||
change_filename_requested = 1;
|
||||
}
|
||||
|
||||
|
||||
void sigterm_handler(int sig)
|
||||
{
|
||||
printf("Received SIGTERM, terminating as soon as possible.\n");
|
||||
@@ -151,7 +158,7 @@ int main(int argc, char *argv[])
|
||||
signal_ctx = ctx;
|
||||
m_signal(SIGINT, sigint_handler);
|
||||
m_signal(SIGTERM, sigterm_handler);
|
||||
create_signal(SIGINT);
|
||||
m_signal(SIGUSR1, sigusr1_handler);
|
||||
#endif
|
||||
terminate_asap = 0;
|
||||
|
||||
@@ -243,7 +250,14 @@ int main(int argc, char *argv[])
|
||||
{
|
||||
fatal (EXIT_INCOMPATIBLE_PARAMETERS, "MP4 requires an actual file, it's not possible to read from a stream, including stdin.\n");
|
||||
}
|
||||
tmp = processmp4(ctx, &ctx->mp4_cfg, ctx->inputfile[ctx->current_file]);
|
||||
if(ccx_options.extract_chapters)
|
||||
{
|
||||
tmp = dumpchapters(ctx, &ctx->mp4_cfg, ctx->inputfile[ctx->current_file]);
|
||||
}
|
||||
else
|
||||
{
|
||||
tmp = processmp4(ctx, &ctx->mp4_cfg, ctx->inputfile[ctx->current_file]);
|
||||
}
|
||||
if (ccx_options.print_file_reports)
|
||||
print_file_report(ctx);
|
||||
if (!ret) ret = tmp;
|
||||
|
||||
@@ -190,6 +190,39 @@ static int process_avc_track(struct lib_ccx_ctx *ctx, const char* basename, GF_I
|
||||
return status;
|
||||
}
|
||||
|
||||
static char *format_duration(u64 dur, u32 timescale, char *szDur)
|
||||
{
|
||||
u32 h, m, s, ms;
|
||||
if ((dur==(u64) -1) || (dur==(u32) -1)) {
|
||||
strcpy(szDur, "Unknown");
|
||||
return szDur;
|
||||
}
|
||||
dur = (u64) (( ((Double) (s64) dur)/timescale)*1000);
|
||||
h = (u32) (dur / 3600000);
|
||||
m = (u32) (dur/ 60000) - h*60;
|
||||
s = (u32) (dur/1000) - h*3600 - m*60;
|
||||
ms = (u32) (dur) - h*3600000 - m*60000 - s*1000;
|
||||
if (h<=24) {
|
||||
sprintf(szDur, "%02d:%02d:%02d.%03d", h, m, s, ms);
|
||||
} else {
|
||||
u32 d = (u32) (dur / 3600000 / 24);
|
||||
h = (u32) (dur/3600000)-24*d;
|
||||
if (d<=365) {
|
||||
sprintf(szDur, "%d Days, %02d:%02d:%02d.%03d", d, h, m, s, ms);
|
||||
} else {
|
||||
u32 y=0;
|
||||
while (d>365) {
|
||||
y++;
|
||||
d-=365;
|
||||
if (y%4) d--;
|
||||
}
|
||||
sprintf(szDur, "%d Years %d Days, %02d:%02d:%02d.%03d", y, d, h, m, s, ms);
|
||||
}
|
||||
|
||||
}
|
||||
return szDur;
|
||||
}
|
||||
|
||||
unsigned char * ccdp_find_data(unsigned char * ccdp_atom_content, unsigned int len, unsigned int *cc_count)
|
||||
{
|
||||
unsigned char *data = ccdp_atom_content;
|
||||
@@ -286,7 +319,7 @@ unsigned char * ccdp_find_data(unsigned char * ccdp_atom_content, unsigned int l
|
||||
*/
|
||||
int processmp4 (struct lib_ccx_ctx *ctx,struct ccx_s_mp4Cfg *cfg, char *file)
|
||||
{
|
||||
int caps = 0;
|
||||
int mp4_ret = 0;
|
||||
GF_ISOFile* f;
|
||||
u32 i, j, track_count, avc_track_count, cc_track_count;
|
||||
struct cc_subtitle dec_sub;
|
||||
@@ -296,7 +329,7 @@ int processmp4 (struct lib_ccx_ctx *ctx,struct ccx_s_mp4Cfg *cfg, char *file)
|
||||
dec_ctx = update_decoder_list(ctx);
|
||||
|
||||
memset(&dec_sub,0,sizeof(dec_sub));
|
||||
mprint("opening \'%s\': ", file);
|
||||
mprint("Opening \'%s\': ", file);
|
||||
#ifdef MP4_DEBUG
|
||||
gf_log_set_tool_level(GF_LOG_CONTAINER,GF_LOG_DEBUG);
|
||||
#endif
|
||||
@@ -330,7 +363,7 @@ int processmp4 (struct lib_ccx_ctx *ctx,struct ccx_s_mp4Cfg *cfg, char *file)
|
||||
avc_track_count++;
|
||||
}
|
||||
|
||||
mprint("mp4: found %u tracks: %u avc and %u cc\n", track_count, avc_track_count, cc_track_count);
|
||||
mprint("MP4: found %u tracks: %u avc and %u cc\n", track_count, avc_track_count, cc_track_count);
|
||||
|
||||
for(i = 0; i < track_count; i++)
|
||||
{
|
||||
@@ -349,7 +382,7 @@ int processmp4 (struct lib_ccx_ctx *ctx,struct ccx_s_mp4Cfg *cfg, char *file)
|
||||
}
|
||||
if(dec_sub.got_output)
|
||||
{
|
||||
caps = 1;
|
||||
mp4_ret = 1;
|
||||
encode_sub(enc_ctx, &dec_sub);
|
||||
dec_sub.got_output = 0;
|
||||
}
|
||||
@@ -377,7 +410,7 @@ int processmp4 (struct lib_ccx_ctx *ctx,struct ccx_s_mp4Cfg *cfg, char *file)
|
||||
}
|
||||
if(dec_sub.got_output)
|
||||
{
|
||||
caps = 1;
|
||||
mp4_ret = 1;
|
||||
encode_sub(enc_ctx, &dec_sub);
|
||||
dec_sub.got_output = 0;
|
||||
}
|
||||
@@ -472,14 +505,14 @@ int processmp4 (struct lib_ccx_ctx *ctx,struct ccx_s_mp4Cfg *cfg, char *file)
|
||||
|
||||
if (cc_info == CDP_SECTION_SVC_INFO || cc_info == CDP_SECTION_FOOTER)
|
||||
{
|
||||
dbg_print(CCX_DMT_PARSE, "mp4-708: premature end of sample (0x73 or 0x74)\n");
|
||||
dbg_print(CCX_DMT_PARSE, "MP4-708: premature end of sample (0x73 or 0x74)\n");
|
||||
break;
|
||||
}
|
||||
|
||||
if ((cc_info == 0xFA || cc_info == 0xFC || cc_info == 0xFD)
|
||||
&& (cc_data[1] & 0x7F) == 0 && (cc_data[2] & 0x7F) == 0)
|
||||
{
|
||||
dbg_print(CCX_DMT_PARSE, "mp4-708: skipped (zero cc data)\n");
|
||||
dbg_print(CCX_DMT_PARSE, "MP4-708: skipped (zero cc data)\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -490,7 +523,7 @@ int processmp4 (struct lib_ccx_ctx *ctx,struct ccx_s_mp4Cfg *cfg, char *file)
|
||||
|
||||
if (cc_type < 2)
|
||||
{
|
||||
dbg_print(CCX_DMT_PARSE, "mp4-708: atom skipped (cc_type < 2)\n");
|
||||
dbg_print(CCX_DMT_PARSE, "MP4-708: atom skipped (cc_type < 2)\n");
|
||||
continue;
|
||||
}
|
||||
dec_ctx->dtvcc->encoder = (void *)enc_ctx; //WARN: otherwise cea-708 will not work
|
||||
@@ -522,7 +555,7 @@ int processmp4 (struct lib_ccx_ctx *ctx,struct ccx_s_mp4Cfg *cfg, char *file)
|
||||
tdata += ret;
|
||||
cb_field1++;
|
||||
if (dec_sub.got_output) {
|
||||
caps = 1;
|
||||
mp4_ret = 1;
|
||||
encode_sub(enc_ctx, &dec_sub);
|
||||
dec_sub.got_output = 0;
|
||||
}
|
||||
@@ -550,7 +583,7 @@ int processmp4 (struct lib_ccx_ctx *ctx,struct ccx_s_mp4Cfg *cfg, char *file)
|
||||
|
||||
free(dec_ctx->xds_ctx);
|
||||
|
||||
mprint("\nclosing media: ");
|
||||
mprint("\nClosing media: ");
|
||||
|
||||
gf_isom_close(f);
|
||||
f = NULL;
|
||||
@@ -567,9 +600,66 @@ int processmp4 (struct lib_ccx_ctx *ctx,struct ccx_s_mp4Cfg *cfg, char *file)
|
||||
if (cc_track_count)
|
||||
mprint ("Found %d CC track(s).\n", cc_track_count);
|
||||
else
|
||||
mprint ("found no dedicated CC track(s).\n");
|
||||
mprint ("Found no dedicated CC track(s).\n");
|
||||
|
||||
ctx->freport.mp4_cc_track_cnt = cc_track_count;
|
||||
|
||||
return caps;
|
||||
return mp4_ret;
|
||||
}
|
||||
|
||||
int dumpchapters (struct lib_ccx_ctx *ctx,struct ccx_s_mp4Cfg *cfg, char *file)
|
||||
{
|
||||
int mp4_ret = 0;
|
||||
GF_ISOFile* f;
|
||||
mprint("Opening \'%s\': ", file);
|
||||
#ifdef MP4_DEBUG
|
||||
gf_log_set_tool_level(GF_LOG_CONTAINER,GF_LOG_DEBUG);
|
||||
#endif
|
||||
|
||||
if((f = gf_isom_open(file, GF_ISOM_OPEN_READ, NULL)) == NULL)
|
||||
{
|
||||
mprint("failed to open\n");
|
||||
return 5;
|
||||
}
|
||||
|
||||
mprint("ok\n");
|
||||
|
||||
char szName[1024];
|
||||
FILE *t;
|
||||
u32 i, count;
|
||||
count = gf_isom_get_chapter_count(f, 0);
|
||||
if(count>0)
|
||||
{
|
||||
if (file)
|
||||
{
|
||||
strcpy(szName, get_basename(file));
|
||||
strcat(szName, ".txt");
|
||||
|
||||
t = gf_fopen(szName, "wt");
|
||||
if (!t) return 5;
|
||||
}
|
||||
else {
|
||||
t = stdout;
|
||||
}
|
||||
mp4_ret=1;
|
||||
printf("Writing chapters into %s\n",szName);
|
||||
}
|
||||
else
|
||||
{
|
||||
mprint("No chapters information found!\n");
|
||||
}
|
||||
|
||||
|
||||
|
||||
for (i=0; i<count; i++) {
|
||||
u64 chapter_time;
|
||||
const char *name;
|
||||
char szDur[20];
|
||||
gf_isom_get_chapter(f, 0, i+1, &chapter_time, &name);
|
||||
fprintf(t, "CHAPTER%02d=%s\n", i+1, format_duration(chapter_time, 1000, szDur));
|
||||
fprintf(t, "CHAPTER%02dNAME=%s\n", i+1, name);
|
||||
|
||||
}
|
||||
if (file) gf_fclose(t);
|
||||
return mp4_ret;
|
||||
}
|
||||
|
||||
@@ -49,6 +49,7 @@ void init_options (struct ccx_s_options *options)
|
||||
options->auto_myth = 2; // 2=auto
|
||||
/* MP4 related stuff */
|
||||
options->mp4vidtrack=0; // Process the video track even if a CC dedicated track exists.
|
||||
options->extract_chapters=0; // By default don't extract chapters.
|
||||
/* General stuff */
|
||||
options->usepicorder = 0; // Force the use of pic_order_cnt_lsb in AVC/H.264 data streams
|
||||
options->xmltv=0; // 1 = full output. 2 = live output. 3 = both
|
||||
|
||||
@@ -115,6 +115,7 @@ struct ccx_s_options // Options from user parameters
|
||||
int auto_myth; // Use myth-tv mpeg code? 0=no, 1=yes, 2=auto
|
||||
/* MP4 related stuff */
|
||||
unsigned mp4vidtrack; // Process the video track even if a CC dedicated track exists.
|
||||
int extract_chapters; // If 1, extracts chapters (if present), from MP4 files.
|
||||
/* General settings */
|
||||
int usepicorder; // Force the use of pic_order_cnt_lsb in AVC/H.264 data streams
|
||||
int xmltv; // 1 = full output. 2 = live output. 3 = both
|
||||
|
||||
@@ -279,7 +279,7 @@ void ccx_dtvcc_write_transcript(ccx_dtvcc_writer_ctx *writer, ccx_dtvcc_service_
|
||||
if (strlen(buf))
|
||||
write(encoder->dtvcc_writers[tv->service_number - 1].fd, buf, strlen(buf));
|
||||
|
||||
_dtvcc_write_row(writer, tv, i, encoder, 0);
|
||||
_dtvcc_write_row(writer, decoder, i, encoder, 0);
|
||||
write(encoder->dtvcc_writers[tv->service_number - 1].fd,
|
||||
encoder->encoded_crlf, encoder->encoded_crlf_length);
|
||||
}
|
||||
|
||||
@@ -4,4 +4,5 @@
|
||||
|
||||
|
||||
int processmp4 (struct lib_ccx_ctx *ctx,struct ccx_s_mp4Cfg *cfg, char *file);
|
||||
int dumpchapters(struct lib_ccx_ctx *ctx,struct ccx_s_mp4Cfg *cfg, char *file);
|
||||
#endif
|
||||
|
||||
@@ -249,7 +249,6 @@ void timestamp_to_srttime(uint64_t timestamp, char *buffer);
|
||||
void timestamp_to_smptetttime(uint64_t timestamp, char *buffer);
|
||||
int levenshtein_dist (const uint64_t *s1, const uint64_t *s2, unsigned s1len, unsigned s2len);
|
||||
void millis_to_date (uint64_t timestamp, char *buffer, enum ccx_output_date_format date_format, char millis_separator);
|
||||
void create_signal(int sigtype);
|
||||
void signal_handler(int sig_type);
|
||||
struct encoder_ctx* change_filename(struct encoder_ctx*);
|
||||
#ifndef _WIN32
|
||||
|
||||
@@ -977,7 +977,15 @@ int start_upd_srv(const char *addr_str, unsigned port)
|
||||
struct sockaddr_in servaddr;
|
||||
servaddr.sin_family = AF_INET;
|
||||
servaddr.sin_port = htons(port);
|
||||
#if _WIN32
|
||||
// Doesn't seem correct, if there's more than one multicast stream with the same
|
||||
// port number we get corruption - IP address needs to be specified, but
|
||||
// in Windows we get an error 10049 (cannot bind).
|
||||
// http ://stackoverflow.com/questions/6140734/cannot-bind-to-multicast-address-windows
|
||||
servaddr.sin_addr.s_addr = htonl(IN_MULTICAST(addr) ? INADDR_ANY : addr);
|
||||
#else
|
||||
servaddr.sin_addr.s_addr = htonl(addr);
|
||||
#endif
|
||||
|
||||
if (bind(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) != 0)
|
||||
{
|
||||
|
||||
@@ -161,7 +161,7 @@ fail:
|
||||
|
||||
BOX* ignore_alpha_at_edge(png_byte *alpha, unsigned char* indata, int w, int h, PIX *in, PIX **out)
|
||||
{
|
||||
int i, j, index, start_y, end_y;
|
||||
int i, j, index, start_y=0, end_y=0;
|
||||
int find_end_x = CCX_FALSE;
|
||||
BOX* cropWindow;
|
||||
for (j = 1; j < w-1; j++)
|
||||
@@ -434,7 +434,7 @@ char* ocr_bitmap(void* arg, png_color *palette,png_byte *alpha, unsigned char* i
|
||||
if(strstr(text_out,word))
|
||||
{
|
||||
char *text_out_copy = strdup(text_out);
|
||||
free(text_out);
|
||||
TessDeleteText(text_out);
|
||||
text_out = malloc(strlen(text_out_copy)+strlen(substr)+1);
|
||||
memset(text_out,0,strlen(text_out_copy)+strlen(substr)+1);
|
||||
int pos = (int)(strstr(text_out_copy,word)-text_out_copy);
|
||||
@@ -448,7 +448,7 @@ char* ocr_bitmap(void* arg, png_color *palette,png_byte *alpha, unsigned char* i
|
||||
else if(!written_tag)
|
||||
{
|
||||
char *text_out_copy = strdup(text_out);
|
||||
free(text_out);
|
||||
TessDeleteText(text_out);
|
||||
text_out = malloc(strlen(text_out_copy)+strlen(substr)+1);
|
||||
memset(text_out,0,strlen(text_out_copy)+strlen(substr)+1);
|
||||
strcpy(text_out,substr);
|
||||
@@ -464,7 +464,7 @@ char* ocr_bitmap(void* arg, png_color *palette,png_byte *alpha, unsigned char* i
|
||||
freep(&histogram);
|
||||
freep(&mcit);
|
||||
freep(&iot);
|
||||
|
||||
TessDeleteText(word);
|
||||
} while (TessPageIteratorNext((TessPageIterator *)ri,level));
|
||||
|
||||
//Write closing </font> at the end of the line
|
||||
@@ -473,7 +473,7 @@ char* ocr_bitmap(void* arg, png_color *palette,png_byte *alpha, unsigned char* i
|
||||
{
|
||||
char *substr = "</font>";
|
||||
char *text_out_copy = strdup(text_out);
|
||||
free(text_out);
|
||||
TessDeleteText(text_out);
|
||||
text_out = malloc(strlen(text_out_copy)+strlen(substr)+1);
|
||||
memset(text_out,0,strlen(text_out_copy)+strlen(substr)+1);
|
||||
char *str = strtok(text_out_copy,"\n");
|
||||
|
||||
@@ -490,6 +490,9 @@ void print_usage (void)
|
||||
mprint (" --webvtt-create-css: Create a separate file for CSS instead of inline.\n");
|
||||
mprint ("\n");
|
||||
mprint ("Options that affect what kind of output will be produced:\n");
|
||||
mprint (" -chapters: (Experimental) Produces a chapter file from MP4 files.\n");
|
||||
mprint (" Note that this must only be used with MP4 files,\n");
|
||||
mprint (" for other files it will simply generate subtitles file.\n");
|
||||
mprint (" -bom: Append a BOM (Byte Order Mark) to output files.\n");
|
||||
mprint (" Note that most text processing tools in linux will not\n");
|
||||
mprint (" like BOM.\n");
|
||||
@@ -1199,6 +1202,11 @@ int parse_parameters (struct ccx_s_options *opt, int argc, char *argv[])
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (strcmp(argv[i], "-chapters") == 0){
|
||||
opt->extract_chapters= 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strcmp (argv[i],"-bi")==0 ||
|
||||
strcmp (argv[i],"--bufferinput")==0)
|
||||
@@ -2195,6 +2203,13 @@ int parse_parameters (struct ccx_s_options *opt, int argc, char *argv[])
|
||||
{
|
||||
fatal (EXIT_INCOMPATIBLE_PARAMETERS, "MP4 requires an actual file, it's not possible to read from a stream, including stdin.\n");
|
||||
}
|
||||
|
||||
if(opt->extract_chapters)
|
||||
{
|
||||
mprint("Request to extract chapters recieved.\n");
|
||||
mprint("Note that this must only be used with MP4 files,\n");
|
||||
mprint("for other files it will simply generate subtitles file.\n\n");
|
||||
}
|
||||
|
||||
if(opt->gui_mode_reports)
|
||||
{
|
||||
|
||||
@@ -411,22 +411,6 @@ void m_signal(int sig, void (*func)(int))
|
||||
return;
|
||||
}
|
||||
|
||||
void create_signal(int sigtype)
|
||||
{
|
||||
if (signal(sigtype, signal_handler) == SIG_ERR)
|
||||
mprint("Can't catch signal %d.\n", sigtype);
|
||||
}
|
||||
|
||||
void signal_handler(int sig_type)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (sig_type == SIGUSR1)
|
||||
{
|
||||
mprint("Caught SIGUSR1. Filename Change Requested\n");
|
||||
change_filename_requested = 1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
struct encoder_ctx *change_filename(struct encoder_ctx *enc_ctx)
|
||||
|
||||
@@ -399,10 +399,11 @@
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;_FILE_OFFSET_BITS=64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<MinimalRebuild>true</MinimalRebuild>
|
||||
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
<PrecompiledHeader />
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>WS2_32.Lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
@@ -555,10 +556,12 @@ xcopy /y $(ProjectDir)libs\lib\libtesseract304d.dll $(ProjectDir)$(OutDir)</Comm
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>..\src\win_spec_incld;..\src\lib_ccx;..\src\lib_hash;..\src\zvbi;..\src\protobuf-c;..\src\gpacmp4;..\src\win_iconv;..\src\zlib;..\src\libpng;..\src;libs\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>VERSION_FILE_PRESENT;WIN32;NDEBUG;_CONSOLE;_FILE_OFFSET_BITS=64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<PrecompiledHeader />
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
<InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>WS2_32.Lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
|
||||
Reference in New Issue
Block a user