胡斌

V2.0.3

1.没有老师,但是有两个学生时,默认使用一对多布局
2.一对一时,老师和学生的视频尺寸不同时,合成的视频高度取老师视频高度加上学生视频高度(之前版本假定老师和学生视频大小一致,使用的是最大高度的二倍)
3.一对多时,支持学生的视频尺寸不一致的情况(之前版本假定只有一种视频尺寸,其它尺寸视为异常)
4.一对多时,最多只在老师视频下部排4个学生,多于4个学生的情况,扩大合成视频的高度,把学生视频排列在老师视频下方,保证老师视频部分最多只有一排学生视频,避免老师视频被过度遮挡
#include "AVDecoder.h"
extern "C" {
#include <libswscale/swscale.h>
}
CAVDecoder::CAVDecoder() :
_a_start_time_ms(INT64_MAX),
... ... @@ -9,7 +11,12 @@ _cur_v_ts_ms(INT64_MAX),
_end_time_ms(0),
_cur_a_frame(NULL),
_cur_v_frame(NULL),
_media_role(mr_student)
_media_role(mr_student),
_scaled_width(0),
_scaled_height(0),
_src_width(0),
_src_height(0),
_sws_ctx(NULL)
{
}
... ... @@ -18,6 +25,10 @@ CAVDecoder::~CAVDecoder()
{
free_cur_v_frame();
free_cur_a_frame();
if (_sws_ctx) {
sws_freeContext(_sws_ctx);
_sws_ctx = NULL;
}
}
int CAVDecoder::add(media_info &info)
... ... @@ -116,6 +127,32 @@ void CAVDecoder::free_cur_a_frame()
}
}
int CAVDecoder::scale_frame(AVFrame * pFrame, AVFrame * pScaledFrame, int scaled_width, int scaled_height)
{
if (pFrame->width == _src_width && pFrame->height == _src_height && scaled_width == _scaled_width && scaled_height == _scaled_height) {
return sws_scale(_sws_ctx, pFrame->data, pFrame->linesize, 0, pFrame->height,
pScaledFrame->data, pScaledFrame->linesize);
}
else {
if (_sws_ctx) {
sws_freeContext(_sws_ctx);
_sws_ctx = NULL;
}
_sws_ctx = sws_getContext(pFrame->width, pFrame->height, AV_PIX_FMT_YUV420P,
scaled_width, scaled_height, AV_PIX_FMT_YUV420P, SWS_BILINEAR,
NULL, NULL, NULL);
if (!_sws_ctx) {
return -1;
}
_src_width = pFrame->width;
_src_height = pFrame->height;
_scaled_width = scaled_width;
_scaled_height = scaled_height;
return sws_scale(_sws_ctx, pFrame->data, pFrame->linesize, 0, pFrame->height,
pScaledFrame->data, pScaledFrame->linesize);
}
}
void CAVDecoder::free_cur_v_frame()
{
if (_cur_v_frame) {
... ...
... ... @@ -37,5 +37,15 @@ protected:
protected:
void free_cur_v_frame();
void free_cur_a_frame();
public:
int scale_frame(AVFrame * pFrame, AVFrame * pScaledFrame, int scaled_width, int scaled_height);
protected:
int _scaled_width;
int _scaled_height;
int _src_width;
int _src_height;
struct SwsContext * _sws_ctx;
};
... ...
... ... @@ -13,8 +13,13 @@ extern "C" {
uint8_t blank_r = 0x16;
uint8_t blank_g = 0x5a;
uint8_t blank_b = 0x82;
int pip_x_gap = 8;
int pip_y_gap = 4;
int pip_x_reduce = 3;
int pip_y_reduce = 3;
int pip_x_border = 4;
CAVTranscoder::CAVTranscoder(bool bOne2One, int width_teacher, int height_teacher, int width_student, int height_student) :
CAVTranscoder::CAVTranscoder(bool bOne2One, int width_teacher, int height_teacher, int width_student, int height_student, bool has_teacher, int max_audio) :
_start_time(INT64_MAX),
_all_processed(true),
_nOutputWidth(320),
... ... @@ -29,7 +34,9 @@ _scaled_frame_h_w(NULL),
_scaled_frame_h_h(NULL),
_last_videos_got(-1),
_teacherFrame(NULL),
_studentFrame(NULL)
_studentFrame(NULL),
_pip_width(0),
_pip_height(0)
{
_teacher_width = width_teacher;
_teacher_height = height_teacher;
... ... @@ -38,6 +45,7 @@ _studentFrame(NULL)
_scaled_width = _teacher_width * 10 / 32;
_scaled_height = _teacher_height * 10 / 32;
_one2one = bOne2One;
if (_one2one) {
_nOutputWidth = max(_teacher_width, _student_width);
... ... @@ -45,7 +53,23 @@ _studentFrame(NULL)
}
else {
_nOutputWidth = _teacher_width;
_nOutputHeight = _teacher_height;
int n_students = (max_audio - (has_teacher ? 1 : 0));
int extent_student_lines = n_students / 4;
int part_student = n_students % 4;
_pip_width = _scaled_height - pip_x_reduce; //use the scaled height,not the scaled width as pip_width
_pip_height = _scaled_height - pip_y_reduce;
_nOutputHeight = _teacher_height + extent_student_lines * (_pip_height + pip_y_gap) - (part_student == 0 ? (pip_y_gap) : 0);
_nOutputHeight = ((_nOutputHeight + 1) / 2) * 2;
int student_line_width = 4 * (_pip_width)+3 * pip_x_gap + 2 * pip_x_border;
if (student_line_width > _nOutputWidth) {
pip_x_gap -= (student_line_width - _nOutputWidth) / 3;
}
student_line_width = 4 * (_pip_width) + 3 * pip_x_gap + 2 * pip_x_border;
pip_x_border -= (student_line_width - _nOutputWidth) / 2;
init_scale_context(&_sws_ctx_w_h, &_scaled_frame_w_h, _student_width, _student_height, _scaled_width, _scaled_height);
init_scale_context(&_sws_ctx_h_w, &_scaled_frame_h_w, _student_height, _student_width, _scaled_height, _scaled_width);
... ... @@ -356,12 +380,17 @@ int CAVTranscoder::open_output_file(const char *filename)
}
if (_teacherFrame) {
fillDestFrame(pDstFrame, _teacherFrame, 0, 0);
if (_nOutputHeight > _teacherFrame->height) {
memset(pDstFrame->data[0] + _teacher_height * pDstFrame->linesize[0], _blank_y, pDstFrame->linesize[0] * (_nOutputHeight - _teacherFrame->height));
memset(pDstFrame->data[1] + _teacher_height / 2 * pDstFrame->linesize[1], _blank_u, pDstFrame->linesize[1] * (_nOutputHeight - _teacherFrame->height) / 2);
memset(pDstFrame->data[2] + _teacher_height / 2 * pDstFrame->linesize[2], _blank_v, pDstFrame->linesize[2] * (_nOutputHeight - _teacherFrame->height) / 2);
}
}
else
{//fill with pure color
memset(pDstFrame->data[0], _blank_y, _nOutputWidth * _nOutputHeight);
memset(pDstFrame->data[1], _blank_u, _nOutputWidth *_nOutputHeight / 4);
memset(pDstFrame->data[2], _blank_v, _nOutputWidth * _nOutputHeight / 4);
memset(pDstFrame->data[0], _blank_y, pDstFrame->linesize[0] * _nOutputHeight);
memset(pDstFrame->data[1], _blank_u, pDstFrame->linesize[1] * _nOutputHeight / 2);
memset(pDstFrame->data[2], _blank_v, pDstFrame->linesize[2] * _nOutputHeight / 2);
}
int imageIdx = 0;
... ... @@ -382,7 +411,7 @@ int CAVTranscoder::open_output_file(const char *filename)
continue;
}
_scaled_frame_w_h->pkt_dts = pFrame->pkt_dts;//pass rotation
fillDestFrame(pDstFrame, _scaled_frame_w_h, _teacher_width - (imageIdx % 4 + 1) * (_scaled_height + 5) + 4, _teacher_height - _scaled_height + 3 - (_scaled_height + 1)*(imageIdx / 4), (_scaled_width - _scaled_height) / 2, 0, _scaled_height - 3, _scaled_height - 3);
fillDestFrame(pDstFrame, _scaled_frame_w_h, _teacher_width - (imageIdx % 4 + 1) * (_pip_width + pip_x_gap) - pip_x_border + pip_x_gap, _nOutputHeight - _scaled_height + pip_y_reduce - (_pip_height + pip_y_gap)*(imageIdx / 4), (_scaled_width - _scaled_height) / 2, 0, _pip_width, _pip_height);
}
else if (pFrame->width == _student_height && pFrame->height == _student_width) {
h = sws_scale(_sws_ctx_h_w, pFrame->data, pFrame->linesize, 0, pFrame->height,
... ... @@ -392,7 +421,7 @@ int CAVTranscoder::open_output_file(const char *filename)
continue;
}
_scaled_frame_h_w->pkt_dts = pFrame->pkt_dts;//pass rotation
fillDestFrame(pDstFrame, _scaled_frame_h_w, _teacher_width - (imageIdx % 4 + 1) * (_scaled_height + 5) + 4, _teacher_height - _scaled_height + 3 - (_scaled_height + 1)*(imageIdx / 4), 0, (_scaled_width - _scaled_height) / 2, _scaled_height - 3, _scaled_height - 3);
fillDestFrame(pDstFrame, _scaled_frame_h_w, _teacher_width - (imageIdx % 4 + 1) * (_pip_width + pip_x_gap) - pip_x_border + pip_x_gap, _nOutputHeight - _scaled_height + pip_y_reduce - (_pip_height + pip_y_gap)*(imageIdx / 4), 0, (_scaled_width - _scaled_height) / 2, _pip_width, _pip_height);
}
else if (pFrame->width == _student_height && pFrame->height == _student_height) {
... ... @@ -403,12 +432,38 @@ int CAVTranscoder::open_output_file(const char *filename)
continue;
}
_scaled_frame_h_h->pkt_dts = pFrame->pkt_dts;//pass rotation
fillDestFrame(pDstFrame, _scaled_frame_h_h, _teacher_width - (imageIdx % 4 + 1) * (_scaled_height + 5) + 4, _teacher_height - _scaled_height + 3 - (_scaled_height + 1)*(imageIdx / 4), 0, 0, _scaled_height - 3, _scaled_height - 3);
fillDestFrame(pDstFrame, _scaled_frame_h_h, _teacher_width - (imageIdx % 4 + 1) * (_pip_width + pip_x_gap) - pip_x_border + pip_x_gap, _nOutputHeight - _scaled_height + pip_y_reduce - (_pip_height + pip_y_gap)*(imageIdx / 4), 0, 0, _pip_width, _pip_height);
}
else {
printf("\nthe frame resolution %dx%d is unexpected! ignored!", pFrame->width, pFrame->height);
if (pFrame->width > pFrame->height) {
h = pDecoder->scale_frame(pFrame, _scaled_frame_w_h, _scaled_width, _scaled_height);
if (h <= 0){
printf("\nscale output result:%d?,ignored", h);
continue;
}
_scaled_frame_w_h->pkt_dts = pFrame->pkt_dts;//pass rotation
fillDestFrame(pDstFrame, _scaled_frame_w_h, _teacher_width - (imageIdx % 4 + 1) * (_pip_width + pip_x_gap) - pip_x_border + pip_x_gap, _nOutputHeight - _scaled_height + pip_y_reduce - (_pip_height + pip_y_gap)*(imageIdx / 4), (_scaled_width - _scaled_height) / 2, 0, _pip_width, _pip_height);
}
else if (pFrame->width == pFrame->height)
{
h = pDecoder->scale_frame(pFrame, _scaled_frame_h_h, _scaled_height, _scaled_height);
if (h <= 0){
printf("\nscale output result:%d?,ignored", h);
continue;
}
_scaled_frame_h_h->pkt_dts = pFrame->pkt_dts;//pass rotation
fillDestFrame(pDstFrame, _scaled_frame_h_h, _teacher_width - (imageIdx % 4 + 1) * (_pip_width + pip_x_gap) - pip_x_border + pip_x_gap, _nOutputHeight - _scaled_height + pip_y_reduce - (_pip_height + pip_y_gap)*(imageIdx / 4), 0, 0, _pip_width, _pip_height);
}
else {
h = pDecoder->scale_frame(pFrame, _scaled_frame_h_w, _scaled_height, _scaled_width);
if (h <= 0){
printf("\nscale output result:%d?,ignored", h);
continue;
}
_scaled_frame_h_w->pkt_dts = pFrame->pkt_dts;//pass rotation
fillDestFrame(pDstFrame, _scaled_frame_h_w, _teacher_width - (imageIdx % 4 + 1) * (_pip_width + pip_x_gap) - pip_x_border + pip_x_gap, _nOutputHeight - _scaled_height + pip_y_reduce - (_pip_height + pip_y_gap)*(imageIdx / 4), 0, (_scaled_width - _scaled_height) / 2, _pip_width, _pip_height);
}
}
imageIdx++;
}
... ... @@ -508,9 +563,9 @@ int CAVTranscoder::open_output_file(const char *filename)
memcpy(pDstFrame->data[0] + (y + i)*pDstFrame->linesize[0] + x, pSrcFrame->data[0] + (i + srcy) * pSrcFrame->linesize[0] + srcx, w);
}
for (int i = 0; i < h / 2; i++){
memcpy(pDstFrame->data[1] + (y / 2 + i)*pDstFrame->linesize[1] + x / 2, pSrcFrame->data[1] + (i + srcy / 2) * pSrcFrame->linesize[1] + srcx/2, w / 2);
memcpy(pDstFrame->data[2] + (y / 2 + i)*pDstFrame->linesize[2] + x / 2, pSrcFrame->data[2] + (i + srcy / 2) * pSrcFrame->linesize[2] + srcx/2, w / 2);
for (int i = 0; i < (h +1) / 2; i++){
memcpy(pDstFrame->data[1] + (y / 2 + i)*pDstFrame->linesize[1] + x / 2, pSrcFrame->data[1] + (i + srcy / 2) * pSrcFrame->linesize[1] + srcx/2, (w +1)/ 2);
memcpy(pDstFrame->data[2] + (y / 2 + i)*pDstFrame->linesize[2] + x / 2, pSrcFrame->data[2] + (i + srcy / 2) * pSrcFrame->linesize[2] + srcx/2, (w +1)/ 2);
}
}
else if (pSrcFrame->pkt_dts == 180) {
... ... @@ -525,16 +580,16 @@ int CAVTranscoder::open_output_file(const char *filename)
}
unsigned char * startSrcU = pSrcFrame->data[1] + pSrcFrame->width / 2 + ((pSrcFrame->height - srcy -1)/ 2) * pSrcFrame->linesize[1] - srcx / 2 - 1;
unsigned char * startSrcV = pSrcFrame->data[2] + pSrcFrame->width / 2 + ((pSrcFrame->height - srcy -1)/ 2) * pSrcFrame->linesize[2] - srcx / 2 - 1;
for (int i = 0; i < h / 2; i++){
for (int i = 0; i < (h + 1) / 2; i++){
unsigned char * psrc = startSrcU - i * pSrcFrame->linesize[1];
unsigned char * pdst = pDstFrame->data[1] + (y / 2 + i)*pDstFrame->linesize[1] + x / 2;
unsigned char * pdst_end = pdst + w/2;
unsigned char * pdst_end = pdst + (w + 1)/2;
for (; pdst < pdst_end; psrc--, pdst++) {
*pdst = *psrc;
}
psrc = startSrcV - i * pSrcFrame->linesize[2];
pdst = pDstFrame->data[2] + (y / 2 + i)*pDstFrame->linesize[2] + x / 2;
pdst_end = pdst + w/2;
pdst_end = pdst + (w +1)/2;
for (; pdst < pdst_end; psrc--, pdst++) {
*pdst = *psrc;
}
... ... @@ -552,9 +607,9 @@ int CAVTranscoder::open_output_file(const char *filename)
}
unsigned char * startSrcU = pSrcFrame->data[1] + srcy/2 * pSrcFrame->linesize[1] + srcx/2;
for (int i = 0; i < h/2; i++) {
for (int i = 0; i < (h + 1)/2; i++) {
unsigned char * psrc = startSrcU + i* pSrcFrame->linesize[1];
unsigned char * psrc_end = psrc + w/2;
unsigned char * psrc_end = psrc + (w +1)/2;
unsigned char * pdst = pDstFrame->data[1] + y/2*pDstFrame->linesize[1] + h/2 -1 - i +x/2;
for (; psrc < psrc_end; psrc++, pdst += pDstFrame->linesize[1]) {
*pdst = *psrc;
... ... @@ -562,9 +617,9 @@ int CAVTranscoder::open_output_file(const char *filename)
}
unsigned char * startSrcV= pSrcFrame->data[2] + srcy / 2 * pSrcFrame->linesize[2] + srcx / 2;
for (int i = 0; i < h / 2; i++) {
for (int i = 0; i < (h + 1) / 2; i++) {
unsigned char * psrc = startSrcV + i* pSrcFrame->linesize[2];
unsigned char * psrc_end = psrc + w / 2;
unsigned char * psrc_end = psrc + (w + 1) / 2;
unsigned char * pdst = pDstFrame->data[2] + y / 2 * pDstFrame->linesize[2] + h / 2 -1 - i + x/2;
for (; psrc < psrc_end; psrc++, pdst += pDstFrame->linesize[2]) {
*pdst = *psrc;
... ... @@ -607,55 +662,55 @@ int CAVTranscoder::open_output_file(const char *filename)
}
if (!_teacherFrame || !_studentFrame) {
memset(pDstFrame->data[0], _blank_y, _nOutputWidth * _nOutputHeight);
memset(pDstFrame->data[1], _blank_u, _nOutputWidth * _nOutputHeight / 4);
memset(pDstFrame->data[2], _blank_v, _nOutputWidth * _nOutputHeight / 4);
memset(pDstFrame->data[0], _blank_y, pDstFrame->linesize[0] * _nOutputHeight);
memset(pDstFrame->data[1], _blank_u, pDstFrame->linesize[1] * _nOutputHeight / 2);
memset(pDstFrame->data[2], _blank_v, pDstFrame->linesize[2] * _nOutputHeight / 2);
}
if (_teacherFrame) {
if (_teacherFrame->width == _teacher_width && _teacherFrame->height == _teacher_height) {
if (_teacherFrame->pkt_dts != 90){
if (_teacher_width < _nOutputWidth) {
memset(pDstFrame->data[0], _blank_y, _nOutputWidth * _teacher_height);
memset(pDstFrame->data[1], _blank_u, _nOutputWidth * _teacher_height / 4);
memset(pDstFrame->data[2], _blank_v, _nOutputWidth * _teacher_height / 4);
memset(pDstFrame->data[0], _blank_y, pDstFrame->linesize[0] * _teacher_height);
memset(pDstFrame->data[1], _blank_u, pDstFrame->linesize[1] * _teacher_height / 2);
memset(pDstFrame->data[2], _blank_v, pDstFrame->linesize[2] * _teacher_height / 2);
}
fillDestFrame(pDstFrame, _teacherFrame, 0, 0);
}
else {
memset(pDstFrame->data[0], _blank_y, _nOutputWidth * _teacher_height);
memset(pDstFrame->data[1], _blank_u, _nOutputWidth * _teacher_height / 4);
memset(pDstFrame->data[2], _blank_v, _nOutputWidth * _teacher_height / 4);
memset(pDstFrame->data[1], _blank_u, _nOutputWidth * _teacher_height / 2);
memset(pDstFrame->data[2], _blank_v, _nOutputWidth * _teacher_height / 2);
fillDestFrame(pDstFrame, _teacherFrame, (_nOutputWidth - _teacher_height) / 2, 0, (_teacher_width - _teacher_height) / 2, 0, _teacher_height, _teacher_height);
}
}
else if (_teacherFrame->width == _teacher_height && _teacherFrame->height == _teacher_width) {
if (_teacherFrame->pkt_dts == 90){
if (_teacher_width < _nOutputWidth) {
memset(pDstFrame->data[0], _blank_y, _nOutputWidth * _teacher_height);
memset(pDstFrame->data[1], _blank_u, _nOutputWidth * _teacher_height / 4);
memset(pDstFrame->data[2], _blank_v, _nOutputWidth * _teacher_height / 4);
memset(pDstFrame->data[0], _blank_y, pDstFrame->linesize[0] * _teacher_height);
memset(pDstFrame->data[1], _blank_u, pDstFrame->linesize[1] * _teacher_height / 2);
memset(pDstFrame->data[2], _blank_v, pDstFrame->linesize[2] * _teacher_height / 2);
}
fillDestFrame(pDstFrame, _teacherFrame, 0, 0);
}
else {
memset(pDstFrame->data[0], _blank_y, _nOutputWidth * _teacher_height);
memset(pDstFrame->data[1], _blank_u, _nOutputWidth * _teacher_height / 4);
memset(pDstFrame->data[2], _blank_v, _nOutputWidth * _teacher_height / 4);
memset(pDstFrame->data[0], _blank_y, pDstFrame->linesize[0] * _teacher_height);
memset(pDstFrame->data[1], _blank_u, pDstFrame->linesize[1] * _teacher_height / 2);
memset(pDstFrame->data[2], _blank_v, pDstFrame->linesize[2] * _teacher_height / 2);
fillDestFrame(pDstFrame, _teacherFrame, (_nOutputWidth - _teacher_height) / 2, 0, 0, (_teacher_width - _teacher_height) / 2, _teacher_height, _teacher_height);
}
}
else if (_teacherFrame->width == _teacher_height && _teacherFrame->height == _teacher_height) {
memset(pDstFrame->data[0], _blank_y, _nOutputWidth * _teacher_height);
memset(pDstFrame->data[1], _blank_u, _nOutputWidth * _teacher_height / 4);
memset(pDstFrame->data[2], _blank_v, _nOutputWidth * _teacher_height / 4);
memset(pDstFrame->data[0], _blank_y, pDstFrame->linesize[0] * _teacher_height);
memset(pDstFrame->data[1], _blank_u, pDstFrame->linesize[1] * _teacher_height / 2);
memset(pDstFrame->data[2], _blank_v, pDstFrame->linesize[2] * _teacher_height / 2);
fillDestFrame(pDstFrame, _teacherFrame, (_nOutputWidth - _teacher_height) / 2, 0);
}
else {
//printf("\nresolution: %dx%d unexpected!", _teacherFrame->width, _teacherFrame->height);
memset(pDstFrame->data[0], _blank_y, _nOutputWidth * _teacher_height);
memset(pDstFrame->data[1], _blank_u, _nOutputWidth * _teacher_height / 4);
memset(pDstFrame->data[2], _blank_v, _nOutputWidth * _teacher_height / 4);
memset(pDstFrame->data[0], _blank_y, pDstFrame->linesize[0] * _teacher_height);
memset(pDstFrame->data[1], _blank_u, pDstFrame->linesize[1] * _teacher_height / 2);
memset(pDstFrame->data[2], _blank_v, pDstFrame->linesize[2] * _teacher_height / 2);
fillDestFrame(pDstFrame, _teacherFrame, 0, 0);
}
... ... @@ -663,31 +718,31 @@ int CAVTranscoder::open_output_file(const char *filename)
if (_studentFrame->width == _student_width) {
if (_studentFrame->pkt_dts != 90){
if (_student_width < _nOutputWidth) {
memset(pDstFrame->data[0] + _teacher_height * pDstFrame->linesize[0], _blank_y, _nOutputWidth * _student_height);
memset(pDstFrame->data[1] + _teacher_height / 2 * pDstFrame->linesize[1], _blank_u, _nOutputWidth * _student_height / 4);
memset(pDstFrame->data[2] + _teacher_height / 2 * pDstFrame->linesize[2], _blank_v, _nOutputWidth * _student_height / 4);
memset(pDstFrame->data[0] + _teacher_height * pDstFrame->linesize[0], _blank_y, pDstFrame->linesize[0] * _student_height);
memset(pDstFrame->data[1] + _teacher_height / 2 * pDstFrame->linesize[1], _blank_u, pDstFrame->linesize[1] * _student_height / 2);
memset(pDstFrame->data[2] + _teacher_height / 2 * pDstFrame->linesize[2], _blank_v, pDstFrame->linesize[2] * _student_height / 2);
}
fillDestFrame(pDstFrame, _studentFrame, 0, _teacher_height);
}
else {
memset(pDstFrame->data[0] + _teacher_height * pDstFrame->linesize[0], _blank_y, _nOutputWidth * _student_height);
memset(pDstFrame->data[1] + _teacher_height / 2 * pDstFrame->linesize[1], _blank_u, _nOutputWidth * _student_height / 4);
memset(pDstFrame->data[2] + _teacher_height / 2 * pDstFrame->linesize[2], _blank_v, _nOutputWidth * _student_height / 4);
memset(pDstFrame->data[0] + _teacher_height * pDstFrame->linesize[0], _blank_y, pDstFrame->linesize[0] * _student_height);
memset(pDstFrame->data[1] + _teacher_height / 2 * pDstFrame->linesize[1], _blank_u, pDstFrame->linesize[1] * _student_height / 2);
memset(pDstFrame->data[2] + _teacher_height / 2 * pDstFrame->linesize[2], _blank_v, pDstFrame->linesize[2] * _student_height / 2);
fillDestFrame(pDstFrame, _studentFrame, (_nOutputWidth - _student_height) / 2, _teacher_height, (_student_width - _student_height) / 2, 0, _student_height, _student_height);
}
}
else if (_studentFrame->pkt_dts == 90){
if (_student_width < _nOutputWidth) {
memset(pDstFrame->data[0] + _teacher_height * pDstFrame->linesize[0], _blank_y, _nOutputWidth * _student_height);
memset(pDstFrame->data[1] + _teacher_height / 2 * pDstFrame->linesize[1], _blank_u, _nOutputWidth * _student_height / 4);
memset(pDstFrame->data[2] + _teacher_height / 2 * pDstFrame->linesize[2], _blank_v, _nOutputWidth * _student_height / 4);
memset(pDstFrame->data[0] + _teacher_height * pDstFrame->linesize[0], _blank_y, pDstFrame->linesize[0] * _student_height);
memset(pDstFrame->data[1] + _teacher_height / 2 * pDstFrame->linesize[1], _blank_u, pDstFrame->linesize[1] * _student_height / 2);
memset(pDstFrame->data[2] + _teacher_height / 2 * pDstFrame->linesize[2], _blank_v, pDstFrame->linesize[2] * _student_height / 2);
}
fillDestFrame(pDstFrame, _studentFrame, 0, _teacher_height);
}
else {
memset(pDstFrame->data[0] + _teacher_height * pDstFrame->linesize[0], _blank_y, _nOutputWidth * _student_height);
memset(pDstFrame->data[1] + _teacher_height / 2 * pDstFrame->linesize[1], _blank_u, _nOutputWidth * _student_height / 4);
memset(pDstFrame->data[2] + _teacher_height / 2 * pDstFrame->linesize[2], _blank_v, _nOutputWidth * _student_height / 4);
memset(pDstFrame->data[0] + _teacher_height * pDstFrame->linesize[0], _blank_y, pDstFrame->linesize[0] * _student_height);
memset(pDstFrame->data[1] + _teacher_height / 2 * pDstFrame->linesize[1], _blank_u, pDstFrame->linesize[1] * _student_height / 2);
memset(pDstFrame->data[2] + _teacher_height / 2 * pDstFrame->linesize[2], _blank_v, pDstFrame->linesize[2] * _student_height / 2);
fillDestFrame(pDstFrame, _studentFrame, (_nOutputWidth - _student_height) / 2, _teacher_height, 0, (_student_width - _student_height) / 2, _student_height, _student_height);
}
}
... ... @@ -714,9 +769,9 @@ int CAVTranscoder::open_output_file(const char *filename)
}
else {
//printf("\nresolution: %dx%d unexpected!", _studentFrame->width, _studentFrame->height);
memset(pDstFrame->data[0], _blank_y, _nOutputWidth * _student_height);
memset(pDstFrame->data[1], _blank_u, _nOutputWidth * _student_height / 4);
memset(pDstFrame->data[2], _blank_v, _nOutputWidth * _student_height / 4);
memset(pDstFrame->data[0], _blank_y, pDstFrame->linesize[0] * _teacher_height);
memset(pDstFrame->data[1], _blank_u, pDstFrame->linesize[1] * _teacher_height / 2);
memset(pDstFrame->data[2], _blank_v, pDstFrame->linesize[2] * _teacher_height / 2);
fillDestFrame(pDstFrame, _studentFrame, 0, 0);
}
}
... ...
... ... @@ -5,7 +5,7 @@
class CAVTranscoder
{
public:
CAVTranscoder(bool bOne2One, int width_teacher, int height_teacher, int student_width,int student_height);
CAVTranscoder(bool bOne2One, int width_teacher, int height_teacher, int student_width,int student_height, bool has_teacher, int max_audio);
virtual ~CAVTranscoder();
int add(media_info & info);
... ... @@ -46,6 +46,8 @@ private:
int _max_audio;
int _scaled_width;
int _scaled_height;
int _pip_width;
int _pip_height;
int _teacher_width;
int _teacher_height;
int _student_width;
... ...
... ... @@ -42,5 +42,11 @@ V2.0.1
V2.0.2
1.修改学生视频为320x240,老师的视频为240x180时,老师背景有花屏
2.修改老师和学生视频都为240x180视频时,视频宽度仍为240, 且有花屏
2.修改老师和学生视频都为240x180视频时,视频宽度仍为240(由于之前假定只有320x240的视频尺寸), 且有花屏
3.只有一路视频时,默认合成为上下布局
V2.0.3
1.没有老师,但是有两个学生时,默认使用一对多布局
2.一对一时,老师和学生的视频尺寸不同时,合成的视频高度取老师视频高度加上学生视频高度(之前版本假定老师和学生视频大小一致,使用的是最大高度的二倍)
3.一对多时,支持学生的视频尺寸不一致的情况(之前版本假定只有一种视频尺寸,其它尺寸视为异常)
4.一对多时,最多只在老师视频下部排4个学生,多于4个学生的情况,扩大合成视频的高度,把学生视频排列在老师视频下方,保证老师视频部分最多只有一排学生视频,避免老师视频被过度遮挡
\ No newline at end of file
... ...
... ... @@ -1123,7 +1123,7 @@ int process_av_files(char * record_info, int piptype)
}
}
CAVTranscoder videoTranscoder(one2one, width_teacher, height_teacher,width_student, height_student);
CAVTranscoder videoTranscoder(one2one, width_teacher, height_teacher,width_student, height_student, has_teacher, max_audio);
videoTranscoder.set_max_audio(max_audio);
int64_t cur_time = 0;
... ...