diff --git a/app/CalypAppModuleIf.cpp b/app/CalypAppModuleIf.cpp index 3252066..7af6e18 100644 --- a/app/CalypAppModuleIf.cpp +++ b/app/CalypAppModuleIf.cpp @@ -125,7 +125,7 @@ void CalypAppModuleIf::run() if( m_pcModule->m_iModuleType == CLP_FRAME_PROCESSING_MODULE ) { - if( m_pcModule->m_iModuleAPI == CLP_MODULE_API_2 ) + if( m_pcModule->m_iModuleAPI >= CLP_MODULE_API_2 ) { m_pcProcessedFrame = m_pcModule->process( apcFrameList ); } @@ -136,7 +136,7 @@ void CalypAppModuleIf::run() } else if( m_pcModule->m_iModuleType == CLP_FRAME_MEASUREMENT_MODULE ) { - if( m_pcModule->m_iModuleAPI == CLP_MODULE_API_2 ) + if( m_pcModule->m_iModuleAPI >= CLP_MODULE_API_2 ) { m_dMeasurementResult = m_pcModule->measure( apcFrameList ); } diff --git a/app/ModulesHandle.cpp b/app/ModulesHandle.cpp index 582c21a..ed37fd5 100644 --- a/app/ModulesHandle.cpp +++ b/app/ModulesHandle.cpp @@ -422,7 +422,7 @@ void ModulesHandle::activateModule() // Create Module bool moduleCreated = false; - if( pcCurrAppModuleIf->m_pcModule->m_iModuleAPI == CLP_MODULE_API_2 ) + if( pcCurrAppModuleIf->m_pcModule->m_iModuleAPI >= CLP_MODULE_API_2 ) { std::vector apcFrameList; for( int i = 0; i < videoSubWindowList.size(); i++ ) diff --git a/lib/CalypFrame.cpp b/lib/CalypFrame.cpp index 829b256..93c1610 100644 --- a/lib/CalypFrame.cpp +++ b/lib/CalypFrame.cpp @@ -514,7 +514,7 @@ void CalypFrame::setPixel( unsigned int xPos, unsigned int yPos, CalypPixel pixe void CalypFrame::copyFrom( const CalypFrame& other ) { - if( haveSameFmt( other, MATCH_ALL ) ) + if( !haveSameFmt( other, MATCH_ALL ) ) return; d->m_bHasRGBPel = false; d->m_bHasHistogram = false; @@ -529,7 +529,7 @@ void CalypFrame::copyFrom( const CalypFrame* other ) void CalypFrame::copyFrom( const CalypFrame& other, unsigned int xPos, unsigned int yPos ) { - if( haveSameFmt( other, MATCH_ALL ) ) + if( !haveSameFmt( other, MATCH_COLOR_SPACE | MATCH_PEL_FMT | MATCH_BITS ) ) return; ClpPel*** pInput = other.getPelBufferYUV(); for( unsigned int ch = 0; ch < d->m_pcPelFormat->numberChannels; ch++ ) diff --git a/lib/CalypModuleIf.h b/lib/CalypModuleIf.h index 9cb5d2c..2120a9e 100644 --- a/lib/CalypModuleIf.h +++ b/lib/CalypModuleIf.h @@ -50,6 +50,11 @@ public: \ if( !apcFrameList[i] ) \ return false; +#define _BASIC_MODULE_API_3_BREAK_CONDITION_ \ + if( m_iFrameBufferCount == 0 ) \ + if( apcFrameList.size() <= 0 ) \ + return NULL; + /** Module_API_Version Enum * \ingroup Calyp_Modules * Version of the modules API required @@ -59,6 +64,7 @@ enum Module_API_Version { CLP_MODULE_API_1, CLP_MODULE_API_2, + CLP_MODULE_API_3, }; /** Module_Type Enum @@ -118,6 +124,8 @@ public: //! Features/Requirements unsigned int m_uiModuleRequirements; + unsigned int m_iFrameBufferCount; + CalypOptions m_cModuleOptions; CalypModuleIf() @@ -149,6 +157,9 @@ public: virtual double measure( std::vector ) { return 0; } virtual bool keyPressed( enum Module_Key_Supported ) { return false; } virtual ClpString moduleInfo() { return ClpString(); } + + virtual bool needFrame() { return true; }; + virtual bool flush() { return false; }; }; #endif // __CALYPMODULESIF_H__ diff --git a/modules/CMakeLists.txt b/modules/CMakeLists.txt index b427985..f033136 100644 --- a/modules/CMakeLists.txt +++ b/modules/CMakeLists.txt @@ -30,6 +30,7 @@ ADD_MODULE( FrameCrop "FrameCrop" ) ADD_MODULE( LumaAverage "LumaAverage" ) ADD_MODULE( WeightedPSNR "WeightedPSNR" ) ADD_MODULE( HEVCIntraPrediction "HEVCIntraPrediction" ) +ADD_MODULE( ThreeSixtySpatialtoTemporal "ThreeSixtySpatialtoTemporal" ) ADD_MODULE_USE_OPENCV( MeasureOpticalFlowDualTVL1 "MeasureOpticalFlowDualTVL1" VERSION 2.4.13.0 MODULES video ) ADD_MODULE_USE_OPENCV( DisparityStereoBM "DisparityStereoBM" VERSION 2.4.13.0 MODULES calib3d ) diff --git a/modules/ThreeSixtySpatialtoTemporal.cpp b/modules/ThreeSixtySpatialtoTemporal.cpp new file mode 100644 index 0000000..3b0e56f --- /dev/null +++ b/modules/ThreeSixtySpatialtoTemporal.cpp @@ -0,0 +1,116 @@ +/* This file is a part of Calyp project + * Copyright (C) 2014-2019 by Joao Carreira (jfmcarreira@gmail.com) + * Luis Lucas (luisfrlucas@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 FrameRotate.cpp + * \brief Frame Difference module + */ + +#include "ThreeSixtySpatialtoTemporal.h" + +ThreeSixtySpatialtoTemporal::ThreeSixtySpatialtoTemporal() +{ + /* Module Definition */ + m_iModuleAPI = CLP_MODULE_API_3; + m_iModuleType = CLP_FRAME_PROCESSING_MODULE; + m_pchModuleCategory = "360Video"; + m_pchModuleLongName = "Spatial to Temporal"; + m_pchModuleName = "SpatialtoTemporal"; + m_pchModuleTooltip = "Convert 360 video from Cube Map Projection to temporal frames"; + m_uiNumberOfFrames = 1; + m_uiModuleRequirements = CLP_MODULE_REQUIRES_SKIP_WHILE_PLAY; + + m_pcFrameProcessed = NULL; + + uiFacesX = 3; + uiFacesY = 2; + + flush(); +} + +bool ThreeSixtySpatialtoTemporal::flush() +{ + m_iFrameBufferCount = 0; + uiCopyX = 0; + uiCopyY = 0; + return true; +}; + +bool ThreeSixtySpatialtoTemporal::needFrame() +{ + if( m_iFrameBufferCount == 0 ) + { + return true; + } + return false; +}; + +bool ThreeSixtySpatialtoTemporal::create( std::vector apcFrameList ) +{ + _BASIC_MODULE_API_2_CHECK_ + + unsigned int iWidth; + unsigned int iHeight; + + iWidth = apcFrameList[0]->getWidth() / uiFacesX; + iHeight = apcFrameList[0]->getHeight() / uiFacesY; + + m_pcFrameProcessed = new CalypFrame( iWidth, iHeight, apcFrameList[0]->getPelFormat(), + apcFrameList[0]->getBitsPel() ); + + m_pcTmpFrame = new CalypFrame( apcFrameList[0]->getWidth(), apcFrameList[0]->getHeight(), apcFrameList[0]->getPelFormat(), + apcFrameList[0]->getBitsPel() ); + return true; +} + +CalypFrame* ThreeSixtySpatialtoTemporal::process( std::vector apcFrameList ) +{ + _BASIC_MODULE_API_3_BREAK_CONDITION_ + + if( m_iFrameBufferCount == 0 ) + { + m_pcTmpFrame->copyFrom( apcFrameList[0] ); + uiCopyX = 0; + uiCopyY = 0; + + m_iFrameBufferCount = uiFacesX * uiFacesY; + } + + m_pcFrameProcessed->copyFrom( m_pcTmpFrame, uiCopyX, uiCopyY ); + m_iFrameBufferCount--; + + uiCopyX += m_pcFrameProcessed->getWidth(); + if( uiCopyX >= m_pcTmpFrame->getWidth() ) + { + uiCopyX = 0; + uiCopyY += m_pcFrameProcessed->getHeight(); + } + + return m_pcFrameProcessed; +} + +void ThreeSixtySpatialtoTemporal::destroy() +{ + if( m_pcFrameProcessed ) + delete m_pcFrameProcessed; + m_pcFrameProcessed = NULL; + if( m_pcTmpFrame ) + delete m_pcTmpFrame; + m_pcTmpFrame = NULL; +} diff --git a/modules/ThreeSixtySpatialtoTemporal.h b/modules/ThreeSixtySpatialtoTemporal.h new file mode 100644 index 0000000..ab4f42b --- /dev/null +++ b/modules/ThreeSixtySpatialtoTemporal.h @@ -0,0 +1,53 @@ +/* This file is a part of Calyp project + * Copyright (C) 2014-2019 by Joao Carreira (jfmcarreira@gmail.com) + * Luis Lucas (luisfrlucas@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 FrameRotate.h + * \brief Module to aapply a mask to an image + */ + +#ifndef __THREESIXTYSPATIALTOTEMPORAL_H__ +#define __THREESIXTYSPATIALTOTEMPORAL_H__ + +// CalypLib +#include "lib/CalypModuleIf.h" + +class ThreeSixtySpatialtoTemporal : public CalypModuleIf +{ + REGISTER_CLASS_FACTORY( ThreeSixtySpatialtoTemporal ) + +private: + CalypFrame* m_pcFrameProcessed; + CalypFrame* m_pcTmpFrame; + unsigned int uiFacesX; + unsigned int uiFacesY; + unsigned int uiCopyX; + unsigned int uiCopyY; + +public: + ThreeSixtySpatialtoTemporal(); + virtual ~ThreeSixtySpatialtoTemporal() {} + bool create( std::vector apcFrameList ); + bool needFrame(); + CalypFrame* process( std::vector apcFrameList ); + bool flush(); + void destroy(); +}; + +#endif // __THREESIXTYSPATIALTOTEMPORAL_H__ diff --git a/tools/CalypTools.cpp b/tools/CalypTools.cpp index 188c35b..dd2eb33 100644 --- a/tools/CalypTools.cpp +++ b/tools/CalypTools.cpp @@ -313,7 +313,7 @@ int CalypTools::Open( int argc, char* argv[] ) { apcFrameList.push_back( m_apcInputStreams[i]->getCurrFrame() ); } - if( m_pcCurrModuleIf->m_iModuleAPI == CLP_MODULE_API_2 ) + if( m_pcCurrModuleIf->m_iModuleAPI >= CLP_MODULE_API_2 ) { moduleCreated = m_pcCurrModuleIf->create( apcFrameList ); } @@ -338,13 +338,14 @@ int CalypTools::Open( int argc, char* argv[] ) if( outputFileNames.size() == 1 ) { CalypFrame* pcModFrame; - if( m_pcCurrModuleIf->m_iModuleAPI == CLP_MODULE_API_2 ) + if( m_pcCurrModuleIf->m_iModuleAPI >= CLP_MODULE_API_2 ) { pcModFrame = m_pcCurrModuleIf->process( apcFrameList ); + m_pcCurrModuleIf->flush(); } else { - pcModFrame = applyFrameModule(); + pcModFrame = m_pcCurrModuleIf->process( m_apcInputStreams[0]->getCurrFrame() ); } CalypStream* pcModStream = new CalypStream; try @@ -520,73 +521,100 @@ int CalypTools::QualityOperation() return 0; } -CalypFrame* CalypTools::applyFrameModule() +//CalypFrame* CalypTools::applyFrameModule() +//{ +// CalypFrame* pcProcessedFrame = NULL; +// if( m_pcCurrModuleIf->m_iModuleType == CLP_FRAME_PROCESSING_MODULE ) +// { + +// } +// return pcProcessedFrame; +//} + +std::vector CalypTools::readInput() { - CalypFrame* pcProcessedFrame = NULL; - if( m_pcCurrModuleIf->m_iModuleType == CLP_FRAME_PROCESSING_MODULE ) + std::vector apcFrameList; + apcFrameList.clear(); + // Check EOF and read next frame + bool abEOF[MAX_NUMBER_INPUTS]; + for( unsigned int s = 0; s < m_apcInputStreams.size(); s++ ) { - pcProcessedFrame = m_pcCurrModuleIf->process( m_apcInputStreams[0]->getCurrFrame() ); + abEOF[s] = m_apcInputStreams[s]->setNextFrame(); + if( abEOF[s] ) + { + return apcFrameList; + } + m_apcInputStreams[s]->readNextFrame(); } - return pcProcessedFrame; + for( unsigned int i = 0; i < m_pcCurrModuleIf->m_uiNumberOfFrames; i++ ) + { + apcFrameList.push_back( m_apcInputStreams[i]->getCurrFrame() ); + } + return apcFrameList; } int CalypTools::ModuleOperation() { - std::vector apcFrameList; log( CLP_LOG_INFO, " Applying Module %s/%s ...\n", m_pcCurrModuleIf->m_pchModuleCategory, m_pcCurrModuleIf->m_pchModuleName ); CalypFrame* pcProcessedFrame = NULL; double dMeasurementResult = 0.0; double dAveragedMeasurementResult = 0; - bool abEOF[MAX_NUMBER_INPUTS]; - for( unsigned int s = 0; s < m_apcInputStreams.size(); s++ ) + std::vector apcFrameList; + for( unsigned int i = 0; i < m_pcCurrModuleIf->m_uiNumberOfFrames; i++ ) { - abEOF[s] = false; + apcFrameList.push_back( m_apcInputStreams[i]->getCurrFrame() ); } for( unsigned int frame = 0; frame < m_uiNumberOfFrames; frame++ ) { - apcFrameList.clear(); - for( unsigned int i = 0; i < m_pcCurrModuleIf->m_uiNumberOfFrames; i++ ) + bool bReadFrame = true; + if( apcFrameList.size() == 0 ) { - apcFrameList.push_back( m_apcInputStreams[i]->getCurrFrame() ); + break; } if( m_pcCurrModuleIf->m_iModuleType == CLP_FRAME_PROCESSING_MODULE ) { - if( m_pcCurrModuleIf->m_iModuleAPI == CLP_MODULE_API_2 ) - { + if( m_pcCurrModuleIf->m_iModuleAPI >= CLP_MODULE_API_2 ) pcProcessedFrame = m_pcCurrModuleIf->process( apcFrameList ); - } else - { - pcProcessedFrame = applyFrameModule(); - } - m_apcOutputStreams[0]->writeFrame( pcProcessedFrame ); + pcProcessedFrame = m_pcCurrModuleIf->process( m_apcInputStreams[0]->getCurrFrame() ); + + if( pcProcessedFrame ) + m_apcOutputStreams[0]->writeFrame( pcProcessedFrame ); } else if( m_pcCurrModuleIf->m_iModuleType == CLP_FRAME_MEASUREMENT_MODULE ) { - if( m_pcCurrModuleIf->m_iModuleAPI == CLP_MODULE_API_2 ) - { + if( m_pcCurrModuleIf->m_iModuleAPI >= CLP_MODULE_API_2 ) dMeasurementResult = m_pcCurrModuleIf->measure( apcFrameList ); - } else - { dMeasurementResult = m_pcCurrModuleIf->measure( m_apcInputStreams[0]->getCurrFrame() ); - } log( CLP_LOG_INFO, " %3d", frame ); log( CLP_LOG_RESULT, " %8.3f \n", dMeasurementResult ); dAveragedMeasurementResult = ( dAveragedMeasurementResult * double( frame ) + dMeasurementResult ) / double( frame + 1 ); } - - for( unsigned int s = 0; s < m_apcInputStreams.size(); s++ ) + apcFrameList.clear(); + if( m_pcCurrModuleIf->m_iModuleAPI == CLP_MODULE_API_3 ) { - abEOF[s] = m_apcInputStreams[s]->setNextFrame(); - if( !abEOF[s] ) + bReadFrame = m_pcCurrModuleIf->needFrame(); + } + if( bReadFrame ) + apcFrameList = readInput(); + } + + if( m_pcCurrModuleIf->m_iModuleAPI >= CLP_MODULE_API_3 ) + { + while( true ) + { + if( m_pcCurrModuleIf->m_iModuleType == CLP_FRAME_PROCESSING_MODULE ) { - m_apcInputStreams[s]->readNextFrame(); + pcProcessedFrame = m_pcCurrModuleIf->process( apcFrameList ); + if( !pcProcessedFrame ) + break; + m_apcOutputStreams[0]->writeFrame( pcProcessedFrame ); } } } diff --git a/tools/CalypTools.h b/tools/CalypTools.h index 40aef81..52433ad 100644 --- a/tools/CalypTools.h +++ b/tools/CalypTools.h @@ -84,6 +84,7 @@ private: std::vector m_apcOutputStreams; int openInputs(); + std::vector readInput(); typedef int ( CalypTools::*FpProcess )(); FpProcess m_fpProcess; @@ -98,7 +99,7 @@ private: int QualityOperation(); CalypModuleIf* m_pcCurrModuleIf; - CalypFrame* applyFrameModule(); + //CalypFrame* applyFrameModule(); int ModuleOperation(); };