胡斌

first commit of using ffmpeg code

@@ -21,6 +21,11 @@ enum media_type{ @@ -21,6 +21,11 @@ enum media_type{
21 mt_av = 3, 21 mt_av = 3,
22 }; 22 };
23 23
  24 +enum media_role {
  25 + mr_teacher =0,
  26 + mr_student =1,
  27 +};
  28 +
24 enum timestamp_type{ 29 enum timestamp_type{
25 tt_start = 0, 30 tt_start = 0,
26 tt_end = 1, 31 tt_end = 1,
@@ -33,7 +38,7 @@ public: @@ -33,7 +38,7 @@ public:
33 string name; 38 string name;
34 int index; 39 int index;
35 media_type m_type; 40 media_type m_type;
36 - int channel; 41 + media_role m_rote;
37 int rotate; //degree,0,90,180 ... 42 int rotate; //degree,0,90,180 ...
38 }; 43 };
39 44
@@ -47,8 +52,8 @@ public: @@ -47,8 +52,8 @@ public:
47 52
48 float duration; 53 float duration;
49 int index; 54 int index;
50 - int channel;  
51 media_type m_type; 55 media_type m_type;
  56 + media_role m_rote;
52 timestamp_type t_type; 57 timestamp_type t_type;
53 }; 58 };
54 59
@@ -120,40 +125,24 @@ char acodec_param[1024]; @@ -120,40 +125,24 @@ char acodec_param[1024];
120 char pip_param[1024]; 125 char pip_param[1024];
121 char pip1_param[1024]; 126 char pip1_param[1024];
122 127
123 -bool first_time_set = false;  
124 -float start_time = 0.0f;  
125 -  
126 -void init_read_file() {  
127 - first_time_set = false;  
128 - start_time = 0.0f;  
129 -}  
130 -  
131 -  
132 -void addinfo(string t, string name, bool bstart){ 128 +void addinfo(float t, string name, bool bstart,media_role role){
133 media_type mtype = name.substr(name.length() - 4, name.length()) == ".aac" ? mt_audio : mt_video; 129 media_type mtype = name.substr(name.length() - 4, name.length()) == ".aac" ? mt_audio : mt_video;
134 if (bstart) { 130 if (bstart) {
135 fileinfo f; 131 fileinfo f;
136 - f.start_time = atof(t.c_str()); 132 + f.start_time = t;
137 f.end_time = f.start_time; 133 f.end_time = f.start_time;
138 f.name = name; 134 f.name = name;
139 f.m_type = mtype; 135 f.m_type = mtype;
  136 + f.m_rote = role;
140 f.rotate = 0; 137 f.rotate = 0;
141 138
142 - if (!first_time_set) {  
143 - first_time_set = true;  
144 - start_time = f.start_time;  
145 - }  
146 -  
147 - f.start_time -= start_time;  
148 -  
149 media_files.push_back(f); 139 media_files.push_back(f);
150 } 140 }
151 else { 141 else {
152 int i; 142 int i;
153 for (i = 0; i < media_files.size(); i++) { 143 for (i = 0; i < media_files.size(); i++) {
154 if (media_files[i].name == name) { 144 if (media_files[i].name == name) {
155 - media_files[i].end_time = atof(t.c_str());  
156 - media_files[i].end_time -= start_time; 145 + media_files[i].end_time = t;
157 break; 146 break;
158 } 147 }
159 } 148 }
@@ -187,7 +176,6 @@ void addinfo(float start, float duration, string name, int channel){ @@ -187,7 +176,6 @@ void addinfo(float start, float duration, string name, int channel){
187 f.end_time = f.start_time + duration; 176 f.end_time = f.start_time + duration;
188 f.name = name; 177 f.name = name;
189 f.m_type = mtype; 178 f.m_type = mtype;
190 - f.channel = channel;  
191 179
192 media_files.push_back(f); 180 media_files.push_back(f);
193 } 181 }
@@ -680,7 +668,6 @@ void add_media_infos() @@ -680,7 +668,6 @@ void add_media_infos()
680 m.end_time = f.end_time; 668 m.end_time = f.end_time;
681 m.m_type = f.m_type; 669 m.m_type = f.m_type;
682 m.t_type = tt_start; 670 m.t_type = tt_start;
683 - m.channel = f.channel;  
684 m.duration = f.end_time - f.start_time; 671 m.duration = f.end_time - f.start_time;
685 m.type_time = m.start_time; 672 m.type_time = m.start_time;
686 m.rotate = f.rotate; 673 m.rotate = f.rotate;
@@ -847,54 +834,6 @@ int find_video_between_the_audio() @@ -847,54 +834,6 @@ int find_video_between_the_audio()
847 return video_index; 834 return video_index;
848 } 835 }
849 836
850 -int merge_video_pip(vector<media_info> & files)  
851 -{  
852 - char ch0_file[1024], ch1_file[1024];  
853 - vector<string> merge_video_files;  
854 -  
855 - media_info ch0_start, ch0_end, ch1_start, ch1_end;  
856 -  
857 - if (files[0].channel == 0) {  
858 - ch0_start = files[0];  
859 - ch0_end = files[2];  
860 - ch1_start = files[1];  
861 - ch1_end = files[3];  
862 - }  
863 - else {  
864 - ch0_start = files[1];  
865 - ch0_end = files[3];  
866 - ch1_start = files[0];  
867 - ch1_end = files[2];  
868 - }  
869 -  
870 -  
871 - if (ch0_start.type_time - ch0_start.start_time > 0.10 || ch0_end.end_time - ch0_end.type_time > 0.10) {  
872 - sprintf(ch0_file, "%d_%s", nf, ch0_start.name.c_str());  
873 - split_av(ch0_start.name.c_str(), ch0_start.type_time - ch0_start.start_time, ch0_end.type_time - ch0_start.type_time, ch0_file);  
874 - tmp_files.push_back(ch0_file);  
875 - }  
876 - else{  
877 - strcpy(ch0_file, ch0_start.name.c_str());  
878 - }  
879 -  
880 -  
881 - if (ch1_start.type_time - ch1_start.start_time > 0.10 || ch1_end.end_time - ch1_end.type_time > 0.10) {  
882 - sprintf(ch1_file, "%d_%s", nf, ch1_start.name.c_str());  
883 - split_av(ch1_start.name.c_str(), ch1_start.type_time - ch1_start.start_time, ch1_end.type_time - ch1_start.type_time, ch1_file);  
884 - tmp_files.push_back(ch1_file);  
885 - }  
886 - else{  
887 - strcpy(ch1_file, ch1_start.name.c_str());  
888 - }  
889 -  
890 - sprintf(destfile, "%d.ts", nf);  
891 - merge_video_pip(ch0_file, ch1_file, destfile);  
892 - merged_files.push_back(destfile);  
893 - nf++;  
894 -  
895 - return 0;  
896 -}  
897 -  
898 837
899 int transcode_file(vector<media_info> files) 838 int transcode_file(vector<media_info> files)
900 { 839 {
@@ -952,10 +891,6 @@ bool is_audio_start(int index) @@ -952,10 +891,6 @@ bool is_audio_start(int index)
952 return (sorted_infos[index].m_type == mt_audio && sorted_infos[index].t_type == tt_start); 891 return (sorted_infos[index].m_type == mt_audio && sorted_infos[index].t_type == tt_start);
953 } 892 }
954 893
955 -bool is_ch0_start(int index)  
956 -{  
957 - return (sorted_infos[index].channel == 0 && sorted_infos[index].t_type == tt_start);  
958 -}  
959 894
960 895
961 int split_audio_for_video(int audio_start,vector<media_info> & result) 896 int split_audio_for_video(int audio_start,vector<media_info> & result)
@@ -1362,159 +1297,7 @@ int process_va_files() @@ -1362,159 +1297,7 @@ int process_va_files()
1362 return 0; 1297 return 0;
1363 } 1298 }
1364 1299
1365 -int process_merged_files()  
1366 -{  
1367 - char outputfile[1024];  
1368 - vector<media_info> cur_processing;  
1369 -  
1370 - int nOutPutFile = 0;  
1371 - float start_time;  
1372 - bool is_start = true;  
1373 - string start_file;  
1374 1300
1375 - while (sorted_infos.size())  
1376 - {  
1377 - int channel = sorted_infos[0].channel;  
1378 - if (sorted_infos[1].index == sorted_infos[0].index)  
1379 - {  
1380 - get_front_info(1, cur_processing);  
1381 - transcode_file(cur_processing);  
1382 - }  
1383 - else if (sorted_infos[1].type_time - sorted_infos[0].type_time > 0.2) {  
1384 - split_ch0_for_no_process(cur_processing);  
1385 - transcode_file(cur_processing);  
1386 - }  
1387 - else {  
1388 - split_ch0_for_ch1( cur_processing);  
1389 - merge_video_pip(cur_processing);  
1390 - }  
1391 - //if the duration between the processed end and the start of not processed is large than 200 ms, reopen a new file  
1392 - if (is_start){  
1393 - start_time = cur_processing[0].start_time;  
1394 - start_file = cur_processing[0].name;  
1395 - is_start = false;  
1396 - }  
1397 - if (is_need_output(nOutPutFile, cur_processing, start_file.c_str(), outputfile, PIP_PREFIX)){  
1398 - nOutPutFile++;  
1399 - concate_files_and_adjust_timecode(outputfile);  
1400 - save_out_info(start_time, outputfile);  
1401 - is_start = true;  
1402 - }  
1403 - }  
1404 - return 0;  
1405 -}  
1406 -  
1407 -int process_record_file_to_ts()  
1408 -{  
1409 - //don't split video, for a video, using merged audios to mix with it  
1410 - //for audio, mix with video or jpg  
1411 - char outputfile[1024];  
1412 - init_merge_av();  
1413 -  
1414 - if (!media_files.size()){  
1415 - return 0;  
1416 - }  
1417 -  
1418 - fp_out_info = fopen(out_info_file, "wt");  
1419 -  
1420 - // judge if it is only one type  
1421 - media_type mt = media_files[0].m_type;  
1422 - bool only_one_type = true;  
1423 - for (int i = 1; i < media_files.size(); i++){  
1424 - if (mt != media_files[i].m_type){  
1425 - only_one_type = false;  
1426 - break;  
1427 - }  
1428 - }  
1429 -  
1430 - if (only_one_type){  
1431 - if (mt == mt_audio) {  
1432 - for (int i = 0; i < media_files.size(); i++){  
1433 - fileinfo audio = media_files[i];  
1434 - get_output_file_name(i, audio.name.c_str(), MERGED_PREFIX, outputfile);  
1435 - merge_audio_pic(audio.name.c_str(), blank_pic_file, outputfile);  
1436 - save_out_info(audio.start_time, outputfile);  
1437 - }  
1438 - }  
1439 - else {  
1440 - for (int i = 0; i < media_files.size(); i++){  
1441 - fileinfo video = media_files[i];  
1442 - get_output_file_name(i, video.name.c_str(), MERGED_PREFIX, outputfile);  
1443 - merge_video_silence(video, silence_aac_file, destfile);  
1444 - save_out_info(video.start_time, outputfile);  
1445 - }  
1446 - }  
1447 - }  
1448 - else {  
1449 - process_va_files();  
1450 - }  
1451 -  
1452 - if (fp_out_info) {  
1453 - fclose(fp_out_info);  
1454 - }  
1455 -  
1456 - return 0;  
1457 -}  
1458 -  
1459 -int process_merged_files_to_pip_files()  
1460 -{  
1461 - //don't split video, for a video, using merged audios to mix with it  
1462 - //for audio, mix with video or jpg  
1463 - char outputfile[1024];  
1464 -  
1465 -  
1466 - if (!media_files.size()){  
1467 - return 0;  
1468 - }  
1469 -  
1470 - init_merge_pip();  
1471 -  
1472 - fp_out_info = fopen(out_info_file, "wt");  
1473 -  
1474 - process_merged_files();  
1475 -  
1476 - if (fp_out_info) {  
1477 - fclose(fp_out_info);  
1478 - }  
1479 -  
1480 - return 0;  
1481 -}  
1482 -  
1483 -int readfile(const char * filename)  
1484 -{  
1485 - init_read_file();  
1486 - media_files.clear();  
1487 -  
1488 - ifstream fin(filename);  
1489 - if (!fin) {  
1490 - return -1;  
1491 - }  
1492 -  
1493 - const int LINE_LENGTH = 1000;  
1494 - char str[LINE_LENGTH];  
1495 - while (fin.getline(str, LINE_LENGTH))  
1496 - {  
1497 - vector < string > res;  
1498 - split(str, " ", res);  
1499 - if (res.size() >= 3) {  
1500 - if (res[2] == "create"){  
1501 - addinfo(res[0], res[1], true);  
1502 - }  
1503 - else if (res[2] == "close") {  
1504 - addinfo(res[0], res[1], false);  
1505 - }  
1506 - else if (res[2] == "info") {  
1507 - if (res.size() > 5) {  
1508 - const char * pInfo = res[5].c_str();  
1509 - if (!strncmp(pInfo, "rotation=", 9)){  
1510 - addinfo(res[0].c_str(), res[1].c_str(), pInfo + 9);  
1511 - }  
1512 - }  
1513 - }  
1514 - }  
1515 - }  
1516 - return 0;  
1517 -}  
1518 1301
1519 // parse the filename like 4165000_20180203013327202.aac 1302 // parse the filename like 4165000_20180203013327202.aac
1520 #define get_sub_str_to_x(x , source, len, result) strncpy(x, source, len); x[len] = 0; source += len; result = atoi(x); 1303 #define get_sub_str_to_x(x , source, len, result) strncpy(x, source, len); x[len] = 0; source += len; result = atoi(x);
@@ -1524,8 +1307,12 @@ float get_start_time_from_filename(const char * filename) @@ -1524,8 +1307,12 @@ float get_start_time_from_filename(const char * filename)
1524 int year, month, day, hour, min, sec, minsec; 1307 int year, month, day, hour, min, sec, minsec;
1525 char buf[5]; 1308 char buf[5];
1526 const char * start = strstr(filename, "_"); 1309 const char * start = strstr(filename, "_");
  1310 + const char * end = strstr(start + 1, "_");
  1311 + if (end) {//get the next
  1312 + start = end;
  1313 + }
