From fee9f0b1615cd833fa1d8a7a0f7807feffd96453 Mon Sep 17 00:00:00 2001 From: Joao Carreira Date: Fri, 27 Jun 2014 05:19:51 +0100 Subject: [PATCH] Add support for modules to use Dock widgets to show the result. Add PSNR measurement as an example --- source/app/ModuleHandleDock.cpp | 97 +++++++++++++++++++++++++++++++++ source/app/ModuleHandleDock.h | 69 +++++++++++++++++++++++ source/app/ModulesHandle.cpp | 47 ++++++++++++++-- source/app/ModulesHandle.h | 10 ++-- source/app/PlaYUVerModuleIf.cpp | 49 ++++++++++++----- source/app/PlaYUVerModuleIf.h | 11 +++- source/modules/MeasurePSNR.cpp | 33 ++++++++--- source/modules/MeasurePSNR.h | 3 +- 8 files changed, 284 insertions(+), 35 deletions(-) create mode 100644 source/app/ModuleHandleDock.cpp create mode 100644 source/app/ModuleHandleDock.h diff --git a/source/app/ModuleHandleDock.cpp b/source/app/ModuleHandleDock.cpp new file mode 100644 index 0000000..7f80c04 --- /dev/null +++ b/source/app/ModuleHandleDock.cpp @@ -0,0 +1,97 @@ +/* This file is a part of plaYUVer project + * Copyright (C) 2014 by Luis Lucas (luisfrlucas@gmail.com) + * Joao Carreira (jfmcarreira@gmail.com) + * + * This program 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 of the License, or + * (at your option) any later version. + * + * This program 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 this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +/** + * \file ModuleHandleDock.cpp + * \brief Module handle dock + */ + +#include +#include "ModuleHandleDock.h" +#include "PlaYUVerModuleIf.h" +#include "ModulesHandle.h" + +namespace plaYUVer +{ + +ModuleHandleDock::ModuleHandleDock( QWidget* parent, PlaYUVerModuleIf* moduleIf ) : + QWidget( parent ), + m_pcCurrModuleIf( moduleIf ) +{ + + PlaYUVerModuleDefinition ModuleDef = moduleIf->getModuleDefinition(); + + // ----------------- Dock definition ----------------- + + QString labelStr; + labelStr.append( ModuleDef.m_pchModuleName ); + labelStr.append( " Result:" ); + labelModulueValueLabel = new QLabel( labelStr ); + labelModulueValueLabel->setAlignment( Qt::AlignLeft | Qt::AlignVCenter ); + + labelModulueReturnValue = new QLabel; + labelModulueReturnValue->setAlignment( Qt::AlignRight | Qt::AlignVCenter ); + + QGridLayout *modulesPropertiesLayout = new QGridLayout; + Int layout_line = 0; + modulesPropertiesLayout->addWidget( labelModulueValueLabel, layout_line, 0 ); + modulesPropertiesLayout->addWidget( labelModulueReturnValue, layout_line, 1 ); + layout_line++; + + modulesPropertiesLayout->setRowStretch( 8, 10 ); + setLayout( modulesPropertiesLayout ); + + setEnabled( true ); + +} + +ModuleHandleDock::~ModuleHandleDock() +{ + +} + +Void ModuleHandleDock::setModulueReturnValue( Double value ) +{ + labelModulueReturnValue->clear(); + QString strValue = QString( "%1" ).arg( value ); + labelModulueReturnValue->setText( strValue ); +} + +Void ModuleHandleDock::visibilityChangedSlot( bool visiblity ) +{ + if( !visiblity && m_pcCurrModuleIf ) + { + PlaYUVerModuleIf* pcCurrentModule = m_pcCurrModuleIf; + m_pcCurrModuleIf = NULL; + ModulesHandle::destroyModuleIf( pcCurrentModule ); + } +} + +QSize ModuleHandleDock::sizeHint() const +{ + QSize currSize = size(); + QSize bestSize( 180, currSize.height() ); + if( currSize.width() < bestSize.width() ) + return bestSize; + else + return currSize; +} + +} // NAMESPACE + diff --git a/source/app/ModuleHandleDock.h b/source/app/ModuleHandleDock.h new file mode 100644 index 0000000..72010bb --- /dev/null +++ b/source/app/ModuleHandleDock.h @@ -0,0 +1,69 @@ +/* This file is a part of plaYUVer project + * Copyright (C) 2014 by Luis Lucas (luisfrlucas@gmail.com) + * Joao Carreira (jfmcarreira@gmail.com) + * + * This program 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 of the License, or + * (at your option) any later version. + * + * This program 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 this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +/** + * \file ModuleHandleDock.h + * \brief Module handle dock + */ + +#ifndef __MODULEHANDLEDOCK_H__ +#define __MODULEHANDLEDOCK_H__ + +#include "config.h" +#include "PlaYUVerDefs.h" +#if( QT_VERSION_PLAYUVER == 5 ) +#include +#elif( QT_VERSION_PLAYUVER == 4 ) +#include +#include +#endif + + +namespace plaYUVer +{ + +class PlaYUVerModuleIf; + +class ModuleHandleDock: public QWidget +{ +Q_OBJECT +public: + ModuleHandleDock( QWidget* parent, PlaYUVerModuleIf* moduleIf ); + ~ModuleHandleDock(); + + Void setModulueReturnValue( Double value ); + + QSize sizeHint() const; + +private: + + PlaYUVerModuleIf* m_pcCurrModuleIf; + + Bool m_bIsVisible; + QLabel* labelModulueValueLabel; + QLabel* labelModulueReturnValue; + +public Q_SLOTS: + void visibilityChangedSlot( bool ); + +}; + +} // NAMESPACE + +#endif // __MODULEHANDLEDOCK_H__ diff --git a/source/app/ModulesHandle.cpp b/source/app/ModulesHandle.cpp index 6e968f9..a57a43f 100644 --- a/source/app/ModulesHandle.cpp +++ b/source/app/ModulesHandle.cpp @@ -33,7 +33,7 @@ namespace plaYUVer { -ModulesHandle::ModulesHandle( QWidget * parent, QMdiArea *mdiArea ) : +ModulesHandle::ModulesHandle( QMainWindow * parent, QMdiArea *mdiArea ) : QObject( parent ), m_pcParent( parent ), m_pcMdiArea( mdiArea ), @@ -157,7 +157,18 @@ SubWindowHandle* ModulesHandle::enableModuleIf( PlaYUVerModuleIf *pcCurrModuleIf { if( pcCurrModuleIf->m_cModuleDef.m_uiModuleRequirements & MODULE_REQUIRES_SIDEBAR ) { - pcCurrModuleIf->m_pcModuleDock = new ModuleHandleDock( m_pcParent ); + pcCurrModuleIf->m_pcModuleDock = new ModuleHandleDock( m_pcParent, pcCurrModuleIf ); + QString titleDockWidget; + titleDockWidget.append( pcCurrModuleIf->m_cModuleDef.m_pchModuleName ); + titleDockWidget.append( " Information" ); + pcCurrModuleIf->m_pcDockWidget = new QDockWidget( titleDockWidget, m_pcParent ); + pcCurrModuleIf->m_pcDockWidget->setAllowedAreas( Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea ); + pcCurrModuleIf->m_pcDockWidget->setWidget( pcCurrModuleIf->m_pcModuleDock ); + pcCurrModuleIf->m_pcDockWidget->setAttribute( Qt::WA_DeleteOnClose ); + pcCurrModuleIf->m_pcDockWidget->setTitleBarWidget( 0 ); + m_pcParent->addDockWidget( Qt::RightDockWidgetArea, pcCurrModuleIf->m_pcDockWidget ); + + connect( pcCurrModuleIf->m_pcDockWidget, SIGNAL( visibilityChanged(bool) ), pcCurrModuleIf->m_pcModuleDock, SLOT( visibilityChangedSlot(bool) ) ); } } @@ -176,7 +187,16 @@ SubWindowHandle* ModulesHandle::enableModuleIf( PlaYUVerModuleIf *pcCurrModuleIf Void ModulesHandle::destroyModuleIf( PlaYUVerModuleIf *pcCurrModuleIf ) { - pcCurrModuleIf->m_pcAction->setChecked( false ); + if( pcCurrModuleIf->m_pcModuleDock ) + { + pcCurrModuleIf->m_pcModuleDock->close(); + pcCurrModuleIf->m_pcModuleDock = NULL; + } + if( pcCurrModuleIf->m_pcDockWidget ) + { + pcCurrModuleIf->m_pcDockWidget->close(); + pcCurrModuleIf->m_pcDockWidget = NULL; + } if( pcCurrModuleIf->m_pcDisplaySubWindow ) pcCurrModuleIf->m_pcDisplaySubWindow->close(); pcCurrModuleIf->m_pcDisplaySubWindow = NULL; @@ -189,6 +209,7 @@ Void ModulesHandle::destroyModuleIf( PlaYUVerModuleIf *pcCurrModuleIf ) pcCurrModuleIf->m_pcSubWindow[i] = NULL; } } + pcCurrModuleIf->m_pcAction->setChecked( false ); pcCurrModuleIf->destroy(); } @@ -212,10 +233,11 @@ Bool ModulesHandle::applyModuleIf( PlaYUVerModuleIf *pcCurrModuleIf, Bool isPlay #endif pcCurrModuleIf->run(); - if( pcCurrModuleIf->m_pcDisplaySubWindow ) + if( pcCurrModuleIf->m_pcDisplaySubWindow || pcCurrModuleIf->m_cModuleDef.m_iModuleType == FRAME_MEASUREMENT_MODULE ) { bRet = true; } + } else { @@ -319,6 +341,13 @@ Bool ModulesHandle::showModuleIf( PlaYUVerModuleIf *pcCurrModuleIf, PlaYUVerFram return bRet; } +Bool ModulesHandle::showModuleIf( PlaYUVerModuleIf *pcCurrModuleIf, Double moduleResult ) +{ + Bool bRet = false; + pcCurrModuleIf->m_pcModuleDock->setModulueReturnValue(moduleResult); + return bRet; +} + Void ModulesHandle::swapModulesWindowsIf( PlaYUVerModuleIf *pcCurrModuleIf ) { if( pcCurrModuleIf->m_cModuleDef.m_uiNumberOfFrames == MODULE_REQUIRES_TWO_FRAMES ) @@ -338,7 +367,15 @@ Void ModulesHandle::customEvent( QEvent *event ) PlaYUVerModuleIf::EventData *eventData = ( PlaYUVerModuleIf::EventData* )event; if( eventData->m_bSuccess ) { - showModuleIf( eventData->m_pcModule, eventData->m_pcProcessedFrame ); + switch( eventData->m_pcModule->m_cModuleDef.m_iModuleType ) + { + case FRAME_PROCESSING_MODULE: + showModuleIf( eventData->m_pcModule, eventData->m_pcProcessedFrame ); + break; + case FRAME_MEASUREMENT_MODULE: + showModuleIf( eventData->m_pcModule, eventData->m_dMeasurementResult ); + break; + } } } diff --git a/source/app/ModulesHandle.h b/source/app/ModulesHandle.h index 161b800..d65238d 100644 --- a/source/app/ModulesHandle.h +++ b/source/app/ModulesHandle.h @@ -36,19 +36,20 @@ #elif( QT_VERSION_PLAYUVER == 4 ) #include #endif - #include "PlaYUVerModuleIf.h" +#include "PlaYUVerFrame.h" namespace plaYUVer { +class PlaYUVerModuleIf; class SubWindowHandle; class ModulesHandle: public QObject { Q_OBJECT public: - ModulesHandle( QWidget * parent = 0, QMdiArea *mdiArea = 0 ); + ModulesHandle( QMainWindow* parent = 0, QMdiArea *mdiArea = 0 ); ~ModulesHandle(); QMenu* createMenus( QMenuBar* MainAppMenuBar ); @@ -59,11 +60,11 @@ public: static Bool applyModuleIf( PlaYUVerModuleIf* pcCurrModuleIf, Bool isPlaying, Bool disableThreads = false ); static Void swapModulesWindowsIf( PlaYUVerModuleIf *pcCurrModuleIf ); static Bool showModuleIf( PlaYUVerModuleIf *pcCurrModuleIf, PlaYUVerFrame* processedFrame ); - + static Bool showModuleIf( PlaYUVerModuleIf *pcCurrModuleIf, Double moduleResult ); static Void applyAllModuleIf( PlaYUVerModuleIf* pcCurrModuleIf ); private: - QWidget *m_pcParent; + QMainWindow *m_pcParent; QMdiArea *m_pcMdiArea; UInt m_uiModulesCount; Int m_iOptionSelected; @@ -101,6 +102,7 @@ private: private Q_SLOTS: void selectModule( int index ); void destroyAllModulesIf(); + }; } // NAMESPACE diff --git a/source/app/PlaYUVerModuleIf.cpp b/source/app/PlaYUVerModuleIf.cpp index 48ca425..f212863 100644 --- a/source/app/PlaYUVerModuleIf.cpp +++ b/source/app/PlaYUVerModuleIf.cpp @@ -31,6 +31,7 @@ namespace plaYUVer PlaYUVerModuleIf::PlaYUVerModuleIf() : m_pcAction( NULL ), m_pcDisplaySubWindow( NULL ), + m_pcDockWidget( NULL ), m_pcModuleDock( NULL ), m_pcModuleStream( NULL ), m_pcProcessedFrame( NULL ) @@ -43,28 +44,50 @@ PlaYUVerModuleIf::PlaYUVerModuleIf() : void PlaYUVerModuleIf::run() { - switch( m_cModuleDef.m_uiNumberOfFrames ) + m_pcProcessedFrame = NULL; + m_dMeasurementResult = 0; + + if( m_cModuleDef.m_iModuleType == FRAME_PROCESSING_MODULE ) { - case MODULE_REQUIRES_ONE_FRAME: - m_pcProcessedFrame = process( m_pcSubWindow[0]->getCurrFrame() ); - break; - case MODULE_REQUIRES_TWO_FRAMES: - m_pcProcessedFrame = process( m_pcSubWindow[0]->getCurrFrame(), m_pcSubWindow[1]->getCurrFrame() ); - break; - case MODULE_REQUIRES_THREE_FRAMES: - m_pcProcessedFrame = process( m_pcSubWindow[0]->getCurrFrame(), m_pcSubWindow[1]->getCurrFrame(), m_pcSubWindow[2]->getCurrFrame() ); - break; + switch( m_cModuleDef.m_uiNumberOfFrames ) + { + case MODULE_REQUIRES_ONE_FRAME: + m_pcProcessedFrame = process( m_pcSubWindow[0]->getCurrFrame() ); + break; + case MODULE_REQUIRES_TWO_FRAMES: + m_pcProcessedFrame = process( m_pcSubWindow[0]->getCurrFrame(), m_pcSubWindow[1]->getCurrFrame() ); + break; + case MODULE_REQUIRES_THREE_FRAMES: + m_pcProcessedFrame = process( m_pcSubWindow[0]->getCurrFrame(), m_pcSubWindow[1]->getCurrFrame(), m_pcSubWindow[2]->getCurrFrame() ); + break; + } } - postProgress( true, m_pcProcessedFrame ); + else if( m_cModuleDef.m_iModuleType == FRAME_MEASUREMENT_MODULE ) + { + switch( m_cModuleDef.m_uiNumberOfFrames ) + { + case MODULE_REQUIRES_ONE_FRAME: + m_dMeasurementResult = measure( m_pcSubWindow[0]->getCurrFrame() ); + break; + case MODULE_REQUIRES_TWO_FRAMES: + m_dMeasurementResult = measure( m_pcSubWindow[0]->getCurrFrame(), m_pcSubWindow[1]->getCurrFrame() ); + break; + case MODULE_REQUIRES_THREE_FRAMES: + m_dMeasurementResult = measure( m_pcSubWindow[0]->getCurrFrame(), m_pcSubWindow[1]->getCurrFrame(), m_pcSubWindow[2]->getCurrFrame() ); + break; + } + } + postProgress( true, m_pcProcessedFrame, m_dMeasurementResult ); } -Void PlaYUVerModuleIf::postProgress( Bool success, PlaYUVerFrame* pcProcessedFrame ) +Void PlaYUVerModuleIf::postProgress( Bool success, PlaYUVerFrame* pcProcessedFrame, Double moduleResult ) { EventData *eventData = new EventData(); eventData->m_bSuccess = success; eventData->m_pcProcessedFrame = pcProcessedFrame; + eventData->m_dMeasurementResult = moduleResult; eventData->m_pcModule = this; - if( parent() && pcProcessedFrame ) + if( parent() && ( pcProcessedFrame || moduleResult ) ) QCoreApplication::postEvent( parent(), eventData ); } diff --git a/source/app/PlaYUVerModuleIf.h b/source/app/PlaYUVerModuleIf.h index 1eaceee..f897527 100644 --- a/source/app/PlaYUVerModuleIf.h +++ b/source/app/PlaYUVerModuleIf.h @@ -98,14 +98,17 @@ private: SubWindowHandle* m_pcSubWindow[MAX_NUMBER_FRAMES]; SubWindowHandle* m_pcDisplaySubWindow; + + QDockWidget* m_pcDockWidget; ModuleHandleDock* m_pcModuleDock; PlaYUVerModuleDefinition m_cModuleDef; PlaYUVerStream* m_pcModuleStream; PlaYUVerFrame* m_pcProcessedFrame; + Double m_dMeasurementResult; - Void postProgress( Bool success, PlaYUVerFrame* pcProcessedFrame ); + Void postProgress( Bool success, PlaYUVerFrame* pcProcessedFrame, Double moduleResult ); public: class EventData: public QEvent { @@ -115,10 +118,12 @@ public: { m_bSuccess = false; m_pcProcessedFrame = NULL; + m_dMeasurementResult = 0; m_pcModule = NULL; } Bool m_bSuccess; PlaYUVerFrame* m_pcProcessedFrame; + Double m_dMeasurementResult; PlaYUVerModuleIf* m_pcModule; }; @@ -139,8 +144,8 @@ public: virtual Void destroy() { } - Void setModuleDefinition( PlaYUVerModuleDefinition def ) { m_cModuleDef = def; } - + Void setModuleDefinition( PlaYUVerModuleDefinition def ) { m_cModuleDef = def; } + PlaYUVerModuleDefinition getModuleDefinition() { return m_cModuleDef; } protected: virtual void run(); }; diff --git a/source/modules/MeasurePSNR.cpp b/source/modules/MeasurePSNR.cpp index d344c5b..e69d4bf 100644 --- a/source/modules/MeasurePSNR.cpp +++ b/source/modules/MeasurePSNR.cpp @@ -34,12 +34,11 @@ static PlaYUVerModuleDefinition MeasurePSNRDef = { FRAME_MEASUREMENT_MODULE, "Quality", - "PSNR", + "PSNR Y", "Measure the PSNR between two images", MODULE_REQUIRES_TWO_FRAMES, MODULE_REQUIRES_SIDEBAR, - APPLY_WHILE_PLAYING, -}; + APPLY_WHILE_PLAYING, }; MeasurePSNR::MeasurePSNR() { @@ -50,23 +49,39 @@ Void MeasurePSNR::create( PlaYUVerFrame* Org ) { } -Double MeasurePSNR::measure( PlaYUVerFrame* Org, PlaYUVerFrame* Rec ) +Double MeasurePSNR::getMSE( PlaYUVerFrame* Org, PlaYUVerFrame* Rec, Int component ) { - Pel* pInput1PelYUV = Org->getPelBufferYUV()[0][0]; - Pel* pInput2PelYUV = Rec->getPelBufferYUV()[0][0]; + Pel* pInput1PelYUV = Org->getPelBufferYUV()[component][0]; + Pel* pInput2PelYUV = Rec->getPelBufferYUV()[component][0]; Int aux_pel_1, aux_pel_2; - Double diff = 0; + Int diff = 0; + Double ssd = 0; for( UInt y = 0; y < Org->getHeight(); y++ ) for( UInt x = 0; x < Org->getWidth(); x++ ) { aux_pel_1 = *pInput1PelYUV++; aux_pel_2 = *pInput2PelYUV++; - diff += abs( aux_pel_1 - aux_pel_2 ); + diff = aux_pel_1 - aux_pel_2; + ssd += ( Double )( diff * diff ); } + if( ssd == 0.0 ) + { + return 0.0; + } + return ssd / ( Org->getWidth() * Org->getHeight() ); +} - return diff; +Double MeasurePSNR::measure( PlaYUVerFrame* Org, PlaYUVerFrame* Rec ) +{ + Double psnrY = 100; + Double mseY = MeasurePSNR::getMSE( Org, Rec, LUMA ); + + if( mseY != 0 ) + psnrY = 10 * log10( 65025 / mseY ); + + return psnrY; } Void MeasurePSNR::destroy() diff --git a/source/modules/MeasurePSNR.h b/source/modules/MeasurePSNR.h index 84c5fc7..9224a87 100644 --- a/source/modules/MeasurePSNR.h +++ b/source/modules/MeasurePSNR.h @@ -40,7 +40,6 @@ namespace plaYUVer class MeasurePSNR: public PlaYUVerModuleIf { private: - public: MeasurePSNR(); virtual ~MeasurePSNR() @@ -50,6 +49,8 @@ public: Double measure( PlaYUVerFrame*, PlaYUVerFrame* ); Void destroy(); + static Double getMSE( PlaYUVerFrame* Org, PlaYUVerFrame* Rec, Int component ); + }; } // NAMESPACE