胡斌

part of pip,not finished

@@ -5,6 +5,8 @@ VisualStudioVersion = 12.0.31101.0 @@ -5,6 +5,8 @@ VisualStudioVersion = 12.0.31101.0
5 MinimumVisualStudioVersion = 10.0.40219.1 5 MinimumVisualStudioVersion = 10.0.40219.1
6 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "merge_av", "merge_av\merge_av.vcxproj", "{F607DD90-3E62-40BA-BF8A-185E597D646D}" 6 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "merge_av", "merge_av\merge_av.vcxproj", "{F607DD90-3E62-40BA-BF8A-185E597D646D}"
7 EndProject 7 EndProject
  8 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pip", "pip\pip.vcxproj", "{7D6B14AD-7FD2-45F1-A196-A2455406D4FB}"
  9 +EndProject
8 Global 10 Global
9 GlobalSection(SolutionConfigurationPlatforms) = preSolution 11 GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 Debug|Win32 = Debug|Win32 12 Debug|Win32 = Debug|Win32
@@ -15,6 +17,10 @@ Global @@ -15,6 +17,10 @@ Global
15 {F607DD90-3E62-40BA-BF8A-185E597D646D}.Debug|Win32.Build.0 = Debug|Win32 17 {F607DD90-3E62-40BA-BF8A-185E597D646D}.Debug|Win32.Build.0 = Debug|Win32
16 {F607DD90-3E62-40BA-BF8A-185E597D646D}.Release|Win32.ActiveCfg = Release|Win32 18 {F607DD90-3E62-40BA-BF8A-185E597D646D}.Release|Win32.ActiveCfg = Release|Win32
17 {F607DD90-3E62-40BA-BF8A-185E597D646D}.Release|Win32.Build.0 = Release|Win32 19 {F607DD90-3E62-40BA-BF8A-185E597D646D}.Release|Win32.Build.0 = Release|Win32
  20 + {7D6B14AD-7FD2-45F1-A196-A2455406D4FB}.Debug|Win32.ActiveCfg = Debug|Win32
  21 + {7D6B14AD-7FD2-45F1-A196-A2455406D4FB}.Debug|Win32.Build.0 = Debug|Win32
  22 + {7D6B14AD-7FD2-45F1-A196-A2455406D4FB}.Release|Win32.ActiveCfg = Release|Win32
  23 + {7D6B14AD-7FD2-45F1-A196-A2455406D4FB}.Release|Win32.Build.0 = Release|Win32