1527 start++; 1314 start++;
1528 - const char * end = strstr(start, "."); 1315 + end = strstr(start, ".");
1529 1316
1530 get_sub_str_to_x(buf, start, 4, year); 1317 get_sub_str_to_x(buf, start, 4, year);
1531 1318
@@ -1552,37 +1339,43 @@ float get_start_time_from_filename(const char * filename) @@ -1552,37 +1339,43 @@ float get_start_time_from_filename(const char * filename)
1552 return (float)(t) + minsec / 1000.0; 1339 return (float)(t) + minsec / 1000.0;
1553 } 1340 }
1554 1341
1555 -vector<string> all_input_files_for_pip;  
1556 1342
1557 -int readfile(const char * filename, int channel) 1343 +int readfile(const char * filename, media_role role)
1558 { 1344 {
1559 - init_read_file();  
1560 -  
1561 ifstream fin(filename); 1345 ifstream fin(filename);
1562 if (!fin) { 1346 if (!fin) {
1563 return -1; 1347 return -1;
1564 } 1348 }
1565 1349
  1350 + float start_time = get_start_time_from_filename(filename);
  1351 +
1566 const int LINE_LENGTH = 1000; 1352 const int LINE_LENGTH = 1000;
1567 char str[LINE_LENGTH]; 1353 char str[LINE_LENGTH];
1568 - float start_time;  
1569 - bool bstart_time = true;  
1570 while (fin.getline(str, LINE_LENGTH)) 1354 while (fin.getline(str, LINE_LENGTH))
1571 { 1355 {
1572 vector < string > res; 1356 vector < string > res;
1573 split(str, " ", res); 1357 split(str, " ", res);
1574 - if (res.size() == 3) {  
1575 - if (bstart_time) {  
1576 - start_time = get_start_time_from_filename(res[2].c_str() + strlen(MERGED_PREFIX));  
1577 - bstart_time = false; 1358 + if (res.size() >= 3) {
  1359 + if (res[2] == "create"){
  1360 + addinfo(start_time + atof(res[0].c_str()), res[1], true, role);
  1361 + }
  1362 + else if (res[2] == "close") {
  1363 + addinfo(start_time + atof(res[0].c_str()), res[1], false, role);
  1364 + }
  1365 + else if (res[2] == "info") {
  1366 + if (res.size() > 5) {
  1367 + const char * pInfo = res[5].c_str();
  1368 + if (!strncmp(pInfo, "rotation=", 9)){
  1369 + addinfo(res[0].c_str(), res[1].c_str(), pInfo + 9);
  1370 + }
  1371 + }
1578 } 1372 }
1579 - addinfo(atof(res[0].c_str()) + start_time ,atof(res[1].c_str()) , res[2], channel);  
1580 - all_input_files_for_pip.push_back(res[2]);  
1581 } 1373 }
1582 } 1374 }
1583 return 0; 1375 return 0;
1584 } 1376 }
1585 1377
  1378 +vector<string> all_input_files_for_pip;
