胡斌

support rotate 90 degree,need more test

... ... @@ -24,7 +24,9 @@ _cur_out_v_ts(0),
_cur_out_a_ts(0),
_max_audio(1),
_swsCtx(NULL),
_swsCtxPortrait(NULL),
_scaledFrame(NULL),
_scaledPortraitFrame(NULL),
_last_videos_got(-1),
_teacherFrame(NULL),
_studentFrame(NULL)
... ... @@ -38,17 +40,31 @@ _studentFrame(NULL)
_swsCtx = sws_getContext(SRC_W, SRC_H, AV_PIX_FMT_YUV420P,
SCALED_W, SCALED_H, AV_PIX_FMT_YUV420P, SWS_BILINEAR,
NULL, NULL, NULL);
_swsCtxPortrait = sws_getContext(SRC_H, SRC_W, AV_PIX_FMT_YUV420P,
SCALED_H, SCALED_W, AV_PIX_FMT_YUV420P, SWS_BILINEAR,
NULL, NULL, NULL);
_scaledFrame = av_frame_alloc();
_scaledFrame->format = AV_PIX_FMT_YUV420P;
_scaledFrame->width = SCALED_W;
_scaledFrame->height = SCALED_H;
_scaledFrame->pts = 0;
_scaledPortraitFrame = av_frame_alloc();
_scaledPortraitFrame->format = AV_PIX_FMT_YUV420P;
_scaledPortraitFrame->width = SCALED_H;
_scaledPortraitFrame->height = SCALED_W;
_scaledPortraitFrame->pts = 0;
int ret = av_frame_get_buffer(_scaledFrame, 32);
if (ret != 0)
{
printf("Error alloc frame buffer for scaling video frame");
}
ret = av_frame_get_buffer(_scaledPortraitFrame, 32);
if (ret != 0)
{
printf("Error alloc frame buffer for scaling portrait video frame");
}
}
RGB2YUV(blank_r, blank_g, blank_b, &_blank_y, &_blank_u, &_blank_v);
}
... ... @@ -102,7 +118,6 @@ int64_t CAVTranscoder::transcode()
mix_and_output_vframe(decoders_got_frame);
_cur_v_time += VFRAME_DURATION_MS;
//sws_scale(img_convert_ctx, (const uint8_t* const*)pFrame->data, pFrame->linesize, 0, pCodecCtx->height, pFrameYUV->data, pFrameYUV->linesize);
while (_cur_a_time < _cur_v_time)
{
... ... @@ -132,17 +147,25 @@ bool CAVTranscoder::all_processed()
int CAVTranscoder::close()
{
flush_encoder(0);
flush_encoder(1);
av_write_trailer(_ofmt_ctx);
if (_swsCtx) {
sws_freeContext(_swsCtx);
_swsCtx = NULL;
}
if (_swsCtxPortrait){
sws_freeContext(_swsCtxPortrait);
_swsCtxPortrait = NULL;
}
if (_scaledFrame) {
av_frame_unref(_scaledFrame);
av_frame_free(&_scaledFrame);
}
flush_encoder(0);
flush_encoder(1);
av_write_trailer(_ofmt_ctx);
if (_scaledPortraitFrame) {
av_frame_free(&_scaledPortraitFrame);
}
#if USE_H264BSF
av_bitstream_filter_close(h264bsfc);
... ... @@ -337,10 +360,14 @@ int CAVTranscoder::open_output_file(const char *filename)
}
AVFrame *pDstFrame = av_frame_alloc();
int nDstSize = avpicture_get_size(AV_PIX_FMT_YUV420P, _nOutputWidth, _nOutputHeight);
uint8_t *dstbuf = new uint8_t[nDstSize];
avpicture_fill((AVPicture*)pDstFrame, dstbuf, AV_PIX_FMT_YUV420P, _nOutputWidth, _nOutputHeight);
pDstFrame->format = AV_PIX_FMT_YUV420P;
pDstFrame->width = _nOutputWidth;
pDstFrame->height = _nOutputHeight;
int ret = av_frame_get_buffer(pDstFrame, 32);
if (ret < 0) {
printf("\n error av_frame_get_buffer: %d", ret);
return -1;
}
if (idxTeacher != -1) {
//copy teacher frame to dest frame
... ... @@ -371,16 +398,33 @@ int CAVTranscoder::open_output_file(const char *filename)
if (!pFrame) {
continue;
}
int h = sws_scale(_swsCtx, pFrame->data, pFrame->linesize, 0, pFrame->height,
_scaledFrame->data, _scaledFrame->linesize);
if (h <= 0){
printf("scale output 0?");
int h = 0;
if (pFrame->width == SRC_W && pFrame->height == SRC_H) {
h = sws_scale(_swsCtx, pFrame->data, pFrame->linesize, 0, pFrame->height,
_scaledFrame->data, _scaledFrame->linesize);
if (h <= 0){
printf("\nscale output result:%d?,ignored", h);
continue;
}
_scaledFrame->pkt_dts = pFrame->pkt_dts;//pass rotation
fillDestFrame(pDstFrame, _scaledFrame, SRC_W - (imageIdx % 4 + 1) * (SCALED_H + 5) + 4, SRC_H - SCALED_H + 3 - (SCALED_H + 4)*(imageIdx / 4), (SCALED_W - SCALED_H) / 2, 0, SCALED_H - 3, SCALED_H - 3);
}
else if (pFrame->width == SRC_H && pFrame->height == SRC_W) {
h = sws_scale(_swsCtxPortrait, pFrame->data, pFrame->linesize, 0, pFrame->height,
_scaledPortraitFrame->data, _scaledPortraitFrame->linesize);
if (h <= 0){
printf("\nscale output result:%d?,ignored", h);
continue;
}
_scaledPortraitFrame->pkt_dts = pFrame->pkt_dts;//pass rotation
fillDestFrame(pDstFrame, _scaledPortraitFrame, SRC_W - (imageIdx % 4 + 1) * (SCALED_H + 5) + 4, SRC_H - SCALED_H + 3 - (SCALED_H + 4)*(imageIdx / 4), 0, (SCALED_W - SCALED_H) / 2, SCALED_H - 3, SCALED_H - 3);
}
else {
printf("\nthe frame resolution %dx%d is unexpected! ignored!", pFrame->width, pFrame->height);
continue;
}
_scaledFrame->pkt_dts = pFrame->pkt_dts;//pass rotation
//copy each frame to the dest frame
fillDestFrame(pDstFrame, _scaledFrame, SRC_W - (imageIdx % 4 + 1) * (SCALED_H + 5) + 4, SRC_H - SCALED_H + 3 - (SCALED_H + 4)*(imageIdx / 4), (SCALED_W - SCALED_H) / 2, 0, SCALED_H - 3, SCALED_H - 3);
imageIdx++;
}
}
... ... @@ -397,7 +441,6 @@ int CAVTranscoder::open_output_file(const char *filename)
//send to encoder
int got_frame = 0;
encode_write_frame(pDstFrame, 0, &got_frame);
delete dstbuf;
return 0;
}
... ... @@ -407,7 +450,18 @@ int CAVTranscoder::open_output_file(const char *filename)
if (!pSrcFrame){
return 0;
}
if (pSrcFrame->pkt_dts == 180) {
if (pSrcFrame->pkt_dts == 0) {
for (int i = 0; i < pSrcFrame->height; i++) {
memcpy(pDstFrame->data[0] + (y + i)*pDstFrame->linesize[0] + x, pSrcFrame->data[0] + i * pSrcFrame->linesize[0], pSrcFrame->linesize[0] > 0 ? pSrcFrame->linesize[0] : -pSrcFrame->linesize[0]);
}
for (int i = 0; i < pSrcFrame->height / 2; i++){
memcpy(pDstFrame->data[1] + (y / 2 + i)*pDstFrame->linesize[1] + x / 2, pSrcFrame->data[1] + i * pSrcFrame->linesize[1], pSrcFrame->linesize[1] > 0 ? pSrcFrame->linesize[1] : -pSrcFrame->linesize[1]);
memcpy(pDstFrame->data[2] + (y / 2 + i)*pDstFrame->linesize[2] + x / 2, pSrcFrame->data[2] + i * pSrcFrame->linesize[2], pSrcFrame->linesize[2] > 0 ? pSrcFrame->linesize[2] : -pSrcFrame->linesize[2]);
}
}
else if (pSrcFrame->pkt_dts == 180) {
unsigned char * startSrcY = pSrcFrame->data[0] + pSrcFrame->width + (pSrcFrame->height- 1 ) * pSrcFrame->linesize[0];
for (int i = 0; i < pSrcFrame->height; i++) {
unsigned char * psrc = startSrcY - i * pSrcFrame->linesize[0];
... ... @@ -434,22 +488,47 @@ int CAVTranscoder::open_output_file(const char *filename)
}
}
}
else {
else if (pSrcFrame->pkt_dts == 90) {
for (int i = 0; i < pSrcFrame->height; i++) {
memcpy(pDstFrame->data[0] + (y + i)*pDstFrame->linesize[0] + x, pSrcFrame->data[0] + i * pSrcFrame->linesize[0], pSrcFrame->linesize[0] > 0 ? pSrcFrame->linesize[0] : -pSrcFrame->linesize[0]);
unsigned char * psrc = pSrcFrame->data[0] + i * pSrcFrame->linesize[0];
unsigned char * psrc_end = psrc + pSrcFrame->width;
unsigned char * pdst = pDstFrame->data[0] + y * pDstFrame->linesize[0] + pSrcFrame->height -1 - i;
for (; psrc < psrc_end; psrc++ ,pdst += pDstFrame->linesize[0]) {
*pdst = *psrc;
}
}
for (int i = 0; i < pSrcFrame->height / 2; i++){
memcpy(pDstFrame->data[1] + (y / 2 + i)*pDstFrame->linesize[1] + x / 2, pSrcFrame->data[1] + i * pSrcFrame->linesize[1], pSrcFrame->linesize[1] > 0 ? pSrcFrame->linesize[1] : -pSrcFrame->linesize[1]);
memcpy(pDstFrame->data[2] + (y / 2 + i)*pDstFrame->linesize[2] + x / 2, pSrcFrame->data[2] + i * pSrcFrame->linesize[2], pSrcFrame->linesize[2] > 0 ? pSrcFrame->linesize[2] : -pSrcFrame->linesize[2]);
for (int i = 0; i < pSrcFrame->height/2; i++) {
unsigned char * psrc = pSrcFrame->data[1] + i * pSrcFrame->linesize[1];
unsigned char * psrc_end = psrc + pSrcFrame->width/2;
unsigned char * pdst = pDstFrame->data[1] + y /2 * pDstFrame->linesize[1] + pSrcFrame->height/2 -1 - i;
for (; psrc < psrc_end; psrc++, pdst += pDstFrame->linesize[1]) {
*pdst = *psrc;
}
psrc = pSrcFrame->data[2] + i * pSrcFrame->linesize[2];
psrc_end = psrc + pSrcFrame->width / 2;
pdst = pDstFrame->data[2] + y / 2 * pDstFrame->linesize[2] + pSrcFrame->height / 2 - 1 - i;
for (; psrc < psrc_end; psrc++, pdst += pDstFrame->linesize[2]) {
*pdst = *psrc;
}
}
}
}
return 0;
}
int CAVTranscoder::fillDestFrame(AVFrame * pDstFrame, AVFrame * pSrcFrame, int x, int y, int srcx, int srcy, int w, int h)
{
if (pSrcFrame->pkt_dts == 180) {
if (pSrcFrame->pkt_dts == 0) {
for (int i = 0; i < h; i++) {
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], w / 2);
memcpy(pDstFrame->data[2] + (y / 2 + i)*pDstFrame->linesize[2] + x / 2, pSrcFrame->data[2] + (i + srcy / 2) * pSrcFrame->linesize[2], w / 2);
}
}
else if (pSrcFrame->pkt_dts == 180) {
unsigned char * startSrcY = pSrcFrame->data[0] + pSrcFrame->width + (pSrcFrame->height - srcy - 1) * pSrcFrame->linesize[0] - srcx;
for (int i = 0; i < h; i++) {
unsigned char * psrc = startSrcY - i * pSrcFrame->linesize[0];
... ... @@ -476,14 +555,35 @@ int CAVTranscoder::open_output_file(const char *filename)
}
}
}
else {
else if (pSrcFrame->pkt_dts == 90) {
unsigned char * startSrcY = pSrcFrame->data[0] + srcy * pSrcFrame->linesize[0] + srcx;
for (int i = 0; i < h; i++) {
memcpy(pDstFrame->data[0] + (y + i)*pDstFrame->linesize[0] + x, pSrcFrame->data[0] + (i + srcy) * pSrcFrame->linesize[0] + srcx, w);
unsigned char * psrc = startSrcY + i * pSrcFrame->linesize[0];
unsigned char * psrc_end = psrc + w;
unsigned char * pdst = pDstFrame->data[0] + y*pDstFrame->linesize[0] + h -1 - i;
for (; psrc < psrc_end; psrc++, pdst+=pDstFrame->linesize[0]) {
*pdst = *psrc;
}
}
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], w / 2);
memcpy(pDstFrame->data[2] + (y / 2 + i)*pDstFrame->linesize[2] + x / 2, pSrcFrame->data[2] + (i + srcy / 2) * pSrcFrame->linesize[2], w / 2);
unsigned char * startSrcU = pSrcFrame->data[1] + srcy/2 * pSrcFrame->linesize[1] + srcx/2;
for (int i = 0; i < h/2; i++) {
unsigned char * psrc = startSrcU + i* pSrcFrame->linesize[1];
unsigned char * psrc_end = psrc + w/2;
unsigned char * pdst = pDstFrame->data[1] + y/2*pDstFrame->linesize[1] + h/2 -1 - i;
for (; psrc < psrc_end; psrc++, pdst += pDstFrame->linesize[1]) {
*pdst = *psrc;
}
}
unsigned char * startSrcV= pSrcFrame->data[2] + srcy / 2 * pSrcFrame->linesize[2] + srcx / 2;
for (int i = 0; i < h / 2; i++) {
unsigned char * psrc = startSrcV + i* pSrcFrame->linesize[2];
unsigned char * psrc_end = psrc + w / 2;
unsigned char * pdst = pDstFrame->data[2] + y / 2 * pDstFrame->linesize[2] + h / 2 -1 - i;
for (; psrc < psrc_end; psrc++, pdst += pDstFrame->linesize[2]) {
*pdst = *psrc;
}
}
}
return 0;
... ... @@ -493,9 +593,14 @@ int CAVTranscoder::open_output_file(const char *filename)
{
//prepare one2one base frame
AVFrame *pDstFrame = av_frame_alloc();
int nDstSize = avpicture_get_size(AV_PIX_FMT_YUV420P,_nOutputWidth, _nOutputHeight);
uint8_t *dstbuf = new uint8_t[nDstSize];
avpicture_fill((AVPicture*)pDstFrame, dstbuf, AV_PIX_FMT_YUV420P, _nOutputWidth, _nOutputHeight);
pDstFrame->format = AV_PIX_FMT_YUV420P;
pDstFrame->width = _nOutputWidth;
pDstFrame->height = _nOutputHeight;
int ret = av_frame_get_buffer(pDstFrame, 32);
if (ret < 0) {
printf("\n error av_frame_get_buffer: %d", ret);
return -1;
}
for (unsigned int i = 0; i < decoders_got_frame.size(); i++) {
if (decoders_got_frame[i]->_media_role == mr_teacher) {
... ... @@ -525,11 +630,40 @@ int CAVTranscoder::open_output_file(const char *filename)
if (_teacherFrame) {
fillDestFrame(pDstFrame, _teacherFrame, 0, 0);
if (_studentFrame) {
fillDestFrame(pDstFrame, _studentFrame, 0, 240);
if (_studentFrame->width == SRC_W) {
if (_studentFrame->pkt_dts != 90){
fillDestFrame(pDstFrame, _studentFrame, 0, 240);
}
else {
fillDestFrame(pDstFrame, _studentFrame, (SRC_W - SRC_H) / 2, 240, (SRC_W - SRC_H) / 2, 0, SRC_H, SRC_H);
}
}
else if (_studentFrame->pkt_dts != 90){
fillDestFrame(pDstFrame, _studentFrame, 0, 240);
}
else {
memset(pDstFrame->data[0] + 240 * pDstFrame->linesize[0], _blank_y, _nOutputWidth * _nOutputHeight / 2);
memset(pDstFrame->data[1] + 120 * pDstFrame->linesize[1], _blank_u, _nOutputWidth * _nOutputHeight / 8);
memset(pDstFrame->data[2] + 120 * pDstFrame->linesize[2], _blank_v, _nOutputWidth * _nOutputHeight / 8);
fillDestFrame(pDstFrame, _studentFrame, (SRC_W - SRC_H) / 2, 240, 0, (SRC_W - SRC_H) / 2, SRC_H, SRC_H);
}
}
}
else if (_studentFrame) {
fillDestFrame(pDstFrame, _studentFrame, 0, 0);
if (_studentFrame->width == SRC_W) {
if (_studentFrame->pkt_dts != 90){
fillDestFrame(pDstFrame, _studentFrame, 0, 0);
}
else {
fillDestFrame(pDstFrame, _studentFrame, (SRC_W - SRC_H) / 2, 0, (SRC_W - SRC_H) / 2, 0, SRC_W, SRC_H);
}
}
else if (_studentFrame->pkt_dts == 90){
fillDestFrame(pDstFrame, _studentFrame, 0, 0);
}
else {
fillDestFrame(pDstFrame, _studentFrame, (SRC_W - SRC_H) / 2, 0, 0, (SRC_W - SRC_H) / 2, SRC_W, SRC_H);
}
}
if (decoders_got_frame.size() == 2){
... ... @@ -569,7 +703,6 @@ int CAVTranscoder::open_output_file(const char *filename)
//send to encoder
int got_frame = 0;
encode_write_frame(pDstFrame, 0, &got_frame);
delete dstbuf;
return 0;
}
... ...
... ... @@ -42,7 +42,9 @@ private:
void * _a_frame_pool;
int _max_audio;
struct SwsContext * _swsCtx;
struct SwsContext * _swsCtxPortrait;
AVFrame * _scaledFrame;
AVFrame * _scaledPortraitFrame;
int _last_videos_got;
AVFrame * _teacherFrame;
AVFrame * _studentFrame; // for one2one,keep the last frame
... ...
... ... @@ -312,12 +312,9 @@ int CVideoDecoder::filter_encode_write_frame(AVFrame *frame, unsigned int stream
}
filt_frame->pict_type = AV_PICTURE_TYPE_NONE;
if (_rotate == 180) {
filt_frame->pkt_dts = 180;//use this to indicate rotate 180
}
else {
filt_frame->pkt_dts = 0;
}
filt_frame->pkt_dts = _rotate;//pass rotate for mixing
_decoded_frames.push_back(filt_frame);
}
... ...
... ... @@ -1062,7 +1062,7 @@ int process_av_files(char * record_info, int piptype)
encode_loop_count++;
if (encode_loop_count == 1200) {
encode_loop_count = 0;
printf("\n encoded : %d seconds\n", cur_time / 1000);
printf("\n encoded : %d s\n", cur_time / 1000);
}
}
... ... @@ -1071,7 +1071,7 @@ int process_av_files(char * record_info, int piptype)
encode_loop_count++;
if (encode_loop_count == 1200) {
encode_loop_count = 0;
printf("\n encoded : %d seconds\n", cur_time / 1000);
printf("\n encoded : %d s\n", cur_time / 1000);
}
}
... ... @@ -1081,7 +1081,7 @@ int process_av_files(char * record_info, int piptype)
time(&end);
printf("\nfinished,used %"PRIu64" second,encoded %.0lf second, the speed ratio is %.3lfX\n", end - start, (double)cur_time / 1000, cur_time / 1000.0 / (end - start));
printf("\nfinished,used %"PRIu64" s, encoded %.0lf s, the speed ratio is %.3lfX\n", end - start, (double)cur_time / 1000, cur_time / 1000.0 / (end - start));
return 0;
}
... ... @@ -1096,16 +1096,16 @@ int main(int argc, char * argv[])
return -1;
}
get_config_path();
//get_config_path();
load_codec_param();
//load_codec_param();
int piptype = 0;
for (int i = 2; i < argc; i++){
if (!strcmp(argv[i], "-t")){
i++;
if (i > argc) {
printf("error,should be 0,1 or 2 after -t");
printf("error,should be 0, 1 or 2 after -t");
return -2;
}
piptype = atoi(argv[i]);
... ...
... ... @@ -70,12 +70,14 @@
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>ADD_FFMPEG_LIB;WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>..\..\liveAssistant\third-lib\ffmpeg\include</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalLibraryDirectories>..\..\liveAssistant\third-lib\ffmpeg\lib;</AdditionalLibraryDirectories>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
... ...