胡斌

V2.0.6

1. 命令行添加-s可选参数,在一对一布局下起作用。缺省为1
  1 如果老师和学生的视频大小不一致,会放大较小的视频使得老师和学生视频大小相同。
  0 保持原有视频大小
@@ -31,7 +31,7 @@ int pip_x_border = 4; @@ -31,7 +31,7 @@ int pip_x_border = 4;
31 31
32 #define ensure_no_zero(x, v) if(!x) x = v 32 #define ensure_no_zero(x, v) if(!x) x = v
33 33
34 -CAVTranscoder::CAVTranscoder(bool bOne2One, int width_teacher, int height_teacher, int width_student, int height_student, bool has_teacher, int max_audio) : 34 +CAVTranscoder::CAVTranscoder(bool bOne2One, bool one2one_same_size, int width_teacher, int height_teacher, int width_student, int height_student, bool has_teacher, int max_audio) :
35 _start_time(INT64_MAX), 35 _start_time(INT64_MAX),
36 _all_processed(true), 36 _all_processed(true),
37 _nOutputWidth(320), 37 _nOutputWidth(320),
@@ -48,7 +48,16 @@ _last_videos_got(-1), @@ -48,7 +48,16 @@ _last_videos_got(-1),
48 _teacherFrame(NULL), 48 _teacherFrame(NULL),
49 _studentFrame(NULL), 49 _studentFrame(NULL),
50 _pip_width(0), 50 _pip_width(0),
51 -_pip_height(0) 51 +_pip_height(0),
  52 +_sws_ctx_teacher(NULL),
  53 +_scaled_frame_teacher(NULL),
  54 +_sws_ctx_student(NULL),
  55 +_scaled_frame_student(NULL),
  56 +_src_width_teacher(0),
  57 +_src_height_teacher(0),
  58 +_src_width_student(0),
  59 +_src_height_student(0),
  60 +_one2one_same_size(one2one_same_size)
