Ticket #2581: 2581_aspectRatio-trunk.patch

File 2581_aspectRatio-trunk.patch, 17.4 KB (added by cpinkham, 3 years ago)

Aspect Ratio patch modified to work with trunk & with deinterlacing ability

  • libs/libmythtv/recordingprofile.cpp

     
    571571    }; 
    572572}; 
    573573 
     574class MPEG4AspectRatio: public ComboBoxSetting, public CodecParamStorage { 
     575public: 
     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 
     589class MPEG4DeInterlace: public ComboBoxSetting, public CodecParamStorage { 
     590public: 
     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 
    574602class MPEG4QualDiff : public SliderSetting, public CodecParamStorage 
    575603{ 
    576604  public: 
     
    822850 
    823851        params = new VerticalConfigurationGroup(false); 
    824852        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 
    828866        params->addChild(new MPEG4QualDiff(parent)); 
    829         params->addChild(new ScaleBitrate(parent)); 
    830867 
     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 
    831874        HorizontalConfigurationGroup *hq; 
    832875        hq = new HorizontalConfigurationGroup(false, false); 
    833876        hq->addChild(new MPEG4OptionVHQ(parent)); 
  • programs/mythtranscode/transcode.cpp

     
    3232#include "mythdbcon.h" 
    3333 
    3434 
    35 extern "C" { 
    36 #include "libavcodec/avcodec.h" 
    37 #include "libswscale/swscale.h" 
    38 } 
    39  
    4035#define LOC QString("Transcode: ") 
    4136#define LOC_ERR QString("Transcode, Error: ") 
    4237 
     
    248243    fifow(NULL), 
    249244    kfa_table(NULL), 
    250245    showprogress(false), 
    251     recorderOptions("")    
     246    recorderOptions(""), 
     247    m_deinterlace(false), 
     248    m_scontext(NULL) 
    252249{ 
    253250} 
    254251 
     
    268265        delete fifow; 
    269266    if (kfa_table) 
    270267        delete kfa_table; 
     268 
     269    if (m_deinterlace) 
     270        avpicture_free(&m_imageDeInt); 
     271    if (m_scontext) 
     272        sws_freeContext(m_scontext); 
    271273} 
    272274void Transcode::ReencoderAddKFA(long curframe, long lastkey, long num_keyframes) 
    273275{ 
     
    333335        // If a bad profile is specified, there will be trouble 
    334336        if (isNum && profileID > 0) 
    335337            profile.loadByID(profileID); 
    336         else 
     338        else if (!profile.loadByGroup(profileName, "Transcoders")) 
    337339        { 
    338340            VERBOSE(VB_IMPORTANT, QString("Couldn't find profile #: %1"). 
    339341                    arg(profileName)); 
     
    379381  nvr->WriteText(buf, len, timecode, pagenr); 
    380382} 
    381383 
     384void 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 
    382436int Transcode::TranscodeFile( 
    383437    const QString &inputname, 
    384438    const QString &outputname, 
     
    486540    QSize buf_size = nvp->GetVideoBufferSize(); 
    487541    int video_width = buf_size.width(); 
    488542    int video_height = buf_size.height(); 
    489       
     543 
    490544    if (video_height == 1088) { 
    491545       VERBOSE(VB_IMPORTANT, "Found video height of 1088.  This is unusual and " 
    492546               "more than likely the video is actually 1080 so mythtranscode " 
     
    498552    int newWidth = video_width; 
    499553    int newHeight = video_height; 
    500554 
     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 
    501568    kfa_table = new vector<struct kfatable_entry>; 
    502569 
    503570    if (fifodir.isEmpty()) 
     
    553620            newWidth = get_int_option(profile, "width"); 
    554621            newHeight = get_int_option(profile, "height"); 
    555622 
     623            int profWidth = newWidth; 
     624            int profHeight = newHeight; 
     625 
    556626            // If height or width are 0, then we need to calculate them 
    557627            if (newHeight == 0 && newWidth > 0) 
    558628                newHeight = (int)(1.0 * newWidth * actualHeight / video_width); 
     
    569639                } 
    570640            } 
    571641 
     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 
    572705            if (encodingType.left(4).toLower() == "mpeg") 
    573706            { 
    574707                // make sure dimensions are valid for MPEG codecs 
     
    579712            VERBOSE(VB_IMPORTANT, QString("Resizing from %1x%2 to %3x%4") 
    580713                    .arg(video_width).arg(video_height) 
    581714                    .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)); 
    582720        } 
    583721        else  // lossy and no resize 
    584722            nvp->SetVideoFilters(vidfilters); 
     
    593731        nvr->SetOption("vbiformat", gContext->GetSetting("VbiFormat")); 
    594732 
    595733        nvr->SetFrameRate(video_frame_rate); 
    596         nvr->SetVideoAspect(video_aspect); 
     734        nvr->SetVideoAspect(newAspect); 
    597735        nvr->SetTranscoding(true); 
    598736 
    599737        if ((vidsetting == "MPEG-4") || 
     
    804942    unsigned char *newFrame = new unsigned char[frame.size]; 
    805943 
    806944    frame.buf = newFrame; 
    807     AVPicture imageIn, imageOut; 
    808     struct SwsContext  *scontext = NULL; 
    809945 
     946    if (m_deinterlace) 
     947        avpicture_alloc(&m_imageDeInt, PIX_FMT_YUV420P, 
     948                        video_width, video_height); 
     949 
    810950    if (fifow) 
    811951        VERBOSE(VB_GENERAL, "Dumping Video and Audio data to fifos"); 
    812952    else if (copyaudio) 
     
    9621102            if (! nvp->WriteStoredData(outRingBuffer, (did_ff == 0), 
    9631103                                       timecodeOffset)) 
    9641104            { 
    965                 if (video_aspect != nvp->GetVideoAspect()) 
     1105                if (oldAspect != nvp->GetVideoAspect()) 
    9661106                { 
    9671107                    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); 
    9691113                } 
    9701114 
    9711115                QSize buf_size = nvp->GetVideoBufferSize(); 
     
    9961140                else 
    9971141                { 
    9981142                    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); 
    10031143 
    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); 
    10131147                } 
    10141148 
    10151149                nvr->WriteVideo(&frame, true, writekeyframe); 
     
    10291163            if (video_aspect != nvp->GetVideoAspect()) 
    10301164            { 
    10311165                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); 
    10331170            } 
    10341171 
    10351172 
     
    10531190            else 
    10541191            { 
    10551192                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); 
    10601193 
    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); 
    10701197            } 
    10711198 
    10721199            // audio is fully decoded, so we need to reencode it 
     
    11641291        frame.frameNumber = 1 + (curFrameNum << 1); 
    11651292    } 
    11661293 
    1167     sws_freeContext(scontext); 
    1168  
    11691294    if (! fifow) 
    11701295    { 
    11711296        if (m_proginfo) 
  • programs/mythtranscode/transcode.h

     
    22#include "fifowriter.h" 
    33#include "transcodedefs.h" 
    44 
     5extern "C" { 
     6#include "libavcodec/avcodec.h" 
     7#include "libswscale/swscale.h" 
     8} 
     9 
    510class PlayerContext; 
    611class ProgramInfo; 
    712class NuppelVideoRecorder; 
     
    2025        const QString &profileName, 
    2126        bool honorCutList, bool framecontrol, int jobID, 
    2227        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); 
    2331    void ShowProgress(bool val) { showprogress = val; } 
    2432    void SetRecorderOptions(QString options) { recorderOptions = options; } 
    2533 
     
    4250    KFATable               *kfa_table; 
    4351    bool                    showprogress; 
    4452    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; 
    4560}; 
    4661 
    4762/* vim: set expandtab tabstop=4 shiftwidth=4: */