home *** CD-ROM | disk | FTP | other *** search
- /*
- * PostProcessing.cpp
- *
- * Copyright (C) Alberto Vigata - January 2000 - ultraflask@yahoo.com
- *
- * This file is part of FlasKMPEG, a free MPEG to MPEG/AVI converter
- *
- * FlasKMPEG is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * FlasKMPEG is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with GNU Make; see the file COPYING. If not, write to
- * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
- #include <windows.h>
- #include ".\resizer\resizer.h"
- #include "Deinterlacer.h"
- #include "postprocessing.h"
- #include "flaskmpeg.h"
- #include "FlBrightness.h"
-
- #include "debug.h"
-
- // Auxiliary Post processing functions
-
- // Fix absurd post processing settings
- void FixPPostSettings(TPPost *pp){
- long width, height;
-
- if( pp->bResize ) {
- width = pp->resWidth;
- height = pp->resHeight;
- }
- else {
- width = pp->nInWidth;
- height = pp->nInHeight;
- }
-
- if( pp->cropWidth + pp->cropLeftOffset > width )
- pp->crop = 0;
- if( pp->cropHeight + pp->cropTopOffset > height )
- pp->crop = 0;
-
- #if 0
- if( pp->cropWidth + pp->cropLeftOffset > width )
- if( width - pp->cropLeftOffset > 0 ) {
- pp->cropWidth = width - pp->cropLeftOffset;
- }
- else {
- pp->crop = 0;
- pp->cropLeftOffset = 0;
- }
-
- if( pp->cropHeight + pp->cropTopOffset > height )
- if( height - pp->cropTopOffset > 0 ) {
- pp->cropHeight = height - pp->cropTopOffset;
- }
- else {
- pp->crop = 0;
- pp->cropTopOffset = 0;
- }
- #endif
- }
-
- int CheckVideoParameters(TPPost *pp){
- // Create a postprocessing object
- FlPostProcess ppObj;
- TPPost pps = *pp;
-
- pps.nInWidth = 640;
- pps.nInHeight = 480;
-
- // Try to set the settings
- return ppObj.Set( &pps )==true ? 1 : 0;
- }
-
- int CheckVideoParametersOld(TPPost *pp){
- int w,h;
-
- //FixPPostSettings(pp);
- // Image dimension settings
- if( (pp->cropHeight%16 != 0) || (pp->cropWidth%16 != 0) )
- return 0;
-
- if (! pp->crop) {
- // if we don't crop, the resize dims must be multipl of 16
- if( (pp->resWidth%16 != 0) || (pp->resHeight%16 != 0) )
- return 0;
- }
- else {
- // if we are cropping, the only requirement is that the resize width be
- // a multiple of 2 (needed by the bicubic code and friends)
- if (pp->resWidth%2 != 0)
- return 0;
- }
-
- //Crop Checkings
- // Crop widht&height must be less than input image resolution
- if( pp->crop && (pp->cropHeight > pp->resHeight) )
- return 0;
- if( pp->crop && (pp->cropWidth > pp->resWidth) )
- return 0;
- if( pp->crop && ((pp->cropTopOffset + pp->cropHeight) > pp->resHeight) )
- return 0;
- if( pp->crop && ((pp->cropLeftOffset + pp->cropWidth) > pp->resWidth) )
- return 0;
-
- if( (pp->cropHeight < 0) || (pp->cropWidth < 0) )
- return 0;
- if( pp->crop && ((pp->cropTopOffset<0) ) )
- return 0;
- if( pp->crop && ((pp->cropLeftOffset<0) || (pp->cropLeftOffset > pp->cropWidth-16)) )
- return 0;
-
- // image size
- if( pp->resWidth > 2048 || pp->resHeight > 2048)
- return 0;
-
- // Letterboxing
- w = pp->crop ? pp->cropWidth : pp->resWidth;
- h = pp->crop ? pp->cropHeight : pp->resHeight;
-
- if( pp->letterbox && (pp->letterboxLeft>w || pp->letterboxRight >w
- || pp->letterboxTop >h || pp->letterboxBottom>h))
- return 0;
- if( pp->letterbox && (pp->letterboxLeft<0 || pp->letterboxRight <0
- || pp->letterboxTop <0 || pp->letterboxBottom<0))
- return 0;
-
-
- return 1;
- }
-
- void FromPPostToConfig( TProfile *prof, TPPost *pp){
-
- prof->crop = pp->crop;
- prof->cropWidth = pp->cropWidth;
- prof->cropHeight = pp->cropHeight;
- prof->cropTopOffset = pp->cropTopOffset;
- prof->cropLeftOffset = pp->cropLeftOffset;
-
- prof->letterbox = pp->letterbox;
- prof->letterboxBottom= pp->letterboxBottom;
- prof->letterboxTop = pp->letterboxTop;
- prof->letterboxLeft = pp->letterboxLeft;
- prof->letterboxRight = pp->letterboxRight;
-
-
- prof->videocontrols = pp->videocontrols;
- prof->brightness = pp->brightness;
- prof->contrast = pp->contrast;
- prof->hue = pp->hue;
-
- prof->bResize = pp->bResize;
- prof->InterpolatedWidth = pp->resWidth;
- prof->InterpolatedHeight = pp->resHeight;
- prof->filter = pp->filterMode;
- prof->keepAspect = (pp->doAR ? KEEP_AR : 0) | pp->outAR;
-
- prof->deinterlace = pp->deinterlace;
- prof->blend = pp->blend_fields;
- prof->threshold = pp->threshold;
- }
-
- void FromConfigToPPost( TProfile *prof, TPPost *pp, int nSrcWidth, int nSrcHeight, double fDar, int nProcessingFormat ){
-
- pp->iDAR = fDar;
- pp->nInHeight = nSrcHeight;
- pp->nInWidth = nSrcWidth;
- pp->nProcessingFormat = nProcessingFormat;
-
- pp->crop = prof->crop;
- pp->cropWidth = prof->cropWidth;
- pp->cropHeight = prof->cropHeight;
- pp->cropTopOffset = prof->cropTopOffset;
- pp->cropLeftOffset= prof->cropLeftOffset;
-
-
- pp->letterbox = prof->letterbox;
- pp->letterboxBottom = prof->letterboxBottom;
- pp->letterboxTop = prof->letterboxTop;
- pp->letterboxLeft = prof->letterboxLeft;
- pp->letterboxRight = prof->letterboxRight;
-
-
- pp->videocontrols = prof->videocontrols;
- pp->hue = prof->hue;
- pp->brightness = prof->brightness;
- pp->contrast = prof->contrast;
-
- pp->bResize = prof->bResize;
- pp->resWidth = prof->InterpolatedWidth ;
- pp->resHeight = prof->InterpolatedHeight;
- pp->filterMode = prof->filter;
- pp->doAR = prof->keepAspect & KEEP_AR;
- pp->outAR = prof->keepAspect & AR_BITS;
-
- pp->deinterlace = prof->deinterlace;
- pp->blend_fields = prof->blend;
- pp->threshold = prof->threshold;
-
- FixPPostSettings( pp );
-
- }
-
-
- FlPostProcess::FlPostProcess()
- {
- m_filc = 0;
- m_nHeight = m_nWidth = 0;
- }
- bool FlPostProcess::Set(TPPost *pp)
- {
- bool bSuccess = true;
- TPPost m_old = m_pp;
- m_pp = *pp;
-
- if( !BuildChain() ) {
- bSuccess = false;
- }
-
- if( bSuccess ) {
- DestroyChain();
- m_pp = *pp;
- }
- else {
- m_pp = m_old;
- }
- return bSuccess;
- }
-
- bool FlPostProcess::Start()
- {
- bool bSuccess = false;
- if( BuildChain() )
- {
- // Start chain
- for( int i=0; i<m_filc; i++ )
- {
- if(!m_fil[i]->Start())
- {
- DBG_STR((str, "FlPostProcess::Start - %d filter failed to start", i))
- bSuccess = false;
- break;
- }
- }
- bSuccess = true;
- }
- return bSuccess;
- }
-
- int FlPostProcess::Process(CFrame *pSrc, CFrame *pDst)
- {
-
- if( !pSrc || !pDst )
- return 0;
-
- if( pSrc->GetWidth()!=m_pp.nInWidth ||
- pSrc->GetHeight()!=m_pp.nInHeight )
- {
- DBG_STR((str, "PostProcess - Input resolution incorrect\n"))
- return 0;
- }
-
- m_pIn = pSrc;
-
- if( m_filc == 0 )
- pDst->SetFrame( pSrc );
- else
- m_fil[m_filc-1]->Process( pDst );
-
- return flfil_ok;
- }
-
- bool FlPostProcess::Stop()
- {
- // Stop chain
- for( int i=0; i<m_filc; i++ )
- m_fil[i]->Stop();
-
- return DestroyChain()==flfil_ok;
- }
-
- bool FlPostProcess::GetFrame( CFrame **ppFrame )
- {
- *ppFrame = m_pIn;
- return true;
- }
-
- int FlPostProcess::BuildChain()
- {
- m_filc = 0;
-
- // Fix settings
- // FixPPostSettings( &m_pp );
- // Only FRAME_YV12 supported only
- m_pp.nProcessingFormat = FRAME_YV12;
-
- /////////////////////////
- // prepare deinterlacing
- ////////////////////////
- if( m_pp.deinterlace )
- {
- FlDeinterlacer *fil = new FlDeinterlacer;
-
- TDeinterlacerConfig cfg;
-
- cfg.blend = m_pp.blend_fields;
- cfg.threshold = m_pp.threshold;
-
- fil->Configure( &cfg, sizeof TDeinterlacerConfig );
-
- m_fil[m_filc++] = fil;
- }
-
- ///////////////////////
- // prepare resizing
- ///////////////////////
- if( m_pp.bResize || m_pp.doAR )
- {
- // If you are doing aspect ratio
- // and one of the resolutions don't match
- // is the only case where you have to do something
- if( m_pp.doAR==true ||
- m_pp.resWidth != m_pp.nInWidth ||
- m_pp.resHeight!= m_pp.nInHeight )
- {
- FlResize *rs = new FlResize;
-
- TResizeCfg cfg;
-
- cfg.doar = m_pp.doAR ? 1 : 0;
- cfg.idar = m_pp.iDAR;
- cfg.odar = m_pp.outAR&AR_43 ? (3.0/4.0) :
- m_pp.outAR&AR_169 ? (9.0/16.0):
- (double)m_pp.resHeight/(double)m_pp.resWidth;
-
-
- cfg.owidth = m_pp.bResize ? m_pp.resWidth : m_pp.nInWidth;
- cfg.oheight = m_pp.bResize ? m_pp.resHeight : m_pp.nInHeight;
- cfg.method = m_pp.filterMode;
-
- rs->Configure( &cfg, sizeof TResizeCfg );
-
- m_fil[m_filc++] = rs;
- }
- }
-
- //////////////////////
- // Prepare letterboxing
- if(m_pp.letterbox)
- {
- FlLetterbox *fil = new FlLetterbox;
-
- TLetterboxConfig cfg;
-
- cfg.left = m_pp.letterboxLeft;
- cfg.right = m_pp.letterboxRight;
- cfg.top = m_pp.letterboxTop;
- cfg.bottom = m_pp.letterboxBottom;
-
- fil->Configure( &cfg, sizeof TLetterboxConfig );
-
- m_fil[m_filc++] = fil;
- }
-
- ///////////////////////
- // Prepare cropping
- if(m_pp.crop)
- {
- FlCrop *cr = new FlCrop;
-
- TCropConfig cfg;
- cfg.left = m_pp.cropLeftOffset;
- cfg.right = m_pp.cropLeftOffset + m_pp.cropWidth;
-
- cfg.top = m_pp.cropTopOffset;
- cfg.bottom = m_pp.cropTopOffset + m_pp.cropHeight;
- cr->Configure( &cfg, sizeof TCropConfig );
-
- m_fil[m_filc++] = cr;
- }
-
- //////////////////////
- // video controls
- if( m_pp.videocontrols ) {
- FlBrightness *fil = new FlBrightness;
-
- TBrightnessCfg cfg;
-
- cfg.brightness = m_pp.brightness;
- cfg.contrast = m_pp.contrast;
- cfg.hue = m_pp.hue;
-
- fil->Configure( &cfg, sizeof TBrightnessCfg );
-
- m_fil[m_filc++] = fil;
- }
-
- if( Validate() != flfil_ok )
- {
- DBG_STR((str, "PostProcessingStart - Could not validate settings\n"))
- return 0;
- }
-
- return 1;
- }
-
- int FlPostProcess::Validate()
- {
- // validate the filter chain
- flfilter_conf fc, myfs;
- CFrameSource *pInput;
-
- if( !m_pp.nInHeight ||
- !m_pp.nInWidth )
- return flfil_error;
-
- fc.iformat = FRAME_YV12;
- fc.id = 0;
- fc.iw = m_pp.nInWidth;
- fc.ih = m_pp.nInHeight;
- fc.icanmodify = 0;
- fc.iprovided = 1;
- fc.input = this;
- pInput = this;
-
- fc.ocanmodify = 0;
- fc.olag = 0;
- fc.od = fc.id;
- fc.ow = fc.iw;
- fc.oh = fc.ih;
- fc.oprovided = fc.iprovided;
- fc.op = 0;
-
- for( int i=0; i<m_filc; i++ )
- {
- myfs.input = pInput;
- myfs.iprovided = fc.oprovided;
- myfs.iw = fc.ow;
- myfs.ih = fc.oh;
- myfs.id = fc.od;
- myfs.iformat = fc.iformat;
- myfs.icanmodify = fc.ocanmodify;
-
- if(!m_fil[i]->ValFilterConf(&myfs))
- {
- DBG_STR((str, "FlPostProcess::Validate - %d filter validation failed\n", i))
- return flfil_error;
- }
-
- fc.olag += myfs.olag;
- fc.od = myfs.od;
- fc.ow = myfs.ow;
- fc.oh = myfs.oh;
- fc.ocanmodify = myfs.ocanmodify;
- fc.oprovided = myfs.oprovided;
- fc.op = 0;
- pInput = m_fil[i];
- }
-
- m_nWidth = fc.ow;
- m_nHeight = fc.oh;
-
- return flfil_ok;
- }
-
- int FlPostProcess::DestroyChain()
- {
- // delete objects
- for( int i=0; i<m_filc; i++ )
- {
- if( m_fil[i] )
- delete m_fil[i];
- m_fil[i] = 0;
- }
- m_filc = 0;
-
- return 1;
- }