胡斌

V2.0.13

1.命令行增加可选参数-r {0|1},控制视频缩放后是否裁剪以适应目标区域
2.命令行增加可选参数-k {0|1},控制一对多时合成的视频是否保持4:3宽高比
@@ -34,7 +34,7 @@ int g_fps; @@ -34,7 +34,7 @@ int g_fps;
34 34
35 #define ensure_no_zero(x, v) if(!x) x = v 35 #define ensure_no_zero(x, v) if(!x) x = v
36 36
37 -CAVTranscoder::CAVTranscoder(bool bOne2One, bool one2one_same_size, bool one2many_inflat, int width_teacher, int height_teacher, int width_student, int height_student, bool has_teacher, int max_audio, int max_video, int keep_4_3) : 37 +CAVTranscoder::CAVTranscoder(bool bOne2One, bool one2one_same_size, bool one2many_inflat, int width_teacher, int height_teacher, int width_student, int height_student, bool has_teacher, int max_audio, int max_video, bool crop, bool keep_4_3) :
38 _start_time(INT64_MAX), 38 _start_time(INT64_MAX),
39 _all_processed(true), 39 _all_processed(true),
40 _nOutputWidth(320), 40 _nOutputWidth(320),
@@ -61,7 +61,8 @@ _src_width_teacher(0), @@ -61,7 +61,8 @@ _src_width_teacher(0),
61 _src_height_teacher(0), 61 _src_height_teacher(0),
62 _src_width_student(0), 62 _src_width_student(0),
63 _src_height_student(0), 63 _src_height_student(0),
64 -_one2one_same_size(one2one_same_size) 64 +_one2one_same_size(one2one_same_size),
  65 +_crop(crop)
65 { 66 {
66 ensure_no_zero(width_teacher, 320); 67 ensure_no_zero(width_teacher, 320);
67 ensure_no_zero(height_teacher, 240); 68 ensure_no_zero(height_teacher, 240);
@@ -120,6 +121,15 @@ _one2one_same_size(one2one_same_size) @@ -120,6 +121,15 @@ _one2one_same_size(one2one_same_size)
120 _nOutputHeight = _nOutputHeight - (part_student == 0 ? (pip_y_gap) : 0); 121 _nOutputHeight = _nOutputHeight - (part_student == 0 ? (pip_y_gap) : 0);
121 } 122 }
122 _nOutputHeight = ((_nOutputHeight + 1) / 2) * 2; 123 _nOutputHeight = ((_nOutputHeight + 1) / 2) * 2;
  124 + if (keep_4_3){
  125 + int nOutputHeight = _nOutputWidth * 3 / 4;
  126 + if (_nOutputHeight < nOutputHeight) {
  127 + _nOutputHeight = nOutputHeight;
  128 + }
  129 + }
  130 + if (_crop){
  131 + _teacher_height = _nOutputHeight;
  132 + }
