home *** CD-ROM | disk | FTP | other *** search
/ PC Welt 2004 March / PCWELT_3_2004.ISO / pcwsoft / flaskmpeg_078_39_src.z.exe / flaskmpeg / PostProcessing.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2002-10-28  |  11.7 KB  |  489 lines

  1. /* 
  2.  *  PostProcessing.cpp 
  3.  *
  4.  *    Copyright (C) Alberto Vigata - January 2000 - ultraflask@yahoo.com
  5.  *
  6.  *  This file is part of FlasKMPEG, a free MPEG to MPEG/AVI converter
  7.  *    
  8.  *  FlasKMPEG is free software; you can redistribute it and/or modify
  9.  *  it under the terms of the GNU General Public License as published by
  10.  *  the Free Software Foundation; either version 2, or (at your option)
  11.  *  any later version.
  12.  *   
  13.  *  FlasKMPEG is distributed in the hope that it will be useful,
  14.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16.  *  GNU General Public License for more details.
  17.  *   
  18.  *  You should have received a copy of the GNU General Public License
  19.  *  along with GNU Make; see the file COPYING.  If not, write to
  20.  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 
  21.  *
  22.  */
  23.  
  24. #include <windows.h>
  25. #include ".\resizer\resizer.h"
  26. #include "Deinterlacer.h"
  27. #include "postprocessing.h"
  28. #include "flaskmpeg.h"
  29. #include "FlBrightness.h"
  30.  
  31. #include "debug.h"
  32.  
  33. // Auxiliary Post processing functions
  34.  
  35. // Fix absurd post processing settings
  36. void FixPPostSettings(TPPost *pp){
  37.   long width, height;
  38.  
  39.   if( pp->bResize ) {
  40.     width = pp->resWidth;
  41.     height = pp->resHeight;
  42.   }
  43.   else {
  44.     width = pp->nInWidth;
  45.     height = pp->nInHeight;
  46.   }
  47.  
  48.   if( pp->cropWidth + pp->cropLeftOffset > width )
  49.     pp->crop = 0;
  50.   if( pp->cropHeight + pp->cropTopOffset > height )
  51.     pp->crop = 0;
  52.  
  53. #if 0
  54.   if( pp->cropWidth + pp->cropLeftOffset > width )
  55.     if( width - pp->cropLeftOffset > 0 ) {
  56.             pp->cropWidth  = width - pp->cropLeftOffset;
  57.     }
  58.     else {
  59.       pp->crop = 0;
  60.       pp->cropLeftOffset = 0;
  61.     }
  62.  
  63.   if( pp->cropHeight + pp->cropTopOffset > height )
  64.     if( height - pp->cropTopOffset > 0 ) {
  65.             pp->cropHeight  = height - pp->cropTopOffset;
  66.     }
  67.     else {
  68.       pp->crop = 0;
  69.       pp->cropTopOffset = 0;
  70.     }
  71. #endif
  72. }
  73.  
  74. int CheckVideoParameters(TPPost *pp){
  75.   // Create a postprocessing object
  76.   FlPostProcess ppObj;
  77.   TPPost pps = *pp;
  78.  
  79.   pps.nInWidth = 640;
  80.   pps.nInHeight = 480;
  81.  
  82.   // Try to set the settings
  83.   return ppObj.Set( &pps )==true ? 1 : 0;
  84. }
  85.  
  86. int CheckVideoParametersOld(TPPost *pp){
  87.   int w,h;
  88.   
  89.   //FixPPostSettings(pp);
  90.   // Image dimension settings
  91.   if( (pp->cropHeight%16 != 0) || (pp->cropWidth%16 != 0) )
  92.     return 0;
  93.   
  94.   if (! pp->crop) { 
  95.     // if we don't crop, the resize dims must be multipl of 16
  96.     if( (pp->resWidth%16 != 0) || (pp->resHeight%16 != 0) )
  97.       return 0;
  98.   }
  99.   else {
  100.     // if we are cropping, the only requirement is that the resize width be
  101.     // a multiple of 2 (needed by the bicubic code and friends)
  102.     if (pp->resWidth%2 != 0)
  103.       return 0;
  104.   }
  105.   
  106.   //Crop Checkings
  107.   // Crop widht&height must be less than input image resolution
  108.   if( pp->crop && (pp->cropHeight > pp->resHeight) )
  109.     return 0;
  110.   if( pp->crop && (pp->cropWidth  > pp->resWidth) )
  111.     return 0;
  112.   if( pp->crop && ((pp->cropTopOffset + pp->cropHeight) > pp->resHeight)  )
  113.     return 0;
  114.   if( pp->crop && ((pp->cropLeftOffset + pp->cropWidth) > pp->resWidth)  )
  115.     return 0;
  116.   
  117.   if( (pp->cropHeight < 0) || (pp->cropWidth < 0) )
  118.     return 0;
  119.   if( pp->crop && ((pp->cropTopOffset<0) ) )
  120.     return 0;
  121.   if( pp->crop && ((pp->cropLeftOffset<0) ||  (pp->cropLeftOffset > pp->cropWidth-16)) )
  122.     return 0;
  123.   
  124.   // image size
  125.   if( pp->resWidth > 2048 || pp->resHeight > 2048)
  126.     return 0;
  127.   
  128.   // Letterboxing
  129.   w = pp->crop ? pp->cropWidth  : pp->resWidth;
  130.   h = pp->crop ? pp->cropHeight : pp->resHeight;
  131.   
  132.   if( pp->letterbox && (pp->letterboxLeft>w || pp->letterboxRight >w
  133.     || pp->letterboxTop >h || pp->letterboxBottom>h))
  134.     return 0;
  135.   if( pp->letterbox && (pp->letterboxLeft<0 || pp->letterboxRight <0
  136.     || pp->letterboxTop <0 || pp->letterboxBottom<0))
  137.     return 0;
  138.   
  139.  
  140.     return 1;
  141. }
  142.  
  143. void FromPPostToConfig( TProfile *prof, TPPost *pp){
  144.  
  145.   prof->crop           =   pp->crop;
  146.   prof->cropWidth      =   pp->cropWidth;
  147.   prof->cropHeight     =   pp->cropHeight;
  148.   prof->cropTopOffset  =   pp->cropTopOffset;
  149.   prof->cropLeftOffset =   pp->cropLeftOffset;
  150.   
  151.   prof->letterbox      =   pp->letterbox;
  152.   prof->letterboxBottom=   pp->letterboxBottom;
  153.   prof->letterboxTop   =   pp->letterboxTop;
  154.   prof->letterboxLeft  =   pp->letterboxLeft;
  155.   prof->letterboxRight =   pp->letterboxRight;
  156.   
  157.  
  158.   prof->videocontrols  = pp->videocontrols;
  159.   prof->brightness    = pp->brightness;
  160.   prof->contrast      = pp->contrast;
  161.   prof->hue           = pp->hue;
  162.  
  163.   prof->bResize             = pp->bResize;
  164.   prof->InterpolatedWidth   = pp->resWidth;
  165.   prof->InterpolatedHeight  = pp->resHeight;
  166.   prof->filter              = pp->filterMode;
  167.   prof->keepAspect          = (pp->doAR ? KEEP_AR : 0) | pp->outAR;
  168.   
  169.   prof->deinterlace = pp->deinterlace;
  170.   prof->blend = pp->blend_fields;
  171.   prof->threshold = pp->threshold;
  172. }
  173.  
  174. void FromConfigToPPost(  TProfile *prof, TPPost *pp, int nSrcWidth, int nSrcHeight, double fDar, int nProcessingFormat ){
  175.     
  176.   pp->iDAR = fDar;
  177.   pp->nInHeight = nSrcHeight;
  178.   pp->nInWidth  = nSrcWidth;
  179.   pp->nProcessingFormat = nProcessingFormat;
  180.  
  181.   pp->crop          =  prof->crop;
  182.   pp->cropWidth     =  prof->cropWidth;
  183.   pp->cropHeight    =  prof->cropHeight;
  184.   pp->cropTopOffset =  prof->cropTopOffset;
  185.   pp->cropLeftOffset=  prof->cropLeftOffset;
  186.   
  187.   
  188.   pp->letterbox       =  prof->letterbox;
  189.   pp->letterboxBottom =  prof->letterboxBottom;
  190.   pp->letterboxTop    =  prof->letterboxTop;
  191.   pp->letterboxLeft   =  prof->letterboxLeft;
  192.   pp->letterboxRight  =  prof->letterboxRight;
  193.   
  194.  
  195.   pp->videocontrols   = prof->videocontrols;
  196.   pp->hue             = prof->hue;
  197.   pp->brightness      = prof->brightness;
  198.   pp->contrast        = prof->contrast;
  199.  
  200.   pp->bResize    = prof->bResize;
  201.   pp->resWidth   = prof->InterpolatedWidth ;
  202.   pp->resHeight  = prof->InterpolatedHeight;
  203.   pp->filterMode = prof->filter;
  204.   pp->doAR       = prof->keepAspect & KEEP_AR;
  205.   pp->outAR         = prof->keepAspect & AR_BITS;
  206.   
  207.   pp->deinterlace  = prof->deinterlace;
  208.   pp->blend_fields = prof->blend;
  209.   pp->threshold    = prof->threshold;
  210.  
  211.   FixPPostSettings( pp );
  212.  
  213. }
  214.  
  215.  
  216. FlPostProcess::FlPostProcess()
  217. {
  218.   m_filc = 0;
  219.   m_nHeight = m_nWidth = 0;
  220. }
  221. bool FlPostProcess::Set(TPPost *pp)
  222. {
  223.   bool bSuccess = true;
  224.   TPPost m_old = m_pp;
  225.   m_pp = *pp;
  226.  
  227.   if( !BuildChain() ) {
  228.     bSuccess = false;
  229.   }
  230.  
  231.   if( bSuccess ) {
  232.     DestroyChain();
  233.     m_pp = *pp;
  234.   }
  235.   else {
  236.     m_pp = m_old;
  237.   }
  238.   return bSuccess;
  239. }
  240.  
  241. bool FlPostProcess::Start()
  242. {
  243.   bool bSuccess = false;
  244.   if( BuildChain() )
  245.   {
  246.     // Start chain
  247.     for( int i=0; i<m_filc; i++ )
  248.     {
  249.       if(!m_fil[i]->Start())
  250.       {
  251.         DBG_STR((str, "FlPostProcess::Start - %d filter failed to start", i))
  252.         bSuccess = false;
  253.         break;
  254.       }
  255.     }
  256.     bSuccess = true;
  257.   }
  258.   return bSuccess;
  259. }
  260.  
  261. int FlPostProcess::Process(CFrame *pSrc, CFrame *pDst)
  262. {
  263.  
  264.   if( !pSrc || !pDst )
  265.     return 0;
  266.  
  267.   if( pSrc->GetWidth()!=m_pp.nInWidth  ||
  268.       pSrc->GetHeight()!=m_pp.nInHeight )
  269.   {
  270.     DBG_STR((str, "PostProcess - Input resolution incorrect\n"))
  271.     return 0;
  272.   }
  273.  
  274.   m_pIn = pSrc;
  275.  
  276.   if( m_filc == 0 )
  277.     pDst->SetFrame( pSrc );
  278.   else
  279.     m_fil[m_filc-1]->Process( pDst );
  280.  
  281.   return flfil_ok;
  282. }
  283.  
  284. bool FlPostProcess::Stop()
  285. {
  286.   // Stop chain
  287.   for( int i=0; i<m_filc; i++ )
  288.     m_fil[i]->Stop();
  289.   
  290.   return DestroyChain()==flfil_ok;
  291. }
  292.  
  293. bool FlPostProcess::GetFrame( CFrame **ppFrame )
  294. {
  295.   *ppFrame = m_pIn;
  296.   return true;
  297. }
  298.  
  299. int FlPostProcess::BuildChain()
  300. {
  301.   m_filc = 0;
  302.  
  303.   // Fix settings
  304.   // FixPPostSettings( &m_pp );
  305.   // Only FRAME_YV12 supported only
  306.   m_pp.nProcessingFormat = FRAME_YV12;
  307.  
  308.   /////////////////////////
  309.   // prepare deinterlacing
  310.   ////////////////////////
  311.   if( m_pp.deinterlace )
  312.   {
  313.     FlDeinterlacer *fil = new FlDeinterlacer;
  314.  
  315.     TDeinterlacerConfig cfg;
  316.   
  317.     cfg.blend = m_pp.blend_fields;
  318.     cfg.threshold = m_pp.threshold;
  319.     
  320.     fil->Configure( &cfg, sizeof TDeinterlacerConfig );
  321.  
  322.     m_fil[m_filc++] = fil;
  323.   }
  324.  
  325.   ///////////////////////
  326.   // prepare resizing
  327.   ///////////////////////
  328.   if(  m_pp.bResize || m_pp.doAR   )
  329.   {
  330.     // If you are doing aspect ratio
  331.     // and one of the resolutions don't match
  332.     // is the only case where you have to do something
  333.     if(  m_pp.doAR==true                 || 
  334.          m_pp.resWidth != m_pp.nInWidth  ||
  335.          m_pp.resHeight!= m_pp.nInHeight )
  336.     {
  337.       FlResize *rs = new FlResize;
  338.     
  339.       TResizeCfg cfg;
  340.  
  341.       cfg.doar = m_pp.doAR ? 1 : 0;
  342.       cfg.idar = m_pp.iDAR;
  343.       cfg.odar = m_pp.outAR&AR_43  ? (3.0/4.0) : 
  344.                  m_pp.outAR&AR_169 ? (9.0/16.0):
  345.                  (double)m_pp.resHeight/(double)m_pp.resWidth;
  346.  
  347.     
  348.       cfg.owidth = m_pp.bResize ? m_pp.resWidth : m_pp.nInWidth;
  349.       cfg.oheight = m_pp.bResize ? m_pp.resHeight : m_pp.nInHeight;
  350.       cfg.method = m_pp.filterMode;
  351.  
  352.       rs->Configure( &cfg, sizeof TResizeCfg );
  353.  
  354.       m_fil[m_filc++] = rs;
  355.     }
  356.   }
  357.  
  358.   //////////////////////
  359.   // Prepare letterboxing
  360.   if(m_pp.letterbox)
  361.   {
  362.     FlLetterbox *fil = new FlLetterbox;
  363.  
  364.     TLetterboxConfig cfg;
  365.  
  366.     cfg.left = m_pp.letterboxLeft;
  367.     cfg.right = m_pp.letterboxRight;
  368.     cfg.top = m_pp.letterboxTop;
  369.     cfg.bottom = m_pp.letterboxBottom;
  370.  
  371.     fil->Configure( &cfg, sizeof TLetterboxConfig );
  372.  
  373.     m_fil[m_filc++] = fil;
  374.   }
  375.   
  376.   ///////////////////////
  377.   // Prepare cropping
  378.   if(m_pp.crop)
  379.   {
  380.     FlCrop *cr = new FlCrop;
  381.     
  382.     TCropConfig cfg;
  383.     cfg.left = m_pp.cropLeftOffset;
  384.     cfg.right = m_pp.cropLeftOffset + m_pp.cropWidth;
  385.     
  386.     cfg.top = m_pp.cropTopOffset;
  387.     cfg.bottom = m_pp.cropTopOffset + m_pp.cropHeight;
  388.     cr->Configure( &cfg, sizeof TCropConfig );
  389.     
  390.     m_fil[m_filc++] = cr;
  391.   }
  392.  
  393.   //////////////////////
  394.   // video controls
  395.   if( m_pp.videocontrols ) {
  396.     FlBrightness *fil = new FlBrightness;
  397.  
  398.     TBrightnessCfg cfg;
  399.  
  400.     cfg.brightness = m_pp.brightness;
  401.     cfg.contrast = m_pp.contrast;
  402.     cfg.hue = m_pp.hue;
  403.  
  404.     fil->Configure( &cfg, sizeof TBrightnessCfg );
  405.  
  406.     m_fil[m_filc++] = fil;
  407.   }
  408.  
  409.   if( Validate() != flfil_ok )
  410.   {
  411.     DBG_STR((str, "PostProcessingStart - Could not validate settings\n"))
  412.     return 0;
  413.   }
  414.  
  415.   return 1;
  416. }
  417.  
  418. int FlPostProcess::Validate()
  419. {
  420.   // validate the filter chain
  421.   flfilter_conf fc, myfs;
  422.   CFrameSource *pInput;
  423.  
  424.   if( !m_pp.nInHeight ||
  425.       !m_pp.nInWidth )
  426.       return flfil_error;
  427.  
  428.   fc.iformat = FRAME_YV12;
  429.   fc.id = 0;
  430.   fc.iw = m_pp.nInWidth;
  431.   fc.ih = m_pp.nInHeight;
  432.   fc.icanmodify = 0;
  433.   fc.iprovided = 1;
  434.   fc.input = this;
  435.   pInput = this;
  436.  
  437.   fc.ocanmodify = 0;
  438.   fc.olag = 0;
  439.   fc.od = fc.id;
  440.   fc.ow = fc.iw;
  441.   fc.oh = fc.ih;
  442.   fc.oprovided = fc.iprovided;
  443.   fc.op = 0;
  444.   
  445.   for( int i=0; i<m_filc; i++ )
  446.   {
  447.     myfs.input     = pInput;
  448.     myfs.iprovided = fc.oprovided;
  449.     myfs.iw = fc.ow;
  450.     myfs.ih = fc.oh;
  451.     myfs.id = fc.od;
  452.     myfs.iformat = fc.iformat;
  453.     myfs.icanmodify = fc.ocanmodify;
  454.     
  455.     if(!m_fil[i]->ValFilterConf(&myfs))
  456.     {
  457.       DBG_STR((str, "FlPostProcess::Validate - %d filter validation failed\n", i))
  458.         return flfil_error;
  459.     }
  460.     
  461.     fc.olag += myfs.olag;
  462.     fc.od = myfs.od;
  463.     fc.ow = myfs.ow;
  464.     fc.oh = myfs.oh;
  465.     fc.ocanmodify = myfs.ocanmodify;
  466.     fc.oprovided = myfs.oprovided;
  467.     fc.op = 0;
  468.     pInput = m_fil[i];
  469.   }
  470.  
  471.   m_nWidth = fc.ow;
  472.   m_nHeight = fc.oh;
  473.  
  474.   return flfil_ok;
  475. }
  476.  
  477. int FlPostProcess::DestroyChain()
  478. {
  479.   // delete objects
  480.   for( int i=0; i<m_filc; i++ )
  481.   {
  482.     if( m_fil[i] )
  483.       delete m_fil[i];
  484.     m_fil[i] = 0;
  485.   }
  486.   m_filc = 0;
  487.  
  488.   return 1;
  489. }