diff --git a/CMakeLists.txt b/CMakeLists.txt index 545c6b5..f7659a7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,7 +17,7 @@ SET( PLAYUVER_VERSION_PATCH "1" ) SET( PLAYUVER_VERSION "${PLAYUVER_VERSION_MAJOR}.${PLAYUVER_VERSION_MINOR}.${PLAYUVER_VERSION_PATCH}") ###################################################################################### -# CMake Definitions +# CMake Defin1itions ###################################################################################### SET(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake ) @@ -30,62 +30,23 @@ IF(DEFINED CMAKE_BUILD_TYPE AND CMAKE_VERSION VERSION_GREATER "2.8") ENDIF() SET( CMAKE_CXX_FLAGS "" ) - ###################################################################################### # Variables ###################################################################################### -OPTION( USE_FERVOR "Add Fervor support" OFF ) -OPTION( PLAYUVER_LONGVERSIONNAME "Use long version name in deb" OFF ) -OPTION( PLAYUVER_WERROR "Warnings as errors" OFF ) -OPTION( PLAYUVER_THREADED_MODULES "Use threads for modules" OFF ) -OPTION( USE_QT4 "Build with QT4" OFF ) +OPTION( PLAYUVER_BUILD_APP "Build GUI Application" ON ) +OPTION( PLAYUVER_BUILD_TOOLS "Build Command Line Application" ON ) OPTION( USE_SSE "Build with SSE support" OFF ) - -##################################################################################### -# Qt library -###################################################################################### - -IF( USE_QT4 ) - SET( DEPENDENCIES_STRING "${DEPENDENCIES_STRING}QT4" ) - FIND_PACKAGE( Qt4 REQUIRED COMPONENTS QtCore QtGui QtDBus QtNetwork QtWebKit ) - - SET( USE_QTDBUS TRUE ) - - IF( NOT QT4_FOUND ) - SET(USE_QT4 FALSE) - ELSE() - INCLUDE( ${QT_USE_FILE} ) - ADD_DEFINITIONS( ${QT_DEFINITIONS} ) - SET( QT_LINKER_LIBS ${QT_LIBRARIES} ) - ENDIF() -ENDIF() - -IF( NOT USE_QT4 ) - - SET( DEPENDENCIES_STRING "${DEPENDENCIES_STRING}QT5" ) - - FIND_PACKAGE( Qt5 REQUIRED COMPONENTS Core Gui Widgets PrintSupport ) - FIND_PACKAGE( Qt5DBus ) - - - LIST(APPEND QT_LINKER_LIBS Qt5::Core Qt5::Gui Qt5::Widgets Qt5::PrintSupport ) - LIST(APPEND QT_MODULES Core Gui Widgets ) - IF( ${Qt5DBus_FOUND} ) - SET( USE_QTDBUS ${Qt5DBus_FOUND} ) - LIST(APPEND QT_LINKER_LIBS Qt5::DBus ) - LIST(APPEND QT_MODULES DBus ) - ENDIF() - - INCLUDE_DIRECTORIES( ${Qt5Core_INCLUDE_DIRS} ${Qt5Gui_INCLUDE_DIRS} ${Qt5Widgets_INCLUDE_DIRS} ${Qt5DBus_INCLUDE_DIRS}) - SET( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${Qt5Core_EXECUTABLE_COMPILE_FLAGS}" ) - -ENDIF() +OPTION( USE_FERVOR "Add Fervor support" OFF ) +OPTION( USE_WERROR "Warnings as errors" OFF ) ###################################################################################### # Dependencies ###################################################################################### +FIND_PACKAGE(Boost COMPONENTS program_options ) +SET_PACKAGE_PROPERTIES(Boost PROPERTIES URL "http://www.boost.org" DESCRIPTION "Boost library support" TYPE REQUIRED) + OPTION( USE_OPENCV "Add OpenCV support" ON ) IF( USE_OPENCV ) FIND_PACKAGE( OpenCV ) @@ -130,10 +91,20 @@ SET( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall" ) SET( CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -g" ) SET( CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O2" ) + +ADD_FEATURE_INFO(PlaYUVerApp PLAYUVER_BUILD_TOOLS "Build Graphical Interface") +ADD_FEATURE_INFO(PlaYUVerTools PLAYUVER_BUILD_APP "Build Command line tool" ) + ADD_SUBDIRECTORY( lib ) ADD_SUBDIRECTORY( modules ) -ADD_SUBDIRECTORY( app ) +IF( ${PLAYUVER_BUILD_TOOLS} ) + ADD_SUBDIRECTORY( tools ) +ENDIF() + +IF( ${PLAYUVER_BUILD_APP} ) + ADD_SUBDIRECTORY( app ) +ENDIF() @@ -144,8 +115,8 @@ MESSAGE("") MESSAGE( STATUS "${PROJECT_NAME} INFORMATION" ) MESSAGE( STATUS "Version: " "${PLAYUVER_VERSION}" ) MESSAGE( STATUS "Configuration:" ) -MESSAGE( STATUS " Build type:" "${CMAKE_BUILD_TYPE}" ) -MESSAGE( STATUS " Build flags:" "${CMAKE_CXX_FLAGS}" ) +MESSAGE( STATUS " Build type: " "${CMAKE_BUILD_TYPE}" ) +MESSAGE( STATUS " Build flags:" "${CMAKE_CXX_FLAGS}" ) FEATURE_SUMMARY(WHAT ALL INCLUDE_QUIET_PACKAGES FATAL_ON_MISSING_REQUIRED_PACKAGES) diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt index f7eabd8..080403a 100644 --- a/app/CMakeLists.txt +++ b/app/CMakeLists.txt @@ -10,6 +10,41 @@ INCLUDE_DIRECTORIES( ${CMAKE_CURRENT_BINARY_DIR}/../ ${CMAKE_CURRENT_SOURCE_DIR}/../modules ${CMAKE_CURRENT_BINARY_DIR}/../modules ) +##################################################################################### +# Qt library +###################################################################################### + +OPTION( USE_QT4 "Build with QT4" OFF ) + +IF( USE_QT4 ) + + FIND_PACKAGE( Qt4 REQUIRED COMPONENTS QtCore QtGui QtDBus QtNetwork QtWebKit ) + SET( USE_QTDBUS TRUE ) + IF( NOT QT4_FOUND ) + SET(USE_QT4 FALSE) + ELSE() + INCLUDE( ${QT_USE_FILE} ) + ADD_DEFINITIONS( ${QT_DEFINITIONS} ) + SET( QT_LINKER_LIBS ${QT_LIBRARIES} ) + ENDIF() +ENDIF() + +IF( NOT USE_QT4 ) + FIND_PACKAGE( Qt5 REQUIRED COMPONENTS Core Gui Widgets PrintSupport Concurrent ) + FIND_PACKAGE( Qt5DBus ) + LIST(APPEND QT_LINKER_LIBS Qt5::Core Qt5::Gui Qt5::Widgets Qt5::PrintSupport Qt5::Concurrent ) + LIST(APPEND QT_MODULES Core Gui Widgets PrintSupport Concurrent ) + IF( ${Qt5DBus_FOUND} ) + SET( USE_QTDBUS ${Qt5DBus_FOUND} ) + LIST(APPEND QT_LINKER_LIBS Qt5::DBus ) + LIST(APPEND QT_MODULES DBus ) + ENDIF() + + #INCLUDE_DIRECTORIES( ${Qt5Core_INCLUDE_DIRS} ${Qt5Gui_INCLUDE_DIRS} ${Qt5Widgets_INCLUDE_DIRS} ${Qt5DBus_INCLUDE_DIRS}) + #SET( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${Qt5Core_EXECUTABLE_COMPILE_FLAGS}" ) + +ENDIF() + set(plaYUver_App_SRCS # Main main.cpp diff --git a/app/ModulesHandle.cpp b/app/ModulesHandle.cpp index d481017..89f512c 100644 --- a/app/ModulesHandle.cpp +++ b/app/ModulesHandle.cpp @@ -164,16 +164,18 @@ Void ModulesHandle::updateMenus() if( pcSubWindow ) { QList apcCurrentModule = pcSubWindow->getModuleArray(); + if( pcSubWindow->getDisplayModule() ) + { + m_arrayActions[APPLY_ALL_ACT]->setEnabled( true ); + m_arrayActions[SWAP_FRAMES_ACT]->setEnabled( true ); + apcCurrentModule.append( pcSubWindow->getDisplayModule() ); + } for( Int i = 0; i < apcCurrentModule.size(); i++ ) { currModuleAction = apcCurrentModule.at( i )->m_pcModuleAction; currModuleAction->setChecked( true ); } - if( apcCurrentModule.size() ) - { - m_arrayActions[APPLY_ALL_ACT]->setEnabled( true ); - m_arrayActions[SWAP_FRAMES_ACT]->setEnabled( true ); - } + } } @@ -194,10 +196,10 @@ Void ModulesHandle::processOpt( Int index ) VideoSubWindow* pcSubWindow = qobject_cast( m_pcMainWindowManager->activeSubWindow() ); if( pcSubWindow ) { - QList apcCurrentModule = pcSubWindow->getModuleArray(); - if( apcCurrentModule.size() > 1 ) + PlaYUVerAppModuleIf* pcCurrentModule = pcSubWindow->getDisplayModule(); + if( pcCurrentModule ) { - PlaYUVerAppModuleIf* pcCurrModule = apcCurrentModule.at( 0 ); + PlaYUVerAppModuleIf* pcCurrModule = pcCurrentModule; switch( index ) { case INVALID_OPT: @@ -304,11 +306,10 @@ Void ModulesHandle::enableModuleIf( PlaYUVerAppModuleIf *pcCurrModuleIf ) pcModuleSubWindow->setWindowName( windowName ); connect( pcModuleSubWindow->getViewArea(), SIGNAL( selectionChanged( QRect ) ), m_appModuleVideo, SLOT( updateSelectionArea( QRect ) ) ); - connect( pcModuleSubWindow, SIGNAL( zoomFactorChanged_SWindow( const double, const QPoint ) ), m_appModuleVideo, SLOT( zoomToFactorAll( double, QPoint ) ) ); + connect( pcModuleSubWindow, SIGNAL( zoomFactorChanged_SWindow( const double, const QPoint ) ), m_appModuleVideo, + SLOT( zoomToFactorAll( double, QPoint ) ) ); connect( pcModuleSubWindow, SIGNAL( scrollBarMoved_SWindow( const QPoint ) ), m_appModuleVideo, SLOT( moveAllScrollBars( const QPoint ) ) ); - - pcCurrModuleIf->m_pcDisplaySubWindow = pcModuleSubWindow; } @@ -468,7 +469,6 @@ Void ModulesHandle::applyAllModuleIf( PlaYUVerAppModuleIf *pcCurrModuleIf ) } supported.append( " )" ); - QStringList filter; filter << supported << formatsList diff --git a/app/VideoHandle.cpp b/app/VideoHandle.cpp index e9e7c33..ed2ce68 100644 --- a/app/VideoHandle.cpp +++ b/app/VideoHandle.cpp @@ -426,7 +426,7 @@ Void VideoHandle::play() if( !m_pcCurrentVideoSubWindow->isPlaying() ) // Not playing { - UInt frameRate; + Double frameRate; UInt timeInterval; if( m_acPlayingSubWindows.size() < 2 ) { @@ -486,7 +486,6 @@ Void VideoHandle::stop() } } emit changed(); - //update(); m_arrayActions[VIDEO_LOCK_ACT]->setVisible( false ); } @@ -523,7 +522,6 @@ Void VideoHandle::playEvent() m_pcCurrentVideoSubWindow->close(); } emit changed(); - //update(); } Void VideoHandle::seekEvent( Int direction ) diff --git a/app/VideoSubWindow.cpp b/app/VideoSubWindow.cpp index eb2a4ee..3597e3a 100644 --- a/app/VideoSubWindow.cpp +++ b/app/VideoSubWindow.cpp @@ -26,6 +26,9 @@ #include "ModulesHandle.h" #include "SubWindowHandle.h" #include "ConfigureFormatDialog.h" +#if( QT_VERSION_PLAYUVER == 5 ) +#include "QtConcurrent/qtconcurrentrun.h" +#endif namespace plaYUVer { @@ -401,7 +404,7 @@ Void VideoSubWindow::setCurrFrame( PlaYUVerFrame* pcCurrFrame ) m_cViewArea->setImage( m_pcCurrFrame ); } -Void VideoSubWindow::refreshFrame() +Void VideoSubWindow::refreshFrameOperation() { Bool bSetFrame = false; if( m_pCurrStream ) @@ -424,6 +427,21 @@ Void VideoSubWindow::refreshFrame() } } +Void VideoSubWindow::refreshFrame( Bool bThreaded ) +{ +#ifndef QT_NO_CONCURRENT + m_cRefreshResult.waitForFinished(); + if( bThreaded ) + { + m_cRefreshResult = QtConcurrent::run( this, &VideoSubWindow::refreshFrameOperation ); + } + else +#endif + { + refreshFrameOperation(); + } +} + Bool VideoSubWindow::save( QString filename ) { Bool iRet = false; @@ -461,11 +479,19 @@ Bool VideoSubWindow::playEvent() Bool bEndOfSeq = false; if( m_pCurrStream && m_bIsPlaying ) { +#ifndef QT_NO_CONCURRENT + m_cRefreshResult.waitForFinished(); + m_cReadResult.waitForFinished(); +#endif bEndOfSeq = m_pCurrStream->setNextFrame(); if( !bEndOfSeq ) { refreshFrame(); - m_pCurrStream->readFrame(); +#ifndef QT_NO_CONCURRENT + m_cReadResult = QtConcurrent::run( m_pCurrStream, &PlaYUVerStream::readFrameFillRGBBuffer ); +#else + m_pCurrStream->readFrameFillRGBBuffer(); +#endif } } return bEndOfSeq; @@ -520,7 +546,7 @@ Void VideoSubWindow::normalSize() Void VideoSubWindow::zoomToFit() { - // Scale to a smaller size that the real to a nicer look +// Scale to a smaller size that the real to a nicer look scaleView( getScrollSize() ); } @@ -557,7 +583,7 @@ Void VideoSubWindow::scaleView( const QSize & size, QPoint center ) QSize newSize = imgViewSize; newSize.scale( size, Qt::KeepAspectRatio ); - // Calc the zoom factor +// Calc the zoom factor Double wfactor = 1; Double hfactor = 1; Double factor; @@ -642,8 +668,8 @@ QSize VideoSubWindow::sizeHint( const QSize & maxSize ) const else if( m_pCurrStream ) isize = QSize( m_pCurrStream->getWidth() + 50, m_pCurrStream->getHeight() + 50 ); - // If the VideoSubWindow needs more space that the avaiable, we'll give - // to the subwindow a reasonable size preserving the image aspect ratio. +// If the VideoSubWindow needs more space that the avaiable, we'll give +// to the subwindow a reasonable size preserving the image aspect ratio. if( !( isize.width() < maxSize.width() && isize.height() < maxSize.height() ) ) { isize.scale( maxSize, Qt::KeepAspectRatio ); diff --git a/app/VideoSubWindow.h b/app/VideoSubWindow.h index dd90509..b0b6690 100644 --- a/app/VideoSubWindow.h +++ b/app/VideoSubWindow.h @@ -32,6 +32,7 @@ #elif( QT_VERSION_PLAYUVER == 4 ) #include #endif +#include "QFuture" #include "lib/PlaYUVerStream.h" #include "SubWindowHandle.h" #include "ViewArea.h" @@ -84,6 +85,16 @@ private: Bool m_bIsPlaying; Bool m_bIsModule; + /** + * Threads variables + * QtConcurrent + */ + QFuture m_cRefreshResult; + QFuture m_cReadResult; + + Void refreshFrame( Bool bThreaded = false ); + Void refreshFrameOperation(); + static Bool guessFormat( QString filename, UInt& rWidth, UInt& rHeight, Int& rInputFormat, UInt& rFrameRate ); /** @@ -105,7 +116,7 @@ public: Bool loadFile( QString cFilename, Bool bForceDialog = false ); Bool loadFile( PlaYUVerStreamInfo* streamInfo ); - Void loadAll( ); + Void loadAll(); Void reloadFile(); Bool save( QString filename ); @@ -122,7 +133,6 @@ public: Void seekAbsoluteEvent( UInt new_frame_num ); Void seekRelativeEvent( Bool bIsFoward ); - Void refreshFrame(); Void setCurrFrame( PlaYUVerFrame* pcCurrFrame ); PlaYUVerStreamInfo getStreamInfo() @@ -170,6 +180,11 @@ public: Void disableModule( PlaYUVerAppModuleIf* pcModule = NULL ); Void associateModule( PlaYUVerAppModuleIf* pcModule ); + PlaYUVerAppModuleIf* getDisplayModule() + { + return m_pcCurrentDisplayModule; + } + QList getModuleArray() { return m_apcCurrentModule; diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index f8771e9..30f4bbe 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -4,6 +4,8 @@ INCLUDE_DIRECTORIES( ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}/../ ) +INCLUDE_DIRECTORIES( ${Boost_INCLUDE_DIRS} ) + set(plaYUver_Lib_SRCS # Frame PlaYUVerFrame.cpp @@ -11,6 +13,8 @@ set(plaYUver_Lib_SRCS PlaYUVerFrameStats.cpp # Stream PlaYUVerStream.cpp + # Command Line Parser + PlaYUVerCmdParser.cpp ) IF( USE_FFMPEG ) @@ -43,7 +47,7 @@ CONFIGURE_FILE( PlaYUVerConfig.cmake.in ${CMAKE_BINARY_DIR}/PlaYUVerConfig.cmake ADD_LIBRARY( PlaYUVerLib STATIC ${plaYUver_Lib_SRCS} ) INCLUDE_DIRECTORIES( ${FFMPEG_INCLUDE_DIRS} ${OpenCV_INCLUDE_DIRS} ) -TARGET_LINK_LIBRARIES( PlaYUVerLib ${FFMPEG_LIBRARIES} ${OpenCV_LIBRARIES} ) +TARGET_LINK_LIBRARIES( PlaYUVerLib ${FFMPEG_LIBRARIES} ${OpenCV_LIBRARIES} ${Boost_LIBRARIES} ) INSTALL(FILES ${plaYUver_Lib_HEADERS} DESTINATION include ) # INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/libPlaYUVerLib${CMAKE_STATIC_LIBRARY_SUFFIX} DESTINATION lib ) diff --git a/lib/LibAvContextHandle.cpp b/lib/LibAvContextHandle.cpp index 4bdbc6e..f9c5055 100644 --- a/lib/LibAvContextHandle.cpp +++ b/lib/LibAvContextHandle.cpp @@ -134,7 +134,7 @@ Void LibAvContextHandle::closeAvFormat() m_bHasStream = false; } -Bool LibAvContextHandle::initAvFormat( const char* filename, UInt& width, UInt& height, Int& pixel_format, UInt& frame_rate, UInt64& num_frames ) +Bool LibAvContextHandle::initAvFormat( const char* filename, UInt& width, UInt& height, Int& pixel_format, Double& frame_rate, UInt64& num_frames ) { fmt_ctx = NULL; video_dec_ctx = NULL; @@ -159,7 +159,7 @@ Bool LibAvContextHandle::initAvFormat( const char* filename, UInt& width, UInt& av_dict_set( &format_opts, "video_size", aux_string, 0 ); } - Int ffmpeg_pel_format = g_PlaYUVerFramePelFormatsList[pixel_format].ffmpegPelFormat; + Int ffmpeg_pel_format = g_PlaYUVerPixFmtDescriptorsList[pixel_format].ffmpegPelFormat; if( ffmpeg_pel_format >= 0 ) { av_dict_set( &format_opts, "pixel_format", av_get_pix_fmt_name( AVPixelFormat( ffmpeg_pel_format ) ), 0 ); @@ -213,9 +213,13 @@ Bool LibAvContextHandle::initAvFormat( const char* filename, UInt& width, UInt& else if( video_stream->codec->time_base.den && video_stream->codec->time_base.num ) fr = 1 / av_q2d( video_stream->codec->time_base ); - frame_rate = ( UInt )fr; + frame_rate = fr; - if( fmt_ctx->duration != AV_NOPTS_VALUE ) + /*if( video_stream->nb_frames ) + { + num_frames = video_stream->nb_frames; + } + else*/ if( fmt_ctx->duration != AV_NOPTS_VALUE ) { Int64 duration = fmt_ctx->duration + 5000; m_uiSecs = duration / AV_TIME_BASE; @@ -248,7 +252,7 @@ Bool LibAvContextHandle::initAvFormat( const char* filename, UInt& width, UInt& pixel_format = PlaYUVerFrame::NO_FMT; for( Int i = 0; i < PLAYUVER_NUMBER_FORMATS; i++ ) { - if( g_PlaYUVerFramePelFormatsList[i].ffmpegPelFormat == pix_fmt ) + if( g_PlaYUVerPixFmtDescriptorsList[i].ffmpegPelFormat == pix_fmt ) { pixel_format = i; break; @@ -293,48 +297,71 @@ Bool LibAvContextHandle::initAvFormat( const char* filename, UInt& width, UInt& return true; } +Bool LibAvContextHandle::decodeVideoPkt() +{ + Int got_frame = 0; + Int decResult; + if( pkt.stream_index == video_stream_idx ) + { + decResult = avcodec_decode_video2( video_dec_ctx, frame, &got_frame, &pkt ); + if( decResult < 0 ) + { + fprintf( stderr, "Error decoding video frame\n" ); + return false; + } + pkt.data += decResult; + pkt.size -= decResult; + } + else + { + pkt.size = 0; + } + Bool bRet = got_frame > 0 ? true : false; + return bRet; +} + Bool LibAvContextHandle::decodeAvFormat() { - Int got_frame; + Bool bGotFrame = false; + AVPacket orig_pkt = pkt; + + bGotFrame |= decodeVideoPkt(); + /* read frames from the file */ - while( av_read_frame( fmt_ctx, &pkt ) >= 0 ) + while( !bGotFrame && ( av_read_frame( fmt_ctx, &pkt ) >= 0 ) ) { - if( pkt.stream_index == video_stream_idx ) + orig_pkt = pkt; + do { - /* decode video frame */ - Int ret = avcodec_decode_video2( video_dec_ctx, frame, &got_frame, &pkt ); - if( ret < 0 ) - { - fprintf( stderr, "Error decoding video frame\n" ); - return false; - } - - if( got_frame ) - { - av_image_copy_to_buffer( m_pchFrameBuffer, m_uiFrameBufferSize, frame->data, frame->linesize, video_dec_ctx->pix_fmt, video_dec_ctx->width, - video_dec_ctx->height, 1 ); - - /* copy decoded frame to destination buffer: - * this is required since rawvideo expects non aligned data */ - // av_image_copy( video_dst_data, video_dst_linesize, ( const uint8_t ** )( frame->data ), frame->linesize, video_dec_ctx->pix_fmt, video_dec_ctx->width, - // video_dec_ctx->height ); - } + bGotFrame |= decodeVideoPkt(); + if( bGotFrame ) + break; } - av_free_packet( &pkt ); - if( got_frame ) - return true; - } - return false; -// /* flush cached frames */ -// pkt.data = NULL; -// pkt.size = 0; -// do -// { -// decode_packet( &got_frame, 1 ); -// } -// while( got_frame ); + while( pkt.size > 0 ); - return true; + if( bGotFrame ) + { + break; + } + } + + /*! Try flush existing packets */ + if( !bGotFrame ) + { + bGotFrame |= decodeVideoPkt(); + } + + if( bGotFrame ) + { + av_image_copy_to_buffer( m_pchFrameBuffer, m_uiFrameBufferSize, frame->data, frame->linesize, video_dec_ctx->pix_fmt, video_dec_ctx->width, + video_dec_ctx->height, 1 ); + + av_free_packet( &orig_pkt ); + + return true; + } + + return false; } Void LibAvContextHandle::seekAvFormat( UInt64 frame_num ) diff --git a/lib/LibAvContextHandle.h b/lib/LibAvContextHandle.h index 52fac8c..2f01b00 100644 --- a/lib/LibAvContextHandle.h +++ b/lib/LibAvContextHandle.h @@ -67,7 +67,7 @@ public: m_bHasStream( false ) { } - Bool initAvFormat( const char* filename, UInt& width, UInt& height, Int& pixel_format, UInt& frame_rate, UInt64& num_frames ); + Bool initAvFormat( const char* filename, UInt& width, UInt& height, Int& pixel_format, Double& frame_rate, UInt64& num_frames ); Void closeAvFormat(); Bool decodeAvFormat(); @@ -104,8 +104,10 @@ private: Bool m_bHasStream; Char m_acCodecName[20]; - UInt m_uiSecs; - UInt m_uiMicroSec; + UInt64 m_uiSecs; + UInt64 m_uiMicroSec; + + Bool decodeVideoPkt(); }; } // NAMESPACE diff --git a/lib/LibMemory.h b/lib/LibMemory.h index 59960fd..6d84b72 100644 --- a/lib/LibMemory.h +++ b/lib/LibMemory.h @@ -177,33 +177,6 @@ Int getMem5D( T****** array5D, Int dim0, Int dim1, Int dim2, Int dim3, Int dim4 return mem_size; } -template -Int getMem3ImageComponents( T**** array3D, Int dim1, Int dim2, Int ratioDim1Chroma, Int ratioDim2Chroma ) -{ - Int dim0 = 3; - Int i, mem_size = ( dim1 * dim2 + dim1 / ratioDim1Chroma * dim2 / ratioDim2Chroma * 2 ) * sizeof(T); - - mem_size += getMem2D( array3D, dim0, dim1 ); - - if( ( ( *array3D )[0][0] = ( T* )xCallocMem( dim1 * dim2 + dim1 / ratioDim1Chroma * dim2 / ratioDim2Chroma * 2, sizeof(T) ) ) == NULL ) - printf( "getMem3DImageComponents: array1D" ); - - // Luma - for( i = 1; i < dim1; i++ ) - ( *array3D )[0][i] = ( *array3D )[0][i - 1] + dim2; - - // Chroma - ( *array3D )[1][0] = ( *array3D )[0][0] + dim2 * dim1; - for( i = 1; i < dim1 / ratioDim1Chroma; i++ ) - ( *array3D )[1][i] = ( *array3D )[1][i - 1] + dim2 / ratioDim2Chroma; - - ( *array3D )[2][0] = ( *array3D )[1][0] + dim2 / ratioDim2Chroma * dim1 / ratioDim1Chroma; - for( i = 1; i < dim1 / ratioDim1Chroma; i++ ) - ( *array3D )[2][i] = ( *array3D )[2][i - 1] + dim2 / ratioDim2Chroma; - - return mem_size; -} - template Void freeMem1D( T *array1D ) { diff --git a/lib/LibOpenCVHandler.cpp b/lib/LibOpenCVHandler.cpp index 3fe9692..ea191b8 100644 --- a/lib/LibOpenCVHandler.cpp +++ b/lib/LibOpenCVHandler.cpp @@ -84,22 +84,22 @@ std::vector LibOpenCVHandler::supportedSaveFormatsName() return formatsName; } -Bool LibOpenCVHandler::loadFrame( PlaYUVerFrame* pcFrame, std::string filename ) +PlaYUVerFrame* LibOpenCVHandler::loadFrame( std::string filename ) { cv::Mat pcCvFrame = cv::imread( filename ); - + Int cvChannels = pcCvFrame.channels(); std::string pelFormatName; - Int iPelFormat; - switch( pcCvFrame.channels() ) + Int iPelFormat = -1; + switch( cvChannels ) { case 1: pelFormatName = "GRAY"; break; - case 4: - pelFormatName = "RGB8"; + case 3: + pelFormatName = "BRG24"; break; default: - return false; + return NULL; } for( UInt i = 0; i < PlaYUVerFrame::supportedPixelFormatListNames().size(); i++ ) @@ -110,17 +110,23 @@ Bool LibOpenCVHandler::loadFrame( PlaYUVerFrame* pcFrame, std::string filename ) break; } } - return true; + + if( iPelFormat >= 0 ) + { + PlaYUVerFrame* pcFrame = new PlaYUVerFrame( pcCvFrame.cols, pcCvFrame.rows, iPelFormat ); + pcFrame->frameFromBuffer( pcCvFrame.ptr(), pcFrame->getBytesPerFrame() ); + return pcFrame; + } + return NULL; } Bool LibOpenCVHandler::saveFrame( PlaYUVerFrame* pcFrame, std::string filename ) { - Int cvType = CV_8UC3; switch( pcFrame->getNumberChannels() ) { case 3: - cvType = CV_8UC4; + cvType = CV_8UC3; break; case 1: cvType = CV_8UC1; @@ -129,10 +135,20 @@ Bool LibOpenCVHandler::saveFrame( PlaYUVerFrame* pcFrame, std::string filename ) return false; break; } + cv::Mat pcCvFrame( pcFrame->getHeight(), pcFrame->getWidth(), cvType ); + if( pcFrame->getColorSpace() != PlaYUVerFrame::COLOR_GRAY ) { - memcpy( pcCvFrame.data, pcFrame->getRGBBuffer(), pcFrame->getHeight() * pcFrame->getWidth() * 4 * sizeof(UChar) ); + UChar* pCvPel = pcCvFrame.data; + UChar* pARGB = pcFrame->getRGBBuffer(); + for( UInt i = 0; i < pcFrame->getHeight() * pcFrame->getWidth(); i++ ) + { + *pCvPel++ = *pARGB++; + *pCvPel++ = *pARGB++; + *pCvPel++ = *pARGB++; + pARGB++; + } } else { diff --git a/lib/LibOpenCVHandler.h b/lib/LibOpenCVHandler.h index 4322322..c310068 100644 --- a/lib/LibOpenCVHandler.h +++ b/lib/LibOpenCVHandler.h @@ -52,7 +52,7 @@ public: { } - static Bool loadFrame( PlaYUVerFrame* pcFrame, std::string filename ); + static PlaYUVerFrame* loadFrame( std::string filename ); static Bool saveFrame( PlaYUVerFrame* pcFrame, std::string filename ); private: diff --git a/lib/PlaYUVerCmdParser.cpp b/lib/PlaYUVerCmdParser.cpp new file mode 100644 index 0000000..0d9c1c8 --- /dev/null +++ b/lib/PlaYUVerCmdParser.cpp @@ -0,0 +1,132 @@ +/* This file is a part of plaYUVer project + * Copyright (C) 2014-2015 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 PlaYUVerCmdParser.cpp + * \brief Command parser + */ + +#include "config.h" +#include +#include +#include +#include +#include "PlaYUVerCmdParser.h" +#include "PlaYUVerFrame.h" + +namespace plaYUVer +{ + +PlaYUVerCmdParser::PlaYUVerCmdParser() +{ + m_iArgc = 0; + m_apcArgv = NULL; + m_ParserOptions.add( GetCommandOpts() ); +} + +PlaYUVerCmdParser::~PlaYUVerCmdParser() +{ + +} + +Void PlaYUVerCmdParser::Config( Int argc, Char *argv[] ) +{ + m_iArgc = argc; + m_apcArgv = argv; +} + +po::options_description PlaYUVerCmdParser::GetCommandOpts() +{ + po::options_description inputOpts( "Input" ); + inputOpts.add_options()/**/ + ( "input,i", po::value >(), "input file" ) /**/ + ( "output,o", po::value >(), "output file" ) /**/ + ( "size,s", po::value(), "size (WxH)" ) /**/ + ( "pel_fmt", po::value(), "pixel format" ) /**/ + ( "pel_fmts", "list pixel formats" ) /**/ + ( "frames,f", po::value(), "number of frames" ); + + po::options_description commonOpts( "Common" ); + commonOpts.add_options()/**/ + ( "help", "produce help message" )/**/ + ( "version", "show version and exit" ); + commonOpts.add( inputOpts ); + return commonOpts; +} + +Void PlaYUVerCmdParser::addOptions( po::options_description opts ) +{ + m_ParserOptions.add( opts ); +} + +Bool PlaYUVerCmdParser::parse() +{ + try + { + po::store( po::command_line_parser( m_iArgc, m_apcArgv ).options( m_ParserOptions ).allow_unregistered().run(), m_cOptionsMap ); + po::notify( m_cOptionsMap ); + + if( m_cOptionsMap.count( "help" ) ) + { + std::cout << m_ParserOptions + << "\n"; + return false; + } + if( m_cOptionsMap.count( "version" ) ) + { + std::cout << "PlaYUVer version " + << PLAYUVER_VERSION_STRING + << "\n"; + return false; + } + if( checkListingOpts() ) + { + return false; + } + } + catch( std::exception& e ) + { + std::cerr << "error: " + << e.what() + << "\n"; + return false; + } + catch( ... ) + { + std::cerr << "Exception of unknown type!\n"; + } + return true; +} + +Bool PlaYUVerCmdParser::checkListingOpts() +{ + Bool bRet = false; + if( m_cOptionsMap.count( "pel_fmts" ) ) + { + printf( "PlaYUVer supported pixel formats: \n" ); + for( UInt i = 0; i < PlaYUVerFrame::supportedPixelFormatListNames().size(); i++ ) + { + printf( " %s\n", PlaYUVerFrame::supportedPixelFormatListNames()[i].c_str() ); + } + bRet |= true; + } + return bRet; +} + +} // NAMESPACE diff --git a/lib/PlaYUVerCmdParser.h b/lib/PlaYUVerCmdParser.h new file mode 100644 index 0000000..6dbee30 --- /dev/null +++ b/lib/PlaYUVerCmdParser.h @@ -0,0 +1,58 @@ +/* This file is a part of plaYUVer project + * Copyright (C) 2014-2015 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 PlaYUVerCmdParser.h + * \brief Command parser + */ + +#include "PlaYUVerDefs.h" +#include +namespace po = boost::program_options; + +namespace plaYUVer +{ + +class PlaYUVerCmdParser +{ +public: + PlaYUVerCmdParser(); + ~PlaYUVerCmdParser(); + + Void Config( Int argc, Char *argv[] ); + Void addOptions( po::options_description ); + Bool parse(); + + po::variables_map getOptionsMap() + { + return m_cOptionsMap; + } + + static po::options_description GetCommandOpts(); + +private: + Int m_iArgc; + Char** m_apcArgv; + po::options_description m_ParserOptions; + po::variables_map m_cOptionsMap; + + Bool checkListingOpts(); +}; + +} // NAMESPACE diff --git a/lib/PlaYUVerDefs.h b/lib/PlaYUVerDefs.h index df040a9..fa07c3e 100644 --- a/lib/PlaYUVerDefs.h +++ b/lib/PlaYUVerDefs.h @@ -48,6 +48,9 @@ typedef unsigned int UInt; typedef double Double; typedef float Float; +typedef unsigned char UInt8; +typedef unsigned int UInt16; + // ==================================================================================================================== // 64-bit integer type // ==================================================================================================================== diff --git a/lib/PlaYUVerFrame.cpp b/lib/PlaYUVerFrame.cpp index 549fce2..59de119 100644 --- a/lib/PlaYUVerFrame.cpp +++ b/lib/PlaYUVerFrame.cpp @@ -48,7 +48,7 @@ std::vector PlaYUVerFrame::supportedPixelFormatListNames() Int numberFormats = PLAYUVER_NUMBER_FORMATS; for( Int i = 0; i < numberFormats; i++ ) { - formatsList.push_back( g_PlaYUVerFramePelFormatsList[i].name ); + formatsList.push_back( g_PlaYUVerPixFmtDescriptorsList[i].name ); } return formatsList; } @@ -76,16 +76,50 @@ PlaYUVerFrame::~PlaYUVerFrame() if( m_pppcInputPel ) freeMem3ImageComponents( m_pppcInputPel ); - if( m_pcRGB32 ) - freeMem1D( m_pcRGB32 ); + if( m_pcARGB32 ) + freeMem1D( m_pcARGB32 ); closePixfc(); } +static Int getMem3ImageComponents( Pel**** array3D, Int dim1, Int dim2, Int log2ChromaHeight, Int log2ChromaWidth ) +{ + Int dim0 = 3; + Int i; + UInt64 total_mem_size = 0; + UInt64 mem_size = ( dim1 * dim2 + CHROMASHIFT( dim1, log2ChromaHeight ) * CHROMASHIFT( dim2, log2ChromaWidth ) * 2 ); + + total_mem_size += getMem2D( array3D, dim0, dim1 ); + + if( ( ( *array3D )[0][0] = ( Pel* )xCallocMem( mem_size, sizeof(Pel) ) ) == NULL ) + printf( "getMem3DImageComponents: array1D" ); + + total_mem_size += mem_size * sizeof(Pel); + + // Luma + for( i = 1; i < dim1; i++ ) + ( *array3D )[0][i] = ( *array3D )[0][i - 1] + dim2; + + // Chroma + ( *array3D )[1][0] = ( *array3D )[0][0] + dim2 * dim1; + + dim1 = CHROMASHIFT( dim1, log2ChromaHeight ); + dim2 = CHROMASHIFT( dim2, log2ChromaWidth ); + + for( i = 1; i < dim1; i++ ) + ( *array3D )[1][i] = ( *array3D )[1][i - 1] + dim2; + + ( *array3D )[2][0] = ( *array3D )[1][0] + dim2 * dim1; + for( i = 1; i < dim1; i++ ) + ( *array3D )[2][i] = ( *array3D )[2][i - 1] + dim2; + + return total_mem_size; +} + Void PlaYUVerFrame::init( UInt width, UInt height, Int pel_format ) { m_pppcInputPel = NULL; - m_pcRGB32 = NULL; + m_pcARGB32 = NULL; m_uiWidth = width; m_uiHeight = height; m_iPixelFormat = pel_format; @@ -99,18 +133,18 @@ Void PlaYUVerFrame::init( UInt width, UInt height, Int pel_format ) return; } - m_pcPelFormat = &( g_PlaYUVerFramePelFormatsList[pel_format] ); + m_pcPelFormat = &( g_PlaYUVerPixFmtDescriptorsList[pel_format] ); m_bHasRGBPel = false; if( m_pcPelFormat->colorSpace == COLOR_GRAY ) { - getMem3ImageComponents( &m_pppcInputPel, m_uiHeight, m_uiWidth, 1, 1 ); + getMem3ImageComponents( &m_pppcInputPel, m_uiHeight, m_uiWidth, 1, 1 ); } else { - getMem3ImageComponents( &m_pppcInputPel, m_uiHeight, m_uiWidth, m_pcPelFormat->ratioChromaHeight, m_pcPelFormat->ratioChromaWidth ); + getMem3ImageComponents( &m_pppcInputPel, m_uiHeight, m_uiWidth, m_pcPelFormat->log2ChromaHeight, m_pcPelFormat->log2ChromaWidth ); } - getMem1D( &m_pcRGB32, m_uiHeight * m_uiWidth * 4 ); + getMem1D( &m_pcARGB32, m_uiHeight * m_uiWidth * 4 ); xSetupStatistics( this ); openPixfc(); @@ -133,23 +167,24 @@ UInt64 PlaYUVerFrame::getBytesPerFrame() UInt64 PlaYUVerFrame::getBytesPerFrame( UInt uiWidth, UInt uiHeight, Int iPixelFormat ) { - PlaYUVerFramePelFormat* pcPelFormat = &( g_PlaYUVerFramePelFormatsList[iPixelFormat] ); + PlaYUVerPixFmtDescriptor* pcPelFormat = &( g_PlaYUVerPixFmtDescriptorsList[iPixelFormat] ); UInt64 numberBytes = uiWidth * uiHeight; if( pcPelFormat->numberChannels > 1 ) { - numberBytes += ( pcPelFormat->numberChannels - 1 ) * ( uiWidth * uiHeight ) / ( pcPelFormat->ratioChromaWidth * pcPelFormat->ratioChromaHeight ); + UInt64 numberBytesChroma = CHROMASHIFT( uiWidth, pcPelFormat->log2ChromaWidth ) * CHROMASHIFT( uiHeight, pcPelFormat->log2ChromaHeight ); + numberBytes += ( pcPelFormat->numberChannels - 1 ) * numberBytesChroma; } return numberBytes; } UInt PlaYUVerFrame::getChromaWidth() const { - return m_pcPelFormat->ratioChromaWidth > 0 ? m_uiWidth / m_pcPelFormat->ratioChromaWidth : 0; + return CHROMASHIFT( m_uiWidth, m_pcPelFormat->log2ChromaWidth ); } UInt PlaYUVerFrame::getChromaHeight() const { - return m_pcPelFormat->ratioChromaHeight > 0 ? m_uiHeight / m_pcPelFormat->ratioChromaHeight : 0; + return CHROMASHIFT( m_uiHeight, m_pcPelFormat->log2ChromaHeight ); } UInt PlaYUVerFrame::getChromaLength() const @@ -161,22 +196,96 @@ Void PlaYUVerFrame::frameFromBuffer( Pel *Buff, UInt64 uiBuffSize ) { if( uiBuffSize != getBytesPerFrame() ) return; - m_pcPelFormat->frameFromBuffer( Buff, m_pppcInputPel, m_uiWidth, m_uiHeight ); + + Pel* ppBuff[MAX_NUMBER_PLANES]; + Pel* pTmpPel, *pTmpBuff; + Int ratioH, ratioW, step; + UInt i, ch; + + ppBuff[0] = Buff; + for( Int i = 1; i < MAX_NUMBER_PLANES; i++ ) + { + ratioW = i > 1 ? m_pcPelFormat->log2ChromaWidth : 0; + ratioH = i > 1 ? m_pcPelFormat->log2ChromaHeight : 0; + ppBuff[i] = ppBuff[i - 1] + CHROMASHIFT( m_uiHeight, ratioH ) * CHROMASHIFT( m_uiWidth, ratioW ); + } + + for( ch = 0; ch < m_pcPelFormat->numberChannels; ch++ ) + { + ratioW = ch > 0 ? m_pcPelFormat->log2ChromaWidth : 0; + ratioH = ch > 0 ? m_pcPelFormat->log2ChromaHeight : 0; + step = m_pcPelFormat->comp[ch].step_minus1 + 1; + + pTmpPel = m_pppcInputPel[ch][0]; + pTmpBuff = ppBuff[m_pcPelFormat->comp[ch].plane] + ( m_pcPelFormat->comp[ch].offset_plus1 - 1 ); + + for( i = 0; i < CHROMASHIFT( m_uiHeight, ratioH ) * CHROMASHIFT( m_uiWidth, ratioW ); i++ ) + { + *pTmpPel++ = *pTmpBuff; + pTmpBuff += step; + } + } + m_bHasRGBPel = false; m_bHasHistogram = false; - fillRGBBuffer(); } Void PlaYUVerFrame::frameToBuffer( Pel *output_buffer ) { - m_pcPelFormat->bufferFromFrame( m_pppcInputPel, output_buffer, m_uiWidth, m_uiHeight ); + Pel* ppBuff[MAX_NUMBER_PLANES]; + Pel* pTmpPel, *pTmpBuff; + Int ratioH, ratioW, step; + UInt i, ch; + + ppBuff[0] = output_buffer; + for( Int i = 1; i < MAX_NUMBER_PLANES; i++ ) + { + ratioW = i > 1 ? m_pcPelFormat->log2ChromaWidth : 0; + ratioH = i > 1 ? m_pcPelFormat->log2ChromaHeight : 0; + ppBuff[i] = ppBuff[i - 1] + CHROMASHIFT( m_uiHeight, ratioH ) * CHROMASHIFT( m_uiWidth, ratioW ); + } + + for( ch = 0; ch < m_pcPelFormat->numberChannels; ch++ ) + { + ratioW = ch > 0 ? m_pcPelFormat->log2ChromaWidth : 0; + ratioH = ch > 0 ? m_pcPelFormat->log2ChromaHeight : 0; + step = m_pcPelFormat->comp[ch].step_minus1 + 1; + + pTmpPel = m_pppcInputPel[ch][0]; + pTmpBuff = ppBuff[m_pcPelFormat->comp[ch].plane]; + + for( i = 0; i < CHROMASHIFT( m_uiHeight, ratioH ) * CHROMASHIFT( m_uiWidth, ratioW ); i++ ) + { + *pTmpBuff = *pTmpPel++; + pTmpBuff += step; + } + } + } Void PlaYUVerFrame::fillRGBBuffer() { if( m_bHasRGBPel ) return; - m_pcPelFormat->fillRGBbuffer( m_pppcInputPel, m_pcRGB32, m_uiWidth, m_uiHeight ); + if( m_pcPelFormat->colorSpace == COLOR_RGB ) + { + Pel* pR = m_pppcInputPel[COLOR_R][0]; + Pel* pG = m_pppcInputPel[COLOR_G][0]; + Pel* pB = m_pppcInputPel[COLOR_B][0]; + Int iR, iG, iB; + UInt* pARGB = ( UInt* )m_pcARGB32; + for( UInt i = 0; i < m_uiHeight * m_uiWidth; i++ ) + { + iR = *pR++; + iG = *pG++; + iB = *pB++; + *pARGB++ = PEL_RGB( iR, iG, iB ); + } + } + else + { + m_pcPelFormat->fillARGB32buffer( m_pppcInputPel, m_pcARGB32, m_uiWidth, m_uiHeight ); + } m_bHasRGBPel = true; } @@ -191,21 +300,21 @@ Void PlaYUVerFrame::copyFrom( PlaYUVerFrame* input_frame ) Void PlaYUVerFrame::adjustSelectedAreaDims( UInt& posX, UInt& posY, UInt& areaWidth, UInt& areaHeight, Int pelFormat ) { - PlaYUVerFramePelFormat* pcPelFormat = &( g_PlaYUVerFramePelFormatsList[pelFormat] ); - if( pcPelFormat->ratioChromaWidth ) + PlaYUVerPixFmtDescriptor* pcPelFormat = &( g_PlaYUVerPixFmtDescriptorsList[pelFormat] ); + if( pcPelFormat->log2ChromaWidth ) { - if( posX % pcPelFormat->ratioChromaWidth ) + if( posX % ( 1 << pcPelFormat->log2ChromaWidth ) ) posX--; - if( ( posX + areaWidth ) % pcPelFormat->ratioChromaWidth ) + if( ( posX + areaWidth ) % ( 1 << pcPelFormat->log2ChromaWidth ) ) areaWidth++; } - if( pcPelFormat->ratioChromaHeight ) + if( pcPelFormat->log2ChromaHeight ) { - if( posY % pcPelFormat->ratioChromaHeight ) + if( posY % ( 1 << pcPelFormat->log2ChromaHeight ) ) posY--; - if( ( posY + areaHeight ) % pcPelFormat->ratioChromaHeight ) + if( ( posY + areaHeight ) % ( 1 << pcPelFormat->log2ChromaHeight ) ) areaHeight++; } } @@ -217,11 +326,11 @@ Void PlaYUVerFrame::copyFrom( PlaYUVerFrame* input_frame, UInt xPos, UInt yPos ) Pel ***pInput = input_frame->getPelBufferYUV(); for( UInt ch = 0; ch < m_pcPelFormat->numberChannels; ch++ ) { - Int ratioH = ch > 0 ? m_pcPelFormat->ratioChromaHeight : 1; - Int ratioW = ch > 0 ? m_pcPelFormat->ratioChromaWidth : 1; - for( UInt i = 0; i < m_uiHeight / ratioH; i++ ) + Int ratioH = ch > 0 ? m_pcPelFormat->log2ChromaWidth : 0; + Int ratioW = ch > 0 ? m_pcPelFormat->log2ChromaHeight : 0; + for( UInt i = 0; i < CHROMASHIFT( m_uiHeight, ratioH ); i++ ) { - memcpy( m_pppcInputPel[ch][i], &( pInput[ch][yPos / ratioH + i][xPos / ratioW] ), m_uiWidth / ratioW * sizeof(Pel) ); + memcpy( m_pppcInputPel[ch][i], &( pInput[ch][( yPos >> ratioH ) + i][( xPos >> ratioW )] ), ( m_uiWidth >> ratioW ) * sizeof(Pel) ); } } m_bHasRGBPel = false; @@ -233,9 +342,9 @@ PlaYUVerFrame::Pixel PlaYUVerFrame::getPixelValue( Int xPos, Int yPos, Int eColo PlaYUVerFrame::Pixel PixelValue( m_pcPelFormat->colorSpace, 0, 0, 0 ); for( UInt ch = 0; ch < m_pcPelFormat->numberChannels; ch++ ) { - Int ratioH = ch > 0 ? m_pcPelFormat->ratioChromaHeight : 1; - Int ratioW = ch > 0 ? m_pcPelFormat->ratioChromaWidth : 1; - PixelValue.Components()[ch] = m_pppcInputPel[ch][yPos / ratioH][xPos / ratioW]; + Int ratioH = ch > 0 ? m_pcPelFormat->log2ChromaWidth : 0; + Int ratioW = ch > 0 ? m_pcPelFormat->log2ChromaHeight : 0; + PixelValue.Components()[ch] = m_pppcInputPel[ch][( yPos >> ratioH )][( xPos >> ratioW )]; } return ConvertPixel( PixelValue, eColorSpace ); } @@ -340,7 +449,7 @@ Void PlaYUVerFrame::getCvMat( Void** ppCvFrame ) if( m_pcPelFormat->colorSpace != PlaYUVerFrame::COLOR_GRAY ) { fillRGBBuffer(); - memcpy( pcCvFrame->data, m_pcRGB32, m_uiWidth * m_uiHeight * 4 * sizeof(UChar) ); + memcpy( pcCvFrame->data, m_pcARGB32, m_uiWidth * m_uiHeight * 4 * sizeof(UChar) ); } else { @@ -382,7 +491,7 @@ Void PlaYUVerFrame::fromCvMat( Void* voidFrame ) Pel* pInputPelY = m_pppcInputPel[LUMA][0]; Pel* pInputPelU = m_pppcInputPel[CHROMA_U][0]; Pel* pInputPelV = m_pppcInputPel[CHROMA_V][0]; - Pel* pcRGBPelInterlaced = m_pcRGB32; + Pel* pcRGBPelInterlaced = m_pcARGB32; memcpy( pcRGBPelInterlaced, opencvFrame->data, m_uiWidth * m_uiHeight * 4 * sizeof(Pel) ); UInt* buff = ( UInt* )pcRGBPelInterlaced; for( UInt i = 0; i < m_uiHeight * m_uiWidth; i++ ) diff --git a/lib/PlaYUVerFrame.h b/lib/PlaYUVerFrame.h index 2c1f252..abbce64 100644 --- a/lib/PlaYUVerFrame.h +++ b/lib/PlaYUVerFrame.h @@ -38,7 +38,7 @@ class PixFcSSE; namespace plaYUVer { -struct PlaYUVerFramePelFormat; +struct PlaYUVerPixFmtDescriptor; /** * \class PlaYUVerFrame @@ -243,9 +243,17 @@ public: m_bHasRGBPel = false; return m_pppcInputPel; } - UChar* getRGBBuffer() const +// UChar* getRGBBuffer() const +// { +// return m_pcRGB32; +// } + UChar* getRGBBuffer() { - return m_pcRGB32; + if( !m_bHasRGBPel ) + { + fillRGBBuffer(); + } + return m_pcARGB32; } /** @@ -284,7 +292,7 @@ public: private: //! Strcut with the pixel format description. - PlaYUVerFramePelFormat* m_pcPelFormat; + PlaYUVerPixFmtDescriptor* m_pcPelFormat; UInt m_uiWidth; //!< Width of the frame UInt m_uiHeight; //!< Height of the frame @@ -295,7 +303,7 @@ private: Pel*** m_pppcInputPel; Bool m_bHasRGBPel; //!< Flag indicating that the ARGB buffer was computed - UChar* m_pcRGB32; //!< Buffer with the ARGB pixels used in Qt libs + UChar* m_pcARGB32; //!< Buffer with the ARGB pixels used in Qt libs Void init( UInt width, UInt height, Int pel_format ); diff --git a/lib/PlaYUVerFramePixelFormats.cpp b/lib/PlaYUVerFramePixelFormats.cpp index 6288af8..2ad9565 100644 --- a/lib/PlaYUVerFramePixelFormats.cpp +++ b/lib/PlaYUVerFramePixelFormats.cpp @@ -52,42 +52,28 @@ namespace plaYUVer #define ADD_FFMPEG_PEL_FMT( fmt ) 0 #endif -/** - * YUV Formats - * Progressive and interlaces - */ -Void frameFromBufferYUVProgressive( Pel* in, Pel ***out, UInt width, UInt height, UInt ratioChroma ) +Void fillARGB32bufferYUV( Pel*** in, UChar* out, UInt width, UInt height, UInt ratioChromaHor, UInt ratioChromaVer ) { - memcpy( &out[LUMA][0][0], in, width * height * sizeof(Pel) ); - memcpy( &out[CHROMA_U][0][0], in + width * height, width * height / ratioChroma * sizeof(Pel) ); - memcpy( &out[CHROMA_V][0][0], in + width * height + width * height / ratioChroma, width * height / ratioChroma * sizeof(Pel) ); -} - -Void bufferFromFrameYUVProgressive( Pel*** in, Pel *out, UInt width, UInt height, UInt ratioChroma ) -{ - memcpy( out, &in[LUMA][0][0], width * height * sizeof(Pel) ); - memcpy( out + width * height, &in[CHROMA_U][0][0], width * height / ratioChroma * sizeof(Pel) ); - memcpy( out + width * height + width * height / ratioChroma, &in[CHROMA_V][0][0], width * height / ratioChroma * sizeof(Pel) ); -} - -Void fillRGBbufferYUV( Pel*** in, UChar* out, UInt width, UInt height, UInt ratioChromaHor, UInt ratioChromaVer ) -{ - Pel* pY = in[LUMA][0]; + Pel* pLineY = in[LUMA][0]; Pel* pLineU = in[CHROMA_U][0]; Pel* pLineV = in[CHROMA_V][0]; - UInt uiChromaStride = width >> ratioChromaHor; + UInt uiChromaStride = CHROMASHIFT( width, ratioChromaHor ); + Pel* pY; Pel* pU; Pel* pV; Int iY, iU, iV, iR, iG, iB; - UInt* buff = ( UInt* )out; + UInt* pARGBLine = ( UInt* )out; + UInt* pARGB; for( UInt y = 0; y < height >> ratioChromaVer; y++ ) { for( Int i = 0; i < 1 << ratioChromaVer; i++ ) { + pY = pLineY; pU = pLineU; pV = pLineV; + pARGB = pARGBLine; for( UInt x = 0; x < width >> ratioChromaHor; x++ ) { iU = *pU++; @@ -96,29 +82,18 @@ Void fillRGBbufferYUV( Pel*** in, UChar* out, UInt width, UInt height, UInt rati { iY = *pY++; YUV2RGB( iY, iU, iV, iR, iG, iB ); - *buff = PEL_RGB( iR, iG, iB ); - buff++; + *pARGB++ = PEL_RGB( iR, iG, iB ); } } + pLineY += width; + pARGBLine += width; } pLineU += uiChromaStride; pLineV += uiChromaStride; } } -/** - * YUV420p 12 bits per pixel - */ - -Void frameFromBufferYUV420p( Pel *in, Pel*** out, UInt width, UInt height ) -{ - frameFromBufferYUVProgressive( in, out, width, height, 4 ); -} -Void bufferFromFrameYUV420p( Pel ***in, Pel* out, UInt width, UInt height ) -{ - bufferFromFrameYUVProgressive( in, out, width, height, 4 ); -} -Void fillRGBbufferYUV420p( Pel*** in, UChar* out, UInt width, UInt height ) +Void fillARGB32bufferYUV420p( Pel*** in, UChar* out, UInt width, UInt height ) { #ifdef USE_SSE if( ( width % 16 ) == 0 ) @@ -261,133 +236,21 @@ Void fillRGBbufferYUV420p( Pel*** in, UChar* out, UInt width, UInt height ) else #endif { - fillRGBbufferYUV( in, out, width, height, 1, 1 ); + fillARGB32bufferYUV( in, out, width, height, 1, 1 ); } } -PlaYUVerFramePelFormat yuv420p = +Void fillARGB32bufferYUV444p( Pel*** in, UChar* out, UInt width, UInt height ) { - "YUV420p", - PlaYUVerFrame::COLOR_YUV, - 3, - 2, - 2, - frameFromBufferYUV420p, - bufferFromFrameYUV420p, - fillRGBbufferYUV420p, - ADD_FFMPEG_PEL_FMT( AV_PIX_FMT_YUV420P ), }; - -/** - * YUV444p 24 bits per pixel - */ - -Void frameFromBufferYUV444p( Pel *in, Pel*** out, UInt width, UInt height ) -{ - frameFromBufferYUVProgressive( in, out, width, height, 1 ); -} -Void bufferFromFrameYUV444p( Pel ***in, Pel* out, UInt width, UInt height ) -{ - bufferFromFrameYUVProgressive( in, out, width, height, 1 ); -} -Void fillRGBbufferYUV444p( Pel*** in, UChar* out, UInt width, UInt height ) -{ - fillRGBbufferYUV( in, out, width, height, 0, 0 ); -} -PlaYUVerFramePelFormat yuv444p = -{ - "YUV444p", - PlaYUVerFrame::COLOR_YUV, - 3, - 1, - 1, - frameFromBufferYUV444p, - bufferFromFrameYUV444p, - fillRGBbufferYUV444p, - ADD_FFMPEG_PEL_FMT( AV_PIX_FMT_YUV444P ), }; - -/** - * YUV422p 16 bits per pixel - */ - -Void frameFromBufferYUV422p( Pel *in, Pel*** out, UInt width, UInt height ) -{ - frameFromBufferYUVProgressive( in, out, width, height, 2 ); -} -Void bufferFromFrameYUV422p( Pel ***in, Pel* out, UInt width, UInt height ) -{ - bufferFromFrameYUVProgressive( in, out, width, height, 2 ); -} -Void fillRGBbufferYUV422( Pel*** in, UChar* out, UInt width, UInt height ) -{ - fillRGBbufferYUV( in, out, width, height, 1, 0 ); -} -PlaYUVerFramePelFormat yuv422p = -{ - "YUV422p", - PlaYUVerFrame::COLOR_YUV, - 3, - 2, - 1, - frameFromBufferYUV422p, - bufferFromFrameYUV422p, - fillRGBbufferYUV422, - ADD_FFMPEG_PEL_FMT( AV_PIX_FMT_YUV422P ), }; - -/** - * YUYV422 16 bits per pixel - */ -Void frameFromBufferYUYV422( Pel *in, Pel*** out, UInt width, UInt height ) -{ - Pel* pY = out[LUMA][0]; - Pel* pU = out[CHROMA_U][0]; - Pel* pV = out[CHROMA_V][0]; - for( UInt i = 0; i < width * height / 2; i++ ) - { - *pY++ = *in++; - *pU++ = *in++; - *pY++ = *in++; - *pV++ = *in++; - } -} -Void bufferFromFrameYUYV422( Pel ***in, Pel* out, UInt width, UInt height ) -{ - Pel* pY = in[LUMA][0]; - Pel* pU = in[CHROMA_U][0]; - Pel* pV = in[CHROMA_V][0]; - for( UInt i = 0; i < height * width / 2; i++ ) - { - *out++ = *pY++; - *out++ = *pU++; - *out++ = *pY++; - *out++ = *pV++; - } + fillARGB32bufferYUV( in, out, width, height, 0, 0 ); } -PlaYUVerFramePelFormat yuyv422 = +Void fillARGB32bufferYUV422( Pel*** in, UChar* out, UInt width, UInt height ) { - "YUYV422", - PlaYUVerFrame::COLOR_YUV, - 3, - 2, - 1, - frameFromBufferYUYV422, - bufferFromFrameYUYV422, - fillRGBbufferYUV422, - ADD_FFMPEG_PEL_FMT( AV_PIX_FMT_YUYV422 ), }; - -/** - * Gray Format - */ - -Void frameFromBufferGray( Pel *in, Pel*** out, UInt width, UInt height ) -{ - memcpy( &out[LUMA][0][0], in, width * height * sizeof(Pel) ); + fillARGB32bufferYUV( in, out, width, height, 1, 0 ); } -Void bufferFromFrameGray( Pel ***in, Pel* out, UInt width, UInt height ) -{ - memcpy( out, &in[LUMA][0][0], width * height * sizeof(Pel) ); -} -Void fillRGBbufferGray( Pel*** in, UChar* out, UInt width, UInt height ) + +Void fillARGB32bufferGray( Pel*** in, UChar* out, UInt width, UInt height ) { Pel *inPel = in[0][0]; Pel iY; @@ -399,42 +262,8 @@ Void fillRGBbufferGray( Pel*** in, UChar* out, UInt width, UInt height ) inPel++; } } -PlaYUVerFramePelFormat gray = -{ - "GRAY", - PlaYUVerFrame::COLOR_GRAY, - 1, - 0, - 0, - frameFromBufferGray, - bufferFromFrameGray, - fillRGBbufferGray, - ADD_FFMPEG_PEL_FMT( AV_PIX_FMT_GRAY8 ), }; -/** - * RGB formats - * Interlaced - */ - -Void frameFromBufferRGB( Pel *in, Pel*** out, UInt64 size, Pel* pFirst, Pel* pSecond, Pel* pthird ) -{ - for( UInt i = 0; i < size; i++ ) - { - *pFirst++ = *in++; - *pSecond++ = *in++; - *pthird++ = *in++; - } -} -Void bufferFromFrameRGB( Pel ***in, Pel* out, UInt64 size, Pel* pFirst, Pel* pSecond, Pel* pthird ) -{ - for( UInt i = 0; i < size; i++ ) - { - *out++ = *pFirst++; - *out++ = *pSecond++; - *out++ = *pthird++; - } -} -Void fillRGBbufferRGB( Pel*** in, UChar* out, UInt width, UInt height ) +Void fillARGB32bufferRGB( Pel*** in, UChar* out, UInt width, UInt height ) { Pel* pR = in[COLOR_R][0]; Pel* pG = in[COLOR_G][0]; @@ -450,51 +279,123 @@ Void fillRGBbufferRGB( Pel*** in, UChar* out, UInt width, UInt height ) } } -/** RGB 8 bits per pixel / 3 channels */ -Void frameFromBufferRGB24( Pel *in, Pel*** out, UInt width, UInt height ) -{ - frameFromBufferRGB( in, out, width * height, out[COLOR_R][0], out[COLOR_G][0], out[COLOR_B][0] ); -} -Void bufferFromFrameRGB24( Pel ***in, Pel* out, UInt width, UInt height ) -{ - bufferFromFrameRGB( in, out, width * height, in[COLOR_R][0], in[COLOR_G][0], in[COLOR_B][0] ); -} -PlaYUVerFramePelFormat RGB24 = +PlaYUVerPixFmtDescriptor yuv420p = +{ + "YUV420p", + PlaYUVerFrame::COLOR_YUV, + 3, + 3, + 1, + 1, + ADD_FFMPEG_PEL_FMT( AV_PIX_FMT_YUV420P ), + { + { 0, 0, 1, 0, 7 }, /* Y */ + { 1, 0, 1, 0, 7 }, /* U */ + { 2, 0, 1, 0, 7 }, /* V */ + }, + fillARGB32bufferYUV420p, +}; + +PlaYUVerPixFmtDescriptor yuv422p = +{ + "YUV422p", + PlaYUVerFrame::COLOR_YUV, + 3, + 3, + 1, + 0, + ADD_FFMPEG_PEL_FMT( AV_PIX_FMT_YUV422P ), + { + { 0, 0, 1, 0, 7 }, /* Y */ + { 1, 0, 1, 0, 7 }, /* U */ + { 2, 0, 1, 0, 7 }, /* V */ + }, + fillARGB32bufferYUV422, +}; + +PlaYUVerPixFmtDescriptor yuv444p = +{ + "YUV444p", + PlaYUVerFrame::COLOR_YUV, + 3, + 3, + 0, + 0, + ADD_FFMPEG_PEL_FMT( AV_PIX_FMT_YUV444P ), + { + { 0, 0, 1, 0, 7 }, /* Y */ + { 1, 0, 1, 0, 7 }, /* U */ + { 2, 0, 1, 0, 7 }, /* V */ + }, + fillARGB32bufferYUV444p, +}; + +PlaYUVerPixFmtDescriptor yuyv422 = +{ + "YUYV422", + PlaYUVerFrame::COLOR_YUV, + 3, + 1, + 1, + 0, + ADD_FFMPEG_PEL_FMT( AV_PIX_FMT_YUYV422 ), + { + { 0, 1, 1, 0, 7 }, /* Y */ + { 0, 3, 2, 0, 7 }, /* U */ + { 0, 3, 4, 0, 7 }, /* V */ + }, + fillARGB32bufferYUV422, +}; + +PlaYUVerPixFmtDescriptor gray = +{ + "GRAY", + PlaYUVerFrame::COLOR_GRAY, + 1, + 1, + 0, + 0, + ADD_FFMPEG_PEL_FMT( AV_PIX_FMT_GRAY8 ), + { { 0, 0, 1, 0, 7 } }, /* Y */ + fillARGB32bufferGray, +}; + +PlaYUVerPixFmtDescriptor RGB24 = { "RGB24", PlaYUVerFrame::COLOR_RGB, 3, 1, - 1, - frameFromBufferRGB24, - bufferFromFrameRGB24, - fillRGBbufferRGB, - ADD_FFMPEG_PEL_FMT( AV_PIX_FMT_RGB24 ), }; + 0, + 0, + ADD_FFMPEG_PEL_FMT( AV_PIX_FMT_RGB24 ), + { + { 0, 2, 1, 0, 7 }, /* R */ + { 0, 2, 2, 0, 7 }, /* G */ + { 0, 2, 3, 0, 7 }, /* B */ + }, + fillARGB32bufferRGB, +}; -/** BGR 8 bits per pixel / 3 channels */ -Void frameFromBufferBGR24( Pel *in, Pel*** out, UInt width, UInt height ) -{ - frameFromBufferRGB( in, out, width * height, out[COLOR_B][0], out[COLOR_G][0], out[COLOR_R][0] ); -} -Void bufferFromFrameBGR24( Pel ***in, Pel* out, UInt width, UInt height ) -{ - bufferFromFrameRGB( in, out, width * height, in[COLOR_B][0], in[COLOR_G][0], in[COLOR_R][0] ); -} - -PlaYUVerFramePelFormat BGR24 = +PlaYUVerPixFmtDescriptor BGR24 = { "BRG24", PlaYUVerFrame::COLOR_RGB, 3, 1, - 1, - frameFromBufferBGR24, - bufferFromFrameBGR24, - fillRGBbufferRGB, - ADD_FFMPEG_PEL_FMT( AV_PIX_FMT_BGR24 ), }; + 0, + 0, + ADD_FFMPEG_PEL_FMT( AV_PIX_FMT_BGR24 ), + { + { 0, 2, 3, 0, 7 }, /* R */ + { 0, 2, 2, 0, 7 }, /* G */ + { 0, 2, 1, 0, 7 }, /* B */ + }, + fillARGB32bufferRGB, +}; -PlaYUVerFramePelFormat g_PlaYUVerFramePelFormatsList[PLAYUVER_NUMBER_FORMATS] = +PlaYUVerPixFmtDescriptor g_PlaYUVerPixFmtDescriptorsList[PLAYUVER_NUMBER_FORMATS] = { yuv420p, yuv444p, @@ -502,6 +403,7 @@ PlaYUVerFramePelFormat g_PlaYUVerFramePelFormatsList[PLAYUVER_NUMBER_FORMATS] = yuyv422, gray, RGB24, - BGR24, }; + BGR24, +}; } // NAMESPACE diff --git a/lib/PlaYUVerFramePixelFormats.h b/lib/PlaYUVerFramePixelFormats.h index 7d6c013..1052ade 100644 --- a/lib/PlaYUVerFramePixelFormats.h +++ b/lib/PlaYUVerFramePixelFormats.h @@ -32,6 +32,12 @@ namespace plaYUVer { +#define CHROMA_RESAMPLING( X ) ( ( ( X + 1 ) >> 1 ) << 1 ) + +#define CHROMARATIO( SIZE, RATIO ) ( RATIO > 1 ? ( ( SIZE + 1 ) / RATIO ) : SIZE ) + +#define CHROMASHIFT( SIZE, SHIFT ) UInt( -( ( - ( Int( SIZE ) ) ) >> SHIFT ) ) + #define CLAMP(X) X = X < 0 ? 0 : X > 255 ? 255 : X; #define YUV2RGB( iY, iU, iV, iR, iG, iB ) \ @@ -70,21 +76,94 @@ inline Int pelAlpha( UInt rgb ) // get alpha part of RGBA #define PEL_RGB( r, g, b ) \ ( 0xffu << 24 ) | ( ( r & 0xff ) << 16 ) | ( ( g & 0xff ) << 8 ) | ( b & 0xff ) -typedef struct PlaYUVerFramePelFormat +typedef struct PlaYUVerComponentDescriptor { - const Char* name; + /** + * Which of the 4 planes contains the component. + */ + UInt16 plane; + + /** + * Number of elements between 2 horizontally consecutive pixels minus 1. + * Elements are bits for bitstream formats, bytes otherwise. + */ + UInt16 step_minus1; + + /** + * Number of elements before the component of the first pixel plus 1. + * Elements are bits for bitstream formats, bytes otherwise. + */ + UInt16 offset_plus1; + + /** + * Number of least significant bits that must be shifted away + * to get the value. + */ + UInt16 shift; + + /** + * Number of bits in the component minus 1. + */ + UInt16 depth_minus1; +} PlaYUVerComponentDescriptor; + +/** + * Descriptor that unambiguously describes how the bits of a pixel are + * stored in the up to 4 data planes of an image. It also stores the + * subsampling factors and number of components. + * + * @note This is separate of the colorspace (RGB, YCbCr, YPbPr, JPEG-style YUV + * and all the YUV variants) AVPixFmtDescriptor just stores how values + * are stored not what these values represent. + */ +typedef struct PlaYUVerPixFmtDescriptor +{ + const char *name; + Int colorSpace; - UInt numberChannels; - Int ratioChromaWidth; - Int ratioChromaHeight; - Void (*frameFromBuffer)( Pel *in, Pel*** out, UInt width, UInt height ); - Void (*bufferFromFrame)( Pel ***in, Pel* out, UInt width, UInt height ); - Void (*fillRGBbuffer)( Pel*** in, UChar* out, UInt width, UInt height ); + + UInt8 numberChannels; ///< The number of components each pixel has, (1-4) + + UInt8 numberPlanes; ///< The number of planes that should be read from the file + + /** + * Amount to shift the luma width right to find the chroma width. + * For YV12 this is 1 for example. + * chroma_width = -((-luma_width) >> log2ChromaWidth) + * The note above is needed to ensure rounding up. + * This value only refers to the chroma components. + */ + UInt8 log2ChromaWidth; ///< chroma_width = -((-luma_width )>>log2ChromaWidth) + + /** + * Amount to shift the luma height right to find the chroma height. + * For YV12 this is 1 for example. + * chroma_height= -((-luma_height) >> log2ChromaHeight) + * The note above is needed to ensure rounding up. + * This value only refers to the chroma components. + */ + UInt8 log2ChromaHeight; + Int ffmpegPelFormat; -}PlaYUVerFramePelFormat; + + /** + * Parameters that describe how pixels are packed. + * If the format has 2 or 4 components, then alpha is last. + * If the format has 1 or 2 components, then luma is 0. + * If the format has 3 or 4 components, + * if the RGB flag is set then 0 is red, 1 is green and 2 is blue; + * otherwise 0 is luma, 1 is chroma-U and 2 is chroma-V. + */ + PlaYUVerComponentDescriptor comp[4]; + + Void (*fillARGB32buffer)( Pel*** in, UChar* out, UInt width, UInt height ); + +} PlaYUVerPixFmtDescriptor; + +#define MAX_NUMBER_PLANES 3 #define PLAYUVER_NUMBER_FORMATS 7 -extern PlaYUVerFramePelFormat g_PlaYUVerFramePelFormatsList[PLAYUVER_NUMBER_FORMATS]; +extern PlaYUVerPixFmtDescriptor g_PlaYUVerPixFmtDescriptorsList[PLAYUVER_NUMBER_FORMATS]; } // NAMESPACE diff --git a/lib/PlaYUVerStream.cpp b/lib/PlaYUVerStream.cpp index 055885e..b30012b 100644 --- a/lib/PlaYUVerStream.cpp +++ b/lib/PlaYUVerStream.cpp @@ -149,7 +149,7 @@ PlaYUVerStream::PlaYUVerStream() m_uiTotalFrameNum = 0; m_iCurrFrameNum = -1; m_iPixelFormat = -1; - m_uiFrameRate = 30; + m_dFrameRate = 30; m_iFileFormat = -1; m_pStreamBuffer = NULL; m_cFilename = ""; @@ -185,7 +185,7 @@ Bool PlaYUVerStream::open( std::string filename, std::string resolution, std::st } for( UInt i = 0; i < PlaYUVerFrame::supportedPixelFormatListNames().size(); i++ ) { - if( PlaYUVerFrame::supportedPixelFormatListNames()[i] == input_format_name ) + if( lowercase( PlaYUVerFrame::supportedPixelFormatListNames()[i] ) == lowercase( input_format_name ) ) { input_format = i; break; @@ -206,7 +206,7 @@ Bool PlaYUVerStream::open( std::string filename, UInt width, UInt height, Int in m_uiWidth = width; m_uiHeight = height; m_iPixelFormat = input_format; - m_uiFrameRate = frame_rate; + m_dFrameRate = frame_rate; m_pchFilename = new Char[m_cFilename.size() + 1]; std::copy( m_cFilename.begin(), m_cFilename.end(), m_pchFilename ); @@ -238,7 +238,7 @@ Bool PlaYUVerStream::open( std::string filename, UInt width, UInt height, Int in m_uiStreamHandler = YUV_IO; } //#ifdef USE_OPENCV -// else if ( m_cFormatName == "png" ) +// else if( m_cFormatName == "png" || m_cFormatName == "jpg" ) // { // m_uiStreamHandler = OPENCV_HANDLER; // } @@ -272,7 +272,7 @@ Bool PlaYUVerStream::open( std::string filename, UInt width, UInt height, Int in #ifdef USE_FFMPEG if( m_uiStreamHandler == FFMPEG ) { - if( !m_cLibAvContext->initAvFormat( m_pchFilename, m_uiWidth, m_uiHeight, m_iPixelFormat, m_uiFrameRate, m_uiTotalFrameNum ) ) + if( !m_cLibAvContext->initAvFormat( m_pchFilename, m_uiWidth, m_uiHeight, m_iPixelFormat, m_dFrameRate, m_uiTotalFrameNum ) ) { throw "Cannot open file using FFmpeg libs"; } @@ -280,6 +280,19 @@ Bool PlaYUVerStream::open( std::string filename, UInt width, UInt height, Int in } #endif +#ifdef USE_OPENCV + if( m_uiStreamHandler == OPENCV_HANDLER ) + { + m_pcCurrFrame = LibOpenCVHandler::loadFrame( m_cFilename ); + if( m_pcCurrFrame ) + { + m_uiWidth = m_pcCurrFrame->getWidth(); + m_uiHeight = m_pcCurrFrame->getHeight(); + m_iPixelFormat = m_pcCurrFrame->getPelFormat(); + } + } +#endif + if( m_uiWidth <= 0 || m_uiHeight <= 0 || m_iPixelFormat < 0 ) { close(); @@ -287,49 +300,59 @@ Bool PlaYUVerStream::open( std::string filename, UInt width, UInt height, Int in return m_bInit; } - if( m_uiStreamHandler == YUV_IO ) + if( m_uiStreamHandler != OPENCV_HANDLER ) { - if( !openFile() ) + if( m_uiStreamHandler == YUV_IO ) { - close(); - throw "[PlaYUVerStream] Cannot open file"; - return m_bInit; + if( !openFile() ) + { + close(); + throw "[PlaYUVerStream] Cannot open file"; + return m_bInit; + } + m_cFormatName = "YUV"; + m_cCodedName = "Raw Video"; } - m_cFormatName = "YUV"; - m_cCodedName = "Raw Video"; - } - getMem1D( &m_ppcFrameBuffer, m_uiFrameBufferSize ); - for( UInt i = 0; i < m_uiFrameBufferSize; i++ ) - { - m_ppcFrameBuffer[i] = new PlaYUVerFrame( m_uiWidth, m_uiHeight, m_iPixelFormat ); - if( !m_ppcFrameBuffer[i] ) + getMem1D( &m_ppcFrameBuffer, m_uiFrameBufferSize ); + for( UInt i = 0; i < m_uiFrameBufferSize; i++ ) { - close(); - throw "[PlaYUVerStream] Cannot allocated frame buffer"; - return m_bInit; + m_ppcFrameBuffer[i] = new PlaYUVerFrame( m_uiWidth, m_uiHeight, m_iPixelFormat ); + if( !m_ppcFrameBuffer[i] ) + { + close(); + throw "[PlaYUVerStream] Cannot allocated frame buffer"; + return m_bInit; + } } - } - m_uiFrameBufferIndex = 0; - m_pcCurrFrame = m_ppcFrameBuffer[m_uiFrameBufferIndex]; + m_uiFrameBufferIndex = 0; + m_pcCurrFrame = m_ppcFrameBuffer[m_uiFrameBufferIndex]; - UInt64 frame_bytes_input = m_pcCurrFrame->getBytesPerFrame(); + UInt64 frame_bytes_input = m_pcCurrFrame->getBytesPerFrame(); - if( m_uiStreamHandler == YUV_IO && m_bIsInput ) - { - fseek( m_pFile, 0, SEEK_END ); - UInt64 fileSize = ftell( m_pFile ); + if( m_uiStreamHandler == YUV_IO && m_bIsInput ) + { + fseek( m_pFile, 0, SEEK_END ); + UInt64 fileSize = ftell( m_pFile ); #if 0 - if( fileSize % frame_bytes_input ) - { - Int remaining = fileSize % frame_bytes_input; - close(); - throw "[PlaYUVerStream] Incorrect configuration: failed ( fileSize % frame_bytes_input = " << remaining << " )"; - return m_bInit; - } + if( fileSize % frame_bytes_input ) + { + Int remaining = fileSize % frame_bytes_input; + close(); + throw "[PlaYUVerStream] Incorrect configuration: failed ( fileSize % frame_bytes_input = " << remaining << " )"; + return m_bInit; + } #endif - m_uiTotalFrameNum = fileSize / frame_bytes_input; - fseek( m_pFile, 0, SEEK_SET ); + m_uiTotalFrameNum = fileSize / frame_bytes_input; + fseek( m_pFile, 0, SEEK_SET ); + } + } + else + { + m_pcNextFrame = NULL; + m_uiFrameBufferSize = 0; + m_uiFrameBufferIndex = 0; + m_uiTotalFrameNum = 1; } if( m_bIsInput && m_uiTotalFrameNum <= 0 ) @@ -420,7 +443,7 @@ Void PlaYUVerStream::getFormat( UInt& rWidth, UInt& rHeight, Int& rInputFormat, rWidth = m_uiWidth; rHeight = m_uiHeight; rInputFormat = m_iPixelFormat; - rFrameRate = m_uiFrameRate; + rFrameRate = m_dFrameRate; } else { @@ -484,7 +507,7 @@ Void PlaYUVerStream::getDuration( Int* duration_array ) else #endif { - secs = m_uiTotalFrameNum / m_uiFrameRate; + secs = m_uiTotalFrameNum / m_dFrameRate; } mins = secs / 60; secs %= 60; @@ -495,6 +518,14 @@ Void PlaYUVerStream::getDuration( Int* duration_array ) *duration_array++ = secs; } +Void PlaYUVerStream::readFrameFillRGBBuffer() +{ + readFrame(); + if( m_pcNextFrame ) + m_pcNextFrame->fillRGBBuffer(); + return; +} + Void PlaYUVerStream::readFrame() { if( !m_bInit || !m_bIsInput || m_bLoadAll ) @@ -506,6 +537,11 @@ Void PlaYUVerStream::readFrame() return; } + if( m_uiStreamHandler == OPENCV_HANDLER ) + { + return; + } + #ifdef USE_FFMPEG if( m_uiStreamHandler == FFMPEG ) { @@ -529,7 +565,6 @@ Void PlaYUVerStream::readFrame() m_pcNextFrame->frameFromBuffer( m_pStreamBuffer, bytes_read ); } m_uiCurrFrameFileIdx++; - m_pcNextFrame->fillRGBBuffer(); return; } @@ -652,6 +687,11 @@ PlaYUVerFrame* PlaYUVerStream::getCurrFrame() return m_pcCurrFrame; } +PlaYUVerFrame* PlaYUVerStream::getNextFrame() +{ + return m_pcNextFrame; +} + Bool PlaYUVerStream::seekInput( UInt64 new_frame_num ) { if( !m_bInit || new_frame_num < 0 || new_frame_num >= m_uiTotalFrameNum || ( Int64 )new_frame_num == m_iCurrFrameNum ) @@ -666,6 +706,10 @@ Bool PlaYUVerStream::seekInput( UInt64 new_frame_num ) setNextFrame(); return true; } + if( m_uiStreamHandler == OPENCV_HANDLER ) + { + return true; + } #ifdef USE_FFMPEG if( m_uiStreamHandler == FFMPEG ) { diff --git a/lib/PlaYUVerStream.h b/lib/PlaYUVerStream.h index c41da5f..a2685aa 100644 --- a/lib/PlaYUVerStream.h +++ b/lib/PlaYUVerStream.h @@ -95,7 +95,7 @@ private: UInt m_uiWidth; UInt m_uiHeight; - UInt m_uiFrameRate; + Double m_dFrameRate; UInt64 m_uiTotalFrameNum; Int64 m_iCurrFrameNum; @@ -134,6 +134,7 @@ public: Void loadAll(); Void readFrame(); + Void readFrameFillRGBBuffer(); Void writeFrame(); Void writeFrame( PlaYUVerFrame *pcFrame ); @@ -143,6 +144,7 @@ public: Bool setNextFrame(); PlaYUVerFrame* getCurrFrame(); PlaYUVerFrame* getCurrFrame( PlaYUVerFrame * ); + PlaYUVerFrame* getNextFrame(); Bool seekInput( UInt64 new_frame_num ); @@ -184,9 +186,9 @@ public: { return m_iCurrFrameNum; } - UInt getFrameRate() + Double getFrameRate() { - return m_uiFrameRate; + return m_dFrameRate; } Void getDuration( Int* duration_array ); diff --git a/modules/FilterComponent.cpp b/modules/FilterComponent.cpp index a030bdf..6102704 100644 --- a/modules/FilterComponent.cpp +++ b/modules/FilterComponent.cpp @@ -60,7 +60,7 @@ FilterComponentLuma::FilterComponentLuma() /* Module Definition */ m_iModuleType = FRAME_PROCESSING_MODULE; // Apply module to the frames or to the whole sequence. // Currently only support for frame - m_pchModuleCategory = "Filter Component"; // Category (sub-menu) + m_pchModuleCategory = "FilterComponent"; // Category (sub-menu) m_pchModuleName = "Luma"; // Name m_pchModuleTooltip = "Filter Y matrix of YUV frame"; // Description m_uiNumberOfFrames = MODULE_REQUIRES_ONE_FRAME; // Number of Frames required (ONE_FRAME, TWO_FRAMES, THREE_FRAMES) @@ -83,8 +83,8 @@ FilterComponentChromaU::FilterComponentChromaU() { /* Module Definition */ m_iModuleType = FRAME_PROCESSING_MODULE; - m_pchModuleCategory = "Filter Component"; - m_pchModuleName = "Chroma U"; + m_pchModuleCategory = "FilterComponent"; + m_pchModuleName = "ChromaU"; m_pchModuleTooltip = "Filter U matrix of YUV frame"; m_uiNumberOfFrames = MODULE_REQUIRES_ONE_FRAME; m_uiModuleRequirements = MODULE_REQUIRES_NOTHING; @@ -105,8 +105,8 @@ FilterComponentChromaV::FilterComponentChromaV() { /* Module Definition */ m_iModuleType = FRAME_PROCESSING_MODULE; - m_pchModuleCategory = "Filter Component"; - m_pchModuleName = "Chroma V"; + m_pchModuleCategory = "FilterComponent"; + m_pchModuleName = "ChromaV"; m_pchModuleTooltip = "Filter V matrix of YUV frame"; m_uiNumberOfFrames = MODULE_REQUIRES_ONE_FRAME; m_uiModuleRequirements = MODULE_REQUIRES_NOTHING; diff --git a/modules/LumaAverage.cpp b/modules/LumaAverage.cpp index 9d8cd6a..c32a79d 100644 --- a/modules/LumaAverage.cpp +++ b/modules/LumaAverage.cpp @@ -32,7 +32,7 @@ LumaAverage::LumaAverage() /* Module Definition */ m_iModuleType = FRAME_MEASUREMENT_MODULE; m_pchModuleCategory = "Measurements"; - m_pchModuleName = "Luma Average"; + m_pchModuleName = "LumaAverage"; m_pchModuleTooltip = "Measure the average of luma component"; m_uiNumberOfFrames = MODULE_REQUIRES_ONE_FRAME; m_uiModuleRequirements = MODULE_REQUIRES_SIDEBAR; diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt new file mode 100644 index 0000000..f45ce07 --- /dev/null +++ b/tools/CMakeLists.txt @@ -0,0 +1,23 @@ +### +### CMakeLists for playuver app component +### + +# This is hard way - please fix +INCLUDE_DIRECTORIES( + ${CMAKE_CURRENT_BINARY_DIR}/../ + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/../ ) + +set(plaYUver_Tools_SRCS + main.cpp + PlaYUVerTools.cpp + CommandLineHandle.cpp +) + +ADD_EXECUTABLE( ${PROJECT_NAME}Tools ${plaYUver_Tools_SRCS} ) + +TARGET_LINK_LIBRARIES( ${PROJECT_NAME}Tools PlaYUVerLib PlaYUVerModules ) + +INSTALL(TARGETS ${PROJECT_NAME}Tools DESTINATION bin ) + + diff --git a/tools/CommandLineHandle.cpp b/tools/CommandLineHandle.cpp new file mode 100644 index 0000000..0c60759 --- /dev/null +++ b/tools/CommandLineHandle.cpp @@ -0,0 +1,143 @@ +/* This file is a part of plaYUVer project + * Copyright (C) 2014-2015 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 CommandLineHandle.cpp + * \brief Handle for command line + */ + +#include +#include "CommandLineHandle.h" +#include "lib/PlaYUVerFrame.h" +#include "modules/PlaYUVerModuleIf.h" +#include "modules/PlaYUVerModuleFactory.h" + +namespace plaYUVer +{ + +CommandLineHandle::CommandLineHandle() +{ + +} + +CommandLineHandle::~CommandLineHandle() +{ + +} + +Int CommandLineHandle::parseToolsArgs() +{ + Int iRet = 0; + + po::options_description qualityOpts( "Quality" ); + qualityOpts.add_options() /**/ + ( "quality", po::value(), "select a quality metric" ) /**/ + ( "quality_metrics", "list supported quality metrics" ); + + po::options_description moduleOpts( "Module" ); + moduleOpts.add_options() /**/ + ( "module", po::value(), "select a module (use internal name)" ) /**/ + ( "module_list", "list supported modules" ) /**/ + ( "module_list_full", "detailed list supported modules" ); + + addOptions( qualityOpts ); + addOptions( moduleOpts ); + + if( !parse() ) + { + iRet = 1; + } + + if( getOptionsMap().count( "quality_metrics" ) ) + { + printf( "PlaYUVer supported quality metrics: \n" ); + for( UInt i = 0; i < PlaYUVerFrame::supportedQualityMetricsList().size(); i++ ) + { + printf( " %s\n", PlaYUVerFrame::supportedQualityMetricsList()[i].c_str() ); + } + iRet = 1; + } + + if( getOptionsMap().count( "module_list" ) || getOptionsMap().count( "module_list_full" ) ) + { + listModules(); + iRet = 1; + } + + return iRet; +} + +Void CommandLineHandle::listModules() +{ + Bool bDetailed = false; + + if( getOptionsMap().count( "module_list_full" ) ) + bDetailed = true; + + PlaYUVerModuleIf* pcCurrModuleIf; + PlaYUVerModuleFactoryMap& PlaYUVerModuleFactoryMap = PlaYUVerModuleFactory::Get()->getMap(); + PlaYUVerModuleFactoryMap::iterator it = PlaYUVerModuleFactoryMap.begin(); + + printf( "PlaYUVer available modules: \n" ); + //printf( " " ); + printf( " [Internal Name] " ); + if( bDetailed ) + { + printf( " [Full Name] " ); + printf( " [Type] " ); + printf( " [Description]" ); + } + printf( " \n" ); + + Char ModuleNameString[40]; + + for( UInt i = 0; it != PlaYUVerModuleFactoryMap.end(); ++it, i++ ) + { + printf( " " ); + printf( "%-30s", it->first ); + if( bDetailed ) + { + ModuleNameString[0] = '\0'; + pcCurrModuleIf = it->second(); + + if( pcCurrModuleIf->m_pchModuleCategory ) + { + strcat( ModuleNameString, pcCurrModuleIf->m_pchModuleCategory ); + strcat( ModuleNameString, "/" ); + } + strcat( ModuleNameString, pcCurrModuleIf->m_pchModuleName ); + printf( " %-40s", ModuleNameString ); + switch( pcCurrModuleIf->m_iModuleType ) + { + case FRAME_PROCESSING_MODULE: + printf( " Processing " ); + break; + case FRAME_MEASUREMENT_MODULE: + printf( " Measurement " ); + break; + } + printf( " %s", pcCurrModuleIf->m_pchModuleTooltip ); + pcCurrModuleIf->Delete(); + } + printf( "\n" ); + } + +} + +} // NAMESPACE diff --git a/tools/CommandLineHandle.h b/tools/CommandLineHandle.h new file mode 100644 index 0000000..1fa6a35 --- /dev/null +++ b/tools/CommandLineHandle.h @@ -0,0 +1,48 @@ +/* This file is a part of plaYUVer project + * Copyright (C) 2014-2015 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 CommandLineHandle.h + * \brief Handle for command line + */ + +#ifndef __COMMANDLINEHANDLE_H__ +#define __COMMANDLINEHANDLE_H__ + +#include "config.h" +#include "lib/PlaYUVerDefs.h" +#include "lib/PlaYUVerCmdParser.h" + +namespace plaYUVer +{ + +class CommandLineHandle: public PlaYUVerCmdParser +{ +public: + CommandLineHandle(); + ~CommandLineHandle(); + + Int parseToolsArgs(); + Void listModules(); + +}; + +} // NAMESPACE + +#endif // __COMMANDLINEHANDLE_H__ diff --git a/tools/PlaYUVerTools.cpp b/tools/PlaYUVerTools.cpp new file mode 100644 index 0000000..d0ba086 --- /dev/null +++ b/tools/PlaYUVerTools.cpp @@ -0,0 +1,368 @@ +/* This file is a part of plaYUVer project + * Copyright (C) 2014-2015 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 PlaYUVerTools.cpp + * \brief Main definition of the PlaYUVerTools APp + */ + +#include "PlaYUVerTools.h" +#include "modules/PlaYUVerModuleIf.h" +#include "modules/PlaYUVerModuleFactory.h" + +namespace plaYUVer +{ + +PlaYUVerTools::PlaYUVerTools() +{ + m_uiOperation = INVALID_OPERATION; + m_uiNumberOfFrames = -1; + + m_uiQualityMetric = -1; + + m_pcCurrModuleIf = NULL; +} + +PlaYUVerTools::~PlaYUVerTools() +{ + for( UInt i = 0; i < m_apcInputStreams.size(); i++ ) + { + m_apcInputStreams[i]->close(); + } + for( UInt i = 0; i < m_apcOutputStreams.size(); i++ ) + { + m_apcOutputStreams[i]->close(); + } +} + +Int PlaYUVerTools::openInputs() +{ + /** + * Create input streams + */ + if( m_cCommandLineParser.getOptionsMap().count( "input" ) ) + { + std::string resolutionString( "" ); + if( m_cCommandLineParser.getOptionsMap().count( "size" ) ) + { + resolutionString = m_cCommandLineParser.getOptionsMap()["size"].as(); + } + std::string fmtString( "yuv420p" ); + if( m_cCommandLineParser.getOptionsMap().count( "pel_fmt" ) ) + { + fmtString = m_cCommandLineParser.getOptionsMap()["pel_fmt"].as(); + } + + std::vector inputFileNames = m_cCommandLineParser.getOptionsMap()["input"].as >(); + + PlaYUVerStream* pcStream; + for( UInt i = 0; i < inputFileNames.size(); i++ ) + { + pcStream = new PlaYUVerStream; + try + { + if( !pcStream->open( inputFileNames[i], resolutionString, fmtString, 1 ) ) + { + printf( "Cannot open input stream %s! ", inputFileNames[i].c_str() ); + return 2; + } + m_apcInputStreams.push_back( pcStream ); + } + catch( const char *msg ) + { + printf( "Cannot open input stream %s with the following error: \n%s\n", inputFileNames[i].c_str(), msg ); + return 2; + } + } + m_uiNumberOfFrames = MAX_UINT; + if( m_cCommandLineParser.getOptionsMap().count( "frames" ) ) + { + m_uiNumberOfFrames = m_cCommandLineParser.getOptionsMap()["frames"].as(); + } + + m_uiNumberOfComponents = MAX_UINT; + for( UInt i = 0; i < m_apcInputStreams.size(); i++ ) + { + if( m_apcInputStreams[i]->getFrameNum() < m_uiNumberOfFrames ) + m_uiNumberOfFrames = m_apcInputStreams[i]->getFrameNum(); + if( m_apcInputStreams[i]->getCurrFrame()->getNumberChannels() < m_uiNumberOfComponents ) + m_uiNumberOfComponents = m_apcInputStreams[i]->getCurrFrame()->getNumberChannels(); + } + } + return 0; +} + +Int PlaYUVerTools::openOutputs() +{ + if( m_cCommandLineParser.getOptionsMap().count( "output" ) ) + { + + } + return 0; +} + +Int PlaYUVerTools::Open( Int argc, Char *argv[] ) +{ + Int iRet = 0; + + m_cCommandLineParser.Config( argc, argv ); + if( ( iRet = m_cCommandLineParser.parseToolsArgs() ) > 0 ) + { + return iRet; + } + + if( openInputs() > 0 ) + { + return 2; + } + + /** + * Check Quality operation + */ + if( m_cCommandLineParser.getOptionsMap().count( "quality" ) ) + { + std::string qualityMetric = m_cCommandLineParser.getOptionsMap()["quality"].as(); + if( m_apcInputStreams.size() != 2 ) + { + printf( "Invalid number of inputs! " ); + return 2; + } + for( UInt i = 0; i < PlaYUVerFrame::supportedQualityMetricsList().size(); i++ ) + { + if( lowercase( PlaYUVerFrame::supportedQualityMetricsList()[i] ) == lowercase( qualityMetric ) ) + { + m_uiQualityMetric = i; + } + } + if( m_uiQualityMetric == -1 ) + { + printf( "Invalid quality metric! " ); + return 2; + } + m_uiOperation = QUALITY_OPERATION; + m_fpProcess = &PlaYUVerTools::QualityOperation; + printf( "PlaYUVer Quality\n" ); + } + + /** + * Check Module operation + */ + if( m_cCommandLineParser.getOptionsMap().count( "module" ) ) + { + std::string moduleName = m_cCommandLineParser.getOptionsMap()["module"].as(); + + PlaYUVerModuleFactoryMap& PlaYUVerModuleFactoryMap = PlaYUVerModuleFactory::Get()->getMap(); + PlaYUVerModuleFactoryMap::iterator it = PlaYUVerModuleFactoryMap.begin(); + for( UInt i = 0; it != PlaYUVerModuleFactoryMap.end(); ++it, i++ ) + { + if( strcmp( it->first, moduleName.c_str() ) == 0 ) + { + m_pcCurrModuleIf = it->second(); + break; + } + } + + if( m_apcInputStreams.size() != m_pcCurrModuleIf->m_uiNumberOfFrames ) + { + printf( "Invalid number of inputs! " ); + return 2; + } + + m_pcCurrModuleIf->create( m_apcInputStreams[0]->getCurrFrame() ); + + if( m_pcCurrModuleIf->m_iModuleType == FRAME_PROCESSING_MODULE ) + { + // Check outputs + std::vector outputFileNames; + if( m_cCommandLineParser.getOptionsMap().count( "output" ) ) + outputFileNames = m_cCommandLineParser.getOptionsMap()["output"].as >(); + + if( outputFileNames.size() == 1 ) + { + PlaYUVerFrame* pcModFrame = applyFrameModule(); + PlaYUVerStream* pcModStream = new PlaYUVerStream; + if( !pcModStream->open( outputFileNames[0], pcModFrame->getWidth(), pcModFrame->getHeight(), pcModFrame->getPelFormat(), 1, false ) ) + { + delete pcModStream; + pcModStream = NULL; + return 2; + } + m_apcOutputStreams.push_back( pcModStream ); + } + else + { + printf( "One output is required! " ); + return 2; + } + } + + m_uiOperation = MODULE_OPERATION; + m_fpProcess = &PlaYUVerTools::ModuleOperation; + printf( "PlaYUVer Module\n" ); + } + + if( m_uiOperation == INVALID_OPERATION ) + { + printf( "No operation was selected! " ); + return 2; + } + return iRet; +} + +Int PlaYUVerTools::Process() +{ + return ( this->*m_fpProcess )(); +} + +Int PlaYUVerTools::Close() +{ +// Finish + return 0; +} + +Int PlaYUVerTools::QualityOperation() +{ + PlaYUVerFrame* apcCurrFrame[m_apcInputStreams.size()]; + Bool abEOF[m_apcInputStreams.size()]; + Double adAverageQuality[m_apcInputStreams.size() - 1][m_uiNumberOfComponents]; + Double dQuality; + + printf( " Measuring Quality using %s ... \n", PlaYUVerFrame::supportedQualityMetricsList()[m_uiQualityMetric].c_str() ); + + for( UInt s = 0; s < m_apcInputStreams.size(); s++ ) + { + abEOF[s] = false; + for( UInt c = 0; c < m_uiNumberOfComponents; c++ ) + { + adAverageQuality[s][c] = 0; + } + } + for( UInt frame = 0; frame < m_uiNumberOfFrames; frame++ ) + { + printf( " %3d", frame ); + for( UInt s = 0; s < m_apcInputStreams.size(); s++ ) + apcCurrFrame[s] = m_apcInputStreams[s]->getCurrFrame(); + + for( UInt s = 1; s < m_apcInputStreams.size(); s++ ) + { + printf( " " ); + for( UInt c = 0; c < m_uiNumberOfComponents; c++ ) + { + dQuality = apcCurrFrame[s]->getQuality( m_uiQualityMetric, apcCurrFrame[0], c ); + adAverageQuality[s - 1][c] = ( adAverageQuality[s - 1][c] * Double( frame ) + dQuality ) / Double( frame + 1 ); + printf( " %5.3f", dQuality ); + } + } + printf( "\n" ); + for( UInt s = 0; s < m_apcInputStreams.size(); s++ ) + { + abEOF[s] = m_apcInputStreams[s]->setNextFrame(); + if( !abEOF[s] ) + { + m_apcInputStreams[s]->readFrame(); + } + } + } + printf( "\n Mean Values: \n " ); + for( UInt s = 0; s < m_apcInputStreams.size() - 1; s++ ) + { + for( UInt c = 0; c < m_uiNumberOfComponents; c++ ) + { + printf( " %5.3f", adAverageQuality[s][c] ); + } + } + printf( "\n" ); + return 0; +} + +PlaYUVerFrame* PlaYUVerTools::applyFrameModule() +{ + PlaYUVerFrame* pcProcessedFrame = NULL; + if( m_pcCurrModuleIf->m_iModuleType == FRAME_PROCESSING_MODULE ) + { + switch( m_pcCurrModuleIf->m_uiNumberOfFrames ) + { + case MODULE_REQUIRES_ONE_FRAME: + pcProcessedFrame = m_pcCurrModuleIf->process( m_apcInputStreams[0]->getCurrFrame() ); + break; + case MODULE_REQUIRES_TWO_FRAMES: + pcProcessedFrame = m_pcCurrModuleIf->process( m_apcInputStreams[0]->getCurrFrame(), m_apcInputStreams[1]->getCurrFrame() ); + break; + } + } + return pcProcessedFrame; +} + +Int PlaYUVerTools::ModuleOperation() +{ + printf( " Applying Module %s/%s ... \n", m_pcCurrModuleIf->m_pchModuleCategory, m_pcCurrModuleIf->m_pchModuleName ); + + PlaYUVerFrame* pcProcessedFrame = NULL; + Double dMeasurementResult = 0.0; + Double dAveragedMeasurementResult = 0; + Bool abEOF[m_apcInputStreams.size()]; + + for( UInt s = 0; s < m_apcInputStreams.size(); s++ ) + { + abEOF[s] = false; + } + + for( UInt frame = 0; frame < m_uiNumberOfFrames; frame++ ) + { + + if( m_pcCurrModuleIf->m_iModuleType == FRAME_PROCESSING_MODULE ) + { + pcProcessedFrame = applyFrameModule(); + m_apcInputStreams[0]->writeFrame( pcProcessedFrame ); + } + else if( m_pcCurrModuleIf->m_iModuleType == FRAME_MEASUREMENT_MODULE ) + { + switch( m_pcCurrModuleIf->m_uiNumberOfFrames ) + { + case MODULE_REQUIRES_ONE_FRAME: + dMeasurementResult = m_pcCurrModuleIf->measure( m_apcInputStreams[0]->getCurrFrame() ); + break; + case MODULE_REQUIRES_TWO_FRAMES: + dMeasurementResult = m_pcCurrModuleIf->measure( m_apcInputStreams[0]->getCurrFrame(), m_apcInputStreams[1]->getCurrFrame() ); + break; + } + printf( " %3d %8.3f \n", frame, dMeasurementResult ); + dAveragedMeasurementResult = ( dAveragedMeasurementResult * Double( frame ) + dMeasurementResult ) / Double( frame + 1 ); + } + + for( UInt s = 0; s < m_apcInputStreams.size(); s++ ) + { + abEOF[s] = m_apcInputStreams[s]->setNextFrame(); + if( !abEOF[s] ) + { + m_apcInputStreams[s]->readFrame(); + } + } + + } + + if( m_pcCurrModuleIf->m_iModuleType == FRAME_MEASUREMENT_MODULE ) + { + printf( "\n Mean Value: \n %8.3f\n", dAveragedMeasurementResult ); + } + + return 0; +} + +} // NAMESPACE diff --git a/tools/PlaYUVerTools.h b/tools/PlaYUVerTools.h new file mode 100644 index 0000000..905b825 --- /dev/null +++ b/tools/PlaYUVerTools.h @@ -0,0 +1,82 @@ +/* This file is a part of plaYUVer project + * Copyright (C) 2014-2015 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 PlaYUVerTools.h + * \brief Main definition of the PlaYUVerTools app + */ + +#ifndef __PLAYUVERTOOLS_H__ +#define __PLAYUVERTOOLS_H__ + +#include "config.h" +#include "lib/PlaYUVerDefs.h" +#include "lib/PlaYUVerFrame.h" +#include "lib/PlaYUVerStream.h" +#include "CommandLineHandle.h" + +namespace plaYUVer +{ + +class PlaYUVerModuleIf; + +class PlaYUVerTools +{ +public: + PlaYUVerTools(); + ~PlaYUVerTools(); + + Int Open( Int argc, Char *argv[] ); + Int Process(); + Int Close(); + +private: + CommandLineHandle m_cCommandLineParser; + + UInt m_uiOperation; + enum TOOLS_OPERATIONS_LIST + { + INVALID_OPERATION, + QUALITY_OPERATION, + MODULE_OPERATION, + }; + + UInt m_uiNumberOfFrames; + UInt m_uiNumberOfComponents; + std::vector m_apcInputStreams; + std::vector m_apcOutputStreams; + + Int openInputs(); + Int openOutputs(); + + typedef Int (PlaYUVerTools::*FpProcess) (); + FpProcess m_fpProcess; + + + Int m_uiQualityMetric; + Int QualityOperation(); + + PlaYUVerModuleIf* m_pcCurrModuleIf; + PlaYUVerFrame* applyFrameModule(); + Int ModuleOperation(); +}; + +} // NAMESPACE + +#endif // __PLAYUVERTOOLS_H__ diff --git a/tools/main.cpp b/tools/main.cpp new file mode 100644 index 0000000..4c31c20 --- /dev/null +++ b/tools/main.cpp @@ -0,0 +1,58 @@ +/* This file is a part of plaYUVer project + * Copyright (C) 2014-2015 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 main.cpp + * \brief main file + */ + +#include "PlaYUVerTools.h" + +using namespace plaYUVer; + +int main( int argc, char *argv[] ) +{ + Int iRet = 0; + PlaYUVerTools PlaYUVerToolsApp; + + iRet = PlaYUVerToolsApp.Open( argc, argv ); + if( iRet == 1 ) + { + return 0; + } + if( iRet > 1 ) + { + printf( "Exiting\n" ); + return 1; + } + + if( PlaYUVerToolsApp.Process() > 1 ) + { + printf( "Exiting\n" ); + return 1; + } + + if( PlaYUVerToolsApp.Close() > 1 ) + { + printf( "Exiting\n" ); + return 1; + } + +}