1586 1379
1587 void load_codec_param() 1380 void load_codec_param()
1588 { 1381 {
@@ -1645,7 +1438,7 @@ void get_outinfo_file_name(char * input) @@ -1645,7 +1438,7 @@ void get_outinfo_file_name(char * input)
1645 strcat(out_info_file, "_out.txt"); 1438 strcat(out_info_file, "_out.txt");
1646 } 1439 }
1647 1440
1648 -int process_record_info_to_ts(char * record_info, vector<string> & merged_info1, vector<string> & merged_info2) 1441 +int load_record_info(char * record_info)
1649 { 1442 {
1650 ifstream fin(record_info); 1443 ifstream fin(record_info);
1651 if (!fin) { 1444 if (!fin) {
@@ -1657,6 +1450,9 @@ int process_record_info_to_ts(char * record_info, vector<string> & merged_info1, @@ -1657,6 +1450,9 @@ int process_record_info_to_ts(char * record_info, vector<string> & merged_info1,
1657 bool bInTeacher = false; 1450 bool bInTeacher = false;
1658 bool bInStudent = false; 1451 bool bInStudent = false;
1659 int nstudent = 0; 1452 int nstudent = 0;
  1453 +
  1454 + media_files.clear();
  1455 +
1660 while (fin.getline(str, LINE_LENGTH)) 1456 while (fin.getline(str, LINE_LENGTH))
1661 { 1457 {
1662 if (!strncmp(str, "teacher:", 8)){ 1458 if (!strncmp(str, "teacher:", 8)){
@@ -1673,40 +1469,26 @@ int process_record_info_to_ts(char * record_info, vector<string> & merged_info1, @@ -1673,40 +1469,26 @@ int process_record_info_to_ts(char * record_info, vector<string> & merged_info1,
1673 continue;//assume the file name > 20 1469 continue;//assume the file name > 20
1674 } 1470 }
1675 else if (bInTeacher){ 1471 else if (bInTeacher){
1676 - readfile(str);  
1677 - get_outinfo_file_name(str);  
1678 - merged_info1.push_back(out_info_file);  
1679 - process_record_file_to_ts(); 1472 + readfile(str, mr_teacher);
1680 } 1473 }
1681 else if (bInStudent){ 1474 else if (bInStudent){
1682 - readfile(str);  
1683 - get_outinfo_file_name(str);  
1684 - merged_info2.push_back(out_info_file);  
1685 - process_record_file_to_ts(); 1475 + readfile(str, mr_student);
1686 } 1476 }
1687 } 1477 }
  1478 +
  1479 + unifiy_start_time();
  1480 +
  1481 + add_media_infos();
  1482 +
1688 return 0; 1483 return 0;
1689 } 1484 }
1690 1485
1691 -//#define TEST  
1692 int main(int argc, char * argv[]) 1486 int main(int argc, char * argv[])
1693 { 1487 {
1694 -#ifdef TEST  
1695 - const char * video = "D:\\media\\talk\\20181112\\talk915_824250397_105638\\137786519_20181112105817677.ts";  
1696 - const char * dest = "D:\\media\\talk\\20181112\\talk915_824250397_105638\\137786519_20181112105817677.ts.jpg";  
1697 - get_config_path();  
1698 - load_codec_param();  
1699 - init_merge_av();  
1700 - get_video_last_frame_jpeg(video, dest);  
1701 - merge_pic_silence(dest, 1.56, "D:\\media\\talk\\20181112\\talk915_824250397_105638\\137786519_20181112105817677_last_s156.ts");  
1702 -#endif  
1703 -  
1704 if (argc < 2) { 1488 if (argc < 2) {
1705 - printf(" merge_pip 1.0.2\n");  
1706 - printf(" run ffmpeg to merge video files to one pip video according to record info file,\nusage:"); 1489 + printf(" merge_pip 2.0.0\n");
  1490 + printf(" merge video files to one pip video according to record info file,\nusage:");
1707 printf("\n %s record_info_filename [-p] [-k]", argv[0]); 1491 printf("\n %s record_info_filename [-p] [-k]", argv[0]);
1708 - printf("\n -p :only print the command,don't run ffmpeg");  
1709 - printf("\n -k :keep the temp files");  
1710 printf("\n -d :individual files for different time segment"); 1492 printf("\n -d :individual files for different time segment");
1711 printf("\n\n"); 1493 printf("\n\n");
1712 return -1; 1494 return -1;
@@ -1716,85 +1498,598 @@ int main(int argc, char * argv[]) @@ -1716,85 +1498,598 @@ int main(int argc, char * argv[])
1716 1498
1717 load_codec_param(); 1499 load_codec_param();
1718 1500
1719 - bool bmerge_files = true;  
1720 -  
1721 for (int i = 2; i < argc; i++){ 1501 for (int i = 2; i < argc; i++){
1722 - if (!strcmp(argv[i], "-p")){  
1723 - only_print = true;  
1724 - }  
1725 - else if (!strcmp(argv[i], "-k")){  
1726 - keep_tmp_files = true;  
1727 - }  
1728 - else if (!strcmp(argv[i], "-n")){  
1729 - bmerge_files = false;  
1730 - }  
1731 - else if (!strcmp(argv[i], "-d")){ 1502 + if (!strcmp(argv[i], "-d")){
1732 out_one_video = false; 1503 out_one_video = false;
1733 } 1504 }
1734 } 1505 }
1735 1506
1736 - vector<string> merged_info1;  
1737 - vector<string> merged_info2;  
1738 -#if 0  
1739 - if (bmerge_files) {  
1740 - if (readfile(argv[1]) < 0) {  
1741 - printf("open file: %s error", argv[1]);  
1742 - return -2;  
1743 - }  
1744 -  
1745 - get_outinfo_file_name(argv[1]);  
1746 - strcpy(merged_info1, out_info_file);  
1747 - process_record_file_to_ts();  
1748 -  
1749 -  
1750 -  
1751 - if (readfile(argv[2]) < 0) {  
1752 - printf("open file: %s error", argv[1]);  
1753 - return -2;  
1754 - }  
1755 -  
1756 - get_outinfo_file_name(argv[2]);  
1757 - strcpy(merged_info2, out_info_file);  
1758 - process_record_file_to_ts();  
1759 - }  
1760 - else {  
1761 - strcpy(merged_info1, argv[1]);  
1762 - strcpy(merged_info2, argv[2]);  
1763 - }  
1764 -#else  
1765 - process_record_info_to_ts(argv[1], merged_info1, merged_info2);  
1766 -  
1767 -#endif  
1768 -  
1769 - media_files.clear();  
1770 - for (int i = 0; i < merged_info1.size(); i++) {  
1771 - if (readfile(merged_info1[i].c_str(), 0) < 0) {  
1772 - printf("open file: %s error", merged_info1[i].c_str());  
1773 - return -2;  
1774 - }  
1775 - }  
1776 -  
1777 - for (int i = 0; i < merged_info2.size(); i++) {  
1778 - if (readfile(merged_info2[i].c_str(), 1) < 0) {  
1779 - printf("open file: %s error", merged_info2[i].c_str());  
1780 - return -2;  
1781 - }  
1782 - }  
1783 -  
1784 -#if 0  
1785 - get_outinfo_file_name(argv[1], argv[2]);  
1786 -#else  
1787 - get_outinfo_file_name(argv[1]);  
1788 -#endif  
1789 -  
1790 - process_merged_files_to_pip_files();  
1791 -  
1792 - if (!keep_tmp_files && bmerge_files) {  
1793 - removefiles(all_input_files_for_pip);  
1794 - removefiles(merged_info1);  
1795 - removefiles(merged_info2);  
1796 - }  
1797 -  
1798 - return 0;  
1799 -} 1507 + load_record_info(argv[1]);
  1508 +}
  1509 +
  1510 +
  1511 +#define __STDC_FORMAT_MACROS
  1512 +#include <stdint.h>
  1513 +#include <inttypes.h>
  1514 +extern "C" {
  1515 +#include <libavcodec/avcodec.h>
  1516 +#include <libavformat/avformat.h>
  1517 +#include <libavfilter/avfiltergraph.h>
  1518 +#include <libavfilter/buffersink.h>
  1519 +#include <libavfilter/buffersrc.h>
  1520 +#include <libavutil/opt.h>
  1521 +#include <libavutil/pixdesc.h>
  1522 +}
  1523 +#ifdef WIN32
  1524 +#pragma comment(lib, "avcodec.lib")
  1525 +#pragma comment(lib, "avdevice.lib")
  1526 +#pragma comment(lib, "avfilter.lib")
  1527 +#pragma comment(lib, "avformat.lib")
  1528 +#pragma comment(lib, "avutil.lib")
  1529 +#pragma comment(lib, "postproc.lib")
  1530 +#pragma comment(lib, "swresample.lib")
  1531 +#pragma comment(lib, "swscale.lib")
  1532 +#endif
  1533 +
  1534 +#if _MSC_VER
  1535 +#define snprintf _snprintf
  1536 +#define PRIu64 "I64u"
  1537 +#define PRId64 "I64d"
  1538 +#define PRIx64 "I64x"
  1539 +#define PRIX64 "I64X"
  1540 +#endif
  1541 +
  1542 +
  1543 +static AVFormatContext *ifmt_ctx;
  1544 +static AVFormatContext *ofmt_ctx;
  1545 +typedef struct FilteringContext {
  1546 + AVFilterContext *buffersink_ctx;
  1547 + AVFilterContext *buffersrc_ctx;
  1548 + AVFilterGraph *filter_graph;
  1549 +} FilteringContext;
  1550 +static FilteringContext *filter_ctx;
  1551 +
  1552 +static int open_input_file(const char *filename)
  1553 +{
  1554 + int ret;
  1555 + unsigned int i;
  1556 +
  1557 + ifmt_ctx = NULL;
  1558 + if ((ret = avformat_open_input(&ifmt_ctx, filename, NULL, NULL)) < 0) {
  1559 + av_log(NULL, AV_LOG_ERROR, "Cannot open input file\n");
  1560 + return ret;
  1561 + }
  1562 +
  1563 + if ((ret = avformat_find_stream_info(ifmt_ctx, NULL)) < 0) {
  1564 + av_log(NULL, AV_LOG_ERROR, "Cannot find stream information\n");
  1565 + return ret;
  1566 + }
  1567 +
  1568 + for (i = 0; i < ifmt_ctx->nb_streams; i++) {
  1569 + AVStream *stream;
  1570 + AVCodecContext *codec_ctx;
  1571 + stream = ifmt_ctx->streams[i];
  1572 + codec_ctx = stream->codec;
  1573 + /* Reencode video & audio and remux subtitles etc. */
  1574 + if (codec_ctx->codec_type == AVMEDIA_TYPE_VIDEO
  1575 + || codec_ctx->codec_type == AVMEDIA_TYPE_AUDIO) {
  1576 + /* Open decoder */
  1577 + ret = avcodec_open2(codec_ctx,
  1578 + avcodec_find_decoder(codec_ctx->codec_id), NULL);
  1579 + if (ret < 0) {
  1580 + av_log(NULL, AV_LOG_ERROR, "Failed to open decoder for stream #%u\n", i);
  1581 + return ret;
  1582 + }
  1583 + }
  1584 + }
  1585 +
  1586 + av_dump_format(ifmt_ctx, 0, filename, 0);
  1587 + return 0;
  1588 +}
  1589 +
  1590 +static int open_output_file(const char *filename)
  1591 +{
  1592 + AVStream *out_stream;
  1593 + AVStream *in_stream;
  1594 + AVCodecContext *dec_ctx, *enc_ctx;
  1595 + AVCodec *encoder;
  1596 + int ret;
  1597 + unsigned int i;
  1598 +
  1599 + ofmt_ctx = NULL;
  1600 + avformat_alloc_output_context2(&ofmt_ctx, NULL, NULL, filename);
  1601 + if (!ofmt_ctx) {
  1602 + av_log(NULL, AV_LOG_ERROR, "Could not create output context\n");
  1603 + return AVERROR_UNKNOWN;
  1604 + }
  1605 +
  1606 +
  1607 + for (i = 0; i < ifmt_ctx->nb_streams; i++) {
  1608 + out_stream = avformat_new_stream(ofmt_ctx, NULL);
  1609 + if (!out_stream) {
  1610 + av_log(NULL, AV_LOG_ERROR, "Failed allocating output stream\n");
  1611 + return AVERROR_UNKNOWN;
  1612 + }
  1613 +
  1614 + in_stream = ifmt_ctx->streams[i];
  1615 + dec_ctx = in_stream->codec;
  1616 + enc_ctx = out_stream->codec;
  1617 +
  1618 + if (dec_ctx->codec_type == AVMEDIA_TYPE_VIDEO
  1619 + || dec_ctx->codec_type == AVMEDIA_TYPE_AUDIO) {
  1620 + /* in this example, we choose transcoding to same codec */
  1621 + encoder = avcodec_find_encoder(dec_ctx->codec_id);
  1622 + if (!encoder) {
  1623 + av_log(NULL, AV_LOG_FATAL, "Necessary encoder not found\n");
  1624 + return AVERROR_INVALIDDATA;
  1625 + }
  1626 +
  1627 + /* In this example, we transcode to same properties (picture size,
  1628 + * sample rate etc.). These properties can be changed for output
  1629 + * streams easily using filters */
  1630 + if (dec_ctx->codec_type == AVMEDIA_TYPE_VIDEO) {
  1631 + enc_ctx->height = dec_ctx->height;
  1632 + enc_ctx->width = dec_ctx->width;
  1633 + enc_ctx->sample_aspect_ratio = dec_ctx->sample_aspect_ratio;
  1634 + /* take first format from list of supported formats */
  1635 + enc_ctx->pix_fmt = encoder->pix_fmts[0];
  1636 + /* video time_base can be set to whatever is handy and supported by encoder */
  1637 + enc_ctx->time_base = dec_ctx->time_base;
  1638 + }
  1639 + else {
  1640 + enc_ctx->sample_rate = dec_ctx->sample_rate;
  1641 + enc_ctx->channel_layout = dec_ctx->channel_layout;
  1642 + enc_ctx->channels = av_get_channel_layout_nb_channels(enc_ctx->channel_layout);
  1643 + /* take first format from list of supported formats */
  1644 + enc_ctx->sample_fmt = encoder->sample_fmts[0];
  1645 + enc_ctx->time_base.num = 1;
  1646 + enc_ctx->time_base.den = enc_ctx->sample_rate;
  1647 + }
  1648 +
  1649 + /* Third parameter can be used to pass settings to encoder */
  1650 + ret = avcodec_open2(enc_ctx, encoder, NULL);
  1651 + if (ret < 0) {
  1652 + av_log(NULL, AV_LOG_ERROR, "Cannot open video encoder for stream #%u\n", i);
  1653 + return ret;
  1654 + }
  1655 + }
  1656 + else if (dec_ctx->codec_type == AVMEDIA_TYPE_UNKNOWN) {
  1657 + av_log(NULL, AV_LOG_FATAL, "Elementary stream #%d is of unknown type, cannot proceed\n", i);
  1658 + return AVERROR_INVALIDDATA;
  1659 + }
  1660 + else {
  1661 + /* if this stream must be remuxed */
  1662 + ret = avcodec_copy_context(ofmt_ctx->streams[i]->codec,
  1663 + ifmt_ctx->streams[i]->codec);
  1664 + if (ret < 0) {
  1665 + av_log(NULL, AV_LOG_ERROR, "Copying stream context failed\n");
  1666 + return ret;
  1667 + }
  1668 + }
  1669 +
  1670 + if (ofmt_ctx->oformat->flags & AVFMT_GLOBALHEADER)
  1671 + enc_ctx->flags |= CODEC_FLAG_GLOBAL_HEADER;
  1672 +
  1673 + }
  1674 + av_dump_format(ofmt_ctx, 0, filename, 1);
  1675 +
  1676 + if (!(ofmt_ctx->oformat->flags & AVFMT_NOFILE)) {
  1677 + ret = avio_open(&ofmt_ctx->pb, filename, AVIO_FLAG_WRITE);
  1678 + if (ret < 0) {
  1679 + av_log(NULL, AV_LOG_ERROR, "Could not open output file '%s'", filename);
  1680 + return ret;
  1681 + }
  1682 + }
  1683 +
  1684 + /* init muxer, write output file header */
  1685 + ret = avformat_write_header(ofmt_ctx, NULL);
  1686 + if (ret < 0) {
  1687 + av_log(NULL, AV_LOG_ERROR, "Error occurred when opening output file\n");
  1688 + return ret;
  1689 + }
  1690 +
  1691 + return 0;
  1692 +}
  1693 +
  1694 +static int init_filter(FilteringContext* fctx, AVCodecContext *dec_ctx,
  1695 + AVCodecContext *enc_ctx, const char *filter_spec)
  1696 +{
  1697 + char args[512];
  1698 + int ret = 0;
  1699 + AVFilter *buffersrc = NULL;
  1700 + AVFilter *buffersink = NULL;
  1701 + AVFilterContext *buffersrc_ctx = NULL;
  1702 + AVFilterContext *buffersink_ctx = NULL;
  1703 + AVFilterInOut *outputs = avfilter_inout_alloc();
  1704 + AVFilterInOut *inputs = avfilter_inout_alloc();
  1705 + AVFilterGraph *filter_graph = avfilter_graph_alloc();
  1706 +
  1707 + if (!outputs || !inputs || !filter_graph) {
  1708 + ret = AVERROR(ENOMEM);
  1709 + goto end;
  1710 + }
  1711 +
  1712 + if (dec_ctx->codec_type == AVMEDIA_TYPE_VIDEO) {
  1713 + buffersrc = avfilter_get_by_name("buffer");
  1714 + buffersink = avfilter_get_by_name("buffersink");
  1715 + if (!buffersrc || !buffersink) {
  1716 + av_log(NULL, AV_LOG_ERROR, "filtering source or sink element not found\n");
  1717 + ret = AVERROR_UNKNOWN;
  1718 + goto end;
  1719 + }
  1720 +
  1721 + snprintf(args, sizeof(args),
  1722 + "video_size=%dx%d:pix_fmt=%d:time_base=%d/%d:pixel_aspect=%d/%d",
  1723 + dec_ctx->width, dec_ctx->height, dec_ctx->pix_fmt,
  1724 + dec_ctx->time_base.num, dec_ctx->time_base.den,
  1725 + dec_ctx->sample_aspect_ratio.num,
  1726 + dec_ctx->sample_aspect_ratio.den);
  1727 +
  1728 + ret = avfilter_graph_create_filter(&buffersrc_ctx, buffersrc, "in",
  1729 + args, NULL, filter_graph);
  1730 + if (ret < 0) {
  1731 + av_log(NULL, AV_LOG_ERROR, "Cannot create buffer source\n");
  1732 + goto end;
  1733 + }
  1734 +
  1735 + ret = avfilter_graph_create_filter(&buffersink_ctx, buffersink, "out",
  1736 + NULL, NULL, filter_graph);
  1737 + if (ret < 0) {
  1738 + av_log(NULL, AV_LOG_ERROR, "Cannot create buffer sink\n");
  1739 + goto end;
  1740 + }
  1741 +
  1742 + ret = av_opt_set_bin(buffersink_ctx, "pix_fmts",
  1743 + (uint8_t*)&enc_ctx->pix_fmt, sizeof(enc_ctx->pix_fmt),
  1744 + AV_OPT_SEARCH_CHILDREN);
  1745 + if (ret < 0) {
  1746 + av_log(NULL, AV_LOG_ERROR, "Cannot set output pixel format\n");
  1747 + goto end;
  1748 + }
  1749 + }
  1750 + else if (dec_ctx->codec_type == AVMEDIA_TYPE_AUDIO) {
  1751 + buffersrc = avfilter_get_by_name("abuffer");
  1752 + buffersink = avfilter_get_by_name("abuffersink");
  1753 + if (!buffersrc || !buffersink) {
  1754 + av_log(NULL, AV_LOG_ERROR, "filtering source or sink element not found\n");
  1755 + ret = AVERROR_UNKNOWN;
  1756 + goto end;
  1757 + }
  1758 +
  1759 + if (!dec_ctx->channel_layout)
  1760 + dec_ctx->channel_layout =
  1761 + av_get_default_channel_layout(dec_ctx->channels);
  1762 + sprintf(args, //sizeof(args),
  1763 + "time_base=%d/%d:sample_rate=%d:sample_fmt=%s:channel_layout=0x%"PRIx64,
  1764 + dec_ctx->time_base.num, dec_ctx->time_base.den, dec_ctx->sample_rate,
  1765 + av_get_sample_fmt_name(dec_ctx->sample_fmt),
  1766 + dec_ctx->channel_layout);
  1767 + ret = avfilter_graph_create_filter(&buffersrc_ctx, buffersrc, "in",
  1768 + args, NULL, filter_graph);
  1769 + if (ret < 0) {
  1770 + av_log(NULL, AV_LOG_ERROR, "Cannot create audio buffer source\n");
  1771 + goto end;
  1772 + }
  1773 +
  1774 + ret = avfilter_graph_create_filter(&buffersink_ctx, buffersink, "out",
  1775 + NULL, NULL, filter_graph);
  1776 + if (ret < 0) {
  1777 + av_log(NULL, AV_LOG_ERROR, "Cannot create audio buffer sink\n");
  1778 + goto end;
  1779 + }
  1780 +
  1781 + ret = av_opt_set_bin(buffersink_ctx, "sample_fmts",
  1782 + (uint8_t*)&enc_ctx->sample_fmt, sizeof(enc_ctx->sample_fmt),
  1783 + AV_OPT_SEARCH_CHILDREN);
  1784 + if (ret < 0) {
  1785 + av_log(NULL, AV_LOG_ERROR, "Cannot set output sample format\n");
  1786 + goto end;
  1787 + }
  1788 +
  1789 + ret = av_opt_set_bin(buffersink_ctx, "channel_layouts",
  1790 + (uint8_t*)&enc_ctx->channel_layout,
  1791 + sizeof(enc_ctx->channel_layout), AV_OPT_SEARCH_CHILDREN);
  1792 + if (ret < 0) {
  1793 + av_log(NULL, AV_LOG_ERROR, "Cannot set output channel layout\n");
  1794 + goto end;
  1795 + }
  1796 +
  1797 + ret = av_opt_set_bin(buffersink_ctx, "sample_rates",
  1798 + (uint8_t*)&enc_ctx->sample_rate, sizeof(enc_ctx->sample_rate),
  1799 + AV_OPT_SEARCH_CHILDREN);
  1800 + if (ret < 0) {
  1801 + av_log(NULL, AV_LOG_ERROR, "Cannot set output sample rate\n");
  1802 + goto end;
  1803 + }
  1804 + }
  1805 + else {
  1806 + ret = AVERROR_UNKNOWN;
  1807 + goto end;
  1808 + }
  1809 +
  1810 + /* Endpoints for the filter graph. */
  1811 + outputs->name = av_strdup("in");
  1812 + outputs->filter_ctx = buffersrc_ctx;
  1813 + outputs->pad_idx = 0;
  1814 + outputs->next = NULL;
  1815 +
  1816 + inputs->name = av_strdup("out");
  1817 + inputs->filter_ctx = buffersink_ctx;
  1818 + inputs->pad_idx = 0;
  1819 + inputs->next = NULL;
  1820 +
  1821 + if (!outputs->name || !inputs->name) {
  1822 + ret = AVERROR(ENOMEM);
  1823 + goto end;
  1824 + }
  1825 +
  1826 + if ((ret = avfilter_graph_parse_ptr(filter_graph, filter_spec,
  1827 + &inputs, &outputs, NULL)) < 0)
  1828 + goto end;
  1829 +
  1830 + if ((ret = avfilter_graph_config(filter_graph, NULL)) < 0)
  1831 + goto end;
  1832 +
  1833 + /* Fill FilteringContext */
  1834 + fctx->buffersrc_ctx = buffersrc_ctx;
  1835 + fctx->buffersink_ctx = buffersink_ctx;
  1836 + fctx->filter_graph = filter_graph;
  1837 +
  1838 +end:
  1839 + avfilter_inout_free(&inputs);
  1840 + avfilter_inout_free(&outputs);
  1841 +
  1842 + return ret;
  1843 +}
  1844 +
  1845 +static int init_filters(void)
  1846 +{
  1847 + const char *filter_spec;
  1848 + unsigned int i;
  1849 + int ret;
  1850 + filter_ctx = (FilteringContext *)av_malloc_array(ifmt_ctx->nb_streams, sizeof(*filter_ctx));
  1851 + if (!filter_ctx)
  1852 + return AVERROR(ENOMEM);
  1853 +
  1854 + for (i = 0; i < ifmt_ctx->nb_streams; i++) {
  1855 + filter_ctx[i].buffersrc_ctx = NULL;
  1856 + filter_ctx[i].buffersink_ctx = NULL;
  1857 + filter_ctx[i].filter_graph = NULL;
  1858 + if (!(ifmt_ctx->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO
  1859 + || ifmt_ctx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO))
  1860 + continue;
  1861 +
  1862 +
  1863 + if (ifmt_ctx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO)
  1864 + filter_spec = "null"; /* passthrough (dummy) filter for video */
  1865 + else
  1866 + filter_spec = "anull"; /* passthrough (dummy) filter for audio */
  1867 + ret = init_filter(&filter_ctx[i], ifmt_ctx->streams[i]->codec,
  1868 + ofmt_ctx->streams[i]->codec, filter_spec);
  1869 + if (ret)
  1870 + return ret;
  1871 + }
  1872 + return 0;
  1873 +}
  1874 +
  1875 +static int encode_write_frame(AVFrame *filt_frame, unsigned int stream_index, int *got_frame) {
  1876 + int ret;
  1877 + int got_frame_local;
  1878 + AVPacket enc_pkt;
  1879 + int(*enc_func)(AVCodecContext *, AVPacket *, const AVFrame *, int *) =
  1880 + (ifmt_ctx->streams[stream_index]->codec->codec_type ==
  1881 + AVMEDIA_TYPE_VIDEO) ? avcodec_encode_video2 : avcodec_encode_audio2;
  1882 +
  1883 + if (!got_frame)
  1884 + got_frame = &got_frame_local;
  1885 +
  1886 + av_log(NULL, AV_LOG_INFO, "Encoding frame\n");
  1887 + /* encode filtered frame */
  1888 + enc_pkt.data = NULL;
  1889 + enc_pkt.size = 0;
  1890 + av_init_packet(&enc_pkt);
  1891 + ret = enc_func(ofmt_ctx->streams[stream_index]->codec, &enc_pkt,
  1892 + filt_frame, got_frame);
  1893 + av_frame_free(&filt_frame);
  1894 + if (ret < 0)
  1895 + return ret;
  1896 + if (!(*got_frame))
  1897 + return 0;
  1898 +
  1899 + /* prepare packet for muxing */
  1900 + enc_pkt.stream_index = stream_index;
  1901 + av_packet_rescale_ts(&enc_pkt,
  1902 + ofmt_ctx->streams[stream_index]->codec->time_base,
  1903 + ofmt_ctx->streams[stream_index]->time_base);
  1904 +
  1905 + av_log(NULL, AV_LOG_DEBUG, "Muxing frame\n");
  1906 + /* mux encoded frame */
  1907 + ret = av_interleaved_write_frame(ofmt_ctx, &enc_pkt);
  1908 + return ret;
  1909 +}
  1910 +
  1911 +static int filter_encode_write_frame(AVFrame *frame, unsigned int stream_index)
  1912 +{
  1913 + int ret;
  1914 + AVFrame *filt_frame;
  1915 +
  1916 + av_log(NULL, AV_LOG_INFO, "Pushing decoded frame to filters\n");
  1917 + /* push the decoded frame into the filtergraph */
  1918 + ret = av_buffersrc_add_frame_flags(filter_ctx[stream_index].buffersrc_ctx,
  1919 + frame, 0);
  1920 + if (ret < 0) {
  1921 + av_log(NULL, AV_LOG_ERROR, "Error while feeding the filtergraph\n");
  1922 + return ret;
  1923 + }
  1924 +
  1925 + /* pull filtered frames from the filtergraph */
  1926 + while (1) {
  1927 + filt_frame = av_frame_alloc();
  1928 + if (!filt_frame) {
  1929 + ret = AVERROR(ENOMEM);
  1930 + break;
  1931 + }
  1932 + av_log(NULL, AV_LOG_INFO, "Pulling filtered frame from filters\n");
  1933 + ret = av_buffersink_get_frame(filter_ctx[stream_index].buffersink_ctx,
  1934 + filt_frame);
  1935 + if (ret < 0) {
  1936 + /* if no more frames for output - returns AVERROR(EAGAIN)
  1937 + * if flushed and no more frames for output - returns AVERROR_EOF
  1938 + * rewrite retcode to 0 to show it as normal procedure completion
  1939 + */
  1940 + if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
  1941 + ret = 0;
  1942 + av_frame_free(&filt_frame);
  1943 + break;
  1944 + }
  1945 +
  1946 + filt_frame->pict_type = AV_PICTURE_TYPE_NONE;
  1947 + ret = encode_write_frame(filt_frame, stream_index, NULL);
  1948 + if (ret < 0)
  1949 + break;
  1950 + }
  1951 +
  1952 + return ret;
  1953 +}
  1954 +
  1955 +static int flush_encoder(unsigned int stream_index)
  1956 +{
  1957 + int ret;
  1958 + int got_frame;
  1959 +
  1960 + if (!(ofmt_ctx->streams[stream_index]->codec->codec->capabilities &
  1961 + CODEC_CAP_DELAY))
  1962 + return 0;
  1963 +
  1964 + while (1) {
  1965 + av_log(NULL, AV_LOG_INFO, "Flushing stream #%u encoder\n", stream_index);
  1966 + ret = encode_write_frame(NULL, stream_index, &got_frame);
  1967 + if (ret < 0)
  1968 + break;
  1969 + if (!got_frame)
  1970 + return 0;
  1971 + }
  1972 + return ret;
  1973 +}
  1974 +
  1975 +int transcode(int argc, char *argv[]){
  1976 + int ret;
  1977 + AVPacket packet;
  1978 + AVFrame *frame = NULL;
  1979 + enum AVMediaType type;
  1980 + unsigned int stream_index;
  1981 + unsigned int i;
  1982 + int got_frame;
  1983 + int(*dec_func)(AVCodecContext *, AVFrame *, int *, const AVPacket *);
  1984 + memset(&packet, 0, sizeof(AVPacket));
  1985 +
  1986 + if (argc != 3) {
  1987 + av_log(NULL, AV_LOG_ERROR, "Usage: %s <input file> <output file>\n", argv[0]);
  1988 + return 1;
  1989 + }
  1990 +
  1991 + av_register_all();
  1992 + avfilter_register_all();
  1993 +
  1994 + if ((ret = open_input_file(argv[1])) < 0)
  1995 + goto end;
  1996 + if ((ret = open_output_file(argv[2])) < 0)
  1997 + goto end;
  1998 + if ((ret = init_filters()) < 0)
  1999 + goto end;
  2000 +
  2001 + /* read all packets */
  2002 + while (1) {
  2003 + if ((ret = av_read_frame(ifmt_ctx, &packet)) < 0)
  2004 + break;
  2005 + stream_index = packet.stream_index;
  2006 + type = ifmt_ctx->streams[packet.stream_index]->codec->codec_type;
  2007 + av_log(NULL, AV_LOG_DEBUG, "Demuxer gave frame of stream_index %u\n",
  2008 + stream_index);
  2009 +
  2010 + if (filter_ctx[stream_index].filter_graph) {
  2011 + av_log(NULL, AV_LOG_DEBUG, "Going to reencode&filter the frame\n");
  2012 + frame = av_frame_alloc();
  2013 + if (!frame) {
  2014 + ret = AVERROR(ENOMEM);
  2015 + break;
  2016 + }
  2017 + av_packet_rescale_ts(&packet,
  2018 + ifmt_ctx->streams[stream_index]->time_base,
  2019 + ifmt_ctx->streams[stream_index]->codec->time_base);
  2020 + dec_func = (type == AVMEDIA_TYPE_VIDEO) ? avcodec_decode_video2 :
  2021 + avcodec_decode_audio4;
  2022 + ret = dec_func(ifmt_ctx->streams[stream_index]->codec, frame,
  2023 + &got_frame, &packet);
  2024 + if (ret < 0) {
  2025 + av_frame_free(&frame);
  2026 + av_log(NULL, AV_LOG_ERROR, "Decoding failed\n");
  2027 + break;
  2028 + }
  2029 +
  2030 + if (got_frame) {
  2031 + frame->pts = av_frame_get_best_effort_timestamp(frame);
  2032 + ret = filter_encode_write_frame(frame, stream_index);
  2033 + av_frame_free(&frame);
  2034 + if (ret < 0)
  2035 + goto end;
  2036 + }
  2037 + else {
  2038 + av_frame_free(&frame);
  2039 + }
  2040 + }
  2041 + else {
  2042 + /* remux this frame without reencoding */
  2043 + av_packet_rescale_ts(&packet,
  2044 + ifmt_ctx->streams[stream_index]->time_base,
  2045 + ofmt_ctx->streams[stream_index]->time_base);
  2046 +
  2047 + ret = av_interleaved_write_frame(ofmt_ctx, &packet);
  2048 + if (ret < 0)
  2049 + goto end;
  2050 + }
  2051 + av_packet_unref(&packet);
  2052 + }
  2053 +
  2054 + /* flush filters and encoders */
  2055 + for (i = 0; i < ifmt_ctx->nb_streams; i++) {
  2056 + /* flush filter */
  2057 + if (!filter_ctx[i].filter_graph)
  2058 + continue;
  2059 + ret = filter_encode_write_frame(NULL, i);
  2060 + if (ret < 0) {
  2061 + av_log(NULL, AV_LOG_ERROR, "Flushing filter failed\n");
  2062 + goto end;
  2063 + }
  2064 +
  2065 + /* flush encoder */
  2066 + ret = flush_encoder(i);
  2067 + if (ret < 0) {
  2068 + av_log(NULL, AV_LOG_ERROR, "Flushing encoder failed\n");
  2069 + goto end;
  2070 + }
  2071 + }
  2072 +
  2073 + av_write_trailer(ofmt_ctx);
  2074 +end:
  2075 + av_packet_unref(&packet);
  2076 + av_frame_free(&frame);
  2077 + for (i = 0; i < ifmt_ctx->nb_streams; i++) {
  2078 + avcodec_close(ifmt_ctx->streams[i]->codec);
  2079 + if (ofmt_ctx && ofmt_ctx->nb_streams > i && ofmt_ctx->streams[i] && ofmt_ctx->streams[i]->codec)
  2080 + avcodec_close(ofmt_ctx->streams[i]->codec);
  2081 + if (filter_ctx && filter_ctx[i].filter_graph)
  2082 + avfilter_graph_free(&filter_ctx[i].filter_graph);
  2083 + }
  2084 + av_free(filter_ctx);
  2085 + avformat_close_input(&ifmt_ctx);
  2086 + if (ofmt_ctx && !(ofmt_ctx->oformat->flags & AVFMT_NOFILE))
  2087 + avio_closep(&ofmt_ctx->pb);
  2088 + avformat_free_context(ofmt_ctx);
  2089 +
  2090 + //if (ret < 0)
  2091 + // av_log(NULL, AV_LOG_ERROR, "Error occurred: %s\n", av_err2str(ret));
  2092 +
  2093 + return ret ? 1 : 0;
  2094 +}
1800 2095
@@ -53,10 +53,12 @@ @@ -53,10 +53,12 @@
53 <WarningLevel>Level3</WarningLevel> 53 <WarningLevel>Level3</WarningLevel>
54 <Optimization>Disabled</Optimization> 54 <Optimization>Disabled</Optimization>
55 <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions> 55 <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
  56 + <AdditionalIncludeDirectories>..\..\liveAssistant\third-lib\ffmpeg\include</AdditionalIncludeDirectories>
56 </ClCompile> 57 </ClCompile>
57 <Link> 58 <Link>
58 <SubSystem>Console</SubSystem> 59 <SubSystem>Console</SubSystem>
59 <GenerateDebugInformation>true</GenerateDebugInformation> 60 <GenerateDebugInformation>true</GenerateDebugInformation>
  61 + <AdditionalLibraryDirectories>..\..\liveAssistant\third-lib\ffmpeg\lib;</AdditionalLibraryDirectories>
60 </Link> 62 </Link>
61 </ItemDefinitionGroup> 63 </ItemDefinitionGroup>
62 <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> 64 <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">