123 133
124 int student_line_width = 4 * (_pip_width)+3 * pip_x_gap + 2 * pip_x_border; 134 int student_line_width = 4 * (_pip_width)+3 * pip_x_gap + 2 * pip_x_border;
125 if (student_line_width > _nOutputWidth) { 135 if (student_line_width > _nOutputWidth) {
@@ -785,7 +795,12 @@ int CAVTranscoder::open_output_file(const char *filename) @@ -785,7 +795,12 @@ int CAVTranscoder::open_output_file(const char *filename)
785 memset(pDstFrame->data[0], _blank_y, pDstFrame->linesize[0] * _teacher_height); 795 memset(pDstFrame->data[0], _blank_y, pDstFrame->linesize[0] * _teacher_height);
786 memset(pDstFrame->data[1], _blank_u, pDstFrame->linesize[1] * _teacher_height / 2); 796 memset(pDstFrame->data[1], _blank_u, pDstFrame->linesize[1] * _teacher_height / 2);
787 memset(pDstFrame->data[2], _blank_v, pDstFrame->linesize[2] * _teacher_height / 2); 797 memset(pDstFrame->data[2], _blank_v, pDstFrame->linesize[2] * _teacher_height / 2);
788 - fillDestFrame(pDstFrame, _teacherFrame, (_nOutputWidth - _teacherFrame->width) / 2, (_teacher_height - _teacherFrame->height) / 2); 798 + if (_crop){
  799 + fillDestFrame(pDstFrame, _teacherFrame, 0, 0, (_teacherFrame->width - _teacher_width) / 2, (_teacherFrame->height - _teacher_height) / 2, _teacher_width, _teacher_height);
  800 + }
  801 + else {
  802 + fillDestFrame(pDstFrame, _teacherFrame, (_nOutputWidth - _teacherFrame->width) / 2, (_teacher_height - _teacherFrame->height) / 2);
  803 + }
789 } 804 }
790 else { 805 else {
791 fillDestFrame(pDstFrame, _teacherFrame, 0, 0); 806 fillDestFrame(pDstFrame, _teacherFrame, 0, 0);
@@ -835,7 +850,12 @@ int CAVTranscoder::open_output_file(const char *filename) @@ -835,7 +850,12 @@ int CAVTranscoder::open_output_file(const char *filename)
835 memset(pDstFrame->data[0] + y * pDstFrame->linesize[0], _blank_y, pDstFrame->linesize[0] * _student_height); 850 memset(pDstFrame->data[0] + y * pDstFrame->linesize[0], _blank_y, pDstFrame->linesize[0] * _student_height);
836 memset(pDstFrame->data[1] + y * pDstFrame->linesize[1] / 2, _blank_u, pDstFrame->linesize[1] * _student_height / 2); 851 memset(pDstFrame->data[1] + y * pDstFrame->linesize[1] / 2, _blank_u, pDstFrame->linesize[1] * _student_height / 2);
837 memset(pDstFrame->data[2] + y * pDstFrame->linesize[2] / 2, _blank_v, pDstFrame->linesize[2] * _student_height / 2); 852 memset(pDstFrame->data[2] + y * pDstFrame->linesize[2] / 2, _blank_v, pDstFrame->linesize[2] * _student_height / 2);
838 - fillDestFrame(pDstFrame, _studentFrame, (_nOutputWidth - _studentFrame->width) / 2, (_student_height - _studentFrame->height) / 2 + y); 853 + if (_crop){
  854 + fillDestFrame(pDstFrame, _studentFrame, 0, y, (_studentFrame->width - _student_width) / 2, (_studentFrame->height - _student_height) / 2,_student_width,_student_height);
  855 + }
  856 + else{
  857 + fillDestFrame(pDstFrame, _studentFrame, (_nOutputWidth - _studentFrame->width) / 2, (_student_height - _studentFrame->height) / 2 + y);
  858 + }
839 } 859 }
840 else { 860 else {
841 fillDestFrame(pDstFrame, _studentFrame, 0, y); 861 fillDestFrame(pDstFrame, _studentFrame, 0, y);
@@ -911,13 +931,25 @@ int CAVTranscoder::open_output_file(const char *filename) @@ -911,13 +931,25 @@ int CAVTranscoder::open_output_file(const char *filename)
911 if (pFrame->pkt_dts == 0 || pFrame->pkt_dts == 180) { 931 if (pFrame->pkt_dts == 0 || pFrame->pkt_dts == 180) {
912 double src_wh_ratio = pFrame->width / (double)pFrame->height; 932 double src_wh_ratio = pFrame->width / (double)pFrame->height;
913 double dest_wh_ratio = dest_width / (double)dest_height; 933 double dest_wh_ratio = dest_width / (double)dest_height;
914 - if (src_wh_ratio > dest_wh_ratio) {  
915 - *scaled_width = dest_width;  
916 - *scaled_height =(int)( dest_width / src_wh_ratio + 0.5); 934 + if (_crop){
  935 + if (src_wh_ratio > dest_wh_ratio) {
  936 + *scaled_width = (int)(dest_width*src_wh_ratio + 0.5);
  937 + *scaled_height = dest_height;
  938 + }
  939 + else {
  940 + *scaled_width = dest_width;
  941 + *scaled_height = (int)(dest_width / src_wh_ratio + 0.5);
  942 + }
917 } 943 }
918 else { 944 else {
919 - *scaled_height = dest_height;  
920 - *scaled_width = (int)(dest_height * src_wh_ratio); 945 + if (src_wh_ratio > dest_wh_ratio) {
  946 + *scaled_width = dest_width;
  947 + *scaled_height = (int)(dest_width / src_wh_ratio + 0.5);
  948 + }
  949 + else {
  950 + *scaled_height = dest_height;
  951 + *scaled_width = (int)(dest_height * src_wh_ratio);
  952 + }
921 } 953 }
922 } 954 }
923 else { 955 else {
@@ -943,7 +975,12 @@ int CAVTranscoder::open_output_file(const char *filename) @@ -943,7 +975,12 @@ int CAVTranscoder::open_output_file(const char *filename)
943 free_scale_context(&_sws_ctx_teacher, &_scaled_frame_teacher); 975 free_scale_context(&_sws_ctx_teacher, &_scaled_frame_teacher);
944 976
945 int scaled_width, scaled_height; 977 int scaled_width, scaled_height;
946 - get_scaled_dest_size(_teacherFrame, _teacher_width, _teacher_height, &scaled_width, &scaled_height); 978 + if (_crop){
  979 + get_scaled_dest_size(_teacherFrame, _nOutputWidth, _nOutputHeight, &scaled_width, &scaled_height);
  980 + }
  981 + else {
  982 + get_scaled_dest_size(_teacherFrame, _teacher_width, _teacher_height, &scaled_width, &scaled_height);
  983 + }
947 init_scale_context(&_sws_ctx_teacher, &_scaled_frame_teacher, _teacherFrame->width, _teacherFrame->height, scaled_width, scaled_height); 984 init_scale_context(&_sws_ctx_teacher, &_scaled_frame_teacher, _teacherFrame->width, _teacherFrame->height, scaled_width, scaled_height);
948 985
949 _src_width_teacher = _teacherFrame->width; 986 _src_width_teacher = _teacherFrame->width;
@@ -965,7 +1002,12 @@ int CAVTranscoder::open_output_file(const char *filename) @@ -965,7 +1002,12 @@ int CAVTranscoder::open_output_file(const char *filename)
965 memset(pDstFrame->data[1], _blank_u, pDstFrame->linesize[1] * (_teacherFrame->height) / 2); 1002 memset(pDstFrame->data[1], _blank_u, pDstFrame->linesize[1] * (_teacherFrame->height) / 2);
966 memset(pDstFrame->data[2], _blank_v, pDstFrame->linesize[2] * (_teacherFrame->height) / 2); 1003 memset(pDstFrame->data[2], _blank_v, pDstFrame->linesize[2] * (_teacherFrame->height) / 2);
967 } 1004 }
968 - fillDestFrame(pDstFrame, _teacherFrame, 0, 0); 1005 + if (_crop){
  1006 + fillDestFrame(pDstFrame, _teacherFrame, 0, 0, (_teacherFrame->width - _nOutputWidth) / 2, (_teacherFrame->height - _nOutputHeight) / 2, _nOutputWidth, _nOutputHeight);
  1007 + }
  1008 + else {
  1009 + fillDestFrame(pDstFrame, _teacherFrame, 0, 0);
  1010 + }
969 1011
970 return 0; 1012 return 0;
971 } 1013 }
@@ -5,7 +5,7 @@ @@ -5,7 +5,7 @@
5 class CAVTranscoder 5 class CAVTranscoder
6 { 6 {
7 public: 7 public:
8 - CAVTranscoder(bool bOne2One, bool one2one_same_size, bool one2many_inflat, int width_teacher, int height_teacher, int student_width, int student_height, bool has_teacher, int max_audio, int max_video, int keep_4_3= true); 8 + CAVTranscoder(bool bOne2One, bool one2one_same_size, bool one2many_inflat, int width_teacher, int height_teacher, int student_width, int student_height, bool has_teacher, int max_audio, int max_video, bool crop = false, bool keep_4_3= true);
9 virtual ~CAVTranscoder(); 9 virtual ~CAVTranscoder();
10 10
11 int add(media_info & info); 11 int add(media_info & info);
@@ -56,6 +56,7 @@ private: @@ -56,6 +56,7 @@ private:
56 int _student_width; 56 int _student_width;
57 int _student_height; 57 int _student_height;
58 bool _one2one_same_size;//top and bottom are same size ,if not ,scale the smaller to the larger 58 bool _one2one_same_size;//top and bottom are same size ,if not ,scale the smaller to the larger
  59 + bool _crop;//
59 struct SwsContext * _sws_ctx_w_h; //for one2many student frame 60 struct SwsContext * _sws_ctx_w_h; //for one2many student frame
60 struct SwsContext * _sws_ctx_h_w; 61 struct SwsContext * _sws_ctx_h_w;
61 struct SwsContext * _sws_ctx_h_h; 62 struct SwsContext * _sws_ctx_h_h;
@@ -51,12 +51,23 @@ merge_pip_codec.cfg主要编码参数: @@ -51,12 +51,23 @@ merge_pip_codec.cfg主要编码参数:
51 1 在一对一时, 如果老师和学生的视频大小不一致,会放大较小的视频使得老师和学生视频大小相同。在一对多时,如果老师视频由多段不同分辨率视频组成,会对老师视频进行缩放统一 51 1 在一对一时, 如果老师和学生的视频大小不一致,会放大较小的视频使得老师和学生视频大小相同。在一对多时,如果老师视频由多段不同分辨率视频组成,会对老师视频进行缩放统一
52 0 保持原有视频大小 52 0 保持原有视频大小
53 53
  54 +-r 为可选参数。缺省为0
  55 +0 视频保持原有宽高比缩放后,宽或高与目标区域相同,完整视频放置在目标区域,上下或左右填充背景色
  56 +1 视频保持原有宽高比缩放后,宽或高与目标区域相同,裁剪上下或左右,铺满目标区域
  57 +
  58 +-k 为可选参数。缺省为1
  59 +0 1对多时,合成的视频大小为老师原始视频大小
  60 +1 1对多时,合成的视频保持4:3的宽高比
  61 +
54 合屏后生成完成信息文件,文件名为"m_" + 输入文件名" + ".txt",合成的mp4文件名为"m_" + 输入文件名" + ".mp4" 62 合屏后生成完成信息文件,文件名为"m_" + 输入文件名" + ".txt",合成的mp4文件名为"m_" + 输入文件名" + ".mp4"
55 如merge_pip 1.txt 63 如merge_pip 1.txt
56 生成的完成信息文件是m_1.txt,m_1.txt只有一行,记录输出的mp4文件名(m_1.mp4)、参与合成m_1.mp4的第一个媒体文件名(用于帮助确认m_1.mp4的开始时间)及mp4的时长。下面是一个实际的m_1.txt内容: 64 生成的完成信息文件是m_1.txt,m_1.txt只有一行,记录输出的mp4文件名(m_1.mp4)、参与合成m_1.mp4的第一个媒体文件名(用于帮助确认m_1.mp4的开始时间)及mp4的时长。下面是一个实际的m_1.txt内容:
57 m_1.mp4 859282931_20181112133025316.mp4 3397.150 65 m_1.mp4 859282931_20181112133025316.mp4 3397.150
58 66
59 67
  68 +
  69 +
  70 +
60 V2.0.1 71 V2.0.1
61 1.修改bug: 复制缩小后的视频时,U、V分量x偏移不正确 72 1.修改bug: 复制缩小后的视频时,U、V分量x偏移不正确
62 73
@@ -101,4 +112,8 @@ V2.0.11 @@ -101,4 +112,8 @@ V2.0.11
101 1.修改1对多布局时,缺省不扩大合成视频大小,-t 3参数时才根据学生数量扩大合成视频大小 112 1.修改1对多布局时,缺省不扩大合成视频大小,-t 3参数时才根据学生数量扩大合成视频大小
102 113
103 V2.0.12 114 V2.0.12
104 -1.在一对一时,强制老师和学生的视频大小一致,且宽高比均为4:3,当不为4:3时,保持视频原始宽高比,水平或垂直居中  
  115 +1.在一对一时,强制老师和学生的视频大小一致,且宽高比均为4:3,当不为4:3时,保持视频原始宽高比,水平或垂直居中
  116 +
  117 +V2.0.13
  118 +1.命令行增加可选参数-r {0|1},控制视频缩放后是否裁剪以适应目标区域
  119 +2.命令行增加可选参数-k {0|1},控制一对多时合成的视频是否保持4:3宽高比
@@ -14,6 +14,8 @@ @@ -14,6 +14,8 @@
14 bool only_print = false; 14 bool only_print = false;
15 bool keep_tmp_files = false; 15 bool keep_tmp_files = false;
16 bool out_one_video = true; 16 bool out_one_video = true;
  17 +bool crop = false;
  18 +bool keep_4_3 = false;
17 19
18 20
19 class fileinfo { 21 class fileinfo {
@@ -683,6 +685,7 @@ int height_teacher = 0; @@ -683,6 +685,7 @@ int height_teacher = 0;
683 int width_student = 0; 685 int width_student = 0;
684 int height_student = 0; 686 int height_student = 0;
685 bool has_teacher = false; 687 bool has_teacher = false;
  688 +bool has_student = false;
686 689
687 void add_media_infos() 690 void add_media_infos()
688 { 691 {
@@ -780,6 +783,7 @@ void add_media_infos() @@ -780,6 +783,7 @@ void add_media_infos()
780 } 783 }
781 } 784 }
782 else { 785 else {
  786 + has_student = true;
783 if (it->rotate == 0 || it->rotate == 180) { 787 if (it->rotate == 0 || it->rotate == 180) {
784 if (width_student < it->width) { 788 if (width_student < it->width) {
785 width_student = it->width; 789 width_student = it->width;
@@ -942,7 +946,7 @@ float get_uid_start_time_from_filename(const char * filename, unsigned int &uid) @@ -942,7 +946,7 @@ float get_uid_start_time_from_filename(const char * filename, unsigned int &uid)
942 const char * end = strstr(start + 1, "_"); 946 const char * end = strstr(start + 1, "_");
943 if (end) {//get the next 947 if (end) {//get the next
944 *(char *)end = 0; 948 *(char *)end = 0;
945 - uid = atoi(start + 1); 949 + uid = atoi(start);
946 *(char *)end = '_'; 950 *(char *)end = '_';
947 951
948 start = end; 952 start = end;
@@ -1173,6 +1177,10 @@ int process_av_files(char * record_info, int piptype, bool one2one_same_size, in @@ -1173,6 +1177,10 @@ int process_av_files(char * record_info, int piptype, bool one2one_same_size, in
1173 one2one = false; 1177 one2one = false;
1174 } 1178 }
1175 1179
  1180 + if (has_student == false){
  1181 + one2one = false;
  1182 + }
  1183 +
1176 bool one_to_many_inflat = false; 1184 bool one_to_many_inflat = false;
1177 1185
1178 if (1 == piptype) { 1186 if (1 == piptype) {
@@ -1202,7 +1210,11 @@ int process_av_files(char * record_info, int piptype, bool one2one_same_size, in @@ -1202,7 +1210,11 @@ int process_av_files(char * record_info, int piptype, bool one2one_same_size, in
1202 } 1210 }
1203 } 1211 }
1204 1212
1205 - CAVTranscoder videoTranscoder(one2one, one2one_same_size, one_to_many_inflat, width_teacher, height_teacher, width_student, height_student, has_teacher, max_audio, max_video); 1213 + bool k = keep_4_3;
  1214 + if (one2one){
  1215 + k = true;
  1216 + }
  1217 + CAVTranscoder videoTranscoder(one2one, one2one_same_size, one_to_many_inflat, width_teacher, height_teacher, width_student, height_student, has_teacher, max_audio, max_video, crop, k);
1206 1218
1207 int64_t cur_time = 0; 1219 int64_t cur_time = 0;
1208 bool has_file = sorted_media.size()!=0; 1220 bool has_file = sorted_media.size()!=0;
@@ -1285,9 +1297,9 @@ int process_av_files(char * record_info, int piptype, bool one2one_same_size, in @@ -1285,9 +1297,9 @@ int process_av_files(char * record_info, int piptype, bool one2one_same_size, in
1285 int main(int argc, char * argv[]) 1297 int main(int argc, char * argv[])
1286 { 1298 {
1287 if (argc < 2) { 1299 if (argc < 2) {
1288 - printf(" merge_pip 2.0.12\n"); 1300 + printf(" merge_pip 2.0.13\n");
1289 printf(" merge video files to one pip video according to record info file,\nusage:"); 1301 printf(" merge video files to one pip video according to record info file,\nusage:");
1290 - printf("\n %s record_info_filename [-t {0,1,2,3}] [-c codec.cfg] [-s {1,0}]", argv[0]); 1302 + printf("\n %s record_info_filename [-t {0,1,2,3}] [-c codec.cfg] [-s {1,0}] [-r {0,1}] [-k {0,1}]", argv[0]);
1291 printf("\n\n"); 1303 printf("\n\n");
1292 return -1; 1304 return -1;
1293 } 1305 }
@@ -1328,6 +1340,22 @@ int main(int argc, char * argv[]) @@ -1328,6 +1340,22 @@ int main(int argc, char * argv[])
1328 } 1340 }
1329 max_duration = atoi(argv[i]); 1341 max_duration = atoi(argv[i]);
1330 } 1342 }
  1343 + else if (!strcmp(argv[i], "-r")){
  1344 + i++;
  1345 + if (i > argc) {
  1346 + printf("error,should be 0 or 1 after -r");
  1347 + return -2;
  1348 + }
  1349 + crop = atoi(argv[i]);
  1350 + }
  1351 + else if (!strcmp(argv[i], "-k")){
  1352 + i++;
  1353 + if (i > argc) {
  1354 + printf("error,should be 1 or 0 after -k");
  1355 + return -2;
  1356 + }
  1357 + keep_4_3 = atoi(argv[i]);
  1358 + }
1331 } 1359 }
1332 1360
1333 1361