Ticket #2581: 2581_aspectRatio-trunk.patch
File 2581_aspectRatio-trunk.patch, 17.4 KB (added by , 11 years ago) |
---|
-
libs/libmythtv/recordingprofile.cpp
571 571 }; 572 572 }; 573 573 574 class MPEG4AspectRatio: public ComboBoxSetting, public CodecParamStorage { 575 public: 576 MPEG4AspectRatio(const RecordingProfile& parent): 577 ComboBoxSetting(this), 578 CodecParamStorage(this, parent, "mpeg4aspectratio") { 579 setLabel(QObject::tr("Aspect Ratio")); 580 addSelection(QObject::tr("Original", "Original")); 581 addSelection(QObject::tr("Crop to 4:3", "4:3")); 582 addSelection(QObject::tr("Crop to 16:9", "16:9")); 583 setValue("Original"); 584 setHelpText(QObject::tr("Crop transcoded files to the indicated " 585 "aspect ratio")); 586 }; 587 }; 588 589 class MPEG4DeInterlace: public ComboBoxSetting, public CodecParamStorage { 590 public: 591 MPEG4DeInterlace(const RecordingProfile& parent): 592 ComboBoxSetting(this), 593 CodecParamStorage(this, parent, "mpeg4deinterlace") { 594 setLabel(QObject::tr("DeInterlace")); 595 addSelection(QObject::tr("No", "0")); 596 addSelection(QObject::tr("Yes", "1")); 597 setValue("0"); 598 setHelpText(QObject::tr("DeInterlace video when resizing")); 599 }; 600 }; 601 574 602 class MPEG4QualDiff : public SliderSetting, public CodecParamStorage 575 603 { 576 604 public: … … 822 850 823 851 params = new VerticalConfigurationGroup(false); 824 852 params->setLabel(QObject::tr("MPEG-4 Parameters")); 825 params->addChild(new MPEG4bitrate(parent)); 826 params->addChild(new MPEG4MaxQuality(parent)); 827 params->addChild(new MPEG4MinQuality(parent)); 853 854 HorizontalConfigurationGroup *hbr; 855 hbr = new HorizontalConfigurationGroup(false, false); 856 hbr->addChild(new MPEG4bitrate(parent)); 857 hbr->addChild(new ScaleBitrate(parent)); 858 params->addChild(hbr); 859 860 HorizontalConfigurationGroup *hmmq; 861 hmmq = new HorizontalConfigurationGroup(false, false); 862 hmmq->addChild(new MPEG4MaxQuality(parent)); 863 hmmq->addChild(new MPEG4MinQuality(parent)); 864 params->addChild(hmmq); 865 828 866 params->addChild(new MPEG4QualDiff(parent)); 829 params->addChild(new ScaleBitrate(parent));830 867 868 HorizontalConfigurationGroup *hasp; 869 hasp = new HorizontalConfigurationGroup(false, false); 870 hasp->addChild(new MPEG4AspectRatio(parent)); 871 hasp->addChild(new MPEG4DeInterlace(parent)); 872 params->addChild(hasp); 873 831 874 HorizontalConfigurationGroup *hq; 832 875 hq = new HorizontalConfigurationGroup(false, false); 833 876 hq->addChild(new MPEG4OptionVHQ(parent)); -
programs/mythtranscode/transcode.cpp
32 32 #include "mythdbcon.h" 33 33 34 34 35 extern "C" {36 #include "libavcodec/avcodec.h"37 #include "libswscale/swscale.h"38 }39 40 35 #define LOC QString("Transcode: ") 41 36 #define LOC_ERR QString("Transcode, Error: ") 42 37 … … 248 243 fifow(NULL), 249 244 kfa_table(NULL), 250 245 showprogress(false), 251 recorderOptions("") 246 recorderOptions(""), 247 m_deinterlace(false), 248 m_scontext(NULL) 252 249 { 253 250 } 254 251 … … 268 265 delete fifow; 269 266 if (kfa_table) 270 267 delete kfa_table; 268 269 if (m_deinterlace) 270 avpicture_free(&m_imageDeInt); 271 if (m_scontext) 272 sws_freeContext(m_scontext); 271 273 } 272 274 void Transcode::ReencoderAddKFA(long curframe, long lastkey, long num_keyframes) 273 275 { … … 333 335 // If a bad profile is specified, there will be trouble 334 336 if (isNum && profileID > 0) 335 337 profile.loadByID(profileID); 336 else 338 else if (!profile.loadByGroup(profileName, "Transcoders")) 337 339 { 338 340 VERBOSE(VB_IMPORTANT, QString("Couldn't find profile #: %1"). 339 341 arg(profileName)); … … 379 381 nvr->WriteText(buf, len, timecode, pagenr); 380 382 } 381 383 384 void Transcode::EncodeFrame(unsigned char *srcBuf, int srcWidth, int srcHeight, 385 unsigned char *dstBuf, int dstWidth, int dstHeight, 386 int cr_top, int cr_bottom, 387 int cr_left, int cr_right) 388 { 389 avpicture_fill(&m_imageIn, srcBuf, PIX_FMT_YUV420P, srcWidth, srcHeight); 390 avpicture_fill(&m_imageOut, dstBuf, PIX_FMT_YUV420P, dstWidth, dstHeight); 391 392 int bottomBand = (srcHeight == 1088) ? 8 : 0; 393 if (cr_top || cr_bottom || cr_left || cr_right) 394 { 395 AVPicture *cropSrc = &m_imageIn; 396 if (m_deinterlace) 397 { 398 cropSrc = &m_imageDeInt; 399 avpicture_deinterlace(&m_imageDeInt, &m_imageIn, PIX_FMT_YUV420P, 400 srcWidth, srcHeight); 401 } 402 403 av_picture_crop(&m_imageCrop, cropSrc, 404 PIX_FMT_YUV420P, cr_top, cr_left); 405 406 m_scontext = sws_getCachedContext(m_scontext, 407 srcWidth - cr_left - cr_right, 408 srcHeight - cr_top - cr_bottom, PIX_FMT_YUV420P, 409 dstWidth, dstHeight, PIX_FMT_YUV420P, 410 SWS_FAST_BILINEAR, NULL, NULL, NULL); 411 sws_scale(m_scontext, m_imageCrop.data, m_imageCrop.linesize, 0, 412 srcHeight - bottomBand - cr_top - cr_bottom, 413 m_imageOut.data, m_imageOut.linesize); 414 } 415 else 416 { 417 418 m_scontext = sws_getCachedContext(m_scontext, srcWidth, srcHeight, 419 PIX_FMT_YUV420P, dstWidth, dstHeight, 420 PIX_FMT_YUV420P, SWS_FAST_BILINEAR, 421 NULL, NULL, NULL); 422 423 AVPicture *scaleSrc = &m_imageIn; 424 if (m_deinterlace) 425 { 426 scaleSrc = &m_imageDeInt; 427 avpicture_deinterlace(&m_imageDeInt, &m_imageIn, PIX_FMT_YUV420P, 428 srcWidth, srcHeight); 429 } 430 431 sws_scale(m_scontext, scaleSrc->data, scaleSrc->linesize, 0, 432 srcHeight - bottomBand, m_imageOut.data, m_imageOut.linesize); 433 } 434 } 435 382 436 int Transcode::TranscodeFile( 383 437 const QString &inputname, 384 438 const QString &outputname, … … 486 540 QSize buf_size = nvp->GetVideoBufferSize(); 487 541 int video_width = buf_size.width(); 488 542 int video_height = buf_size.height(); 489 543 490 544 if (video_height == 1088) { 491 545 VERBOSE(VB_IMPORTANT, "Found video height of 1088. This is unusual and " 492 546 "more than likely the video is actually 1080 so mythtranscode " … … 498 552 int newWidth = video_width; 499 553 int newHeight = video_height; 500 554 555 video_aspect = 1.33333333; 556 557 VERBOSE(VB_IMPORTANT, QString("Transcode: current aspect ratio: %1") 558 .arg(video_aspect)); 559 560 561 float newAspect = video_aspect; 562 float oldAspect = video_aspect; 563 int crop_top = 0; 564 int crop_bottom = 0; 565 int crop_left = 0; 566 int crop_right = 0; 567 501 568 kfa_table = new vector<struct kfatable_entry>; 502 569 503 570 if (fifodir.isEmpty()) … … 553 620 newWidth = get_int_option(profile, "width"); 554 621 newHeight = get_int_option(profile, "height"); 555 622 623 int profWidth = newWidth; 624 int profHeight = newHeight; 625 556 626 // If height or width are 0, then we need to calculate them 557 627 if (newHeight == 0 && newWidth > 0) 558 628 newHeight = (int)(1.0 * newWidth * actualHeight / video_width); … … 569 639 } 570 640 } 571 641 642 if (vidsetting == "MPEG-4") 643 { 644 const Setting* setting = profile.byName("mpeg4aspectratio"); 645 if (setting) 646 { 647 if (setting->getValue() == "4:3") { 648 VERBOSE(VB_IMPORTANT, QString( 649 "Transcoder calls for a 4:3 aspect ratio")); 650 newAspect = 1.333333333333; 651 } else if (setting->getValue() == "16:9") { 652 VERBOSE(VB_IMPORTANT, QString( 653 "Transcoder calls for a 16:9 aspect ratio")); 654 newAspect = 1.777777777777; 655 } else if (setting->getValue() == "Original") { 656 VERBOSE(VB_IMPORTANT, QString( 657 "Transcoder leaving aspect ratio unchanged")); 658 } else { 659 VERBOSE(VB_IMPORTANT, QString( 660 "Transcode unable to determine aspect ratio")); 661 } 662 663 // if aspect ratios differ then crop the output 664 if (abs(newAspect - oldAspect) > 0.001) { 665 // calculate the actual pixel ratio for videos, needed 666 // when encoded without square pixels, such as 720x480 667 // NTSC captures 668 float pixelRatio = 669 float(video_width)/float(video_height)/oldAspect; 670 671 // scale the aspect ratio by the pixel ratio 672 float newAspectScaling = newAspect * pixelRatio; 673 if (abs(oldAspect - 1.77777) < 0.001) { 674 if (!profWidth && profHeight) 675 newWidth = (int)(newHeight * newAspectScaling); 676 int scaledWidth = 677 (int)(video_height * newAspectScaling); 678 crop_left = (int)(video_width - scaledWidth) / 2; 679 crop_right = crop_left; 680 } else if (abs(oldAspect - 1.33333) < 0.01) { 681 if (profWidth && !profHeight) 682 newHeight = (int)(newWidth / newAspectScaling); 683 int scaledHeight = 684 (int)(video_width / newAspectScaling); 685 crop_top = (int)(video_height - scaledHeight) / 2; 686 crop_bottom = crop_top; 687 } else { 688 VERBOSE(VB_IMPORTANT, QString("Transcode: Unknown " 689 "aspect ratio %1 on input video, video " 690 "will not be cropped.").arg(oldAspect)); 691 newAspect = oldAspect; 692 } 693 } 694 } else { 695 VERBOSE(VB_IMPORTANT, QString("Transcode: Unable to " 696 "determine aspect ratio")); 697 } 698 699 setting = profile.byName("mpeg4deinterlace"); 700 if (setting) 701 m_deinterlace = setting->getValue().toInt(); 702 } 703 704 572 705 if (encodingType.left(4).toLower() == "mpeg") 573 706 { 574 707 // make sure dimensions are valid for MPEG codecs … … 579 712 VERBOSE(VB_IMPORTANT, QString("Resizing from %1x%2 to %3x%4") 580 713 .arg(video_width).arg(video_height) 581 714 .arg(newWidth).arg(newHeight)); 715 716 if (crop_top || crop_bottom || crop_left || crop_right) 717 VERBOSE(VB_IMPORTANT, QString("Crop Settings %1 %2 %3 %4") 718 .arg(crop_left).arg(crop_right) 719 .arg(crop_top).arg(crop_bottom)); 582 720 } 583 721 else // lossy and no resize 584 722 nvp->SetVideoFilters(vidfilters); … … 593 731 nvr->SetOption("vbiformat", gContext->GetSetting("VbiFormat")); 594 732 595 733 nvr->SetFrameRate(video_frame_rate); 596 nvr->SetVideoAspect( video_aspect);734 nvr->SetVideoAspect(newAspect); 597 735 nvr->SetTranscoding(true); 598 736 599 737 if ((vidsetting == "MPEG-4") || … … 804 942 unsigned char *newFrame = new unsigned char[frame.size]; 805 943 806 944 frame.buf = newFrame; 807 AVPicture imageIn, imageOut;808 struct SwsContext *scontext = NULL;809 945 946 if (m_deinterlace) 947 avpicture_alloc(&m_imageDeInt, PIX_FMT_YUV420P, 948 video_width, video_height); 949 810 950 if (fifow) 811 951 VERBOSE(VB_GENERAL, "Dumping Video and Audio data to fifos"); 812 952 else if (copyaudio) … … 962 1102 if (! nvp->WriteStoredData(outRingBuffer, (did_ff == 0), 963 1103 timecodeOffset)) 964 1104 { 965 if ( video_aspect != nvp->GetVideoAspect())1105 if (oldAspect != nvp->GetVideoAspect()) 966 1106 { 967 1107 video_aspect = nvp->GetVideoAspect(); 968 nvr->SetNewVideoParams(video_aspect); 1108 1109 if (abs(video_aspect - oldAspect) < 0.001) 1110 nvr->SetNewVideoParams(newAspect); 1111 else 1112 nvr->SetNewVideoParams(video_aspect); 969 1113 } 970 1114 971 1115 QSize buf_size = nvp->GetVideoBufferSize(); … … 996 1140 else 997 1141 { 998 1142 frame.buf = newFrame; 999 avpicture_fill(&imageIn, lastDecode->buf, PIX_FMT_YUV420P,1000 video_width, video_height);1001 avpicture_fill(&imageOut, frame.buf, PIX_FMT_YUV420P,1002 newWidth, newHeight);1003 1143 1004 int bottomBand = (video_height == 1088) ? 8 : 0; 1005 scontext = sws_getCachedContext(scontext, video_width, 1006 video_height, PIX_FMT_YUV420P, newWidth, 1007 newHeight, PIX_FMT_YUV420P, 1008 SWS_FAST_BILINEAR, NULL, NULL, NULL); 1009 1010 sws_scale(scontext, imageIn.data, imageIn.linesize, 0, 1011 video_height - bottomBand, 1012 imageOut.data, imageOut.linesize); 1144 EncodeFrame(lastDecode->buf, video_width, video_height, 1145 frame.buf, newWidth, newHeight, 1146 crop_top, crop_bottom, crop_left, crop_right); 1013 1147 } 1014 1148 1015 1149 nvr->WriteVideo(&frame, true, writekeyframe); … … 1029 1163 if (video_aspect != nvp->GetVideoAspect()) 1030 1164 { 1031 1165 video_aspect = nvp->GetVideoAspect(); 1032 nvr->SetNewVideoParams(video_aspect); 1166 if (abs(video_aspect - oldAspect) < 0.001) 1167 nvr->SetNewVideoParams(newAspect); 1168 else 1169 nvr->SetNewVideoParams(video_aspect); 1033 1170 } 1034 1171 1035 1172 … … 1053 1190 else 1054 1191 { 1055 1192 frame.buf = newFrame; 1056 avpicture_fill(&imageIn, lastDecode->buf, PIX_FMT_YUV420P,1057 video_width, video_height);1058 avpicture_fill(&imageOut, frame.buf, PIX_FMT_YUV420P,1059 newWidth, newHeight);1060 1193 1061 int bottomBand = (video_height == 1088) ? 8 : 0; 1062 scontext = sws_getCachedContext(scontext, video_width, 1063 video_height, PIX_FMT_YUV420P, newWidth, 1064 newHeight, PIX_FMT_YUV420P, 1065 SWS_FAST_BILINEAR, NULL, NULL, NULL); 1066 1067 sws_scale(scontext, imageIn.data, imageIn.linesize, 0, 1068 video_height - bottomBand, 1069 imageOut.data, imageOut.linesize); 1194 EncodeFrame(lastDecode->buf, video_width, video_height, 1195 frame.buf, newWidth, newHeight, 1196 crop_top, crop_bottom, crop_left, crop_right); 1070 1197 } 1071 1198 1072 1199 // audio is fully decoded, so we need to reencode it … … 1164 1291 frame.frameNumber = 1 + (curFrameNum << 1); 1165 1292 } 1166 1293 1167 sws_freeContext(scontext);1168 1169 1294 if (! fifow) 1170 1295 { 1171 1296 if (m_proginfo) -
programs/mythtranscode/transcode.h
2 2 #include "fifowriter.h" 3 3 #include "transcodedefs.h" 4 4 5 extern "C" { 6 #include "libavcodec/avcodec.h" 7 #include "libswscale/swscale.h" 8 } 9 5 10 class PlayerContext; 6 11 class ProgramInfo; 7 12 class NuppelVideoRecorder; … … 20 25 const QString &profileName, 21 26 bool honorCutList, bool framecontrol, int jobID, 22 27 QString fifodir, QMap<long long, int> deleteMap); 28 void EncodeFrame(unsigned char *srcBuf, int srcWidth, int srcHeight, 29 unsigned char *dstBuf, int dstWidth, int dstHeight, 30 int cr_top, int cr_bottom, int cr_left, int cr_right); 23 31 void ShowProgress(bool val) { showprogress = val; } 24 32 void SetRecorderOptions(QString options) { recorderOptions = options; } 25 33 … … 42 50 KFATable *kfa_table; 43 51 bool showprogress; 44 52 QString recorderOptions; 53 54 AVPicture m_imageIn; 55 AVPicture m_imageDeInt; 56 AVPicture m_imageCrop; 57 AVPicture m_imageOut; 58 bool m_deinterlace; 59 struct SwsContext *m_scontext; 45 60 }; 46 61 47 62 /* vim: set expandtab tabstop=4 shiftwidth=4: */