52 { 61 {
53 ensure_no_zero(width_teacher, 320); 62 ensure_no_zero(width_teacher, 320);
54 ensure_no_zero(height_teacher, 240); 63 ensure_no_zero(height_teacher, 240);
@@ -66,6 +75,31 @@ _pip_height(0) @@ -66,6 +75,31 @@ _pip_height(0)
66 _one2one = bOne2One; 75 _one2one = bOne2One;
67 if (_one2one) { 76 if (_one2one) {
68 _nOutputWidth = max(_teacher_width, _student_width); 77 _nOutputWidth = max(_teacher_width, _student_width);
  78 +
  79 + if (_one2one_same_size) {
  80 + int max_width = _nOutputWidth;
  81 + int max_height = max(_teacher_height, _student_height);
  82 + int min_width = min(_teacher_width, _student_width);
  83 + int min_height = min(_teacher_height, _student_height);
  84 +
  85 + if (_teacher_width < _student_width) {
  86 + _teacher_width = _student_width;
  87 + }
  88 + else if (_student_width < _teacher_width) {
  89 + _student_width = _teacher_width;
  90 + }
  91 + if (_teacher_height < _student_height) {
  92 + _teacher_height = _student_height;
  93 + }
  94 + else if (_student_height < _teacher_height) {
  95 + _student_height = _teacher_height;
  96 + }
  97 +
  98 + init_scale_context(&_sws_ctx_w_h, &_scaled_frame_w_h, min_width, min_height, max_width, max_height);
  99 + init_scale_context(&_sws_ctx_h_w, &_scaled_frame_h_w, min_height, min_width, max_height, max_width);
  100 + init_scale_context(&_sws_ctx_h_h, &_scaled_frame_h_h, min_height, min_height, max_height, max_height);
  101 + }
  102 +
69 _nOutputHeight = _teacher_height + _student_height; 103 _nOutputHeight = _teacher_height + _student_height;
70 } 104 }
71 else { 105 else {
@@ -180,6 +214,14 @@ int CAVTranscoder::close() @@ -180,6 +214,14 @@ int CAVTranscoder::close()
180 free_scale_context(&_sws_ctx_w_h, &_scaled_frame_w_h); 214 free_scale_context(&_sws_ctx_w_h, &_scaled_frame_w_h);
181 free_scale_context(&_sws_ctx_h_w, &_scaled_frame_h_w); 215 free_scale_context(&_sws_ctx_h_w, &_scaled_frame_h_w);
182 free_scale_context(&_sws_ctx_h_h, &_scaled_frame_h_h); 216 free_scale_context(&_sws_ctx_h_h, &_scaled_frame_h_h);
  217 + if (_scaled_frame_teacher == _teacherFrame) {
  218 + _teacherFrame = NULL;
  219 + }
  220 + free_scale_context(&_sws_ctx_teacher, &_scaled_frame_teacher);
  221 + if (_scaled_frame_student == _studentFrame) {
  222 + _studentFrame = NULL;
  223 + }
  224 + free_scale_context(&_sws_ctx_student, &_scaled_frame_student);
183 225
184 226
185 #if USE_H264BSF 227 #if USE_H264BSF
@@ -686,6 +728,168 @@ int CAVTranscoder::open_output_file(const char *filename) @@ -686,6 +728,168 @@ int CAVTranscoder::open_output_file(const char *filename)
686 return 0; 728 return 0;
687 } 729 }
688 730
  731 + int CAVTranscoder::scale_fill_one2one_teacherframe(AVFrame *pDstFrame)
  732 + {
  733 + if (_src_width_teacher != _teacherFrame->width || _src_height_teacher != _teacherFrame->height) {//init scale context
  734 + free_scale_context(&_sws_ctx_teacher, &_scaled_frame_teacher);
  735 + if (_teacherFrame->width >= _teacherFrame->height) {
  736 + init_scale_context(&_sws_ctx_teacher, &_scaled_frame_teacher, _teacherFrame->width, _teacherFrame->height, _teacher_width, _teacher_height);
  737 + }
  738 + else {
  739 + init_scale_context(&_sws_ctx_teacher, &_scaled_frame_teacher, _teacherFrame->height, _teacherFrame->width, _teacher_width, _teacher_height);
  740 + }
  741 + }
  742 +
  743 + int h = 0;
  744 + h = sws_scale(_sws_ctx_teacher, _teacherFrame->data, _teacherFrame->linesize, 0, _teacherFrame->height,
  745 + _scaled_frame_teacher->data, _scaled_frame_teacher->linesize);
  746 + _scaled_frame_teacher->pkt_dts = _teacherFrame->pkt_dts;//pass rotation
  747 +
  748 + av_frame_free(&_teacherFrame);
  749 + _teacherFrame = _scaled_frame_teacher;
  750 +
  751 + if (_teacherFrame->width == _teacher_width && _teacherFrame->height == _teacher_height) {
  752 + if (_teacherFrame->pkt_dts != 90){
  753 + if (_teacher_width < _nOutputWidth) {
  754 + memset(pDstFrame->data[0], _blank_y, pDstFrame->linesize[0] * _teacher_height);
  755 + memset(pDstFrame->data[1], _blank_u, pDstFrame->linesize[1] * _teacher_height / 2);
  756 + memset(pDstFrame->data[2], _blank_v, pDstFrame->linesize[2] * _teacher_height / 2);
  757 + }
  758 + fillDestFrame(pDstFrame, _teacherFrame, 0, 0);
  759 + }
  760 + else {
  761 + memset(pDstFrame->data[0], _blank_y, _nOutputWidth * _teacher_height);
  762 + memset(pDstFrame->data[1], _blank_u, _nOutputWidth * _teacher_height / 2);
  763 + memset(pDstFrame->data[2], _blank_v, _nOutputWidth * _teacher_height / 2);
  764 + fillDestFrame(pDstFrame, _teacherFrame, (_nOutputWidth - _teacher_height) / 2, 0, (_teacher_width - _teacher_height) / 2, 0, _teacher_height, _teacher_height);
  765 + }
  766 + }
  767 + else if (_teacherFrame->width == _teacher_height && _teacherFrame->height == _teacher_width) {
  768 + if (_teacherFrame->pkt_dts == 90){
  769 + if (_teacher_width < _nOutputWidth) {
  770 + memset(pDstFrame->data[0], _blank_y, pDstFrame->linesize[0] * _teacher_height);
  771 + memset(pDstFrame->data[1], _blank_u, pDstFrame->linesize[1] * _teacher_height / 2);
  772 + memset(pDstFrame->data[2], _blank_v, pDstFrame->linesize[2] * _teacher_height / 2);
  773 + }
  774 + fillDestFrame(pDstFrame, _teacherFrame, 0, 0);
  775 + }
  776 + else {
  777 + memset(pDstFrame->data[0], _blank_y, pDstFrame->linesize[0] * _teacher_height);
  778 + memset(pDstFrame->data[1], _blank_u, pDstFrame->linesize[1] * _teacher_height / 2);
  779 + memset(pDstFrame->data[2], _blank_v, pDstFrame->linesize[2] * _teacher_height / 2);
  780 + fillDestFrame(pDstFrame, _teacherFrame, (_nOutputWidth - _teacher_height) / 2, 0, 0, (_teacher_width - _teacher_height) / 2, _teacher_height, _teacher_height);
  781 + }
  782 + }
  783 + else if (_teacherFrame->width == _teacher_height && _teacherFrame->height == _teacher_height) {
  784 + memset(pDstFrame->data[0], _blank_y, pDstFrame->linesize[0] * _teacher_height);
  785 + memset(pDstFrame->data[1], _blank_u, pDstFrame->linesize[1] * _teacher_height / 2);
  786 + memset(pDstFrame->data[2], _blank_v, pDstFrame->linesize[2] * _teacher_height / 2);
  787 + fillDestFrame(pDstFrame, _teacherFrame, (_nOutputWidth - _teacher_height) / 2, 0);
  788 + }
  789 +
  790 + return 0;
  791 + }
  792 +
  793 + int CAVTranscoder::scale_fill_one2one_studentframe(AVFrame * pDstFrame, int y)
  794 + {
  795 + if (_src_width_student != _studentFrame->width || _src_height_student != _studentFrame->height) {//init scale context
  796 + free_scale_context(&_sws_ctx_student, &_scaled_frame_student);
  797 + if (_studentFrame->width >= _studentFrame->height) {
  798 + init_scale_context(&_sws_ctx_student, &_scaled_frame_student, _studentFrame->width, _studentFrame->height, _student_width, _student_height);
  799 + }
  800 + else {
  801 + init_scale_context(&_sws_ctx_student, &_scaled_frame_student, _studentFrame->height, _studentFrame->width, _student_width, _student_height);
  802 + }
  803 + }
  804 +
  805 + int h = 0;
  806 + h = sws_scale(_sws_ctx_student, _studentFrame->data, _studentFrame->linesize, 0, _studentFrame->height,
  807 + _scaled_frame_student->data, _scaled_frame_student->linesize);
  808 + _scaled_frame_student->pkt_dts = _studentFrame->pkt_dts;//pass rotation
  809 +
  810 + av_frame_free(&_studentFrame);
  811 + _studentFrame = _scaled_frame_student;
  812 +
  813 + if (_studentFrame->width == _student_width && _studentFrame->height == _student_height) {
  814 + if (_studentFrame->pkt_dts != 90){
  815 + if (_student_width < _nOutputWidth) {
  816 + memset(pDstFrame->data[0] + y * pDstFrame->linesize[0], _blank_y, pDstFrame->linesize[0] * _student_height);
  817 + memset(pDstFrame->data[1] + y * pDstFrame->linesize[1] / 2 , _blank_u, pDstFrame->linesize[1] * _student_height / 2);
  818 + memset(pDstFrame->data[2] + y * pDstFrame->linesize[2] / 2 , _blank_v, pDstFrame->linesize[2] * _student_height / 2);
  819 + }
  820 + fillDestFrame(pDstFrame, _studentFrame, 0, y);
  821 + }
  822 + else {
  823 + memset(pDstFrame->data[0] + y * pDstFrame->linesize[0], _blank_y, _nOutputWidth * _student_height);
  824 + memset(pDstFrame->data[1] + y * pDstFrame->linesize[1] / 2, _blank_u, _nOutputWidth * _student_height / 2);
  825 + memset(pDstFrame->data[2] + y * pDstFrame->linesize[2] / 2, _blank_v, _nOutputWidth * _student_height / 2);
  826 + fillDestFrame(pDstFrame, _studentFrame, (_nOutputWidth - _student_height) / 2, y, (_student_width - _student_height) / 2, 0, _student_height, _student_height);
  827 + }
  828 + }
  829 + else if (_studentFrame->width == _student_height && _studentFrame->height == _student_width) {
  830 + if (_studentFrame->pkt_dts == 90){
  831 + if (_student_width < _nOutputWidth) {
  832 + memset(pDstFrame->data[0] + y * pDstFrame->linesize[0], _blank_y, pDstFrame->linesize[0] * _student_height);
  833 + memset(pDstFrame->data[1] + y * pDstFrame->linesize[1] / 2, _blank_u, pDstFrame->linesize[1] * _student_height / 2);
  834 + memset(pDstFrame->data[2] + y * pDstFrame->linesize[2] / 2, _blank_v, pDstFrame->linesize[2] * _student_height / 2);
  835 + }
  836 + fillDestFrame(pDstFrame, _studentFrame, 0, y);
  837 + }
  838 + else {
  839 + memset(pDstFrame->data[0] + y * pDstFrame->linesize[0], _blank_y, pDstFrame->linesize[0] * _student_height);
  840 + memset(pDstFrame->data[1] + y * pDstFrame->linesize[1] / 2, _blank_u, pDstFrame->linesize[1] * _student_height / 2);
  841 + memset(pDstFrame->data[2] + y * pDstFrame->linesize[2] / 2, _blank_v, pDstFrame->linesize[2] * _student_height / 2);
  842 + fillDestFrame(pDstFrame, _studentFrame, (_nOutputWidth - _student_height) / 2, y, 0, (_student_width - _student_height) / 2, _student_height, _student_height);
  843 + }
  844 + }
  845 + else if (_studentFrame->width == _student_height && _studentFrame->height == _student_height) {
  846 + memset(pDstFrame->data[0] + y * pDstFrame->linesize[0], _blank_y, pDstFrame->linesize[0] * _student_height);
  847 + memset(pDstFrame->data[1] + y * pDstFrame->linesize[1] / 2, _blank_u, pDstFrame->linesize[1] * _student_height / 2);
  848 + memset(pDstFrame->data[2] + y * pDstFrame->linesize[2] / 2, _blank_v, pDstFrame->linesize[2] * _student_height / 2);
  849 + fillDestFrame(pDstFrame, _studentFrame, (_nOutputWidth - _student_height) / 2, y);
  850 + }
  851 +
  852 + return 0;
  853 + }
  854 +
  855 +
  856 + int CAVTranscoder::fill_one2one_student_frame(AVFrame * pDstFrame, int y)
  857 + {
  858 + if (_studentFrame->width == _student_width && _studentFrame->height == _student_height) {
  859 + if (_studentFrame->pkt_dts != 90){
  860 + fillDestFrame(pDstFrame, _studentFrame, 0, y);
  861 + }
  862 + else {
  863 + fillDestFrame(pDstFrame, _studentFrame, (_nOutputWidth - _student_height) / 2, y, (_student_width - _student_height) / 2, 0, _student_height, _student_height);
  864 + }
  865 + }
  866 + else if (_studentFrame->width == _student_height && _studentFrame->height == _student_width) {
  867 + if (_studentFrame->pkt_dts == 90){
  868 + fillDestFrame(pDstFrame, _studentFrame, 0, y);
  869 + }
  870 + else {
  871 + fillDestFrame(pDstFrame, _studentFrame, (_nOutputWidth - _student_height) / 2, y, 0, (_student_width - _student_height) / 2, _student_height, _student_height);
  872 + }
  873 + }
  874 + else if (_studentFrame->width == _student_height && _studentFrame->height == _student_height) {
  875 + fillDestFrame(pDstFrame, _studentFrame, (_nOutputWidth - _student_height) / 2, y);
  876 + }
  877 + else {
  878 + if (_one2one_same_size){
  879 + scale_fill_one2one_studentframe(pDstFrame, y);
  880 + }
  881 + else {
  882 + //printf("\nresolution: %dx%d unexpected!", _studentFrame->width, _studentFrame->height);
  883 + memset(pDstFrame->data[0] + y * pDstFrame->linesize[0], _blank_y, pDstFrame->linesize[0] * _teacher_height);
  884 + memset(pDstFrame->data[1] + y * pDstFrame->linesize[1] / 2, _blank_u, pDstFrame->linesize[1] * _teacher_height / 2);
  885 + memset(pDstFrame->data[2] + y * pDstFrame->linesize[2] /2 , _blank_v, pDstFrame->linesize[2] * _teacher_height / 2);
  886 + fillDestFrame(pDstFrame, _studentFrame, 0, y);
  887 + }
  888 + }
  889 + return 0;
  890 + }
  891 +
  892 +
689 int CAVTranscoder::mix_and_output_one2one_vframe(vector<CAVDecoder *> & decoders_got_frame) 893 int CAVTranscoder::mix_and_output_one2one_vframe(vector<CAVDecoder *> & decoders_got_frame)
690 { 894 {
691 //prepare one2one base frame 895 //prepare one2one base frame
@@ -703,7 +907,9 @@ int CAVTranscoder::open_output_file(const char *filename) @@ -703,7 +907,9 @@ int CAVTranscoder::open_output_file(const char *filename)
703 if (decoders_got_frame[i]->_media_role == mr_teacher) { 907 if (decoders_got_frame[i]->_media_role == mr_teacher) {
704 AVFrame * pFrame = decoders_got_frame[i]->_cur_v_frame; 908 AVFrame * pFrame = decoders_got_frame[i]->_cur_v_frame;
705 if (pFrame) { 909 if (pFrame) {
706 - av_frame_free(&_teacherFrame); 910 + if (_teacherFrame != _scaled_frame_teacher) {//if is the scaled frame ,don't free it
  911 + av_frame_free(&_teacherFrame);
  912 + }
707 _teacherFrame = pFrame; 913 _teacherFrame = pFrame;
708 decoders_got_frame[i]->_cur_v_frame = NULL; 914 decoders_got_frame[i]->_cur_v_frame = NULL;
709 } 915 }
@@ -711,7 +917,9 @@ int CAVTranscoder::open_output_file(const char *filename) @@ -711,7 +917,9 @@ int CAVTranscoder::open_output_file(const char *filename)
711 else { 917 else {
712 AVFrame * pFrame = decoders_got_frame[i]->_cur_v_frame; 918 AVFrame * pFrame = decoders_got_frame[i]->_cur_v_frame;
713 if (pFrame) { 919 if (pFrame) {
714 - av_frame_free(&_studentFrame); 920 + if (_studentFrame != _scaled_frame_student) {//if is the scaled frame ,don't free it
  921 + av_frame_free(&_studentFrame);
  922 + }
715 _studentFrame = pFrame; 923 _studentFrame = pFrame;
716 decoders_got_frame[i]->_cur_v_frame = NULL; 924 decoders_got_frame[i]->_cur_v_frame = NULL;
717 } 925 }
@@ -765,72 +973,23 @@ int CAVTranscoder::open_output_file(const char *filename) @@ -765,72 +973,23 @@ int CAVTranscoder::open_output_file(const char *filename)
765 } 973 }
766 else { 974 else {
767 //printf("\nresolution: %dx%d unexpected!", _teacherFrame->width, _teacherFrame->height); 975 //printf("\nresolution: %dx%d unexpected!", _teacherFrame->width, _teacherFrame->height);
768 - memset(pDstFrame->data[0], _blank_y, pDstFrame->linesize[0] * _teacher_height);  
769 - memset(pDstFrame->data[1], _blank_u, pDstFrame->linesize[1] * _teacher_height / 2);  
770 - memset(pDstFrame->data[2], _blank_v, pDstFrame->linesize[2] * _teacher_height / 2);  
771 -  
772 - fillDestFrame(pDstFrame, _teacherFrame, 0, 0);  
773 - }  
774 - if (_studentFrame) {  
775 - if (_studentFrame->width == _student_width) {  
776 - if (_studentFrame->pkt_dts != 90){  
777 - if (_student_width < _nOutputWidth) {  
778 - memset(pDstFrame->data[0] + _teacher_height * pDstFrame->linesize[0], _blank_y, pDstFrame->linesize[0] * _student_height);  
779 - memset(pDstFrame->data[1] + _teacher_height / 2 * pDstFrame->linesize[1], _blank_u, pDstFrame->linesize[1] * _student_height / 2);  
780 - memset(pDstFrame->data[2] + _teacher_height / 2 * pDstFrame->linesize[2], _blank_v, pDstFrame->linesize[2] * _student_height / 2);  
781 - }  
782 - fillDestFrame(pDstFrame, _studentFrame, 0, _teacher_height);  
783 - }  
784 - else {  
785 - memset(pDstFrame->data[0] + _teacher_height * pDstFrame->linesize[0], _blank_y, pDstFrame->linesize[0] * _student_height);  
786 - memset(pDstFrame->data[1] + _teacher_height / 2 * pDstFrame->linesize[1], _blank_u, pDstFrame->linesize[1] * _student_height / 2);  
787 - memset(pDstFrame->data[2] + _teacher_height / 2 * pDstFrame->linesize[2], _blank_v, pDstFrame->linesize[2] * _student_height / 2);  
788 - fillDestFrame(pDstFrame, _studentFrame, (_nOutputWidth - _student_height) / 2, _teacher_height, (_student_width - _student_height) / 2, 0, _student_height, _student_height);  
789 - }  
790 - }  
791 - else if (_studentFrame->pkt_dts == 90){  
792 - if (_student_width < _nOutputWidth) {  
793 - memset(pDstFrame->data[0] + _teacher_height * pDstFrame->linesize[0], _blank_y, pDstFrame->linesize[0] * _student_height);  
794 - memset(pDstFrame->data[1] + _teacher_height / 2 * pDstFrame->linesize[1], _blank_u, pDstFrame->linesize[1] * _student_height / 2);  
795 - memset(pDstFrame->data[2] + _teacher_height / 2 * pDstFrame->linesize[2], _blank_v, pDstFrame->linesize[2] * _student_height / 2);  
796 - }  
797 - fillDestFrame(pDstFrame, _studentFrame, 0, _teacher_height); 976 + if (!_one2one_same_size) {
  977 + memset(pDstFrame->data[0], _blank_y, pDstFrame->linesize[0] * _teacher_height);
  978 + memset(pDstFrame->data[1], _blank_u, pDstFrame->linesize[1] * _teacher_height / 2);
  979 + memset(pDstFrame->data[2], _blank_v, pDstFrame->linesize[2] * _teacher_height / 2);
  980 +
  981 + fillDestFrame(pDstFrame, _teacherFrame, 0, 0);
798 } 982 }
799 else { 983 else {
800 - memset(pDstFrame->data[0] + _teacher_height * pDstFrame->linesize[0], _blank_y, pDstFrame->linesize[0] * _student_height);  
801 - memset(pDstFrame->data[1] + _teacher_height / 2 * pDstFrame->linesize[1], _blank_u, pDstFrame->linesize[1] * _student_height / 2);  
802 - memset(pDstFrame->data[2] + _teacher_height / 2 * pDstFrame->linesize[2], _blank_v, pDstFrame->linesize[2] * _student_height / 2);  
803 - fillDestFrame(pDstFrame, _studentFrame, (_nOutputWidth - _student_height) / 2, _teacher_height, 0, (_student_width - _student_height) / 2, _student_height, _student_height); 984 + scale_fill_one2one_teacherframe(pDstFrame);
804 } 985 }
805 } 986 }
  987 + if (_studentFrame) {
  988 + fill_one2one_student_frame(pDstFrame, _teacher_height);
  989 + }
806 } 990 }
807 else if (_studentFrame) { 991 else if (_studentFrame) {
808 - if (_studentFrame->width == _student_width && _studentFrame->height == _student_height) {  
809 - if (_studentFrame->pkt_dts != 90){  
810 - fillDestFrame(pDstFrame, _studentFrame, 0, 0);  
811 - }  
812 - else {  
813 - fillDestFrame(pDstFrame, _studentFrame, (_nOutputWidth - _student_height) / 2, 0, (_student_width - _student_height) / 2, 0, _student_height, _student_height);  
814 - }  
815 - }  
816 - else if (_studentFrame->width == _student_height && _studentFrame->height == _student_width) {  
817 - if (_studentFrame->pkt_dts == 90){  
818 - fillDestFrame(pDstFrame, _studentFrame, 0, 0);  
819 - }  
820 - else {  
821 - fillDestFrame(pDstFrame, _studentFrame, (_nOutputWidth - _student_height) / 2, 0, 0, (_student_width - _student_height) / 2, _student_height, _student_height);  
822 - }  
823 - }  
824 - else if (_studentFrame->width == _student_height && _studentFrame->height == _student_height) {  
825 - fillDestFrame(pDstFrame, _studentFrame, (_nOutputWidth - _student_height) / 2, 0);  
826 - }  
827 - else {  
828 - //printf("\nresolution: %dx%d unexpected!", _studentFrame->width, _studentFrame->height);  
829 - memset(pDstFrame->data[0], _blank_y, pDstFrame->linesize[0] * _teacher_height);  
830 - memset(pDstFrame->data[1], _blank_u, pDstFrame->linesize[1] * _teacher_height / 2);  
831 - memset(pDstFrame->data[2], _blank_v, pDstFrame->linesize[2] * _teacher_height / 2);  
832 - fillDestFrame(pDstFrame, _studentFrame, 0, 0);  
833 - } 992 + fill_one2one_student_frame(pDstFrame, 0);
834 } 993 }
835 994
836 if (decoders_got_frame.size() == 2){ 995 if (decoders_got_frame.size() == 2){
@@ -5,7 +5,7 @@ @@ -5,7 +5,7 @@
5 class CAVTranscoder 5 class CAVTranscoder
6 { 6 {
7 public: 7 public:
8 - CAVTranscoder(bool bOne2One, int width_teacher, int height_teacher, int student_width,int student_height, bool has_teacher, int max_audio); 8 + CAVTranscoder(bool bOne2One, bool one2one_same_size, int width_teacher, int height_teacher, int student_width,int student_height, bool has_teacher, int max_audio);
9 virtual ~CAVTranscoder(); 9 virtual ~CAVTranscoder();
10 10
11 int add(media_info & info); 11 int add(media_info & info);
@@ -34,6 +34,7 @@ private: @@ -34,6 +34,7 @@ private:
34 int mix_and_output_one2one_vframe(vector<CAVDecoder *> & decoders_got_frame); 34 int mix_and_output_one2one_vframe(vector<CAVDecoder *> & decoders_got_frame);
35 int mix_and_output_one2many_vframe(vector<CAVDecoder *> & decoders_got_frame); 35 int mix_and_output_one2many_vframe(vector<CAVDecoder *> & decoders_got_frame);
36 36
  37 + int scale_fill_one2one_teacherframe(AVFrame *pDstFrame);
37 int fillDestFrame(AVFrame * pDstFrame, AVFrame * pSrcFrame, int x, int y); 38 int fillDestFrame(AVFrame * pDstFrame, AVFrame * pSrcFrame, int x, int y);
38 int fillDestFrame(AVFrame * pDstFrame, AVFrame * pSrcFrame, int destx, int desty, int srcx,int srcy,int w,int h); 39 int fillDestFrame(AVFrame * pDstFrame, AVFrame * pSrcFrame, int destx, int desty, int srcx,int srcy,int w,int h);
39 int encode_write_frame(AVFrame *filt_frame, unsigned int stream_index, int *got_frame); 40 int encode_write_frame(AVFrame *filt_frame, unsigned int stream_index, int *got_frame);
@@ -52,18 +53,32 @@ private: @@ -52,18 +53,32 @@ private:
52 int _teacher_height; 53 int _teacher_height;
53 int _student_width; 54 int _student_width;
54 int _student_height; 55 int _student_height;
55 - struct SwsContext * _sws_ctx_w_h; 56 + bool _one2one_same_size;//top and bottom are same size ,if not ,scale the smaller to the larger
  57 + struct SwsContext * _sws_ctx_w_h; //for one2many student frame
56 struct SwsContext * _sws_ctx_h_w; 58 struct SwsContext * _sws_ctx_h_w;
57 struct SwsContext * _sws_ctx_h_h; 59 struct SwsContext * _sws_ctx_h_h;
58 AVFrame * _scaled_frame_w_h; 60 AVFrame * _scaled_frame_w_h;
59 AVFrame * _scaled_frame_h_w; 61 AVFrame * _scaled_frame_h_w;
60 AVFrame * _scaled_frame_h_h; 62 AVFrame * _scaled_frame_h_h;
61 int _last_videos_got; 63 int _last_videos_got;
  64 +
62 AVFrame * _teacherFrame; 65 AVFrame * _teacherFrame;
63 AVFrame * _studentFrame; // for one2one,keep the last frame 66 AVFrame * _studentFrame; // for one2one,keep the last frame
64 67
  68 + struct SwsContext * _sws_ctx_teacher;//for one2one teacher frame
  69 + AVFrame * _scaled_frame_teacher;
  70 + int _src_width_teacher;
  71 + int _src_height_teacher;
  72 + struct SwsContext * _sws_ctx_student;//for one2one teacher frame
  73 + AVFrame * _scaled_frame_student;
  74 + int _src_width_student;
  75 + int _src_height_student;
  76 +
65 uint8_t _blank_y, _blank_u, _blank_v; 77 uint8_t _blank_y, _blank_u, _blank_v;
66 public: 78 public:
67 void set_max_audio(int max_audio); 79 void set_max_audio(int max_audio);
  80 +private:
  81 + int scale_fill_one2one_studentframe(AVFrame * pDstFrame, int y);
  82 + int fill_one2one_student_frame(AVFrame * pDstFrame, int y);
68 }; 83 };
69 84
@@ -3,7 +3,7 @@ @@ -3,7 +3,7 @@
3 读入合屏信息文件,合成画中画视频。 3 读入合屏信息文件,合成画中画视频。
4 4
5 使用方法: 5 使用方法:
6 -merge_pip merge_info.txt [-t {0,1,2}] [-c codec.cfg] 6 +merge_pip merge_info.txt [-t {0,1,2}] [-c codec.cfg] [-s {1,0}]
7 其中merge_info.txt为合屏信息文件,格式如下: 7 其中merge_info.txt为合屏信息文件,格式如下:
8 8
9 teacher: 9 teacher:
@@ -46,6 +46,9 @@ merge_pip_codec.cfg主要编码参数: @@ -46,6 +46,9 @@ merge_pip_codec.cfg主要编码参数:
46 #音频码率 46 #音频码率
47 a_bit_rate = 64000 47 a_bit_rate = 64000
48 48
  49 +-s 为可选参数,在一对一布局下起作用。缺省为1
  50 +1 如果老师和学生的视频大小不一致,会放大较小的视频使得老师和学生视频大小相同。
  51 +0 保持原有视频大小
49 52
50 合屏后生成完成信息文件,文件名为"m_" + 输入文件名" + ".txt",合成的mp4文件名为"m_" + 输入文件名" + ".mp4" 53 合屏后生成完成信息文件,文件名为"m_" + 输入文件名" + ".txt",合成的mp4文件名为"m_" + 输入文件名" + ".mp4"
51 如merge_pip 1.txt 54 如merge_pip 1.txt
@@ -71,4 +74,9 @@ V2.0.4 @@ -71,4 +74,9 @@ V2.0.4
71 1.支持读取编码配置文件,用于改变编码配置 74 1.支持读取编码配置文件,用于改变编码配置
72 75
73 V2.0.5 76 V2.0.5
74 -1.在录像信息文件里没有老师视频或学生视频时,把老师视频或学生视频的大小设为320x240,避免在一对多布局时出现错误  
  77 +1.在录像信息文件里没有老师视频或学生视频时,把老师视频或学生视频的大小设为320x240,避免在一对多布局时出现错误
  78 +
  79 +V2.0.6
  80 +1. 命令行添加-s可选参数,在一对一布局下起作用。缺省为1
  81 + 1 如果老师和学生的视频大小不一致,会放大较小的视频使得老师和学生视频大小相同。
  82 + 0 保持原有视频大小
@@ -1088,7 +1088,7 @@ int load_record_info(char * record_info) @@ -1088,7 +1088,7 @@ int load_record_info(char * record_info)
1088 1088
1089 #define MIN_TIME_INTERVAL 25 1089 #define MIN_TIME_INTERVAL 25
1090 1090
1091 -int process_av_files(char * record_info, int piptype) 1091 +int process_av_files(char * record_info, int piptype, bool one2one_same_size)
1092 { 1092 {
1093 time_t start, end; 1093 time_t start, end;
1094 time(&start); 1094 time(&start);
@@ -1127,7 +1127,7 @@ int process_av_files(char * record_info, int piptype) @@ -1127,7 +1127,7 @@ int process_av_files(char * record_info, int piptype)
1127 } 1127 }
1128 } 1128 }
1129 1129
1130 - CAVTranscoder videoTranscoder(one2one, width_teacher, height_teacher,width_student, height_student, has_teacher, max_audio); 1130 + CAVTranscoder videoTranscoder(one2one, one2one_same_size, width_teacher, height_teacher, width_student, height_student, has_teacher, max_audio);
1131 videoTranscoder.set_max_audio(max_audio); 1131 videoTranscoder.set_max_audio(max_audio);
1132 1132
1133 int64_t cur_time = 0; 1133 int64_t cur_time = 0;
@@ -1202,14 +1202,15 @@ int process_av_files(char * record_info, int piptype) @@ -1202,14 +1202,15 @@ int process_av_files(char * record_info, int piptype)
1202 int main(int argc, char * argv[]) 1202 int main(int argc, char * argv[])
1203 { 1203 {
1204 if (argc < 2) { 1204 if (argc < 2) {
1205 - printf(" merge_pip 2.0.5\n"); 1205 + printf(" merge_pip 2.0.6\n");
1206 printf(" merge video files to one pip video according to record info file,\nusage:"); 1206 printf(" merge video files to one pip video according to record info file,\nusage:");
1207 - printf("\n %s record_info_filename [-t {0,1,2}] [-c codec.cfg]", argv[0]); 1207 + printf("\n %s record_info_filename [-t {0,1,2}] [-c codec.cfg] [-s {1,0}]", argv[0]);
1208 printf("\n\n"); 1208 printf("\n\n");
1209 return -1; 1209 return -1;
1210 } 1210 }
1211 1211
1212 int piptype = 0; 1212 int piptype = 0;
  1213 + bool one2one_same_size = true;
1213 for (int i = 2; i < argc; i++){ 1214 for (int i = 2; i < argc; i++){
1214 if (!strcmp(argv[i], "-t")){ 1215 if (!strcmp(argv[i], "-t")){
1215 i++; 1216 i++;
@@ -1227,6 +1228,14 @@ int main(int argc, char * argv[]) @@ -1227,6 +1228,14 @@ int main(int argc, char * argv[])
1227 } 1228 }
1228 strcpy(user_codec_cfg,argv[i]); 1229 strcpy(user_codec_cfg,argv[i]);
1229 } 1230 }
  1231 + else if (!strcmp(argv[i], "-s")){
  1232 + i++;
  1233 + if (i > argc) {
  1234 + printf("error,should be 1 or 0 after -s");
  1235 + return -2;
  1236 + }
  1237 + one2one_same_size = argv[i][0] == '1';
  1238 + }
1230 } 1239 }
1231 1240
1232 1241
@@ -1234,5 +1243,5 @@ int main(int argc, char * argv[]) @@ -1234,5 +1243,5 @@ int main(int argc, char * argv[])
1234 1243
1235 load_codec_param(); 1244 load_codec_param();
1236 1245
1237 - return process_av_files(argv[1], piptype); 1246 + return process_av_files(argv[1], piptype, one2one_same_size);
1238 } 1247 }