1.keep still image in one2one mode
2.flip image when retote 180 3.save record info as m_* 4.use stream time base when decode,don't use decode codec time base,because it is varied in some mp4 file
正在显示
4 个修改的文件
包含
111 行增加
和
41 行删除
| @@ -8,8 +8,8 @@ extern "C" { | @@ -8,8 +8,8 @@ extern "C" { | ||
| 8 | #pragma comment(lib,"swscale.lib") | 8 | #pragma comment(lib,"swscale.lib") |
| 9 | #endif | 9 | #endif |
| 10 | 10 | ||
| 11 | -#define SCALED_W 80 | ||
| 12 | -#define SCALED_H 60 | 11 | +#define SCALED_W 100 |
| 12 | +#define SCALED_H 75 | ||
| 13 | #define SRC_W 320 | 13 | #define SRC_W 320 |
| 14 | #define SRC_H 240 | 14 | #define SRC_H 240 |
| 15 | uint8_t blank_r = 0x16; | 15 | uint8_t blank_r = 0x16; |
| @@ -25,7 +25,9 @@ _cur_out_a_ts(0), | @@ -25,7 +25,9 @@ _cur_out_a_ts(0), | ||
| 25 | _max_audio(1), | 25 | _max_audio(1), |
| 26 | _swsCtx(NULL), | 26 | _swsCtx(NULL), |
| 27 | _scaledFrame(NULL), | 27 | _scaledFrame(NULL), |
| 28 | -_last_videos_got(-1) | 28 | +_last_videos_got(-1), |
| 29 | +_teacherFrame(NULL), | ||
| 30 | +_studentFrame(NULL) | ||
| 29 | { | 31 | { |
| 30 | _one2one = bOne2One; | 32 | _one2one = bOne2One; |
| 31 | if (_one2one) { | 33 | if (_one2one) { |
| @@ -54,6 +56,8 @@ _last_videos_got(-1) | @@ -54,6 +56,8 @@ _last_videos_got(-1) | ||
| 54 | 56 | ||
| 55 | CAVTranscoder::~CAVTranscoder() | 57 | CAVTranscoder::~CAVTranscoder() |
| 56 | { | 58 | { |
| 59 | + av_frame_free(&_teacherFrame); | ||
| 60 | + av_frame_free(&_studentFrame); | ||
| 57 | } | 61 | } |
| 58 | 62 | ||
| 59 | int CAVTranscoder::add(media_info & info) | 63 | int CAVTranscoder::add(media_info & info) |
| @@ -369,7 +373,7 @@ int CAVTranscoder::open_output_file(const char *filename) | @@ -369,7 +373,7 @@ int CAVTranscoder::open_output_file(const char *filename) | ||
| 369 | } | 373 | } |
| 370 | 374 | ||
| 371 | //copy each frame to the dest frame | 375 | //copy each frame to the dest frame |
| 372 | - fillDestFrame(pDstFrame, _scaledFrame, SRC_W - SCALED_H - 10 - (imageIdx % 4) * (SCALED_H + 10), SRC_H - SCALED_H - (SCALED_H + 8)*(imageIdx / 4), (SCALED_W - SCALED_H) / 2, 0, SCALED_H, SCALED_H); | 376 | + fillDestFrame(pDstFrame, _scaledFrame, SRC_W - 3 - (imageIdx % 4) * (SCALED_H + 5), SRC_H - SCALED_H - (SCALED_H + 2)*(imageIdx / 4), (SCALED_W - SCALED_H) / 2, 0, SCALED_H-1, SCALED_H-1); |
| 373 | imageIdx++; | 377 | imageIdx++; |
| 374 | } | 378 | } |
| 375 | } | 379 | } |
| @@ -396,14 +400,45 @@ int CAVTranscoder::open_output_file(const char *filename) | @@ -396,14 +400,45 @@ int CAVTranscoder::open_output_file(const char *filename) | ||
| 396 | if (!pSrcFrame){ | 400 | if (!pSrcFrame){ |
| 397 | return 0; | 401 | return 0; |
| 398 | } | 402 | } |
| 399 | - | ||
| 400 | - for (int i = 0; i < pSrcFrame->height; i++) { | ||
| 401 | - 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]); | 403 | + if (pSrcFrame->pkt_dts == 180) { |
| 404 | + unsigned char * startSrcY = pSrcFrame->data[0] + (pSrcFrame->height) * pSrcFrame->linesize[0] - 1; | ||
| 405 | + for (int i = 0; i < pSrcFrame->height; i++) { | ||
| 406 | + //memcpy(pDstFrame->data[0] + (y + i)*pDstFrame->linesize[0] + x, startSrcY - i * pSrcFrame->linesize[0], pSrcFrame->linesize[0]); | ||
| 407 | + unsigned char * psrc = startSrcY - i * pSrcFrame->linesize[0]; | ||
| 408 | + unsigned char * pdst = pDstFrame->data[0] + (y + i)*pDstFrame->linesize[0] + x; | ||
| 409 | + unsigned char * pdst_end = pdst + pSrcFrame->linesize[0]; | ||
| 410 | + for (; pdst < pdst_end; psrc--, pdst++) { | ||
| 411 | + *pdst = *psrc; | ||
| 412 | + } | ||
| 413 | + } | ||
| 414 | + unsigned char * startSrcU = pSrcFrame->data[1] + (pSrcFrame->height/2 ) * pSrcFrame->linesize[1] -1; | ||
| 415 | + unsigned char * startSrcV = pSrcFrame->data[2] + (pSrcFrame->height/2) * pSrcFrame->linesize[2] -1; | ||
| 416 | + for (int i = 0; i < pSrcFrame->height / 2; i++){ | ||
| 417 | + //memcpy(pDstFrame->data[1] + (y / 2 + i)*pDstFrame->linesize[1] + x / 2, startSrcU - i * pSrcFrame->linesize[1], pSrcFrame->linesize[1]); | ||
| 418 | + //memcpy(pDstFrame->data[2] + (y / 2 + i)*pDstFrame->linesize[2] + x / 2, startSrcV - i * pSrcFrame->linesize[2], pSrcFrame->linesize[2]); | ||
| 419 | + unsigned char * psrc = startSrcU - i * pSrcFrame->linesize[1]; | ||
| 420 | + unsigned char * pdst = pDstFrame->data[1] + (y/2 + i)*pDstFrame->linesize[1] + x/2; | ||
| 421 | + unsigned char * pdst_end = pdst + pSrcFrame->linesize[1]; | ||
| 422 | + for (; pdst < pdst_end; psrc--, pdst++) { | ||
| 423 | + *pdst = *psrc; | ||
| 424 | + } | ||
| 425 | + psrc = startSrcV - i * pSrcFrame->linesize[2]; | ||
| 426 | + pdst = pDstFrame->data[2] + (y / 2 + i)*pDstFrame->linesize[2] + x / 2; | ||
| 427 | + pdst_end = pdst + pSrcFrame->linesize[2]; | ||
| 428 | + for (; pdst < pdst_end; psrc--, pdst++) { | ||
| 429 | + *pdst = *psrc; | ||
| 430 | + } | ||
| 431 | + } | ||
| 402 | } | 432 | } |
| 433 | + else { | ||
| 434 | + for (int i = 0; i < pSrcFrame->height; i++) { | ||
| 435 | + 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]); | ||
| 436 | + } | ||
| 403 | 437 | ||
| 404 | - for (int i = 0; i < pSrcFrame->height / 2; i++){ | ||
| 405 | - 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]); | ||
| 406 | - 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]); | 438 | + for (int i = 0; i < pSrcFrame->height / 2; i++){ |
| 439 | + 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]); | ||
| 440 | + 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]); | ||
| 441 | + } | ||
| 407 | } | 442 | } |
| 408 | return 0; | 443 | return 0; |
| 409 | } | 444 | } |
| @@ -429,18 +464,46 @@ int CAVTranscoder::open_output_file(const char *filename) | @@ -429,18 +464,46 @@ int CAVTranscoder::open_output_file(const char *filename) | ||
| 429 | uint8_t *dstbuf = new uint8_t[nDstSize]; | 464 | uint8_t *dstbuf = new uint8_t[nDstSize]; |
| 430 | avpicture_fill((AVPicture*)pDstFrame, dstbuf, AV_PIX_FMT_YUV420P, _nOutputWidth, _nOutputHeight); | 465 | avpicture_fill((AVPicture*)pDstFrame, dstbuf, AV_PIX_FMT_YUV420P, _nOutputWidth, _nOutputHeight); |
| 431 | 466 | ||
| 432 | - memset(pDstFrame->data[0], _blank_y, _nOutputWidth * _nOutputHeight); | ||
| 433 | - memset(pDstFrame->data[1], _blank_u, _nOutputWidth *_nOutputHeight / 4); | ||
| 434 | - memset(pDstFrame->data[2], _blank_v, _nOutputWidth * _nOutputHeight / 4); | 467 | + for (unsigned int i = 0; i < decoders_got_frame.size(); i++) { |
| 468 | + if (decoders_got_frame[i]->_media_role == mr_teacher) { | ||
| 469 | + AVFrame * pFrame = decoders_got_frame[i]->_cur_v_frame; | ||
| 470 | + if (pFrame) { | ||
| 471 | + av_frame_free(&_teacherFrame); | ||
| 472 | + _teacherFrame = pFrame; | ||
| 473 | + decoders_got_frame[i]->_cur_v_frame = NULL; | ||
| 474 | + } | ||
| 475 | + } | ||
| 476 | + else { | ||
| 477 | + AVFrame * pFrame = decoders_got_frame[i]->_cur_v_frame; | ||
| 478 | + if (pFrame) { | ||
| 479 | + av_frame_free(&_studentFrame); | ||
| 480 | + _studentFrame = pFrame; | ||
| 481 | + decoders_got_frame[i]->_cur_v_frame = NULL; | ||
| 482 | + } | ||
| 483 | + } | ||
| 484 | + } | ||
| 485 | + | ||
| 486 | + if (!_teacherFrame && !_studentFrame) { | ||
| 487 | + memset(pDstFrame->data[0], _blank_y, _nOutputWidth * _nOutputHeight); | ||
| 488 | + memset(pDstFrame->data[1], _blank_u, _nOutputWidth * _nOutputHeight / 4); | ||
| 489 | + memset(pDstFrame->data[2], _blank_v, _nOutputWidth * _nOutputHeight / 4); | ||
| 490 | + } | ||
| 491 | + | ||
| 492 | + if (_teacherFrame) { | ||
| 493 | + fillDestFrame(pDstFrame, _teacherFrame, 0, 0); | ||
| 494 | + if (_studentFrame) { | ||
| 495 | + fillDestFrame(pDstFrame, _studentFrame, 0, 240); | ||
| 496 | + } | ||
| 497 | + } | ||
| 498 | + else if (_studentFrame) { | ||
| 499 | + fillDestFrame(pDstFrame, _studentFrame, 0, 0); | ||
| 500 | + } | ||
| 435 | 501 | ||
| 436 | if (decoders_got_frame.size() == 2){ | 502 | if (decoders_got_frame.size() == 2){ |
| 437 | if (_last_videos_got != 2) { | 503 | if (_last_videos_got != 2) { |
| 438 | _last_videos_got = 2; | 504 | _last_videos_got = 2; |
| 439 | printf("\n--get 2 video:%"PRIu64", %s, %s\n", _cur_out_v_ts, decoders_got_frame[0]->get_cur_vfile().c_str(), decoders_got_frame[1]->get_cur_vfile().c_str()); | 505 | printf("\n--get 2 video:%"PRIu64", %s, %s\n", _cur_out_v_ts, decoders_got_frame[0]->get_cur_vfile().c_str(), decoders_got_frame[1]->get_cur_vfile().c_str()); |
| 440 | } | 506 | } |
| 441 | - fillDestFrame(pDstFrame, decoders_got_frame[0]->_cur_v_frame, 0, decoders_got_frame[0]->_media_role == mr_teacher ? 0 : 240); | ||
| 442 | - | ||
| 443 | - fillDestFrame(pDstFrame, decoders_got_frame[1]->_cur_v_frame, 0, decoders_got_frame[1]->_media_role == mr_teacher ? 0 : 240); | ||
| 444 | } | 507 | } |
| 445 | else if (decoders_got_frame.size() == 1) | 508 | else if (decoders_got_frame.size() == 1) |
| 446 | { | 509 | { |
| @@ -448,15 +511,12 @@ int CAVTranscoder::open_output_file(const char *filename) | @@ -448,15 +511,12 @@ int CAVTranscoder::open_output_file(const char *filename) | ||
| 448 | _last_videos_got = 1; | 511 | _last_videos_got = 1; |
| 449 | printf("\n--get 1 video:%"PRIu64", %s\n", _cur_out_v_ts, decoders_got_frame[0]->get_cur_vfile().c_str()); | 512 | printf("\n--get 1 video:%"PRIu64", %s\n", _cur_out_v_ts, decoders_got_frame[0]->get_cur_vfile().c_str()); |
| 450 | } | 513 | } |
| 451 | - fillDestFrame(pDstFrame, decoders_got_frame[0]->_cur_v_frame, 0, 0); | ||
| 452 | - //todo: fill the bottom half image with pure color | ||
| 453 | } | 514 | } |
| 454 | else { | 515 | else { |
| 455 | if (_last_videos_got != 0) { | 516 | if (_last_videos_got != 0) { |
| 456 | _last_videos_got = 0; | 517 | _last_videos_got = 0; |
| 457 | printf("\n--get 0 video:%"PRIu64"\n", _cur_out_v_ts); | 518 | printf("\n--get 0 video:%"PRIu64"\n", _cur_out_v_ts); |
| 458 | } | 519 | } |
| 459 | - //fill with last image? | ||
| 460 | } | 520 | } |
| 461 | #if 0 | 521 | #if 0 |
| 462 | if (_cur_out_v_ts > (26 * 60 + 57) *(1000 /50)) { | 522 | if (_cur_out_v_ts > (26 * 60 + 57) *(1000 /50)) { |
| @@ -44,6 +44,8 @@ private: | @@ -44,6 +44,8 @@ private: | ||
| 44 | struct SwsContext * _swsCtx; | 44 | struct SwsContext * _swsCtx; |
| 45 | AVFrame * _scaledFrame; | 45 | AVFrame * _scaledFrame; |
| 46 | int _last_videos_got; | 46 | int _last_videos_got; |
| 47 | + AVFrame * _teacherFrame; | ||
| 48 | + AVFrame * _studentFrame; // for one2one,keep the last frame | ||
| 47 | 49 | ||
| 48 | uint8_t _blank_y, _blank_u, _blank_v; | 50 | uint8_t _blank_y, _blank_u, _blank_v; |
| 49 | public: | 51 | public: |
| @@ -267,6 +267,7 @@ int CVideoDecoder::open_input_file(const char *filename) | @@ -267,6 +267,7 @@ int CVideoDecoder::open_input_file(const char *filename) | ||
| 267 | av_log(NULL, AV_LOG_ERROR, "Failed to open decoder for stream #%u\n", i); | 267 | av_log(NULL, AV_LOG_ERROR, "Failed to open decoder for stream #%u\n", i); |
| 268 | return ret; | 268 | return ret; |
| 269 | } | 269 | } |
| 270 | + codec_ctx->time_base = stream->time_base; | ||
| 270 | } | 271 | } |
| 271 | } | 272 | } |
| 272 | 273 | ||
| @@ -312,12 +313,10 @@ int CVideoDecoder::filter_encode_write_frame(AVFrame *frame, unsigned int stream | @@ -312,12 +313,10 @@ int CVideoDecoder::filter_encode_write_frame(AVFrame *frame, unsigned int stream | ||
| 312 | 313 | ||
| 313 | filt_frame->pict_type = AV_PICTURE_TYPE_NONE; | 314 | filt_frame->pict_type = AV_PICTURE_TYPE_NONE; |
| 314 | if (_rotate == 180) { | 315 | if (_rotate == 180) { |
| 315 | - filt_frame->data[0] += filt_frame->linesize[0] * (filt_frame->height - 1); | ||
| 316 | - filt_frame->linesize[0] = -filt_frame->linesize[0]; | ||
| 317 | - filt_frame->data[1] += filt_frame->linesize[1] * (filt_frame->height / 2 - 1); | ||
| 318 | - filt_frame->linesize[1] = -filt_frame->linesize[1]; | ||
| 319 | - filt_frame->data[2] += filt_frame->linesize[2] * (filt_frame->height / 2 - 1); | ||
| 320 | - filt_frame->linesize[2] = -filt_frame->linesize[2]; | 316 | + filt_frame->pkt_dts = 180;//use this to indicate rotate 180 |
| 317 | + } | ||
| 318 | + else { | ||
| 319 | + filt_frame->pkt_dts = 0; | ||
| 321 | } | 320 | } |
| 322 | _decoded_frames.push_back(filt_frame); | 321 | _decoded_frames.push_back(filt_frame); |
| 323 | } | 322 | } |
| @@ -372,9 +371,9 @@ int CVideoDecoder::get_one_frame(AVFrame ** pFrame, int64_t & ts) | @@ -372,9 +371,9 @@ int CVideoDecoder::get_one_frame(AVFrame ** pFrame, int64_t & ts) | ||
| 372 | break; | 371 | break; |
| 373 | } | 372 | } |
| 374 | 373 | ||
| 375 | - av_packet_rescale_ts(&packet, | 374 | + /* av_packet_rescale_ts(&packet, |
| 376 | ifmt_ctx->streams[stream_index]->time_base, | 375 | ifmt_ctx->streams[stream_index]->time_base, |
| 377 | - ifmt_ctx->streams[stream_index]->codec->time_base); | 376 | + ifmt_ctx->streams[stream_index]->codec->time_base);*/ |
| 378 | dec_func = (type == AVMEDIA_TYPE_VIDEO) ? avcodec_decode_video2 : | 377 | dec_func = (type == AVMEDIA_TYPE_VIDEO) ? avcodec_decode_video2 : |
| 379 | avcodec_decode_audio4; | 378 | avcodec_decode_audio4; |
| 380 | ret = dec_func(ifmt_ctx->streams[stream_index]->codec, frame, | 379 | ret = dec_func(ifmt_ctx->streams[stream_index]->codec, frame, |
| @@ -652,20 +652,22 @@ void add_media_infos() | @@ -652,20 +652,22 @@ void add_media_infos() | ||
| 652 | printf("\n-------------------------\n"); | 652 | printf("\n-------------------------\n"); |
| 653 | 653 | ||
| 654 | it = audio_type_files.begin(); | 654 | it = audio_type_files.begin(); |
| 655 | - media_info last = *it; | ||
| 656 | - | ||
| 657 | - for (it++; it != audio_type_files.end(); it++) { | ||
| 658 | - if (it->t_type == tt_end) { | ||
| 659 | - if (last.t_type == tt_start) { | ||
| 660 | - float mid = (it->type_time + last.type_time) / 2; | ||
| 661 | - int files_with_mid = count_audio_files(mid); | ||
| 662 | - if (files_with_mid > max_audio) { | ||
| 663 | - max_audio = files_with_mid; | 655 | + if (it != audio_type_files.end()) { |
| 656 | + media_info last = *it; | ||
| 657 | + | ||
| 658 | + for (it++; it != audio_type_files.end(); it++) { | ||
| 659 | + if (it->t_type == tt_end) { | ||
| 660 | + if (last.t_type == tt_start) { | ||
| 661 | + float mid = (it->type_time + last.type_time) / 2; | ||
| 662 | + int files_with_mid = count_audio_files(mid); | ||
| 663 | + if (files_with_mid > max_audio) { | ||
| 664 | + max_audio = files_with_mid; | ||
| 665 | + } | ||
| 664 | } | 666 | } |
| 665 | } | 667 | } |
| 666 | - } | ||
| 667 | - else { | ||
| 668 | - last = *it; | 668 | + else { |
| 669 | + last = *it; | ||
| 670 | + } | ||
| 669 | } | 671 | } |
| 670 | } | 672 | } |
| 671 | } | 673 | } |
| @@ -890,23 +892,30 @@ void load_codec_param() | @@ -890,23 +892,30 @@ void load_codec_param() | ||
| 890 | 892 | ||
| 891 | void get_outinfo_file_name(char * input) | 893 | void get_outinfo_file_name(char * input) |
| 892 | { | 894 | { |
| 895 | +#if 0 | ||
| 893 | strcpy(out_info_file, input); | 896 | strcpy(out_info_file, input); |
| 894 | char * p = strstr(out_info_file, "."); | 897 | char * p = strstr(out_info_file, "."); |
| 895 | if (p) { | 898 | if (p) { |
| 896 | *p = 0; | 899 | *p = 0; |
| 897 | } | 900 | } |
| 898 | strcat(out_info_file, "_out.txt"); | 901 | strcat(out_info_file, "_out.txt"); |
| 902 | +#else | ||
| 903 | + strcpy(out_info_file, "m_"); | ||
| 904 | + strcat(out_info_file, input); | ||
| 905 | +#endif | ||
| 899 | } | 906 | } |
| 900 | 907 | ||
| 901 | string get_outmedia_file_name(const char * input) | 908 | string get_outmedia_file_name(const char * input) |
| 902 | { | 909 | { |
| 903 | char out_media_file[1024]; | 910 | char out_media_file[1024]; |
| 904 | - strcpy(out_media_file, input); | 911 | + strcpy(out_media_file, "m_"); |
| 912 | + | ||
| 913 | + strcat(out_media_file, input); | ||
| 905 | char * p = strstr(out_media_file, "."); | 914 | char * p = strstr(out_media_file, "."); |
| 906 | if (p) { | 915 | if (p) { |
| 907 | *p = 0; | 916 | *p = 0; |
| 908 | } | 917 | } |
| 909 | - strcat(out_media_file, "_out.mp4"); | 918 | + strcat(out_media_file, ".mp4"); |
| 910 | return out_media_file; | 919 | return out_media_file; |
| 911 | } | 920 | } |
| 912 | 921 |
-
请 注册 或 登录 后发表评论