V2.0.6
1. 命令行添加-s可选参数,在一对一布局下起作用。缺省为1 1 如果老师和学生的视频大小不一致,会放大较小的视频使得老师和学生视频大小相同。 0 保持原有视频大小
正在显示
4 个修改的文件
包含
264 行增加
和
73 行删除
| @@ -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 | } |
-
请 注册 或 登录 后发表评论