18 EndGlobalSection 24 EndGlobalSection
19 GlobalSection(SolutionProperties) = preSolution 25 GlobalSection(SolutionProperties) = preSolution
20 HideSolutionNode = FALSE 26 HideSolutionNode = FALSE
  1 +#include <stdio.h>
  2 +#include <stdlib.h>
  3 +#include <string>
  4 +#include <iostream>
  5 +#include <fstream>
  6 +#include <vector>
  7 +#include <string.h>
  8 +#include <list>
  9 +#include <deque>
  10 +#include "tools.h"
  11 +
  12 +
  13 +bool only_print = false;
  14 +bool keep_tmp_files = false;
  15 +using namespace std;
  16 +
  17 +enum media_type{
  18 + mt_audio = 0,
  19 + mt_video = 1,
  20 + mt_av = 3,
  21 +};
  22 +
  23 +enum timestamp_type{
  24 + tt_start = 0,
  25 + tt_end = 1,
  26 +};
  27 +
  28 +class fileinfo {
  29 +public:
  30 + float start_time;
  31 + float end_time;
  32 + string name;
  33 + int index;
  34 + media_type m_type;
  35 + int channel;
  36 +};
  37 +
  38 +class media_info {
  39 +public:
  40 + float type_time;//the time for start or end according to the m_type
  41 + float start_time;
  42 + float end_time;
  43 + string name;
  44 +
  45 + float duration;
  46 + int index;
  47 + int channel;
  48 + media_type m_type;
  49 + timestamp_type t_type;
  50 +};
  51 +
  52 +
  53 +vector<fileinfo> media_files;
  54 +
  55 +
  56 +void run_shell_cmd(const char * cmd)
  57 +{
  58 + if (only_print){
  59 + printf("%s\n", cmd);
  60 + }
  61 + else
  62 + {
  63 + printf("run command:%s\n", cmd);
  64 + system(cmd);
  65 + }
  66 +}
  67 +
  68 +#ifdef WIN32
  69 +#include <Windows.h>
  70 +
  71 +char exe_path[MAX_PATH] = { 0 };
  72 +
  73 +int GetExePath()
  74 +{
  75 + char path_buffer[MAX_PATH] = "";
  76 + char drive[32] = "";
  77 + char dir[256] = "";
  78 + char fname[64] = "";
  79 + char ext[32] = "";
  80 +
  81 + GetModuleFileNameA(NULL, path_buffer, 256);
  82 + _splitpath(path_buffer, drive, dir, fname, ext);
  83 +
  84 + strcpy(exe_path, drive);
  85 + strcat(exe_path, dir);
  86 + return 0;
  87 +}
  88 +#endif
  89 +
  90 +char cfg_path[1024];
  91 +
  92 +void get_config_path(){
  93 +#ifdef WIN32
  94 + GetExePath();
  95 + strcpy(cfg_path, exe_path);
  96 +#else
  97 + strcpy(cfg_path, getenv("HOME"));
  98 + strcat(cfg_path, "/merge_av/");
  99 +#endif
  100 +}
  101 +
  102 +const char * default_vcodec_param = "-vcodec libx264 -level 3.1 -preset veryfast -g 100 -r 20 -bf 0 -vsync cfr";
  103 +const char * default_acodec_param = "-acodec copy";
  104 +const char * default_av_codec_param = "-acodec aac -vcodec libx264 -level 3.1 -preset veryfast -g 100 -r 20 -bf 0 -vsync cfr";
  105 +const char * default_pip_param = "-filter_complex \"[1:v]scale = w = 80:h = 60 : force_original_aspect_ratio = decrease[b]; [0:v][b]overlay = x = 0:y = 0\" -filter_complex amix=inputs=2:duration=first:dropout_transition=2,volume=1";
  106 +
  107 +
  108 +char av_codec_param[1024];
  109 +char vcodec_param[1024];
  110 +char acodec_param[1024];
  111 +char pip_param[1024];
  112 +
  113 +bool first_time_set = false;
  114 +float start_time = 0.0f;
  115 +
  116 +void addinfo(string t, string name, bool bstart){
  117 + media_type mtype = name.substr(name.length() - 4, name.length()) == ".aac" ? mt_audio : mt_video;
  118 + if (bstart) {
  119 + fileinfo f;
  120 + f.start_time = atof(t.c_str());
  121 + f.end_time = f.start_time;
  122 + f.name = name;
  123 + f.m_type = mtype;
  124 +
  125 + if (!first_time_set) {
  126 + first_time_set = true;
  127 + start_time = f.start_time;
  128 + }
  129 +
  130 + f.start_time -= start_time;
  131 +
  132 + media_files.push_back(f);
  133 + }
  134 + else {
  135 + int i;
  136 + for (i = 0; i < media_files.size(); i++) {
  137 + if (media_files[i].name == name) {
  138 + media_files[i].end_time = atof(t.c_str());
  139 + media_files[i].end_time -= start_time;
  140 + break;
  141 + }
  142 + }
  143 +
  144 + if (i == media_files.size())
  145 + {
  146 + printf("\nerror ,file : %s close but not started!", name.c_str());
  147 + }
  148 + }
  149 +}
  150 +
  151 +void addinfo(float start, float duration, string name, int channel){
  152 + media_type mtype = mt_av;
  153 + fileinfo f;
  154 + f.start_time = start;
  155 + f.end_time = f.start_time + duration;
  156 + f.name = name;
  157 + f.m_type = mtype;
  158 + f.channel = channel;
  159 +
  160 + media_files.push_back(f);
  161 +}
  162 +
  163 +void split(string str, string separator, vector<string> &result, bool includeEmptyItem = false) {
  164 + result.clear();
  165 + string::size_type position = str.find(separator);
  166 + string::size_type lastPosition = 0;
  167 + int separatorLength = separator.length();
  168 +
  169 + while (position != str.npos) {
  170 + string s = str.substr(lastPosition, position - lastPosition);
  171 + if (!s.empty() || includeEmptyItem)
  172 + result.push_back(s);
  173 + lastPosition = position + separatorLength;
  174 + position = str.find(separator, lastPosition);
  175 + }
  176 + result.push_back(str.substr(lastPosition, string::npos));
  177 +}
  178 +
  179 +void split_audio(const char * audiofile, float audio_start, float duration, char * destfile)
  180 +{
  181 + char buf[2048];
  182 + sprintf(buf, "ffmpeg -y -i %s -ss %.3f -t %.3f %s %s", audiofile, audio_start, duration, acodec_param, destfile);
  183 + run_shell_cmd(buf);
  184 +}
  185 +
  186 +void split_av(const char * mediafile, float start, float duration, char * destfile)
  187 +{
  188 + char buf[2048];
  189 + sprintf(buf, "ffmpeg -y -i %s -ss %.3f -t %.3f %s %s", mediafile, start, duration, av_codec_param, destfile);
  190 + run_shell_cmd(buf);
  191 +}
  192 +
  193 +void get_video_first_frame_jpeg(const char * video, const char * destfile)
  194 +{
  195 + char buf[2048];
  196 + sprintf(buf, "ffmpeg -y -i %s -vframes 1 -ss 0 -f mjpeg -an %s", video, destfile);
  197 + run_shell_cmd(buf);
  198 +}
  199 +
  200 +void merge_audio_pic(const char * audio, const char * picfile, const char * destfile)
  201 +{
  202 + char buf[2048];
  203 + sprintf(buf, "ffmpeg -y -loop 1 -i %s -i %s -loop 0 -shortest %s %s %s", picfile, audio, acodec_param, vcodec_param, destfile);
  204 + run_shell_cmd(buf);
  205 +}
  206 +
  207 +
  208 +void merge_audio_video(const char * audio, const char * video, const char * destfile)
  209 +{
  210 + char buf[2048];
  211 + sprintf(buf, "ffmpeg -y -i %s -i %s %s %s %s", audio, video, acodec_param, vcodec_param, destfile);
  212 + run_shell_cmd(buf);
  213 +}
  214 +
  215 +void merge_video_pip(const char * ch0, const char * ch1, const char * destfile)
  216 +{
  217 + char buf[2048];
  218 + sprintf(buf, "ffmpeg -i %s -i %s %s %s %s", ch0, ch1, pip_param, av_codec_param, destfile);
  219 + run_shell_cmd(buf);
  220 +}
  221 +
  222 +void merge_video_silence(fileinfo video, const char * aacfile, const char * destfile)
  223 +{
  224 + char buf[2048];
  225 + sprintf(buf, "ffmpeg -y -i %s -i %s -shortest %s %s %s", aacfile, video.name.c_str(), acodec_param, vcodec_param, destfile);
  226 + run_shell_cmd(buf);
  227 +}
  228 +
  229 +
  230 +void concate_files(vector<string > merged_files, const char * destfile)
  231 +{
  232 + char buf[2048];
  233 +#ifdef WIN32
  234 + sprintf(buf, "copy /B %s ", merged_files[0].c_str());
  235 +
  236 + for (int i = 1; i < merged_files.size(); i++) {
  237 + strcat(buf, " + /B ");
  238 + strcat(buf, merged_files[i].c_str());
  239 + }
  240 + strcat(buf, " ");
  241 +#else
  242 + strcpy(buf, "cat ");
  243 +
  244 + for (int i = 0; i < merged_files.size(); i++) {
  245 + strcat(buf, " ");
  246 + strcat(buf, merged_files[i].c_str());
  247 + }
  248 + strcat(buf, "> ");
  249 +#endif // WIN32
  250 + strcat(buf, destfile);
  251 + run_shell_cmd(buf);
  252 +}
  253 +
  254 +void adjust_dest_timecode(const char * src, const char * dest)
  255 +{
  256 + char buf[2048];
  257 + sprintf(buf, "ffmpeg -y -i %s -acodec copy -vcodec copy %s", src, dest);
  258 + run_shell_cmd(buf);
  259 +}
  260 +
  261 +#ifndef WIN32
  262 +#include <unistd.h>
  263 +#endif
  264 +
  265 +
  266 +void remove_file(const char * file)
  267 +{
  268 +#ifdef WIN32
  269 + _unlink(file);
  270 +#else
  271 + unlink(file);
  272 +#endif
  273 +}
  274 +
  275 +void removefiles(vector<string> files)
  276 +{
  277 + for (int i = 0; i < files.size(); i++) {
  278 + remove_file(files[i].c_str());
  279 + }
  280 +}
  281 +
  282 +float parse_ffmpeg_duration(const char * file)
  283 +{
  284 + FILE * fp = fopen(file, "rb");
  285 + if (!fp) {
  286 + printf("\nOpen %s error\n", file);
  287 + return -1.0;
  288 + }
  289 + fseek(fp, 0l, SEEK_END);
  290 + long file_len = ftell(fp);
  291 + fseek(fp, 0l, SEEK_SET);
  292 +
  293 + char * content = new char[file_len + 1];
  294 + fread(content, 1, file_len, fp);
  295 + fclose(fp);
  296 +
  297 + content[file_len] = 0;
  298 +
  299 + if (!keep_tmp_files) {
  300 + remove_file(file);
  301 + }
  302 +
  303 + char * pDuration = strstr(content, "Duration:");
  304 + if (!pDuration){
  305 + printf("\ncan't find 'Duration:' in %s\n", file);
  306 + delete content;
  307 + return -1.0;
  308 + }
  309 +
  310 + char * pComma = strstr(pDuration, ",");
  311 + if (!pDuration){
  312 + printf("\ncan't find ',' after 'Duration:' in %s\n", file);
  313 + delete content;
  314 + return -1.0;
  315 + }
  316 + int len = pComma - pDuration - 10;
  317 + strncpy(content, pDuration + 10, len);
  318 + content[len] = 0;
  319 + vector <string > hms;
  320 + split(content, ":", hms);
  321 +
  322 + delete content;
  323 +
  324 + if (hms.size() != 3) {
  325 + printf("\nerro parsing duration in %s, the duration string is:%s\n", file, content);
  326 + delete content;
  327 + return -1.0;
  328 + }
  329 +
  330 + int hour = atoi(hms[0].c_str());
  331 + int minute = atoi(hms[1].c_str());
  332 + float sec = atof(hms[2].c_str());
  333 +
  334 + return hour * 3600 + minute * 60 + sec;
  335 +}
  336 +
  337 +float get_file_duration(const char *mediafile, bool bVideo)
  338 +{
  339 + char buf[2048];
  340 + if (bVideo){
  341 + sprintf(buf, "ffmpeg -y -i %s -vcodec copy -an %s.mkv", mediafile, mediafile);
  342 + }
  343 + else {
  344 + sprintf(buf, "ffmpeg -y -i %s -acodec copy -vn %s.mkv", mediafile, mediafile);
  345 + }
  346 + run_shell_cmd(buf);
  347 +#ifdef WIN32
  348 + sprintf(buf, "ffmpeg -i %s.mkv > %s.txt 2>&1", mediafile, mediafile);
  349 +#else
  350 + sprintf(buf, "ffmpeg -i %s.mkv &> %s.txt", mediafile, mediafile);
  351 +#endif
  352 +
  353 + run_shell_cmd(buf);
  354 +
  355 + if (!keep_tmp_files) {
  356 + char buf[2048];
  357 + sprintf(buf, "%s.mkv", mediafile);
  358 + remove_file(buf);
  359 + }
  360 +
  361 +
  362 + sprintf(buf, "%s.txt", mediafile);
  363 + return parse_ffmpeg_duration(buf);
  364 +}
  365 +
  366 +void get_duration_from_video_file()
  367 +{
  368 + bool tmp = only_print;
  369 + only_print = false;
  370 +
  371 + for (int i = 0; i < media_files.size(); i++){
  372 + if (media_files[i].m_type == mt_video) {
  373 + float duration = get_file_duration(media_files[i].name.c_str(), true);
  374 + if (duration >= 0.1) {
  375 + printf("file:%s , duration in recording file: %.3f, duration parsed from file: %.3f\n", media_files[i].name.c_str(), media_files[i].end_time - media_files[i].start_time, duration);
  376 + media_files[i].end_time = media_files[i].start_time + duration;
  377 + }
  378 + }
  379 + }
  380 +
  381 + only_print = tmp;
  382 +}
  383 +
  384 +
  385 +int merge_audio_file(vector<string> & files, const char * dest)
  386 +{
  387 + char buf[2048],tsfile[1024];
  388 + vector<string> tsfiles;
  389 +
  390 + for (int i = 0; i < files.size(); i++){
  391 + strcpy(tsfile, files[i].c_str());
  392 + strcat(tsfile, ".ts");
  393 + tsfiles.push_back(tsfile);
  394 +
  395 + sprintf(buf, "ffmpeg -y -i %s -acodec copy -vn %s", files[i].c_str(), tsfile);
  396 + run_shell_cmd(buf);
  397 + }
  398 +
  399 + sprintf(tsfile, "m_%s.ts", dest);
  400 + concate_files(tsfiles, tsfile);
  401 +
  402 + adjust_dest_timecode(tsfile, dest);
  403 +
  404 + if (!keep_tmp_files){
  405 + tsfiles.push_back(tsfile);
  406 + removefiles(tsfiles);
  407 + }
  408 + return 0;
  409 +}
  410 +
  411 +
  412 +list <media_info> sorted_media;
  413 +deque<media_info> sorted_infos;
  414 +vector<media_info> media_infos;
  415 +vector<string > merged_files;
  416 +vector<string> tmp_files;
  417 +int nv; // the index of processing video file
  418 +int nf;//the index of processing target merged ts
  419 +char destfile[1024], audio_file[1024], pic_file[1024];
  420 +char blank_pic_file[1024];
  421 +char silence_aac_file[1024];
  422 +
  423 +char out_info_file[1024];
  424 +FILE * fp_out_info = NULL;
  425 +
  426 +
  427 +
  428 +void add_media_info(media_info m)
  429 +{
  430 + list<media_info>::iterator it = sorted_media.begin();
  431 + for (; it != sorted_media.end(); it++){
  432 + if (it->type_time > m.type_time){
  433 + break;
  434 + }
  435 + }
  436 + sorted_media.insert(it, m);
  437 +}
  438 +
  439 +void add_media_infos()
  440 +{
  441 + for (int i = 0; i < media_files.size(); i++) {
  442 + fileinfo f = media_files[i];
  443 + media_info m;
  444 + m.index = i;
  445 + m.name = f.name;
  446 + m.start_time = f.start_time;
  447 + m.end_time = f.end_time;
  448 + m.m_type = f.m_type;
  449 + m.t_type = tt_start;
  450 + m.channel = f.channel;
  451 + m.duration = f.end_time - f.start_time;
  452 + m.type_time = m.start_time;
  453 + add_media_info(m);
  454 + m.t_type = tt_end;
  455 + m.type_time = m.end_time;
  456 + add_media_info(m);
  457 + }
  458 +
  459 + list<media_info>::iterator it = sorted_media.begin();
  460 + for (int i=0; it != sorted_media.end(); it++, i++ ){
  461 + sorted_infos.push_back(*it);
  462 + }
  463 +}
  464 +
  465 +void unifiy_start_time()
  466 +{
  467 + float min_start = media_files[0].start_time;
  468 + //get the min start
  469 + for (int i = 1; i < media_files.size(); i++) {
  470 + if (min_start > media_files[i].start_time) {
  471 + min_start = media_files[i].start_time;
  472 + }
  473 + }
  474 +
  475 + //all the file start sub the min start
  476 + for (int i = 0; i < media_files.size(); i++) {
  477 + media_files[i].start_time -= min_start;
  478 + media_files[i].end_time -= min_start;
  479 + }
  480 +}
  481 +
  482 +void init()
  483 +{
  484 + strcpy(blank_pic_file, cfg_path);
  485 + strcat(blank_pic_file, "blank.jpg");
  486 +
  487 + strcpy(silence_aac_file, cfg_path);
  488 + strcat(silence_aac_file, "silence.aac");
  489 +
  490 + unifiy_start_time();
  491 +
  492 + add_media_infos();
  493 +
  494 + nv = 0;
  495 + nf = 0;
  496 +}
  497 +
  498 +
  499 +int merge_audio_video(vector<media_info> & files)
  500 +{
  501 + vector<string> merge_audio_files;
  502 + int nsilence = 0;
  503 +
  504 + media_info video = files[0];
  505 + float start_time = video.start_time;
  506 +
  507 + for (int i = 1; i < files.size() - 1; i += 2){
  508 + media_info audio = files[i];
  509 + media_info audio_end = files[i + 1];
  510 + if (audio.type_time - start_time > 0.1){
  511 + sprintf(audio_file, "%d_%d_silence.aac", nf, nsilence++);//a duration of silence
  512 + split_audio(silence_aac_file, 0, audio.type_time - start_time, audio_file);
  513 + merge_audio_files.push_back(audio_file);
  514 + tmp_files.push_back(audio_file);
  515 + }
  516 +
  517 + if (audio.type_time - audio.start_time > 0.10 || audio_end.end_time - audio_end.type_time > 0.10) {
  518 + sprintf(audio_file, "%d_%s", nf, audio.name.c_str());
  519 + split_audio(audio.name.c_str(), audio.type_time - audio.start_time, audio_end.type_time - audio.type_time, audio_file);
  520 + tmp_files.push_back(audio_file);
  521 +
  522 + }
  523 + else{
  524 + strcpy(audio_file, audio.name.c_str());
  525 + }
  526 +
  527 + start_time = audio_end.type_time;
  528 + merge_audio_files.push_back(audio_file);
  529 +
  530 + if (i == files.size() - 2){
  531 + if (video.end_time - audio_end.type_time > 0.1){
  532 + sprintf(audio_file, "%d_%d_silence.aac", nf, nsilence++);//a duration of silence
  533 + split_audio(silence_aac_file, 0, video.end_time - audio_end.type_time, audio_file);
  534 + merge_audio_files.push_back(audio_file);
  535 + tmp_files.push_back(audio_file);
  536 + }
  537 + }
  538 + }
  539 +
  540 + sprintf(audio_file, "%d_merged.aac", nf);
  541 + merge_audio_file(merge_audio_files, audio_file);
  542 + tmp_files.push_back(audio_file);
  543 +
  544 +
  545 + sprintf(destfile, "%d.ts", nf);
  546 + merge_audio_video(audio_file, video.name.c_str(), destfile);
  547 + merged_files.push_back(destfile);
  548 + nf++;
  549 +
  550 + return 0;
  551 +}
  552 +
  553 +int merge_video_pip(vector<media_info> & files)
  554 +{
  555 + vector<string> merge_video_files;
  556 + int nsilence = 0;
  557 +
  558 + media_info video = files[0];
  559 + float start_time = video.start_time;
  560 +
  561 + for (int i = 1; i < files.size() - 1; i += 2){
  562 + media_info audio = files[i];
  563 + media_info audio_end = files[i + 1];
  564 + if (audio.type_time - start_time > 0.1){
  565 + sprintf(audio_file, "%d_%d_silence.aac", nf, nsilence++);//a duration of silence
  566 + split_audio(silence_aac_file, 0, audio.type_time - start_time, audio_file);
  567 + merge_video_files.push_back(audio_file);
  568 + tmp_files.push_back(audio_file);
  569 + }
  570 +
  571 + if (audio.type_time - audio.start_time > 0.10 || audio_end.end_time - audio_end.type_time > 0.10) {
  572 + sprintf(audio_file, "%d_%s", nf, audio.name.c_str());
  573 + split_audio(audio.name.c_str(), audio.type_time - audio.start_time, audio_end.type_time - audio.type_time, audio_file);
  574 + tmp_files.push_back(audio_file);
  575 +
  576 + }
  577 + else{
  578 + strcpy(audio_file, audio.name.c_str());
  579 + }
  580 +
  581 + start_time = audio_end.type_time;
  582 + merge_video_files.push_back(audio_file);
  583 +
  584 + if (i == files.size() - 2){
  585 + if (video.end_time - audio_end.type_time > 0.1){
  586 + sprintf(audio_file, "%d_%d_silence.aac", nf, nsilence++);//a duration of silence
  587 + split_audio(silence_aac_file, 0, video.end_time - audio_end.type_time, audio_file);
  588 + merge_video_files.push_back(audio_file);
  589 + tmp_files.push_back(audio_file);
  590 + }
  591 + }
  592 + }
  593 +
  594 + sprintf(audio_file, "%d_merged.aac", nf);
  595 + merge_audio_file(merge_video_files, audio_file);
  596 + tmp_files.push_back(audio_file);
  597 +
  598 +
  599 + sprintf(destfile, "%d.ts", nf);
  600 + merge_audio_video(audio_file, video.name.c_str(), destfile);
  601 + merged_files.push_back(destfile);
  602 + nf++;
  603 +
  604 + return 0;
  605 +}
  606 +
  607 +
  608 +int transcode_files(vector<media_info> files)
  609 +{
  610 + char video_file[1024];
  611 + media_info video = files[0];
  612 + media_info video_end = files[1];
  613 +
  614 + if (video.type_time - video.start_time > 0.10 || video_end.end_time - video_end.type_time > 0.10) {
  615 + sprintf(video_file, "%d_%s", nf, video.name.c_str());
  616 + split_av(video.name.c_str(), video.type_time - video.start_time, video_end.type_time - video.type_time, video_file);
  617 + tmp_files.push_back(video_file);
  618 + }
  619 + else{
  620 + strcpy(video_file, video.name.c_str());
  621 + }
  622 +
  623 + merged_files.push_back(video_file);
  624 +
  625 + nf++;
  626 +
  627 + return 0;
  628 +}
  629 +
  630 +int find_file_between_the_firstfile()
  631 +{
  632 + int index = sorted_infos[0].index;
  633 + int video_index = -1;
  634 + for (int i = 1; i < sorted_infos.size(); i++){
  635 + if (sorted_infos[i].index == index)
  636 + break;
  637 + video_index = i;
  638 +
  639 +
  640 + }
  641 + return video_index;
  642 +}
  643 +
  644 +int find_video_end()
  645 +{
  646 + int index = sorted_infos[0].index;
  647 + int video_index = 0;
  648 + for (int i = 1; i < sorted_infos.size(); i++){
  649 + if (sorted_infos[i].index == index){
  650 + video_index = i;
  651 + break;
  652 + }
  653 + }
  654 + return video_index;
  655 +}
  656 +
  657 +bool is_audio_start(int index)
  658 +{
  659 + return (sorted_infos[index].m_type == mt_audio && sorted_infos[index].t_type == tt_start);
  660 +}
  661 +
  662 +bool is_ch0_start(int index)
  663 +{
  664 + return (sorted_infos[index].channel == 0 && sorted_infos[index].t_type == tt_start);
  665 +}
  666 +
  667 +
  668 +int split_audio_for_video(int audio_start,vector<media_info> & result)
  669 +{
  670 + media_info audio = sorted_infos[audio_start];
  671 + media_info video = sorted_infos[audio_start + 1];
  672 +
  673 + result.clear();
  674 +
  675 + for (int i = 0; i <= audio_start; i++){
  676 + result.push_back(sorted_infos[i]);
  677 + }
  678 +
  679 + if (sorted_infos[audio_start + 2].index == sorted_infos[audio_start].index){
  680 + if (sorted_infos[audio_start + 2].type_time - sorted_infos[audio_start + 1].type_time < 0.1){//no need to split
  681 + result.push_back(sorted_infos[audio_start + 2]);//put the audio end to the result
  682 + result.push_back(video);//push the video end to the result
  683 + for (int i = 0; i <= audio_start + 2; i++){ //remove the infos including the audio end
  684 + sorted_infos.pop_front();
  685 + }
  686 + return 1;
  687 + }
  688 + }
  689 +
  690 + audio.t_type = tt_end;
  691 + audio.type_time = video.type_time;
  692 + result.push_back(audio);
  693 + result.push_back(video);
  694 +
  695 + for (int i = 0; i <= audio_start +1; i++){ //remove the infos including the video end
  696 + sorted_infos.pop_front();
  697 + }
  698 +
  699 + audio.t_type = tt_start;
  700 + sorted_infos.push_front(audio);
  701 +
  702 + return 0;
  703 +}
  704 +
  705 +int split_ch0_for_ch1(int ch0_start, vector<media_info> & result)
  706 +{
  707 + media_info ch0 = sorted_infos[ch0_start];
  708 + media_info ch1 = sorted_infos[ch0_start + 1];
  709 +
  710 + result.clear();
  711 +
  712 + for (int i = 0; i <= ch0_start; i++){
  713 + result.push_back(sorted_infos[i]);
  714 + }
  715 +
  716 + if (sorted_infos[ch0_start + 2].index == sorted_infos[ch0_start].index){
  717 + if (sorted_infos[ch0_start + 2].type_time - sorted_infos[ch0_start + 1].type_time < 0.1){//no need to split
  718 + result.push_back(sorted_infos[ch0_start + 2]);//put the audio end to the result
  719 + result.push_back(ch1);//push the video end to the result
  720 + for (int i = 0; i <= ch0_start + 2; i++){ //remove the infos including the audio end
  721 + sorted_infos.pop_front();
  722 + }
  723 + return 1;
  724 + }
  725 + }
  726 +
  727 + ch0.t_type = tt_end;
  728 + ch0.type_time = ch1.type_time;
  729 + result.push_back(ch0);
  730 + result.push_back(ch1);
  731 +
  732 + for (int i = 0; i <= ch0_start + 1; i++){ //remove the infos including the video end
  733 + sorted_infos.pop_front();
  734 + }
  735 +
  736 + ch0.t_type = tt_start;
  737 + sorted_infos.push_front(ch0);
  738 +
  739 + return 0;
  740 +}
  741 +
  742 +
  743 +int split_audio_for_pic(vector<media_info> & result)
  744 +{
  745 + media_info audio = sorted_infos[0];
  746 + media_info video = sorted_infos[1];
  747 +
  748 + result.clear();
  749 +
  750 + for (int i = 0; i < 1; i++){
  751 + result.push_back(sorted_infos[i]);
  752 + }
  753 +
  754 + if (sorted_infos[2].index == sorted_infos[0].index){
  755 + if (sorted_infos[2].type_time - sorted_infos[1].type_time < 0.1){//no need to split
  756 + result.push_back(sorted_infos[2]);//put the audio end to the result
  757 + for (int i = 0; i < 3; i++){
  758 + sorted_infos.pop_front();
  759 + }
  760 + sorted_infos.push_front(video);
  761 + return 1;
  762 + }
  763 + }
  764 +
  765 + audio.t_type = tt_end;
  766 + audio.type_time = video.start_time;
  767 + result.push_back(audio);
  768 +
  769 + for (int i = 0; i < 2; i++){
  770 + sorted_infos.pop_front();
  771 + }
  772 +
  773 + audio.t_type = tt_start;
  774 + sorted_infos.push_front(audio);
  775 + sorted_infos.push_front(video);
  776 + return 0;
  777 +}
  778 +
  779 +int split_ch0_for_no_process(vector<media_info> & result)
  780 +{
  781 + media_info first = sorted_infos[0];
  782 + media_info second = sorted_infos[1];
  783 +
  784 + result.clear();
  785 +
  786 + for (int i = 0; i < 1; i++){
  787 + result.push_back(sorted_infos[i]);
  788 + }
  789 +
  790 + if (sorted_infos[2].index == sorted_infos[0].index){
  791 + if (sorted_infos[2].type_time - sorted_infos[1].type_time < 0.1){//no need to split
  792 + result.push_back(sorted_infos[2]);//put the audio end to the result
  793 + for (int i = 0; i < 3; i++){
  794 + sorted_infos.pop_front();
  795 + }
  796 + sorted_infos.push_front(second);
  797 + return 1;
  798 + }
  799 + }
  800 +
  801 + first.t_type = tt_end;
  802 + first.type_time = second.start_time;
  803 + result.push_back(first);
  804 +
  805 + for (int i = 0; i < 2; i++){
  806 + sorted_infos.pop_front();
  807 + }
  808 +
  809 + first.t_type = tt_start;
  810 + sorted_infos.push_front(first);
  811 + sorted_infos.push_front(second);
  812 + return 0;
  813 +}
  814 +
  815 +void get_front_info(int index_to, vector<media_info> &cur_processing)
  816 +{
  817 + cur_processing.clear();
  818 + for (int i = 0; i <= index_to; i++){
  819 + cur_processing.push_back(sorted_infos[i]);
  820 + }
  821 + for (int i = 0; i <= index_to; i++){
  822 + sorted_infos.pop_front();
  823 + }
  824 +}
  825 +
  826 +
  827 +
  828 +int concate_files_and_adjust_timecode(const char * output_dest_file){
  829 + if (merged_files.size() == 1){
  830 + printf("\n rename %s to %s", merged_files[0].c_str(), output_dest_file);
  831 + rename(merged_files[0].c_str(), output_dest_file);
  832 + }
  833 + else {
  834 + concate_files(merged_files, "m.ts");
  835 + tmp_files.push_back("m.ts");
  836 +
  837 + adjust_dest_timecode("m.ts", output_dest_file);
  838 + }
  839 +
  840 + if (!keep_tmp_files) {
  841 + removefiles(tmp_files);
  842 + removefiles(merged_files);
  843 + }
  844 +
  845 + merged_files.clear();
  846 + tmp_files.clear();
  847 +
  848 + return 0;
  849 +}
  850 +
  851 +
  852 +int get_output_file_name(int i, const char * file_prefix, char * outputfile){
  853 + char prefix[128];
  854 + const char * p = strstr(file_prefix, ".");
  855 + if (p) {
  856 + strncpy(prefix, file_prefix, p - file_prefix);
  857 + prefix[p - file_prefix] = 0;
  858 + }
  859 + else {
  860 + strcpy(prefix, file_prefix);
  861 + }
  862 +
  863 + sprintf(outputfile, "%s.ts", prefix, i);
  864 + return 0;
  865 +}
  866 +
  867 +bool is_need_output(int nOutPutFile, vector<media_info> & cur_processing, const char * first_file, char * outputfile)
  868 +{
  869 + if (sorted_infos.size()) {
  870 + int lastEnd = cur_processing[cur_processing.size() - 1].type_time;
  871 + int nextStart = sorted_infos.front().type_time;
  872 + if (nextStart - lastEnd < 0.2) {
  873 + return false;
  874 + }
  875 + }
  876 +
  877 + get_output_file_name(nOutPutFile, first_file, outputfile);
  878 + return true;
  879 +}
  880 +
  881 +void save_out_info(float start_time, char * outputfile)
  882 +{
  883 + if (fp_out_info) {
  884 + float duration = get_file_duration(outputfile, false);
  885 + fprintf(fp_out_info, "%.3f %.3f %s\n", start_time, duration, outputfile);
  886 + }
  887 +}
  888 +
  889 +
  890 +int process_va_files()
  891 +{
  892 + char outputfile[1024];
  893 + vector<media_info> cur_processing;
  894 +
  895 + int nOutPutFile = 0;
  896 + float start_time;
  897 + bool is_start = true;
  898 + string start_file;
  899 +
  900 + while (sorted_infos.size())
  901 + {
  902 + int channel = sorted_infos[0].channel;
  903 + if (0 == channel) {
  904 + if (!sorted_infos[1].index == sorted_infos[0].index)
  905 + {
  906 + split_ch0_for_no_process(cur_processing);
  907 + }
  908 + else{
  909 + get_front_info(1, cur_processing);
  910 + }
  911 + transcode_files(cur_processing);
  912 + }
  913 + else if (1 == channel) {
  914 + int index = find_video_end();
  915 + if (is_ch0_start(index - 1)) {
  916 + split_ch0_for_ch1(index - 1, cur_processing);
  917 + }
  918 + else {
  919 + get_front_info(index, cur_processing);
  920 + }
  921 + merge_audio_video(cur_processing);
  922 + }
  923 + //if the duration between the processed end and the start of not processed is large than 200 ms, reopen a new file
  924 + if (is_start){
  925 + start_time = cur_processing[0].start_time;
  926 + start_file = cur_processing[0].name;
  927 + is_start = false;
  928 + }
  929 + if (is_need_output(nOutPutFile, cur_processing, start_file.c_str(), outputfile)){
  930 + nOutPutFile++;
  931 + concate_files_and_adjust_timecode(outputfile);
  932 + save_out_info(start_time, outputfile);
  933 + is_start = true;
  934 + }
  935 + }
  936 + return 0;
  937 +}
  938 +
  939 +
  940 +int process_files()
  941 +{
  942 + //don't split video, for a video, using merged audios to mix with it
  943 + //for audio, mix with video or jpg
  944 + char outputfile[1024];
  945 + init();
  946 +
  947 + if (!media_files.size()){
  948 + return 0;
  949 + }
  950 +
  951 + fp_out_info = fopen(out_info_file, "wt");
  952 +
  953 + process_va_files();
  954 +
  955 + if (fp_out_info) {
  956 + fclose(fp_out_info);
  957 + }
  958 +
  959 + return 0;
  960 +}
  961 +
  962 +int readfile(char * filename)
  963 +{
  964 + ifstream fin(filename);
  965 + if (!fin) {
  966 + return -1;
  967 + }
  968 +
  969 + const int LINE_LENGTH = 1000;
  970 + char str[LINE_LENGTH];
  971 + while (fin.getline(str, LINE_LENGTH))
  972 + {
  973 + vector < string > res;
  974 + split(str, " ", res);
  975 + if (res.size() >= 3) {
  976 + if (res[2] == "create"){
  977 + addinfo(res[0], res[1], true);
  978 + }
  979 + else if (res[2] == "close") {
  980 + addinfo(res[0], res[1], false);
  981 + }
  982 + }
  983 + }
  984 + return 0;
  985 +}
  986 +// parse the filename like 4165000_20180203013327202.aac
  987 +#define get_sub_str_to_x(x , source, len, result) strncpy(x, source, len); x[len] = 0; source += len; result = atoi(x);
  988 +time_t time_sec_1970_base = 0;
  989 +float get_start_time_from_filename(const char * filename)
  990 +{
  991 + int year, month, day, hour, min, sec, minsec;
  992 + char buf[5];
  993 + const char * start = strstr(filename, "_");
  994 + start++;
  995 + const char * end = strstr(start, ".");
  996 +
  997 + get_sub_str_to_x(buf, start, 4, year);
  998 +
  999 + get_sub_str_to_x(buf, start, 2, month);
  1000 +
  1001 + get_sub_str_to_x(buf, start, 2, day);
  1002 +
  1003 + get_sub_str_to_x(buf, start, 2, hour);
  1004 +
  1005 + get_sub_str_to_x(buf, start, 2, min);
  1006 +
  1007 + get_sub_str_to_x(buf, start, 2, sec);
  1008 +
  1009 + get_sub_str_to_x(buf, start, 3, minsec);
  1010 +
  1011 + time_t t = calc_sec1970(year, month, day, hour, min, sec);
  1012 +
  1013 + if (!time_sec_1970_base) {
  1014 + time_sec_1970_base = calc_sec1970(year, month, day, 0, 0, 0);
  1015 + }
  1016 +
  1017 + t -= time_sec_1970_base;
  1018 +
  1019 + return (float)(t) + minsec / 1000.0;
  1020 +}
  1021 +
  1022 +int readfile(char * filename, int channel)
  1023 +{
  1024 + ifstream fin(filename);
  1025 + if (!fin) {
  1026 + return -1;
  1027 + }
  1028 +
  1029 + const int LINE_LENGTH = 1000;
  1030 + char str[LINE_LENGTH];
  1031 + float start_time;
  1032 + bool bstart_time = true;
  1033 + while (fin.getline(str, LINE_LENGTH))
  1034 + {
  1035 + vector < string > res;
  1036 + split(str, " ", res);
  1037 + if (res.size() == 3) {
  1038 + if (bstart_time) {
  1039 + start_time = get_start_time_from_filename(res[2].c_str());
  1040 + bstart_time = false;
  1041 + }
  1042 + addinfo(atof(res[0].c_str()) + start_time ,atof(res[1].c_str()) , res[2], channel);
  1043 + }
  1044 + }
  1045 + return 0;
  1046 +}
  1047 +
  1048 +
  1049 +void load_codec_param()
  1050 +{
  1051 + strcpy(acodec_param, default_acodec_param);
  1052 + strcpy(vcodec_param, default_vcodec_param);
  1053 + strcpy(av_codec_param, default_av_codec_param);
  1054 + strcpy(pip_param, default_pip_param);
  1055 +
  1056 + char cfgfile[1024];
  1057 +
  1058 + strcpy(cfgfile, cfg_path);
  1059 + strcat(cfgfile, "merge_av.cfg");
  1060 +
  1061 + ifstream fin(cfgfile);
  1062 + if (!fin) {
  1063 + return;
  1064 + }
  1065 + const int LINE_LENGTH = 1000;
  1066 + char str[LINE_LENGTH];
  1067 + str[0] = 0;
  1068 + if (fin.getline(str, LINE_LENGTH))
  1069 + {
  1070 + printf("\nload video codec from %s: %s\n", cfgfile, str);
  1071 + strcpy(vcodec_param, str);
  1072 + }
  1073 + str[0] = 0;
  1074 + if (fin.getline(str, LINE_LENGTH))
  1075 + {
  1076 + printf("load audio codec from %s: %s\n", cfgfile, str);
  1077 + strcpy(acodec_param, str);
  1078 + }
  1079 + str[0] = 0;
  1080 + if (fin.getline(str, LINE_LENGTH))
  1081 + {
  1082 + printf("load av codec from %s: %s\n", cfgfile, str);
  1083 + strcpy(av_codec_param, str);
  1084 + }
  1085 + str[0] = 0;
  1086 + if (fin.getline(str, LINE_LENGTH))
  1087 + {
  1088 + printf("load av codec from %s: %s\n", cfgfile, str);
  1089 + strcpy(pip_param, str);
  1090 + }
  1091 +}
  1092 +
  1093 +void get_outinfo_file_name(char * input1 , char * input2)
  1094 +{
  1095 + strcpy(out_info_file, input1);
  1096 + char * p = strstr(out_info_file, ".");
  1097 + if (p) {
  1098 + *p = 0;
  1099 + }
  1100 + strcat(out_info_file, "__");
  1101 + strcat(out_info_file, input2);
  1102 +}
  1103 +
  1104 +int main(int argc, char * argv[])
  1105 +{
  1106 + if (argc < 3) {
  1107 + printf(" pip 1.0.0\n");
  1108 + printf(" run ffmpeg to merge video files to one pip video according to the processed record info file,\nusage:");
  1109 + printf("\n %s record_info_out_filename1 record_info_out_filename2 [-p] [-k]", argv[0]);
  1110 + printf("\n -p :only print the command,don't run ffmpeg");
  1111 + printf("\n -k :keep the temp files\n");
  1112 + return -1;
  1113 + }
  1114 +
  1115 + if (readfile(argv[1], 0) < 0) {
  1116 + printf("open file: %s error", argv[1]);
  1117 + return -2;
  1118 + }
  1119 +
  1120 + if (readfile(argv[2], 1) < 0) {
  1121 + printf("open file: %s error", argv[1]);
  1122 + return -2;
  1123 + }
  1124 +
  1125 + for (int i = 3; i < argc; i++){
  1126 + if (!strcmp(argv[i], "-p")){
  1127 + only_print = true;
  1128 + }
  1129 + else if (!strcmp(argv[i], "-k")){
  1130 + keep_tmp_files = true;
  1131 + }
  1132 + }
  1133 +
  1134 + get_outinfo_file_name(argv[1], argv[2]);
  1135 +
  1136 + get_config_path();
  1137 +
  1138 + load_codec_param();
  1139 +
  1140 + process_files();
  1141 +
  1142 + return 0;
  1143 +}
  1144 +
  1 +<?xml version="1.0" encoding="utf-8"?>
  2 +<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  3 + <ItemGroup Label="ProjectConfigurations">
  4 + <ProjectConfiguration Include="Debug|Win32">
  5 + <Configuration>Debug</Configuration>
  6 + <Platform>Win32</Platform>
  7 + </ProjectConfiguration>
  8 + <ProjectConfiguration Include="Release|Win32">
  9 + <Configuration>Release</Configuration>
  10 + <Platform>Win32</Platform>
  11 + </ProjectConfiguration>
  12 + </ItemGroup>
  13 + <PropertyGroup Label="Globals">
  14 + <ProjectGuid>{7D6B14AD-7FD2-45F1-A196-A2455406D4FB}</ProjectGuid>
  15 + <Keyword>Win32Proj</Keyword>
  16 + <RootNamespace>pip</RootNamespace>
  17 + </PropertyGroup>
  18 + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
  19 + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
  20 + <ConfigurationType>Application</ConfigurationType>
  21 + <UseDebugLibraries>true</UseDebugLibraries>
  22 + <PlatformToolset>v120</PlatformToolset>
  23 + <CharacterSet>Unicode</CharacterSet>
  24 + </PropertyGroup>
  25 + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
  26 + <ConfigurationType>Application</ConfigurationType>
  27 + <UseDebugLibraries>false</UseDebugLibraries>
  28 + <PlatformToolset>v120</PlatformToolset>
  29 + <WholeProgramOptimization>true</WholeProgramOptimization>
  30 + <CharacterSet>Unicode</CharacterSet>
  31 + </PropertyGroup>
  32 + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
  33 + <ImportGroup Label="ExtensionSettings">
  34 + </ImportGroup>
  35 + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
  36 + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
  37 + </ImportGroup>
  38 + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
  39 + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
  40 + </ImportGroup>
  41 + <PropertyGroup Label="UserMacros" />
  42 + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
  43 + <LinkIncremental>true</LinkIncremental>
  44 + </PropertyGroup>
  45 + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
  46 + <LinkIncremental>false</LinkIncremental>
  47 + </PropertyGroup>
  48 + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
  49 + <ClCompile>
  50 + <PrecompiledHeader>
  51 + </PrecompiledHeader>
  52 + <WarningLevel>Level3</WarningLevel>
  53 + <Optimization>Disabled</Optimization>
  54 + <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
  55 + </ClCompile>
  56 + <Link>
  57 + <SubSystem>Console</SubSystem>
  58 + <GenerateDebugInformation>true</GenerateDebugInformation>
  59 + </Link>
  60 + </ItemDefinitionGroup>
  61 + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
  62 + <ClCompile>
  63 + <WarningLevel>Level3</WarningLevel>
  64 + <PrecompiledHeader>
  65 + </PrecompiledHeader>
  66 + <Optimization>MaxSpeed</Optimization>
  67 + <FunctionLevelLinking>true</FunctionLevelLinking>
  68 + <IntrinsicFunctions>true</IntrinsicFunctions>
  69 + <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
  70 + </ClCompile>
  71 + <Link>
  72 + <SubSystem>Console</SubSystem>
  73 + <GenerateDebugInformation>true</GenerateDebugInformation>
  74 + <EnableCOMDATFolding>true</EnableCOMDATFolding>
  75 + <OptimizeReferences>true</OptimizeReferences>
  76 + </Link>
  77 + </ItemDefinitionGroup>
  78 + <ItemGroup>
  79 + <Text Include="ReadMe.txt" />
  80 + </ItemGroup>
  81 + <ItemGroup>
  82 + <ClCompile Include="pip.cpp" />
  83 + <ClCompile Include="tools.cpp" />
  84 + </ItemGroup>
  85 + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
  86 + <ImportGroup Label="ExtensionTargets">
  87 + </ImportGroup>
  88 +</Project>
  1 +<?xml version="1.0" encoding="utf-8"?>
  2 +<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  3 + <ItemGroup>
  4 + <Filter Include="源文件">
  5 + <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
  6 + <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
  7 + </Filter>
  8 + <Filter Include="头文件">
  9 + <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
  10 + <Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
  11 + </Filter>
  12 + <Filter Include="资源文件">
  13 + <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
  14 + <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
  15 + </Filter>
  16 + </ItemGroup>
  17 + <ItemGroup>
  18 + <Text Include="ReadMe.txt" />
  19 + </ItemGroup>
  20 + <ItemGroup>
  21 + <ClCompile Include="pip.cpp">
  22 + <Filter>源文件</Filter>
  23 + </ClCompile>
  24 + <ClCompile Include="tools.cpp">
  25 + <Filter>源文件</Filter>
  26 + </ClCompile>
  27 + </ItemGroup>
  28 +</Project>
  1 +#include "tools.h"
  2 +
  3 +#define is_leap_year(y) (((y) % 4 == 0 && (y) % 100 != 0) || (y) % 400 == 0)
  4 +
  5 +/* 计算某个日期距1970年1月1日0时0分0秒的秒数 */
  6 +time_t calc_sec1970(int Y, int M, int D, int h, int m, int s)
  7 +{
  8 + int i = 0;
  9 + int sec = 0;
  10 + int days[13] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
  11 +
  12 + /* 年计算 */
  13 + for (i = 1970; i < Y; i++)
  14 + {
  15 + if (is_leap_year(i))
  16 + sec += 366 * 24 * 60 * 60;
  17 + else
  18 + sec += 365 * 24 * 60 * 60;
  19 + }
  20 +
  21 + /* 月计算 */
  22 + for (i = 1; i < M; i++)
  23 + {
  24 + sec += days[i] * 24 * 60 * 60;
  25 + if (i == 2 && is_leap_year(Y))
  26 + {
  27 + sec += 24 * 60 * 60;
  28 + }
  29 + }
  30 +
  31 + /* 天计算 */
  32 + sec += (D - 1) * 24 * 60 * 60;
  33 +
  34 + /* 时分秒计算 */
  35 + sec += h * 60 * 60 + m * 60 + s;
  36 +
  37 + return sec;
  38 +}
  1 +#ifndef TOOLS_H
  2 +#define TOOLS_H
  3 +#include <time.h>
  4 +time_t calc_sec1970(int Y, int M, int D, int h, int m, int s);
  5 +#endif