diff --git a/CMakeLists.txt b/CMakeLists.txt index 0cc40f5..b5b6db0 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,8 +12,6 @@ PROJECT( playuver ) SET( PROJECT_NAME playuver ) -SET( CMAKE_BUILD_TYPE Debug ) - # Project directories SET( SRC_DIR source ) SET( INC_DIR source ) @@ -21,42 +19,182 @@ SET( RSC_DIR resources ) SET( UI_DIR ui ) SET( EXTERNAL_SRC external_lib ) +SET(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}") # Find includes in corresponding build directories SET( CMAKE_INCLUDE_CURRENT_DIR ON ) # Instruct CMake to run moc automatically when needed. SET( CMAKE_AUTOMOC ON ) - -###################################################################################### -# Dependencies -###################################################################################### -#FIND_PACKAGE( OpenCV REQUIRED ) - - -###################################################################################### -# Qt5 library -###################################################################################### -FIND_PACKAGE( Qt5Core ) -FIND_PACKAGE( Qt5Gui ) -FIND_PACKAGE( Qt5Widgets ) - -INCLUDE_DIRECTORIES( ${CMAKE_BINARY_DIR} ${INC_DIR} ) +INCLUDE_DIRECTORIES( ${CMAKE_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR} ${INC_DIR} ) FILE( GLOB SOURCES_FILES ${SRC_DIR}/*.cpp ) FILE( GLOB HEADERS_FILES ${INC_DIR}/*.h ) FILE( GLOB FORMS_FILES ${UI_DIR}/*.ui ) FILE( GLOB RESOURCES_FILES ${RSC_DIR}/*.qrc ) -INCLUDE_DIRECTORIES( ${Qt5Widgets_INCLUDE_DIRS} ${Qt5Core_INCLUDE_DIRS} ${Qt5Gui_INCLUDE_DIRS}) +###################################################################################### +# Macros +###################################################################################### +macro(ADD_OPTION variable description value) + set(__value ${value}) + set(__condition "") + set(__varname "__value") + foreach(arg ${ARGN}) + if(arg STREQUAL "IF" OR arg STREQUAL "if") + set(__varname "__condition") + else() + list(APPEND ${__varname} ${arg}) + endif() + endforeach() + unset(__varname) + if("${__condition}" STREQUAL "") + set(__condition 2 GREATER 1) + endif() -# QT5_WRAP_CPP( HEADERS_MOC_FILES ${HEADERS_FILES} ) -QT5_WRAP_UI( FORMS_HEADERS_FILES ${FORMS_FILES} ) -QT5_ADD_RESOURCES( RESOURCES_RCC_FILES ${RESOURCES_FILES} ) + if(${__condition}) + if("${__value}" MATCHES ";") + if(${__value}) + option(${variable} "${description}" ON) + else() + option(${variable} "${description}" OFF) + endif() + elseif(DEFINED ${__value}) + if(${__value}) + option(${variable} "${description}" ON) + else() + option(${variable} "${description}" OFF) + endif() + else() + option(${variable} "${description}" ${__value}) + endif() + else() + unset(${variable} CACHE) + endif() + unset(__condition) + unset(__value) +endmacro() -SET( QT_USE_QTOPENGL TRUE ) +# Status report function. +# Automatically align right column and selects text based on condition. +# Usage: +# status() +# status( [ ...]) +# status( THEN ELSE ) +function(status text) + set(status_cond) + set(status_then) + set(status_else) -# Add compiler flags for building executables (-fPIE) -SET( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${Qt5Core_EXECUTABLE_COMPILE_FLAGS}" ) + set(status_current_name "cond") + foreach(arg ${ARGN}) + if(arg STREQUAL "THEN") + set(status_current_name "then") + elseif(arg STREQUAL "ELSE") + set(status_current_name "else") + else() + list(APPEND status_${status_current_name} ${arg}) + endif() + endforeach() + + if(DEFINED status_cond) + set(status_placeholder_length 32) + string(RANDOM LENGTH ${status_placeholder_length} ALPHABET " " status_placeholder) + string(LENGTH "${text}" status_text_length) + if(status_text_length LESS status_placeholder_length) + string(SUBSTRING "${text}${status_placeholder}" 0 ${status_placeholder_length} status_text) + elseif(DEFINED status_then OR DEFINED status_else) + message(STATUS ${text}) + set(status_text "${status_placeholder}") + else() + set(status_text "${text}") + endif() + + if(DEFINED status_then OR DEFINED status_else) + if(${status_cond}) + string(REPLACE ";" " " status_then "${status_then}") + string(REGEX REPLACE "^[ \t]+" "" status_then "${status_then}") + message(STATUS "${status_text} ${status_then}") + else() + string(REPLACE ";" " " status_else "${status_else}") + string(REGEX REPLACE "^[ \t]+" "" status_else "${status_else}") + message(STATUS "${status_text} ${status_else}") + endif() + else() + string(REPLACE ";" " " status_cond "${status_cond}") + string(REGEX REPLACE "^[ \t]+" "" status_cond "${status_cond}") + message(STATUS "${status_text} ${status_cond}") + endif() + else() + message(STATUS "${text}") + endif() +endfunction() + + +###################################################################################### +# Variables +###################################################################################### +ADD_OPTION(CMAKE_BUILD_TYPE "Build type" Debug ) +ADD_OPTION(USE_QT4 "Build with QT4" OFF ) +ADD_OPTION(USE_OPENCV "Add OpenCV support" OFF ) +ADD_OPTION(USE_FFMPEG "Add FFMPEG support" OFF ) + +###################################################################################### +# Dependencies +###################################################################################### +IF( USE_OPENCV ) + FIND_PACKAGE( OpenCV ) + IF( NOT OpenCV_FOUND) + SET(USE_OPENCV FALSE) + ELSE() + SET( LINKER_LIBS ${LINKER_LIBS} ${OpenCV_LIBRARIES} ) + ENDIF() +ENDIF() + +IF( USE_FFMPEG ) + FIND_PACKAGE( FFmpeg ) + IF( NOT FFMPEG_FOUND ) + SET( USE_FFMPEG FALSE ) + ELSE() + SET( CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS} -D__STDC_CONSTANT_MACROS ) + INCLUDE_DIRECTORIES(${FFMPEG_INCLUDE_DIR} ${FFMPEG_INCLUDE_DIRS}) + SET( LINKER_LIBS ${LINKER_LIBS} ${FFMPEG_LIBRARIES} ) + ENDIF() +ENDIF() + +###################################################################################### +# Qt library +###################################################################################### +IF( USE_QT4 ) + FIND_PACKAGE( Qt4 REQUIRED QtCore QtGui ) + IF( NOT QT4_FOUND) + SET(USE_QT4 FALSE) + ENDIF() + INCLUDE( ${QT_USE_FILE} ) + ADD_DEFINITIONS( ${QT_DEFINITIONS} ) + + QT4_WRAP_UI( FORMS_HEADERS_FILES ${FORMS_FILES} ) + QT4_ADD_RESOURCES( RESOURCES_RCC_FILES ${RESOURCES_FILES} ) + + SET( LINKER_LIBS ${LINKER_LIBS} ${QT_LIBRARIES} ) +ENDIF() + +IF( NOT USE_QT4 ) + FIND_PACKAGE( Qt5Core REQUIRED ) + FIND_PACKAGE( Qt5Gui REQUIRED ) + FIND_PACKAGE( Qt5Widgets REQUIRED ) + + INCLUDE_DIRECTORIES( ${Qt5Widgets_INCLUDE_DIRS} ${Qt5Core_INCLUDE_DIRS} ${Qt5Gui_INCLUDE_DIRS} ) + # QT5_WRAP_CPP( HEADERS_MOC_FILES ${HEADERS_FILES} ) + QT5_WRAP_UI( FORMS_HEADERS_FILES ${FORMS_FILES} ) + QT5_ADD_RESOURCES( RESOURCES_RCC_FILES ${RESOURCES_FILES} ) + + # Add compiler flags for building executables (-fPIE) + SET( CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS} ${Qt5Core_EXECUTABLE_COMPILE_FLAGS} ) + + SET( LINKER_LIBS ${LINKER_LIBS} ${Qt5Core_LIBRARIES} ${Qt5Gui_LIBRARIES} ${Qt5Widgets_LIBRARIES} ) + + SET( CURR_QT_MODULES Core Gui Widgets ) +ENDIF() ###################################################################################### # External Libs @@ -65,15 +203,26 @@ SET( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${Qt5Core_EXECUTABLE_COMPILE_FLAGS}" ) INCLUDE_DIRECTORIES( ${EXTERNAL_SRC}/scode ) ADD_LIBRARY( Scode ${EXTERNAL_SRC}/scode/viewarea.cpp ${EXTERNAL_SRC}/scode/gridmanager.cpp ${EXTERNAL_SRC}/scode/scosettings.cpp ) +SET( LINKER_LIBS ${LINKER_LIBS} Scode ) +###################################################################################### +# Create config.h +###################################################################################### +CONFIGURE_FILE( ${CMAKE_CURRENT_SOURCE_DIR}/config.h.in ${CMAKE_CURRENT_BINARY_DIR}/config.h ) -SET( LIST_EXTERNAL_LIBS Scode ) ###################################################################################### # Target App ###################################################################################### + ADD_EXECUTABLE( ${PROJECT_NAME} ${SOURCES_FILES} ${HEADERS_MOC_FILES} ${FORMS_HEADERS_FILES} ${RESOURCES_RCC_FILES} ) -TARGET_LINK_LIBRARIES( ${PROJECT_NAME} ${LIST_EXTERNAL_LIBS} ${Qt5Core_LIBRARIES} ${Qt5Gui_LIBRARIES} ${Qt5Widgets_LIBRARIES} ) -QT5_USE_MODULES( ${PROJECT_NAME} Core Gui Widgets ) - + +TARGET_LINK_LIBRARIES( ${PROJECT_NAME} ${LINKER_LIBS} ) + +IF( NOT USE_QT4) + QT5_USE_MODULES( ${PROJECT_NAME} ${CURR_QT_MODULES} ) +ENDIF() +status("Using third-party libraries:") +status(" Use OpenCV:" USE_OPENCV THEN YES ELSE NO) +status(" FFMPEG:" USE_FFMPEG THEN YES ELSE NO) diff --git a/FindFFmpeg.cmake b/FindFFmpeg.cmake new file mode 100644 index 0000000..a780f77 --- /dev/null +++ b/FindFFmpeg.cmake @@ -0,0 +1,111 @@ +# - Try to find FFMPEG +# Once done this will define +# +# FFMPEG_FOUND - system has FFMPEG +# FFMPEG_INCLUDE_DIR - the include directories +# FFMPEG_LIBRARY_DIR - the directory containing the libraries +# FFMPEG_LIBRARIES - link these to use FFMPEG +# FFMPEG_SWSCALE_FOUND - FFMPEG also has SWSCALE +# + +SET( FFMPEG_HEADERS avformat.h avcodec.h avutil.h avdevice.h ) +SET( FFMPEG_PATH_SUFFIXES libavformat libavcodec libavutil libavdevice libffmpeg ) +SET( FFMPEG_SWS_HEADERS swscale.h ) +SET( FFMPEG_SWS_PATH_SUFFIXES libswscale ) + +if( WIN32 ) + SET( FFMPEG_LIBRARIES avformat-52.lib avcodec-51.lib avutil-49.lib avdevice-52.lib ) + SET( FFMPEG_SWS_LIBRARIES swscale-0.lib ) + SET( FFMPEG_LIBRARY_DIR $ENV{FFMPEGDIR}\\lib ) + SET( FFMPEG_INCLUDE_PATHS $ENV{FFMPEGDIR}\\include ) + + # check to see if we can find swscale + SET( TMP_ TMP-NOTFOUND ) + FIND_PATH( TMP_ ${FFMPEG_SWS_LIBRARIES} + PATHS ${FFMPEG_LIBRARY_DIR} ) + IF ( TMP_ ) + SET( SWSCALE_FOUND TRUE ) + ENDIF( TMP_ ) +else( WIN32 ) + SET( FFMPEG_LIBRARIES avformat avcodec avutil avdevice ) + SET( FFMPEG_SWS_LIBRARIES swscale ) + INCLUDE(FindPkgConfig) + if ( PKG_CONFIG_FOUND ) + pkg_check_modules( AVFORMAT libavformat ) + pkg_check_modules( AVCODEC libavcodec ) + pkg_check_modules( AVUTIL libavutil ) + pkg_check_modules( AVDEVICE libavdevice ) + pkg_check_modules( SWSCALE libswscale ) + endif ( PKG_CONFIG_FOUND ) + + SET( FFMPEG_LIBRARY_DIR ${AVFORMAT_LIBRARY_DIRS} + ${AVCODEC_LIBRARY_DIRS} + ${AVUTIL_LIBRARY_DIRS} + ${AVDEVICE_LIBRARY_DIRS} ) + SET( FFMPEG_INCLUDE_PATHS ${AVFORMAT_INCLUDE_DIRS} + ${AVCODEC_INCLUDE_DIRS} + ${AVUTIL_INCLUDE_DIRS} + ${AVDEVICE_INCLUDE_DIRS} ) +endif( WIN32 ) + +# add in swscale if found +IF ( SWSCALE_FOUND ) + SET( FFMPEG_LIBRARY_DIR ${FFMPEG_LIBRARY_DIR} + ${SWSCALE_LIBRARY_DIRS} ) + SET( FFMPEG_INCLUDE_PATHS ${FFMPEG_INCLUDE_PATHS} + ${SWSCALE_INCLUDE_DIRS} ) + SET( FFMPEG_HEADERS ${FFMPEG_HEADERS} + ${FFMPEG_SWS_HEADERS} ) + SET( FFMPEG_PATH_SUFFIXES ${FFMPEG_PATH_SUFFIXES} + ${FFMPEG_SWS_PATH_SUFFIXES} ) + SET( FFMPEG_LIBRARIES ${FFMPEG_LIBRARIES} + ${FFMPEG_SWS_LIBRARIES} ) +ENDIF ( SWSCALE_FOUND ) + +# find includes +SET( INC_SUCCESS 0 ) +SET( TMP_ TMP-NOTFOUND ) +SET( FFMPEG_INCLUDE_DIR ${FFMPEG_INCLUDE_PATHS} ) +FOREACH( INC_ ${FFMPEG_HEADERS} ) + message( "checking: " ${INC_} ) + + FIND_PATH( TMP_ ${INC_} + PATHS ${FFMPEG_INCLUDE_PATHS} + PATH_SUFFIXES ${FFMPEG_PATH_SUFFIXES} ) + IF ( TMP_ ) + message( "found: " ${TMP_} ) + MATH( EXPR INC_SUCCESS ${INC_SUCCESS}+1 ) + SET( FFMPEG_INCLUDE_DIR ${FFMPEG_INCLUDE_DIR} ${TMP_} ) + ENDIF ( TMP_ ) + SET( TMP_ TMP-NOTFOUND ) +ENDFOREACH( INC_ ) + +# clear out duplicates +if(NOT "${FFMPEG_INCLUDE_DIR}" MATCHES "") + LIST( REMOVE_DUPLICATES FFMPEG_INCLUDE_DIR ) +endif(NOT "${FFMPEG_INCLUDE_DIR}" MATCHES "") +if(NOT "${FFMPEG_LIBRARY_DIR}" MATCHES "") + LIST( REMOVE_DUPLICATES FFMPEG_LIBRARY_DIR ) +endif(NOT "${FFMPEG_LIBRARY_DIR}" MATCHES "") + +# find the full paths of the libraries +SET( TMP_ TMP-NOTFOUND ) +IF ( NOT WIN32 ) + FOREACH( LIB_ ${FFMPEG_LIBRARIES} ) + FIND_LIBRARY( TMP_ NAMES ${LIB_} PATHS ${FFMPEG_LIBRARY_DIR} ) + IF ( TMP_ ) + SET( FFMPEG_LIBRARIES_FULL ${FFMPEG_LIBRARIES_FULL} ${TMP_} ) + ENDIF ( TMP_ ) + SET( TMP_ TMP-NOTFOUND ) + ENDFOREACH( LIB_ ) + SET ( FFMPEG_LIBRARIES ${FFMPEG_LIBRARIES_FULL} ) +ENDIF( NOT WIN32 ) + +LIST( LENGTH FFMPEG_HEADERS LIST_SIZE_ ) + +SET( FFMPEG_FOUND FALSE ) +SET( FFMPEG_SWSCALE_FOUND FALSE ) +IF ( ${INC_SUCCESS} EQUAL ${LIST_SIZE_} ) + SET( FFMPEG_FOUND TRUE ) + SET( FFMPEG_SWSCALE_FOUND ${SWSCALE_FOUND} ) +ENDIF ( ${INC_SUCCESS} EQUAL ${LIST_SIZE_} ) diff --git a/config.h.in b/config.h.in new file mode 100644 index 0000000..d2aea32 --- /dev/null +++ b/config.h.in @@ -0,0 +1,29 @@ +/* Input config.h file */ + +#ifndef __CONFIG_PLAYUVER_H__ +#define __CONFIG_PLAYUVER_H__ + + +/* QT definition */ +#cmakedefine USE_QT4 + +#ifndef USE_QT4 + #define QT_VERSION_PLAYUVER 5 +#else + #define QT_VERSION_PLAYUVER 4 +#endif + +/* OpenCV */ +#cmakedefine USE_OPENCV + +/* FFMPEG */ +#cmakedefine USE_FFMPEG + +#ifdef USE_FFMPEG + #ifndef __STDC_CONSTANT_MACROS + //#define __STDC_CONSTANT_MACROS + #define smprintf _snprintf + #endif +#endif + +#endif // __CONFIG_PLAYUVER_H__ diff --git a/source/ConfigureFormatDialog.cpp b/source/ConfigureFormatDialog.cpp index fbd6307..9781458 100755 --- a/source/ConfigureFormatDialog.cpp +++ b/source/ConfigureFormatDialog.cpp @@ -21,8 +21,6 @@ * \brief Dialog box to set the sequence resolution */ -#include -#include #include "ConfigureFormatDialog.h" #include "InputStream.h" diff --git a/source/ConfigureFormatDialog.h b/source/ConfigureFormatDialog.h index 641c492..9d0dce6 100755 --- a/source/ConfigureFormatDialog.h +++ b/source/ConfigureFormatDialog.h @@ -24,15 +24,15 @@ #ifndef __CONFIGURERESOLUTIONDIALOG_H__ #define __CONFIGURERESOLUTIONDIALOG_H__ +#include "config.h" + +#if( QT_VERSION_PLAYUVER == 5 ) +#include +#elif( QT_VERSION_PLAYUVER == 4 ) +#include +#endif #include -#include -#include -#include -#include -#include -#include -#include -#include + #include "TypeDef.h" class QPixmap; @@ -41,7 +41,10 @@ class QColor; namespace plaYUVer { -#define MAX_STANDARD_RESOLUTIONSIZES 10 +#define ADD_STANDARD_RESOLUTION( name, width, height) \ + standardResolutionNames.push_back( QString( name ) ); \ + standardResolutionSizesList.push_back( QSize( width, height ) ) + /** * */ @@ -60,7 +63,7 @@ public: Int getPixelFormat() { - pixelFormatBox->currentIndex(); + return pixelFormatBox->currentIndex(); } private Q_SLOTS: @@ -69,7 +72,6 @@ private Q_SLOTS: private: QStringList standardResolutionNames; QList standardResolutionSizesList; - QSize standardResolutionSizes[MAX_STANDARD_RESOLUTIONSIZES]; QVBoxLayout *MainLayout; QHBoxLayout *headLayout; QLabel *dialogTitleLabel; @@ -96,29 +98,22 @@ private: QSpacerItem *pixelFormatHorizontalSpacer; QComboBox *pixelFormatBox; - QSpacerItem *verticalSpacerConfirmation; QDialogButtonBox *dialogButtonOkCancel; Void setStandardResolutionSizes() { - standardResolutionNames.push_back( QString( "CIF (352x288)" ) ); - standardResolutionSizesList.push_back( QSize( 352, 288 ) ); - - standardResolutionNames.push_back( QString( "VGA (640x480)" ) ); - standardResolutionSizesList.push_back( QSize( 640, 480 ) ); - - standardResolutionNames.push_back( QString( "HD (1024x768)" ) ); - standardResolutionSizesList.push_back( QSize( 1024, 768 ) ); - - standardResolutionNames.push_back( QString( "Full HD (1920x1080)" ) ); - standardResolutionSizesList.push_back( QSize( 1920, 1080 ) ); + ADD_STANDARD_RESOLUTION( "CIF (352x288)", 352, 288 ); + ADD_STANDARD_RESOLUTION( "VGA (640x480)", 640, 480 ); + ADD_STANDARD_RESOLUTION( "XVGA (1024x768)", 1024, 768 ); + ADD_STANDARD_RESOLUTION( "HD (1280x720)", 1280, 720 ); + ADD_STANDARD_RESOLUTION( "Full HD (1920x1080)", 1920, 1080 ); } }; -} // NAMESPACE +} // NAMESPACE #endif // __CONFIGURERESOLUTIONDIALOG_H__ diff --git a/source/InputStream.cpp b/source/InputStream.cpp index dcb92bc..f7bbfcc 100755 --- a/source/InputStream.cpp +++ b/source/InputStream.cpp @@ -23,7 +23,6 @@ #include -#include #include #include "InputStream.h" @@ -37,6 +36,12 @@ InputStream::InputStream() m_iStatus = 0; m_pFile = NULL; + m_uiWidth = 0; + m_uiHeight = 0; + m_uiTotalFrameNum = 0; + m_uiCurrFrameNum = 0; + m_iErrorStatus = 0; + m_iPixelFormat = -1; m_pppcInputPel[0] = NULL; m_pppcInputPel[1] = NULL; m_pppcInputPel[2] = NULL; @@ -60,6 +65,10 @@ InputStream::~InputStream() if( m_pppcRGBPel ) free_mem3Dpel( m_pppcRGBPel ); +#ifdef USE_FFMPEG + m_cLibAvContext.closeAvFormat(); +#endif + m_iStatus = 0; } @@ -67,14 +76,40 @@ QString InputStream::supportedReadFormats() { QString formats; formats = "*.yuv " // Raw video - ; + "*.avi"// Audio video interleaved + ; + return formats; +} + +QString InputStream::supportedWriteFormats() +{ + QString formats; + formats = "*.bmp " // Windows Bitmap + "*.jpg "// Joint Photographic Experts Group + "*.jpeg "// Joint Photographic Experts Group + "*.png "// Portable Network Graphics + ; + return formats; } QStringList InputStream::supportedReadFormatsList() { QStringList formats; - formats << "Raw video (*.yuv)"; + formats << "Raw video (*.yuv)" // Raw video + << "Audio video interleaved (*.avi)" // Audio video interleaved + ; + + return formats; +} + +QStringList InputStream::supportedWriteFormatsList() +{ + QStringList formats; + formats << "Windows Bitmap (*.bmp)" // Windows Bitmap + << "Joint Photographic Experts Group (*.jpg *.jpeg)" // Joint Photographic Experts Group + << "Portable Network Graphics (*.png)" // Portable Network Graphics + ; return formats; } @@ -86,10 +121,34 @@ QStringList InputStream::supportedPixelFormatList() return formats; } +Bool InputStream::needFormatDialog( QString filename ) +{ + return true; + QString fileExtension = QFileInfo( filename ).completeSuffix(); + if( !fileExtension.compare( QString( "yuv" ) ) ) + { + return true; + } + else + { + return false; + } +} + Void InputStream::init( QString filename, UInt width, UInt height, Int input_format ) { - if( width <= 0 || height <= 0 ) + m_uiWidth = width; + m_uiHeight = height; + + m_iFileFormat = YUVFormat; + m_iPixelFormat = input_format; + +#ifdef USE_FFMPEG + Bool avStatus = m_cLibAvContext.initAvFormat( filename, width, height ); +#endif + + if( m_uiWidth <= 0 || m_uiHeight <= 0 ) { //Error return; @@ -103,12 +162,6 @@ Void InputStream::init( QString filename, UInt width, UInt height, Int input_for return; } - m_uiWidth = width; - m_uiHeight = height; - - m_iFileFormat = YUVFormat; - m_iPixelFormat = input_format; - UInt64 frame_bytes_input = m_uiWidth * m_uiHeight * 1.5; UInt64 alloc_memory; @@ -163,15 +216,6 @@ Void InputStream::init( QString filename, UInt width, UInt height, Int input_for return; } -static inline Pel iClip3Pel( Pel pel_value, Pel min_value, Pel max_value ) -{ - if( pel_value > max_value ) - return max_value; - if( pel_value < min_value ) - return min_value; - return pel_value; -} - static inline void yuvToRgb( int iY, int iU, int iV, int &iR, int &iG, int &iB ) { iR = iY + 1402 * iV / 1000; @@ -258,6 +302,19 @@ Void InputStream::readFrame() } UInt64 frame_bytes_input = m_uiWidth * m_uiHeight * 1.5; +#ifdef USE_FFMPEG + if( m_cLibAvContext.getStatus() ) + { + m_cLibAvContext.decodeAvFormat(); + //fwrite( video_dst_data[0], 1, video_dst_bufsize, video_dst_file ); + memcpy( &( m_pppcInputPel[0][0][0] ), m_cLibAvContext.video_dst_data[0], m_uiWidth * m_uiHeight * sizeof(uint8_t) ); + memcpy( &( m_pppcInputPel[1][0][0] ), m_cLibAvContext.video_dst_data[1], m_uiWidth * m_uiHeight * sizeof(uint8_t) / 4 ); + memcpy( &( m_pppcInputPel[2][0][0] ), m_cLibAvContext.video_dst_data[2], m_uiWidth * m_uiHeight * sizeof(uint8_t) / 4 ); + YUV420toRGB(); + return; + } +#endif + switch( m_iPixelFormat ) { case YUV420: @@ -265,21 +322,21 @@ Void InputStream::readFrame() if( bytes_read != ( m_uiWidth * m_uiHeight ) ) { m_iErrorStatus = READING; - qDebug() << " Reading error !!!" << endl; + qDebug( ) << " Reading error !!!" << endl; return; } bytes_read = fread( &( m_pppcInputPel[1][0][0] ), sizeof(Pel), m_uiWidth * m_uiHeight / 4, m_pFile ); if( bytes_read != ( m_uiWidth * m_uiHeight / 4 ) ) { m_iErrorStatus = READING; - qDebug() << " Reading error !!!" << endl; + qDebug( ) << " Reading error !!!" << endl; return; } bytes_read = fread( &( m_pppcInputPel[2][0][0] ), sizeof(Pel), m_uiWidth * m_uiHeight / 4, m_pFile ); if( bytes_read != ( m_uiWidth * m_uiHeight / 4 ) ) { m_iErrorStatus = READING; - qDebug() << " Reading error !!!" << endl; + qDebug( ) << " Reading error !!!" << endl; return; } YUV420toRGB(); @@ -289,6 +346,12 @@ Void InputStream::readFrame() return; } +Bool InputStream::writeFrame( const QString& filename ) +{ + getFrameQImage().save( filename ); + return true; +} + QImage InputStream::getFrameQImage() { // Create QImage @@ -316,6 +379,15 @@ QImage InputStream::getFrameQImage() return img; } +#ifdef USE_OPENCV +cv::Mat InputStream::getFrameCvMat() +{ + cv::Mat cvMat( m_uiHeight, m_uiWidth, CV_8UC3 ); + + return cvMat; +} +#endif + Void InputStream::seekInput( Int new_frame_num ) { UInt64 frame_bytes_input = m_uiWidth * m_uiHeight * 1.5; diff --git a/source/InputStream.h b/source/InputStream.h index a85ac10..9248a77 100755 --- a/source/InputStream.h +++ b/source/InputStream.h @@ -24,13 +24,20 @@ #ifndef __INPUTSTREAM_H__ #define __INPUTSTREAM_H__ +#include "config.h" + #include #include #include #include +#ifdef USE_OPENCV +#include +#endif + #include "TypeDef.h" +#include "LibAvContextHandle.h" namespace plaYUVer { @@ -40,6 +47,7 @@ enum InputStream_Errors NO_ERROR = 0, READING = 1, }; + class InputStream { private: @@ -47,6 +55,10 @@ private: Int m_iStatus; Int m_iErrorStatus; +#ifdef USE_FFMPEG + LibAvContextHandle m_cLibAvContext; +#endif + QString m_cFilename; FILE* m_pFile; /**< The input file pointer >*/ Int m_iFileFormat; @@ -65,28 +77,36 @@ public: ~InputStream(); static QString supportedReadFormats(); + static QString supportedWriteFormats(); static QStringList supportedReadFormatsList(); + static QStringList supportedWriteFormatsList(); + static QStringList supportedPixelFormatList(); enum InputStreamColorSpace { - YUV420, - YUV400, + YUV420, YUV400, }; enum InputStreamFormats { - INVALID = -1, - YUVFormat = 0, // Use color space. + INVALID = -1, YUVFormat = 0, // Use color space. }; + Bool needFormatDialog( QString filename ); + Void init( QString filename, UInt width, UInt height, Int input_format ); Void YUV420toRGB(); Void readFrame(); + Bool writeFrame( const QString& filename ); + QImage getFrameQImage(); +#ifdef USE_OPENCV + cv::Mat getFrameCvMat(); +#endif Void seekInput( Int new_frame_num ); @@ -130,6 +150,6 @@ public: }; -} // NAMESPACE +} // NAMESPACE #endif // __INPUTSTREAM_H__ diff --git a/source/LibAvContextHandle.cpp b/source/LibAvContextHandle.cpp new file mode 100755 index 0000000..e08404c --- /dev/null +++ b/source/LibAvContextHandle.cpp @@ -0,0 +1,213 @@ +/* This file is a part of plaYUVer project + * Copyright (C) 2014 by plaYUVer developers + * + * 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 LibAvContextHandle.cpp + * \brief Interface with libav libs + */ + +#include "LibAvContextHandle.h" + +#ifdef USE_FFMPEG + +#include + +#include + +#include "InputStream.h" +#include "LibMemAlloc.h" + +namespace plaYUVer +{ + +static int open_codec_context( int *stream_idx, AVFormatContext *fmt_ctx, enum AVMediaType type ) +{ + int ret; + AVStream *st; + AVCodecContext *dec_ctx = NULL; + AVCodec *dec = NULL; + + ret = av_find_best_stream( fmt_ctx, type, -1, -1, NULL, 0 ); + if( ret < 0 ) + { + return ret; + } + else + { + *stream_idx = ret; + st = fmt_ctx->streams[*stream_idx]; + + /* find decoder for the stream */ + dec_ctx = st->codec; + dec = avcodec_find_decoder( dec_ctx->codec_id ); + if( !dec ) + { + printf( "Failed to find %s codec\n", av_get_media_type_string( type ) ); + return ret; + } + + if( ( ret = avcodec_open2( dec_ctx, dec, NULL ) ) < 0 ) + { + printf( "Failed to open %s codec\n", av_get_media_type_string( type ) ); + return ret; + } + } + + return 0; +} + +Void LibAvContextHandle::closeAvFormat() +{ + if( video_dec_ctx ) + avcodec_close( video_dec_ctx ); + + avformat_close_input( &fmt_ctx ); + + av_free( frame ); + av_free( video_dst_data[0] ); +} + +Bool LibAvContextHandle::initAvFormat( QString filename, UInt width, UInt height ) +{ + Bool bRet = true; + int ret = 0; + + fmt_ctx = NULL; + video_dec_ctx = NULL; + video_stream = NULL; + video_dst_data[0] = NULL; + video_dst_data[1] = NULL; + video_dst_data[2] = NULL; + video_dst_data[3] = NULL; + video_stream_idx = -1; + frame = NULL; + m_bHasStream = false; + + char *src_filename = filename.toLocal8Bit().data(); + + FILE *video_dst_file = NULL; + + /* register all formats and codecs */ + av_register_all(); + + /* open input file, and allocate format context */ + if( avformat_open_input( &fmt_ctx, src_filename, NULL, NULL ) < 0 ) + { + qDebug( ) << " Could not open source file %s !!!" << filename << endl; + return false; + } + + /* retrieve stream information */ + if( avformat_find_stream_info( fmt_ctx, NULL ) < 0 ) + { + qDebug( ) << " Could not find stream information !!!" << endl; + return false; + } + + if( open_codec_context( &video_stream_idx, fmt_ctx, AVMEDIA_TYPE_VIDEO ) >= 0 ) + { + video_stream = fmt_ctx->streams[video_stream_idx]; + video_dec_ctx = video_stream->codec; + + /* allocate image where the decoded image will be put */ + ret = av_image_alloc( video_dst_data, video_dst_linesize, video_dec_ctx->width, video_dec_ctx->height, video_dec_ctx->pix_fmt, 1 ); + if( ret < 0 ) + { + qDebug( ) << " Could not allocate raw video buffer !!!" << endl; + closeAvFormat(); + return false; + } + video_dst_bufsize = ret; + } + + /* dump input information to stderr */ + av_dump_format( fmt_ctx, 0, src_filename, 0 ); + if( !video_stream ) + { + qDebug( ) << " Could not find audio or video stream in the input, aborting !!!" << endl; + bRet = false; + closeAvFormat(); + return false; + } + + frame = avcodec_alloc_frame(); + if( !frame ) + { + qDebug( ) << " Could not allocate frame !!!" << endl; + ret = AVERROR( ENOMEM ); + closeAvFormat(); + return false; + } + + /* initialize packet, set data to NULL, let the demuxer fill it */ + av_init_packet( &pkt ); + pkt.data = NULL; + pkt.size = 0; + + m_bHasStream = true; + + return true; +} + +Bool LibAvContextHandle::decodeAvFormat() +{ + Int got_frame; + int ret; + /* read frames from the file */ + + if( av_read_frame( fmt_ctx, &pkt ) >= 0 ) + { + if( pkt.stream_index == video_stream_idx ) + { + /* decode video frame */ + 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 ) + { + /* 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 ); + + /* write to rawvideo file */ + //fwrite( video_dst_data[0], 1, video_dst_bufsize, video_dst_file ); + } + } + av_free_packet( &pkt ); + } + +// /* flush cached frames */ +// pkt.data = NULL; +// pkt.size = 0; +// do +// { +// decode_packet( &got_frame, 1 ); +// } +// while( got_frame ); + + true; +} + +} // NAMESPACE + +#endif diff --git a/source/LibAvContextHandle.h b/source/LibAvContextHandle.h new file mode 100755 index 0000000..7b44c26 --- /dev/null +++ b/source/LibAvContextHandle.h @@ -0,0 +1,77 @@ +/* This file is a part of plaYUVer project + * Copyright (C) 2014 by plaYUVer developers + * + * 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 LibAvContextHandle.h + * \brief Interface with libav libs + */ + +#ifndef __LIBAVCONTEXTHANDLE_H__ +#define __LIBAVCONTEXTHANDLE_H__ + +#include "config.h" + +#ifdef USE_FFMPEG + +#include + +extern "C" +{ +#include "libavutil/imgutils.h" +#include "libavutil/samplefmt.h" +#include "libavutil/timestamp.h" +#include "libavformat/avformat.h" +} + +#include "TypeDef.h" + +namespace plaYUVer +{ + +class LibAvContextHandle +{ +public: + Bool initAvFormat( QString filename, UInt width, UInt height ); + Void closeAvFormat(); + Bool decodeAvFormat(); + + Bool getStatus() + { + return m_bHasStream; + } + + uint8_t *video_dst_data[4]; + int video_dst_linesize[4]; + int video_dst_bufsize; + +private: + AVFormatContext *fmt_ctx; + AVCodecContext *video_dec_ctx; + AVStream *video_stream; + Int video_stream_idx; + AVFrame *frame; + AVPacket pkt; + + Bool m_bHasStream; +}; + +} // NAMESPACE + +#endif + +#endif // __LIBAVCONTEXTHANDLE_H__ diff --git a/source/LibMemAlloc.h b/source/LibMemAlloc.h index e131e3d..62512d0 100644 --- a/source/LibMemAlloc.h +++ b/source/LibMemAlloc.h @@ -24,6 +24,8 @@ #ifndef __LIBMEMALLOC_H__ #define __LIBMEMALLOC_H__ +#include "config.h" + #include #include #include "TypeDef.h" diff --git a/source/ImageInterface.cpp b/source/SubWindowHandle.cpp similarity index 67% rename from source/ImageInterface.cpp rename to source/SubWindowHandle.cpp index 2b0d869..19ade75 100644 --- a/source/ImageInterface.cpp +++ b/source/SubWindowHandle.cpp @@ -21,20 +21,14 @@ * \brief Sub windows handling */ -#include -#include -#include -#include -#include - #include "ConfigureFormatDialog.h" -#include "ImageInterface.h" +#include "SubWindowHandle.h" #include "viewarea.h" namespace plaYUVer { -ImageInterface::ImageInterface( QWidget * parent ) : +SubWindowHandle::SubWindowHandle( QWidget * parent ) : QMdiSubWindow( parent ) { setParent( parent ); @@ -58,24 +52,30 @@ ImageInterface::ImageInterface( QWidget * parent ) : } -ImageInterface::~ImageInterface() +SubWindowHandle::~SubWindowHandle() { delete m_cViewArea; } -bool ImageInterface::loadFile( const QString &fileName ) +bool SubWindowHandle::loadFile( const QString &fileName ) { ConfigureFormatDialog formatDialog( this ); - if( formatDialog.exec() == QDialog::Rejected ) + if( m_currStream.needFormatDialog( fileName ) ) { - return false; + if( formatDialog.exec() == QDialog::Rejected ) + { + return false; + } + m_currStream.init( fileName, formatDialog.getResolution().width(), formatDialog.getResolution().height(), formatDialog.getPixelFormat() ); + } + else + { + m_currStream.init( fileName, 0, 0, 0 ); } QApplication::setOverrideCursor( Qt::WaitCursor ); - m_currStream.init( fileName, formatDialog.getResolution().width(), formatDialog.getResolution().height(), formatDialog.getPixelFormat() ); - if( m_currStream.getStatus() == 0 ) { return false; @@ -100,33 +100,55 @@ bool ImageInterface::loadFile( const QString &fileName ) return true; } -bool ImageInterface::save() +bool SubWindowHandle::save() { + QString supported = tr( "Supported Files" ); + QString formats = InputStream::supportedWriteFormats(); + formats.prepend( " (" ); + formats.append( ")" ); + supported.append( formats ); // supported=="Supported Files (*.pbm *.jpg...)" -} + QStringList filter; + filter << supported << InputStream::supportedWriteFormatsList() << tr( "All Files (*)" ); + + QString fileName = QFileDialog::getSaveFileName( this, tr( "Save As" ), m_cCurrFileName, filter.join( ";;" ) ); -bool ImageInterface::saveAs() -{ - QString fileName = QFileDialog::getSaveFileName( this, tr( "Save As" ), m_cCurrFileName ); if( fileName.isEmpty() ) return false; - return saveFile( fileName ); -} + QApplication::setOverrideCursor( Qt::WaitCursor ); -bool ImageInterface::saveFile( const QString &fileName ) -{ + if( !m_currStream.writeFrame( fileName ) ) + { + QApplication::restoreOverrideCursor(); + QMessageBox::warning( this, tr( "SCode" ), tr( "Cannot save file %1" ).arg( fileName ) ); + return false; + } + + QApplication::restoreOverrideCursor(); return true; } -Void ImageInterface::normalSize() +bool SubWindowHandle::nextVideoFrame() +{ + m_currStream.readFrame(); + if( m_currStream.checkErrors( READING ) ) + { + QMessageBox::warning( this, tr( "plaYUVer" ), tr( "Cannot read %1." ).arg( m_cCurrFileName ) ); + return false; + } + m_cViewArea->setImage( QPixmap::fromImage( m_currStream.getFrameQImage() ) ); + return true; +} + +Void SubWindowHandle::normalSize() { m_dScaleFactor = 1.0; m_cViewArea->setZoomFactor( m_dScaleFactor ); } -Void ImageInterface::zoomToFit() +Void SubWindowHandle::zoomToFit() { // Scale to a smaller size that the real to a nicer look QSize niceFit( m_cScrollArea->viewport()->size().width() - 10, m_cScrollArea->viewport()->size().height() - 10 ); @@ -138,7 +160,7 @@ Void ImageInterface::zoomToFit() scaleView( niceFit ); } -Void ImageInterface::scaleView( Double factor ) +Void SubWindowHandle::scaleView( Double factor ) { Q_ASSERT( m_cViewArea->image() ); m_dScaleFactor *= factor; @@ -146,12 +168,12 @@ Void ImageInterface::scaleView( Double factor ) adjustScrollBar( m_dScaleFactor ); } -Void ImageInterface::scaleView( Int width, Int height ) +Void SubWindowHandle::scaleView( Int width, Int height ) { scaleView( QSize( width, height ) ); } -Void ImageInterface::scaleView( const QSize & size ) +Void SubWindowHandle::scaleView( const QSize & size ) { QSize imgViewSize( m_currStream.getWidth(), m_currStream.getHeight() ); QSize newSize = imgViewSize; @@ -171,7 +193,7 @@ Void ImageInterface::scaleView( const QSize & size ) scaleView( hfactor ); } -Void ImageInterface::adjustScrollBar( Double factor ) +Void SubWindowHandle::adjustScrollBar( Double factor ) { QScrollBar *scrollBar = m_cScrollArea->horizontalScrollBar(); scrollBar->setValue( int( factor * scrollBar->value() + ( ( factor - 1 ) * scrollBar->pageStep() / 2 ) ) ); @@ -179,7 +201,7 @@ Void ImageInterface::adjustScrollBar( Double factor ) scrollBar->setValue( int( factor * scrollBar->value() + ( ( factor - 1 ) * scrollBar->pageStep() / 2 ) ) ); } -QSize ImageInterface::sizeHint() const +QSize SubWindowHandle::sizeHint() const { QSize maxSize; // The size of the parent (viewport widget // of the QMdiArea). @@ -192,7 +214,7 @@ QSize ImageInterface::sizeHint() const QSize isize = QSize( m_currStream.getWidth() + 500, m_currStream.getHeight() + 500 ); - // If the ImageInterface needs more space that the avaiable, we'll give + // If the SubWindowHandle 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() ) { @@ -207,17 +229,17 @@ QSize ImageInterface::sizeHint() const return maxSize; } -Void ImageInterface::closeEvent( QCloseEvent *event ) +Void SubWindowHandle::closeEvent( QCloseEvent *event ) { event->accept(); } -QString ImageInterface::userFriendlyCurrentFile() +QString SubWindowHandle::userFriendlyCurrentFile() { return strippedName( m_cCurrFileName ); } -QString ImageInterface::strippedName( const QString &fullFileName ) +QString SubWindowHandle::strippedName( const QString &fullFileName ) { return QFileInfo( fullFileName ).fileName(); } diff --git a/source/ImageInterface.h b/source/SubWindowHandle.h similarity index 88% rename from source/ImageInterface.h rename to source/SubWindowHandle.h index ef6ae62..396f8fb 100644 --- a/source/ImageInterface.h +++ b/source/SubWindowHandle.h @@ -24,15 +24,13 @@ #ifndef __IMAGEINTERFACE_H__ #define __IMAGEINTERFACE_H__ -#include -#include -#include -#include -#include -//#include -//#include -//#include +#include "config.h" +#if( QT_VERSION_PLAYUVER == 5 ) +#include +#elif( QT_VERSION_PLAYUVER == 4 ) +#include +#endif #include "TypeDef.h" #include "InputStream.h" @@ -43,7 +41,7 @@ namespace plaYUVer using namespace SCode; -class ImageInterface: public QMdiSubWindow +class SubWindowHandle: public QMdiSubWindow { Q_OBJECT @@ -54,19 +52,17 @@ private: InputStream m_currStream; - QString m_cCurrFileName; Double m_dScaleFactor; - public: - ImageInterface( QWidget * parent = 0 ); - ~ImageInterface(); + SubWindowHandle( QWidget * parent = 0 ); + ~SubWindowHandle(); bool loadFile( const QString &fileName ); bool save(); - bool saveAs(); - bool saveFile( const QString &fileName ); + + bool nextVideoFrame(); /** * Show the image at its original size @@ -112,7 +108,6 @@ public: * QMdiArea only have a function that arranges @b all the child windows. */ //static void cascader( QList &widgets, const QRect &domain ); - QString userFriendlyCurrentFile(); QString strippedName( const QString &fullFileName ); QString currentFile() @@ -127,6 +122,6 @@ private slots: }; -} // NAMESPACE +} // NAMESPACE #endif // __IMAGEINTERFACE_H__ diff --git a/source/TypeDef.h b/source/TypeDef.h index 05b046d..94959e6 100644 --- a/source/TypeDef.h +++ b/source/TypeDef.h @@ -24,6 +24,8 @@ #ifndef __TYPEDEF_H__ #define __TYPEDEF_H__ +#include "config.h" + // ==================================================================================================================== // Basic type redefinition // ==================================================================================================================== @@ -91,4 +93,14 @@ typedef UChar Pel; ///< 8-bit pixel type #define xFree( ptr ) free ( ptr ) #endif + +// ==================================================================================================================== +// Qt functions +// ==================================================================================================================== + +#if( QT_VERSION_PLAYUVER == 4 ) +#define QStringLiteral QString::fromUtf8 +#endif + + #endif // __TYPEDEF_H__ diff --git a/source/plaYUVerApp.cpp b/source/plaYUVerApp.cpp index 6998f51..9ee4466 100644 --- a/source/plaYUVerApp.cpp +++ b/source/plaYUVerApp.cpp @@ -21,13 +21,16 @@ * \brief Main definition of the plaYUVerApp app */ +#if( QT_VERSION_PLAYUVER == 5 ) #include -#include +#elif( QT_VERSION_PLAYUVER == 4 ) +#include +#endif #include #include "TypeDef.h" #include "plaYUVerApp.h" -#include "ImageInterface.h" +#include "SubWindowHandle.h" #include "InputStream.h" namespace plaYUVer @@ -58,6 +61,10 @@ plaYUVerApp::plaYUVerApp() setWindowTitle( tr( "plaYUVerApp" ) ); setWindowIcon( QIcon( ":/images/playuver.png" ) ); setUnifiedTitleAndToolBarOnMac( true ); + + playingTimer = new QTimer( this ); + + playingTimer->start( 1000 ); } Void plaYUVerApp::closeEvent( QCloseEvent *event ) @@ -100,7 +107,7 @@ void plaYUVerApp::open() return; } - ImageInterface *interfaceChild = new ImageInterface( this ); //createImageInterface(); + SubWindowHandle *interfaceChild = new SubWindowHandle( this ); //createImageInterface(); if( interfaceChild->loadFile( fileName ) ) { addImageInterface( interfaceChild ); @@ -112,10 +119,33 @@ void plaYUVerApp::open() interfaceChild->close(); } } + play(); } -void plaYUVerApp::saveAs() +void plaYUVerApp::save() { + if( activeImageInterface() ) + activeImageInterface()->save(); +} + +// ----------------------- Playing Functions -------------------- + +void plaYUVerApp::play() +{ + + connect( playingTimer, SIGNAL( timeout() ), this, SLOT( playEvent() ) ); + +} + +void plaYUVerApp::playEvent() +{ + if( activeImageInterface() ) + { + if( !activeImageInterface()->nextVideoFrame() ) + { + playingTimer->stop(); + } + } } @@ -165,7 +195,7 @@ void plaYUVerApp::about() void plaYUVerApp::updateMenus() { Bool hasImageInterface = ( activeImageInterface() != 0 ); - saveAsAct->setEnabled( hasImageInterface ); + saveAct->setEnabled( hasImageInterface ); closeAct->setEnabled( hasImageInterface ); closeAllAct->setEnabled( hasImageInterface ); tileAct->setEnabled( hasImageInterface ); @@ -196,7 +226,7 @@ void plaYUVerApp::updateWindowMenu() for( Int i = 0; i < windows.size(); ++i ) { - ImageInterface *child = qobject_cast( windows.at( i ) ); + SubWindowHandle *child = qobject_cast( windows.at( i ) ); QString text; if( i < 9 ) @@ -215,15 +245,15 @@ void plaYUVerApp::updateWindowMenu() } } -ImageInterface *plaYUVerApp::createImageInterface() +SubWindowHandle *plaYUVerApp::createImageInterface() { - ImageInterface *child = new ImageInterface; + SubWindowHandle *child = new SubWindowHandle; mdiArea->addSubWindow( child ); return child; } -void plaYUVerApp::addImageInterface( ImageInterface *child ) +void plaYUVerApp::addImageInterface( SubWindowHandle *child ) { //connect( child, SIGNAL( areaSelected( QRect ) ), this, SLOT( setSelection( QRect ) ) ); @@ -241,10 +271,10 @@ Void plaYUVerApp::createActions() openAct->setStatusTip( tr( "Open an existing file" ) ); connect( openAct, SIGNAL( triggered() ), this, SLOT( open() ) ); - saveAsAct = new QAction( QIcon( ":/images/saveas.png" ), tr( "Save &As..." ), this ); - saveAsAct->setShortcuts( QKeySequence::SaveAs ); - saveAsAct->setStatusTip( tr( "Save the document under a new name" ) ); - connect( saveAsAct, SIGNAL( triggered() ), this, SLOT( saveAs() ) ); + saveAct = new QAction( QIcon( ":/images/save.png" ), tr( "&Save..." ), this ); + saveAct->setShortcuts( QKeySequence::SaveAs ); + saveAct->setStatusTip( tr( "Save the document under a new name" ) ); + connect( saveAct, SIGNAL( triggered() ), this, SLOT( save() ) ); exitAct = new QAction( tr( "E&xit" ), this ); exitAct->setShortcuts( QKeySequence::Quit ); @@ -286,6 +316,8 @@ Void plaYUVerApp::createActions() zoomToFitAct->setShortcut( tr( "Ctrl+F" ) ); connect( zoomToFitAct, SIGNAL( triggered() ), this, SLOT( zoomToFit() ) ); + // ------------ Playing ------------ + // ------------ Window ------------ tileAct = new QAction( tr( "&Tile" ), this ); @@ -352,7 +384,7 @@ Void plaYUVerApp::createMenus() fileMenu = menuBar()->addMenu( tr( "&File" ) ); fileMenu->addAction( openAct ); fileMenu->addSeparator(); - fileMenu->addAction( saveAsAct ); + fileMenu->addAction( saveAct ); fileMenu->addSeparator(); fileMenu->addAction( closeAct ); fileMenu->addAction( exitAct ); @@ -378,7 +410,7 @@ Void plaYUVerApp::createToolBars() { fileToolBar = addToolBar( tr( "File" ) ); fileToolBar->addAction( openAct ); - fileToolBar->addAction( saveAsAct ); + fileToolBar->addAction( saveAct ); fileToolBar->addAction( closeAct ); viewToolBar = addToolBar( tr( "Zoom" ) ); @@ -421,10 +453,10 @@ Void plaYUVerApp::writeSettings() settings.setValue( "size", size() ); } -ImageInterface *plaYUVerApp::activeImageInterface() +SubWindowHandle *plaYUVerApp::activeImageInterface() { if( QMdiSubWindow *activeImageInterface = mdiArea->activeSubWindow() ) - return qobject_cast( activeImageInterface ); + return qobject_cast( activeImageInterface ); return 0; } @@ -433,7 +465,7 @@ QMdiSubWindow *plaYUVerApp::findImageInterface( const QString &fileName ) QString canonicalFilePath = QFileInfo( fileName ).canonicalFilePath(); foreach( QMdiSubWindow * window, mdiArea->subWindowList() ){ - ImageInterface *mdiChild = qobject_cast( window); + SubWindowHandle *mdiChild = qobject_cast( window); if( mdiChild->currentFile() == canonicalFilePath ) return window; } diff --git a/source/plaYUVerApp.h b/source/plaYUVerApp.h index 1ca67c3..92b0f07 100644 --- a/source/plaYUVerApp.h +++ b/source/plaYUVerApp.h @@ -24,6 +24,8 @@ #ifndef __PLAYUVERAPP_H__ #define __PLAYUVERAPP_H__ +#include "config.h" + #include #include "TypeDef.h" @@ -36,7 +38,7 @@ class QSignalMapper; namespace plaYUVer { -class ImageInterface; +class SubWindowHandle; class plaYUVerApp: public QMainWindow { @@ -52,7 +54,11 @@ private slots: //! File functions void open(); - void saveAs(); + void save(); + + //! Playing functions + void play(); + void playEvent(); //! View functions void zoomIn(); @@ -66,8 +72,8 @@ private slots: void updateWindowMenu(); - ImageInterface *createImageInterface(); - void addImageInterface( ImageInterface *child ); + SubWindowHandle *createImageInterface(); + void addImageInterface( SubWindowHandle *child ); void setActiveImageInterface( QWidget *window ); private: @@ -77,7 +83,7 @@ private: Void createStatusBar(); Void readSettings(); Void writeSettings(); - ImageInterface *activeImageInterface(); + SubWindowHandle *activeImageInterface(); QMdiSubWindow *findImageInterface( const QString &fileName ); /** @@ -89,6 +95,7 @@ private: QString m_cLastOpenPath; + QTimer *playingTimer; QMdiArea *mdiArea; QSignalMapper *windowMapper; @@ -102,7 +109,6 @@ private: QAction *openAct; QAction *saveAct; - QAction *saveAsAct; QAction *exitAct; QAction *closeAct; QAction *closeAllAct; @@ -134,6 +140,6 @@ private: }; -} // NAMESPACE +} // NAMESPACE #endif // __PLAYUVERAPP_H__ diff --git a/source/plaYUVerSettings.cpp b/source/plaYUVerSettings.cpp index aa923c3..4872e7f 100755 --- a/source/plaYUVerSettings.cpp +++ b/source/plaYUVerSettings.cpp @@ -21,8 +21,6 @@ * \brief plaYUVer app settings */ -#include - #include "plaYUVerSettings.h" namespace plaYUVer @@ -316,4 +314,4 @@ void PlaYUVerSettings::setImgVDec( QString str ) m_settings.setValue( "MMPdec/imgV", str ); } -} // NAMESPACE +} // NAMESPACE diff --git a/source/plaYUVerSettings.h b/source/plaYUVerSettings.h index ed9f091..3fc5a81 100755 --- a/source/plaYUVerSettings.h +++ b/source/plaYUVerSettings.h @@ -24,14 +24,10 @@ #ifndef __PLAYUVERSETTINGS_H__ #define __PLAYUVERSETTINGS_H__ -#include -#include -#include -#include -#include -#include +#include "config.h" + +#include -#include #include "gridmanager.h" namespace plaYUVer @@ -129,6 +125,6 @@ private: QSettings m_settings; }; -} // NAMESPACE +} // NAMESPACE #endif // __PLAYUVERSETTINGS_H__