diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index 43df34e..f5c8397 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -18,7 +18,7 @@ set(PlaYUVer_Lib_SRCS ) IF( USE_FFMPEG ) - LIST( APPEND PlaYUVer_Lib_SRCS LibAvContextHandle.cpp ) + LIST( APPEND PlaYUVer_Lib_SRCS StreamHandlerLibav.cpp ) ENDIF() IF( USE_OPENCV ) diff --git a/lib/PlaYUVerFrame.cpp b/lib/PlaYUVerFrame.cpp index b23c6d1..b2620c6 100644 --- a/lib/PlaYUVerFrame.cpp +++ b/lib/PlaYUVerFrame.cpp @@ -30,7 +30,7 @@ #include "PlaYUVerFrame.h" #include "PlaYUVerFramePixelFormats.h" #ifdef USE_FFMPEG -#include "LibAvContextHandle.h" +#include "StreamHandlerLibav.h" #endif #ifdef USE_OPENCV #include "LibOpenCVHandler.h" diff --git a/lib/PlaYUVerFramePixelFormats.cpp b/lib/PlaYUVerFramePixelFormats.cpp index c37d74f..95d7b44 100644 --- a/lib/PlaYUVerFramePixelFormats.cpp +++ b/lib/PlaYUVerFramePixelFormats.cpp @@ -32,7 +32,7 @@ #include #endif #ifdef USE_FFMPEG -#include "LibAvContextHandle.h" +#include "StreamHandlerLibav.h" #endif #include "PlaYUVerFramePixelFormats.h" diff --git a/lib/PlaYUVerStream.cpp b/lib/PlaYUVerStream.cpp index dc7c928..36d0b45 100644 --- a/lib/PlaYUVerStream.cpp +++ b/lib/PlaYUVerStream.cpp @@ -28,8 +28,11 @@ #include #include "LibMemory.h" #include "PlaYUVerStream.h" +#include "PlaYUVerStreamHandlerIf.h" +#include "StreamHandlerRaw.h" + #ifdef USE_FFMPEG -#include "LibAvContextHandle.h" +#include "StreamHandlerLibav.h" #endif #ifdef USE_OPENCV #include "LibOpenCVHandler.h" @@ -44,7 +47,7 @@ std::vector PlaYUVerStream::supportedReadFormats() REGIST_PLAYUVER_SUPPORTED_FMT( "Raw Video", "yuv" ); REGIST_PLAYUVER_SUPPORTED_FMT( "Raw Video", "gray" ); #ifdef USE_FFMPEG - APPEND_PLAYUVER_SUPPORTED_FMT( LibAvContextHandle, Read ); + APPEND_PLAYUVER_SUPPORTED_FMT( StreamHandlerLibav, Read ); #endif //#ifdef USE_OPENCV // APPEND_PLAYUVER_SUPPORTED_FMT( LibOpenCVHandler ); @@ -57,7 +60,7 @@ std::vector PlaYUVerStream::supportedWriteFormats() INI_REGIST_PLAYUVER_SUPPORTED_FMT; REGIST_PLAYUVER_SUPPORTED_FMT( "Raw Video", "yuv" ); #ifdef USE_FFMPEG - APPEND_PLAYUVER_SUPPORTED_FMT( LibAvContextHandle, Write ); + APPEND_PLAYUVER_SUPPORTED_FMT( StreamHandlerLibav, Write ); #endif END_REGIST_PLAYUVER_SUPPORTED_FMT; } @@ -67,7 +70,7 @@ std::vector PlaYUVerStream::supportedSaveFormats() INI_REGIST_PLAYUVER_SUPPORTED_FMT; APPEND_PLAYUVER_SUPPORTED_FMT( PlaYUVerStream, Write ); #ifdef USE_FFMPEG - APPEND_PLAYUVER_SUPPORTED_FMT( LibAvContextHandle, Save ); + APPEND_PLAYUVER_SUPPORTED_FMT( StreamHandlerLibav, Save ); #endif #ifdef USE_OPENCV APPEND_PLAYUVER_SUPPORTED_FMT( LibOpenCVHandler, Save ); @@ -108,7 +111,7 @@ PlaYUVerStream::PlaYUVerStream() m_bIsOpened = false; m_bLoadAll = false; m_iStreamHandler = INVALID_HANDLER; - m_pFile = NULL; + m_pcStreamHandler = NULL; m_pchFilename = NULL; m_uiWidth = 0; m_uiHeight = 0; @@ -126,18 +129,27 @@ PlaYUVerStream::PlaYUVerStream() m_uiFrameBufferSize = 2; m_uiFrameBufferIndex = 0; m_uiCurrFrameFileIdx = 0; -#ifdef USE_FFMPEG - m_cLibAvContext = new LibAvContextHandle; -#endif +// #ifdef USE_FFMPEG +// m_cLibAvContext = new StreamHandlerLibav; +// #endif } PlaYUVerStream::~PlaYUVerStream() { close(); -#ifdef USE_FFMPEG - if( m_cLibAvContext ) - delete m_cLibAvContext; -#endif +// #ifdef USE_FFMPEG +// if( m_cLibAvContext ) +// delete m_cLibAvContext; +// #endif +} + +std::string PlaYUVerStream::getFormatName() +{ + return !m_pcStreamHandler ? "" : m_pcStreamHandler->getFormatName(); +} +std::string PlaYUVerStream::getCodecName() +{ + return !m_pcStreamHandler ? "" : m_pcStreamHandler->getCodecName(); } Void PlaYUVerStream::findHandler() @@ -156,12 +168,12 @@ Void PlaYUVerStream::findHandler() if( m_bIsInput ) { #ifdef USE_FFMPEG - std::vector supportedFmts = LibAvContextHandle::supportedReadFormats(); + std::vector supportedFmts = StreamHandlerLibav::supportedReadFormats(); for( UInt i = 0; i < supportedFmts.size(); i++ ) { if( supportedFmts[i].formatExt == currExt ) { - m_cFormatName = uppercase( supportedFmts[i].formatExt ); + //m_cFormatName = uppercase( supportedFmts[i].formatExt ); m_iStreamHandler = FFMPEG; return; } @@ -173,12 +185,12 @@ Void PlaYUVerStream::findHandler() else { #ifdef USE_FFMPEG - std::vector supportedFmts = LibAvContextHandle::supportedWriteFormats(); + std::vector supportedFmts = StreamHandlerLibav::supportedWriteFormats(); for( UInt i = 0; i < supportedFmts.size(); i++ ) { if( supportedFmts[i].formatExt == currExt ) { - m_cFormatName = uppercase( supportedFmts[i].formatExt ); +// m_cFormatName = uppercase( supportedFmts[i].formatExt ); m_iStreamHandler = FFMPEG; return; } @@ -246,17 +258,6 @@ Bool PlaYUVerStream::open( std::string filename, UInt width, UInt height, Int in m_uiFrameBufferSize = m_bIsInput ? 2 : 1; -#ifdef USE_FFMPEG - if( m_iStreamHandler == FFMPEG ) - { - if( !m_cLibAvContext->initAvFormat( m_pchFilename, m_uiWidth, m_uiHeight, m_iPixelFormat, m_uiBitsPerPixel, m_iEndianness, m_dFrameRate, m_uiTotalFrameNum ) ) - { - throw "Cannot open file using FFmpeg libs"; - } - m_cCodedName = m_cLibAvContext->getCodecName(); - } -#endif - #ifdef USE_OPENCV if( m_iStreamHandler == OPENCV_HANDLER ) { @@ -267,9 +268,38 @@ Bool PlaYUVerStream::open( std::string filename, UInt width, UInt height, Int in m_uiHeight = m_pcCurrFrame->getHeight(); m_iPixelFormat = m_pcCurrFrame->getPelFormat(); } + m_pcNextFrame = NULL; + m_uiFrameBufferSize = 0; + m_uiFrameBufferIndex = 0; + m_uiTotalFrameNum = 1; } #endif +#ifdef USE_FFMPEG + if( m_iStreamHandler == FFMPEG ) + { + m_pcStreamHandler = new StreamHandlerLibav; + } +#endif + if( m_iStreamHandler == YUV_IO ) + { + m_pcStreamHandler = new PlaYUVerRawHandler; + } + + if( !m_pcStreamHandler ) + { + close(); + throw "[PlaYUVerStream] Invalid handler"; + } + + if( !m_pcStreamHandler->openHandler( m_cFilename, m_bIsInput ) ) + { + close(); + throw "[PlaYUVerStream] Cannot open file"; + return m_bInit; + } + m_pcStreamHandler->getFormat( m_uiWidth, m_uiHeight, m_iPixelFormat, m_uiBitsPerPixel, m_iEndianness, m_dFrameRate ); + if( m_uiWidth <= 0 || m_uiHeight <= 0 || m_iPixelFormat < 0 ) { close(); @@ -277,62 +307,28 @@ Bool PlaYUVerStream::open( std::string filename, UInt width, UInt height, Int in return m_bInit; } - if( m_iStreamHandler != OPENCV_HANDLER ) + getMem1D( &m_ppcFrameBuffer, m_uiFrameBufferSize ); + for( UInt i = 0; i < m_uiFrameBufferSize; i++ ) { - if( m_iStreamHandler == YUV_IO ) + try { - if( !openFile() ) - { - close(); - throw "[PlaYUVerStream] Cannot open file"; - return m_bInit; - } - m_cFormatName = "YUV"; - m_cCodedName = "Raw Video"; + m_ppcFrameBuffer[i] = new PlaYUVerFrame( m_uiWidth, m_uiHeight, m_iPixelFormat, m_uiBitsPerPixel ); } - - getMem1D( &m_ppcFrameBuffer, m_uiFrameBufferSize ); - for( UInt i = 0; i < m_uiFrameBufferSize; i++ ) + catch( const char *msg ) { - try - { - m_ppcFrameBuffer[i] = new PlaYUVerFrame( m_uiWidth, m_uiHeight, m_iPixelFormat, m_uiBitsPerPixel ); - } - catch( const char *msg ) - { - close(); - throw "[PlaYUVerStream] Cannot allocated frame buffer"; - return m_bInit; - } - } - m_uiFrameBufferIndex = 0; - m_pcCurrFrame = m_ppcFrameBuffer[m_uiFrameBufferIndex]; - - UInt64 frame_bytes_input = m_pcCurrFrame->getBytesPerFrame(); - - if( m_iStreamHandler == 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; - } -#endif - m_uiTotalFrameNum = fileSize / frame_bytes_input; - fseek( m_pFile, 0, SEEK_SET ); + close(); + throw "[PlaYUVerStream] Cannot allocated frame buffer"; + return m_bInit; } } - else + m_uiFrameBufferIndex = 0; + m_pcCurrFrame = m_ppcFrameBuffer[m_uiFrameBufferIndex]; + + m_pcStreamHandler->setBytesPerFrame( m_pcCurrFrame->getBytesPerFrame() ); + + if( m_bIsInput ) { - m_pcNextFrame = NULL; - m_uiFrameBufferSize = 0; - m_uiFrameBufferIndex = 0; - m_uiTotalFrameNum = 1; + m_uiTotalFrameNum = m_pcStreamHandler->calculateFrameNumber(); } if( m_bIsInput && m_uiTotalFrameNum <= 0 ) @@ -368,30 +364,16 @@ Bool PlaYUVerStream::open( std::string filename, UInt width, UInt height, Int in Bool PlaYUVerStream::reload() { -#ifdef USE_FFMPEG - if( m_iStreamHandler == FFMPEG ) - { - m_cLibAvContext->closeAvFormat(); - if( !m_cLibAvContext->initAvFormat( m_pchFilename, m_uiWidth, m_uiHeight, m_iPixelFormat, m_uiBitsPerPixel, m_iEndianness, m_dFrameRate, m_uiTotalFrameNum ) ) + m_pcStreamHandler->setBytesPerFrame( m_pcCurrFrame->getBytesPerFrame() ); + + m_pcStreamHandler->closeHandler(); + if( !m_pcStreamHandler->openHandler( m_cFilename, m_bIsInput ) ) { - throw "Cannot open file using FFmpeg libs"; + throw "[PlaYUVerStream] Cannot open file using FFmpeg libs"; } - m_cCodedName = m_cLibAvContext->getCodecName(); - } -#endif - if( m_iStreamHandler == YUV_IO ) - { - closeFile(); - if( !openFile() ) - { - return false; - } - UInt64 frameBytesInput = m_pcCurrFrame->getBytesPerFrame(); - fseek( m_pFile, 0, SEEK_END ); - UInt64 fileSize = ftell( m_pFile ); - m_uiTotalFrameNum = fileSize / frameBytesInput; - fseek( m_pFile, 0, SEEK_SET ); - } + m_uiTotalFrameNum = m_pcStreamHandler->calculateFrameNumber(); + + if( m_uiWidth <= 0 || m_uiHeight <= 0 || m_iPixelFormat < 0 || m_uiTotalFrameNum < 1 ) { return false; @@ -406,40 +388,14 @@ Bool PlaYUVerStream::reload() return true; } -Bool PlaYUVerStream::openFile() -{ -//m_fsIOStream.open( m_cFilename, std::ios::in | std::ios::binary ) - m_pFile = NULL; - m_pFile = fopen( m_pchFilename, m_bIsInput ? "rb" : "wb" ); - if( m_pFile == NULL ) - { - return false; - } - if( m_bIsInput ) - { - fseek( m_pFile, m_iCurrFrameNum >= 0 ? m_iCurrFrameNum : 0, SEEK_SET ); - } - return true; -} - -Void PlaYUVerStream::closeFile() -{ - if( m_pFile ) - fclose( m_pFile ); -} - Void PlaYUVerStream::close() { if( !m_bInit ) return; - if( m_iStreamHandler == YUV_IO ) - closeFile(); + m_pcStreamHandler->closeHandler(); + -#ifdef USE_FFMPEG - if( m_iStreamHandler == FFMPEG ) - m_cLibAvContext->closeAvFormat(); -#endif if( m_ppcFrameBuffer ) { @@ -529,25 +485,25 @@ Void PlaYUVerStream::loadAll() Void PlaYUVerStream::getDuration( Int* duration_array ) { - Int hours, mins, secs = 0; -#ifdef USE_FFMPEG - if( m_iStreamHandler == FFMPEG ) - { - secs = m_cLibAvContext->getStreamDuration(); - } - else -#endif - if( m_iStreamHandler == YUV_IO ) - { - secs = m_uiTotalFrameNum / m_dFrameRate; - } - mins = secs / 60; - secs %= 60; - hours = mins / 60; - mins %= 60; - *duration_array++ = hours; - *duration_array++ = mins; - *duration_array++ = secs; +// Int hours, mins, secs = 0; +// #ifdef USE_FFMPEG +// if( m_iStreamHandler == FFMPEG ) +// { +// secs = m_cLibAvContext->getStreamDuration(); +// } +// else +// #endif +// if( m_iStreamHandler == YUV_IO ) +// { +// secs = m_uiTotalFrameNum / m_dFrameRate; +// } +// mins = secs / 60; +// secs %= 60; +// hours = mins / 60; +// mins %= 60; +// *duration_array++ = hours; +// *duration_array++ = mins; +// *duration_array++ = secs; } Void PlaYUVerStream::readFrameFillRGBBuffer() @@ -574,28 +530,16 @@ Void PlaYUVerStream::readFrame() return; } -#ifdef USE_FFMPEG - if( m_iStreamHandler == FFMPEG ) - { - if( !m_cLibAvContext->decodeAvFormat() ) - { - throw "[PlaYUVerStream] Error reading frame from libav"; - return; - } - m_pcNextFrame->frameFromBuffer( m_cLibAvContext->m_pchFrameBuffer, m_cLibAvContext->m_uiFrameBufferSize, m_iEndianness ); - } -#endif - if( m_iStreamHandler == YUV_IO ) - { - UInt64 frame_bytes_input = m_pcNextFrame->getBytesPerFrame(); - UInt64 bytes_read = fread( m_pStreamBuffer, sizeof(Byte), frame_bytes_input, m_pFile ); - if( bytes_read != frame_bytes_input ) + UInt64 uiByterPerFrame = m_pcNextFrame->getBytesPerFrame(); + + + if( !m_pcStreamHandler->read( m_pStreamBuffer ) ) { throw "[PlaYUVerStream] Cannot read file"; return; } - m_pcNextFrame->frameFromBuffer( m_pStreamBuffer, bytes_read, m_iEndianness ); - } + m_pcNextFrame->frameFromBuffer( m_pStreamBuffer, uiByterPerFrame, m_iEndianness ); + m_uiCurrFrameFileIdx++; return; } @@ -609,10 +553,8 @@ Void PlaYUVerStream::writeFrame( PlaYUVerFrame *pcFrame ) { if( m_iStreamHandler == YUV_IO ) { - UInt64 frame_bytes_input = pcFrame->getBytesPerFrame(); pcFrame->frameToBuffer( m_pStreamBuffer ); - UInt64 bytes_read = fwrite( m_pStreamBuffer, sizeof(Byte), frame_bytes_input, m_pFile ); - if( bytes_read != frame_bytes_input ) + if( !m_pcStreamHandler->write( m_pStreamBuffer ) ) { throw "[PlaYUVerStream] Cannot write into the file"; } @@ -755,24 +697,12 @@ Bool PlaYUVerStream::seekInput( UInt64 new_frame_num ) setNextFrame(); return true; } - if( m_iStreamHandler == OPENCV_HANDLER ) + + if( !m_pcStreamHandler->seek( new_frame_num ) ) { - return true; - } -#ifdef USE_FFMPEG - if( m_iStreamHandler == FFMPEG ) - { - m_cLibAvContext->seekAvFormat( new_frame_num ); - } -#endif - if( m_iStreamHandler == YUV_IO ) - { - if( !m_pFile ) - return false; - UInt64 frame_bytes_input = m_ppcFrameBuffer[0]->getBytesPerFrame(); - UInt64 nbytes_seek = frame_bytes_input * new_frame_num; - fseek( m_pFile, nbytes_seek, SEEK_SET ); + throw "[PlaYUVerStream] Cannot write into the file"; } + m_uiCurrFrameFileIdx = new_frame_num; m_uiFrameBufferIndex = 0; diff --git a/lib/PlaYUVerStream.h b/lib/PlaYUVerStream.h index 3861958..5fcd2e1 100644 --- a/lib/PlaYUVerStream.h +++ b/lib/PlaYUVerStream.h @@ -35,8 +35,9 @@ namespace plaYUVer { -class LibAvContextHandle; +class StreamHandlerLibav; class LibOpenCVHandler; +class PlaYUVerStreamHandlerIf; typedef struct { @@ -69,6 +70,7 @@ typedef struct formatsList.insert( formatsList.end(), new_fmts.begin(), new_fmts.end() ); \ } + /** * \class PlaYUVerStream * \ingroup PlaYUVerLib PlaYUVerLib_Stream @@ -95,6 +97,9 @@ public: END_OF_SEQ, }; + std::string getFormatName(); + std::string getCodecName(); + Bool open( std::string filename, std::string resolution, std::string input_format, UInt bitsPel, Int endianness, UInt frame_rate, Bool bInput = true ); Bool open( std::string filename, UInt width, UInt height, Int input_format, UInt bitsPel, Int endianness, UInt frame_rate, Bool bInput = true ); @@ -102,9 +107,6 @@ public: Void close(); - Bool openFile(); - Void closeFile(); - Void getFormat( UInt& rWidth, UInt& rHeight, Int& rInputFormat, UInt& rBitsPerPel, Int& rEndianness, UInt& rFrameRate ); Void loadAll(); @@ -134,14 +136,6 @@ public: { return m_cFilename; } - std::string getFormatName() - { - return m_cFormatName; - } - std::string getCodecName() - { - return m_cCodedName; - } UInt getFrameNum() { @@ -182,14 +176,12 @@ private: TOTAL_HANDLERR }; Int m_iStreamHandler; - LibAvContextHandle* m_cLibAvContext; + PlaYUVerStreamHandlerIf* m_pcStreamHandler; + StreamHandlerLibav* m_cLibAvContext; std::string m_cFilename; Char* m_pchFilename; - std::string m_cFormatName; - std::string m_cCodedName; - UInt m_uiWidth; UInt m_uiHeight; Int m_iPixelFormat; @@ -199,8 +191,6 @@ private: UInt64 m_uiTotalFrameNum; Int64 m_iCurrFrameNum; - FILE* m_pFile; /**< The input file pointer >*/ - std::fstream m_fsIOStream; /**< The input file pointer >*/ Byte* m_pStreamBuffer; UInt m_uiFrameBufferSize; diff --git a/lib/PlaYUVerStreamHandlerIf.h b/lib/PlaYUVerStreamHandlerIf.h new file mode 100644 index 0000000..02f9f81 --- /dev/null +++ b/lib/PlaYUVerStreamHandlerIf.h @@ -0,0 +1,85 @@ +/* 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 PlaYUVerStreamHandlerIf.h + * \brief Abstract class for stream handling + */ + +#ifndef __PLAYUVERSTREAMHANDLERIF_H__ +#define __PLAYUVERSTREAMHANDLERIF_H__ + +#include "PlaYUVerDefs.h" +// #include +// #include +// #include + +namespace plaYUVer +{ + +/** + * \class PlaYUVerStreamHandlerIf + * \ingroup PlaYUVerLib PlaYUVerLib_Stream + * \brief Abstract class for stream handling + */ +class PlaYUVerStreamHandlerIf +{ +public: + PlaYUVerStreamHandlerIf() + { + m_bIsInput = true; + } + ~PlaYUVerStreamHandlerIf() + { + } + virtual Bool openHandler( std::string strFilename, Bool bInput ) = 0; + virtual UInt64 calculateFrameNumber() = 0; + virtual Void closeHandler() = 0; + virtual Bool read( Byte* pchBuffer ) = 0; + virtual Bool write( Byte* pchBuffer ) = 0; + virtual Bool seek( UInt64 iFrameNum ) = 0; + + virtual Void getFormat( UInt& rWidth, UInt& rHeight, Int& rInputFormat, UInt& rBitsPerPel, Int& rEndianness, Double& rFrameRate ) + { + return; + } + Void setBytesPerFrame( UInt64 uiNBytes ) + { + m_uiNBytesPerFrame = uiNBytes; + } + std::string getFormatName() + { + return m_strFormatName; + } + std::string getCodecName() + { + return m_strCodecName; + } +protected: + Bool m_bIsInput; + UInt64 m_uiNBytesPerFrame; + std::string m_strFormatName; + std::string m_strCodecName; +}; + + +} // NAMESPACE + +#endif // __PLAYUVERSTREAMHANDLERIF_H__ + diff --git a/lib/LibAvContextHandle.cpp b/lib/StreamHandlerLibav.cpp similarity index 57% rename from lib/LibAvContextHandle.cpp rename to lib/StreamHandlerLibav.cpp index bd095f4..95ae08a 100644 --- a/lib/LibAvContextHandle.cpp +++ b/lib/StreamHandlerLibav.cpp @@ -18,13 +18,13 @@ */ /** - * \file LibAvContextHandle.cpp + * \file StreamHandlerLibav.cpp * \ingroup PlaYUVerLib * \brief Interface with libav libs */ #include -#include "LibAvContextHandle.h" +#include "StreamHandlerLibav.h" #include "PlaYUVerFrame.h" #include "PlaYUVerFramePixelFormats.h" #include "LibMemory.h" @@ -32,7 +32,7 @@ namespace plaYUVer { -std::vector LibAvContextHandle::supportedReadFormats() +std::vector StreamHandlerLibav::supportedReadFormats() { INI_REGIST_PLAYUVER_SUPPORTED_FMT; REGIST_PLAYUVER_SUPPORTED_FMT( "Portable Grayscale Map", "pgm" ); @@ -48,26 +48,26 @@ std::vector LibAvContextHandle::supportedReadFormats() END_REGIST_PLAYUVER_SUPPORTED_FMT; } -std::vector LibAvContextHandle::supportedWriteFormats() +std::vector StreamHandlerLibav::supportedWriteFormats() { INI_REGIST_PLAYUVER_SUPPORTED_FMT; END_REGIST_PLAYUVER_SUPPORTED_FMT; } -std::vector LibAvContextHandle::supportedSaveFormats() +std::vector StreamHandlerLibav::supportedSaveFormats() { INI_REGIST_PLAYUVER_SUPPORTED_FMT; END_REGIST_PLAYUVER_SUPPORTED_FMT; } -static int open_codec_context( int *stream_idx, AVFormatContext *fmt_ctx, enum AVMediaType type ) +static int open_codec_context( int *stream_idx, AVFormatContext *m_cFmtCtx, 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 ); + ret = av_find_best_stream( m_cFmtCtx, type, -1, -1, NULL, 0 ); if( ret < 0 ) { return ret; @@ -75,7 +75,7 @@ static int open_codec_context( int *stream_idx, AVFormatContext *fmt_ctx, enum A else { *stream_idx = ret; - st = fmt_ctx->streams[*stream_idx]; + st = m_cFmtCtx->streams[*stream_idx]; /* find decoder for the stream */ dec_ctx = st->codec; @@ -96,34 +96,21 @@ static int open_codec_context( int *stream_idx, AVFormatContext *fmt_ctx, enum A return 0; } -Void LibAvContextHandle::closeAvFormat() +// Bool StreamHandlerLibav::initAvFormat( const char* filename, UInt& width, UInt& height, Int& pixel_format, UInt& bits_pel, Int& endianness, Double& frame_rate, +// UInt64& num_frames ) +Bool StreamHandlerLibav::openHandler( std::string strFilename, Bool bInput ) { - if( m_bHasStream ) - { - if( video_dec_ctx ) - avcodec_close( video_dec_ctx ); + const char* filename = strFilename.c_str(); - if( fmt_ctx ) - avformat_close_input( &fmt_ctx ); - - av_free( frame ); - //av_free( video_dst_data[0] ); - } - m_bHasStream = false; -} - -Bool LibAvContextHandle::initAvFormat( const char* filename, UInt& width, UInt& height, Int& pixel_format, UInt& bits_pel, Int& endianness, Double& frame_rate, - UInt64& num_frames ) -{ - fmt_ctx = NULL; - video_dec_ctx = NULL; - video_stream = NULL; + m_cFmtCtx = NULL; + m_cCodecCtx = NULL; + m_cStream = 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_iStreamIdx = -1; + m_cFrame = NULL; m_bHasStream = false; AVDictionary *format_opts = NULL; @@ -131,40 +118,40 @@ Bool LibAvContextHandle::initAvFormat( const char* filename, UInt& width, UInt& /* register all formats and codecs */ av_register_all(); - if( width > 0 && height > 0 ) - { - Char aux_string[10]; - sprintf( aux_string, "%dx%d", width, height ); - av_dict_set( &format_opts, "video_size", aux_string, 0 ); - } +// if( width > 0 && height > 0 ) +// { +// Char aux_string[10]; +// sprintf( aux_string, "%dx%d", width, height ); +// av_dict_set( &format_opts, "video_size", aux_string, 0 ); +// } - 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 ); - } +// 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 ); +// } /* open input file, and allocate format context */ - if( avformat_open_input( &fmt_ctx, filename, NULL, &format_opts ) < 0 ) + if( avformat_open_input( &m_cFmtCtx, filename, NULL, &format_opts ) < 0 ) { //qDebug( ) << " Could not open source file %s !!!" << filename << endl; return false; } /* retrieve stream information */ - if( avformat_find_stream_info( fmt_ctx, NULL ) < 0 ) + if( avformat_find_stream_info( m_cFmtCtx, NULL ) < 0 ) { //qDebug( ) << " Could not find stream information !!!" << endl; return false; } - if( open_codec_context( &video_stream_idx, fmt_ctx, AVMEDIA_TYPE_VIDEO ) >= 0 ) + if( open_codec_context( &m_iStreamIdx, m_cFmtCtx, AVMEDIA_TYPE_VIDEO ) >= 0 ) { - video_stream = fmt_ctx->streams[video_stream_idx]; - video_dec_ctx = video_stream->codec; + m_cStream = m_cFmtCtx->streams[m_iStreamIdx]; + m_cCodecCtx = m_cStream->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 ); +// ret = av_image_alloc( video_dst_data, video_dst_linesize, m_cCodecCtx->width, m_cCodecCtx->height, m_cCodecCtx->pix_fmt, 1 ); // if( ret < 0 ) // { // //qDebug( ) << " Could not allocate raw video buffer !!!" << endl; @@ -173,48 +160,31 @@ Bool LibAvContextHandle::initAvFormat( const char* filename, UInt& width, UInt& // } // video_dst_bufsize = ret; - m_uiFrameBufferSize = av_image_get_buffer_size( video_dec_ctx->pix_fmt, video_dec_ctx->width, video_dec_ctx->height, 1 ); + m_uiFrameBufferSize = av_image_get_buffer_size( m_cCodecCtx->pix_fmt, m_cCodecCtx->width, m_cCodecCtx->height, 1 ); getMem1D( &m_pchFrameBuffer, m_uiFrameBufferSize ); } - const char *name = avcodec_get_name( video_dec_ctx->codec_id ); + const char *name = avcodec_get_name( m_cCodecCtx->codec_id ); sprintf( m_acCodecName, "%s", name ); Double fr = 30; - if( video_stream->avg_frame_rate.den && video_stream->avg_frame_rate.num ) - fr = av_q2d( video_stream->avg_frame_rate ); + if( m_cStream->avg_frame_rate.den && m_cStream->avg_frame_rate.num ) + fr = av_q2d( m_cStream->avg_frame_rate ); #if FF_API_R_FRAME_RATE - else if( video_stream->r_frame_rate.den && video_stream->r_frame_rate.num ) - fr = av_q2d( video_stream->r_frame_rate ); + else if( m_cStream->r_frame_rate.den && m_cStream->r_frame_rate.num ) + fr = av_q2d( m_cStream->r_frame_rate ); #endif - else if( video_stream->time_base.den && video_stream->time_base.num ) - fr = 1 / av_q2d( video_stream->time_base ); - else if( video_stream->codec->time_base.den && video_stream->codec->time_base.num ) - fr = 1 / av_q2d( video_stream->codec->time_base ); + else if( m_cStream->time_base.den && m_cStream->time_base.num ) + fr = 1 / av_q2d( m_cStream->time_base ); + else if( m_cStream->codec->time_base.den && m_cStream->codec->time_base.num ) + fr = 1 / av_q2d( m_cStream->codec->time_base ); - frame_rate = fr; + m_dFrameRate = fr; - /*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; - num_frames = m_uiSecs * frame_rate; - m_uiMicroSec = duration % AV_TIME_BASE; - } - else - { - num_frames = 0; - } - num_frames = num_frames == 0 ? 1 : num_frames; - - Int pix_fmt = video_dec_ctx->pix_fmt; + Int pix_fmt = m_cCodecCtx->pix_fmt; // Set bits per pixel to default (8 bits) - bits_pel = 8; + m_uiBitsPerPixel = 8; /** * Auxiliar conversation to re-use similar pixfmt @@ -231,55 +201,52 @@ Bool LibAvContextHandle::initAvFormat( const char* filename, UInt& width, UInt& pix_fmt = AV_PIX_FMT_YUV444P; break; case AV_PIX_FMT_GRAY16LE: - bits_pel = 16; - endianness = 1; + m_uiBitsPerPixel = 16; + m_iEndianness = 1; pix_fmt = AV_PIX_FMT_GRAY8; break; case AV_PIX_FMT_GRAY16BE: - bits_pel = 16; - endianness = 0; + m_uiBitsPerPixel = 16; + m_iEndianness = 0; pix_fmt = AV_PIX_FMT_GRAY8; break; } - width = video_dec_ctx->width; - height = video_dec_ctx->height; + m_uiWidth = m_cCodecCtx->width; + m_uiHeight = m_cCodecCtx->height; - pixel_format = PlaYUVerFrame::NO_FMT; + m_iPixelFormat = PlaYUVerFrame::NO_FMT; for( Int i = 0; i < PLAYUVER_NUMBER_FORMATS; i++ ) { if( g_PlaYUVerPixFmtDescriptorsList[i].ffmpegPelFormat == pix_fmt ) { - pixel_format = i; + m_iPixelFormat = i; break; } } - if( pixel_format == PlaYUVerFrame::NO_FMT ) + if( m_iPixelFormat == PlaYUVerFrame::NO_FMT ) { throw "Cannot open file using FFmpeg libs - unsupported pixel format"; - closeAvFormat(); return false; } /* dump input information to stderr */ - av_dump_format( fmt_ctx, 0, filename, 0 ); - if( !video_stream ) + av_dump_format( m_cFmtCtx, 0, filename, 0 ); + if( !m_cStream ) { //qDebug( ) << " Could not find audio or video stream in the input, aborting !!!" << endl; - closeAvFormat(); + closeHandler(); return false; } #if( LIBAVFORMAT_VERSION_MAJOR >= 55 ) - frame = av_frame_alloc(); + m_cFrame = av_frame_alloc(); #else - frame = avcodec_alloc_frame(); + m_cFrame = avcodec_alloc_frame(); #endif - if( !frame ) + if( !m_cFrame ) { - //qDebug( ) << " Could not allocate frame !!!" << endl; - //ret = AVERROR( ENOMEM ); - closeAvFormat(); + closeHandler(); return false; } @@ -293,13 +260,62 @@ Bool LibAvContextHandle::initAvFormat( const char* filename, UInt& width, UInt& return true; } -Bool LibAvContextHandle::decodeVideoPkt() +Void StreamHandlerLibav::closeHandler() +{ + if( m_bHasStream ) + { + if( m_cCodecCtx ) + avcodec_close( m_cCodecCtx ); + + if( m_cFmtCtx ) + avformat_close_input( &m_cFmtCtx ); + + av_free( m_cFrame ); + } + m_bHasStream = false; +} + +Void StreamHandlerLibav::getFormat( UInt& rWidth, UInt& rHeight, Int& rInputFormat, UInt& rBitsPerPel, Int& rEndianness, Double& rFrameRate ) +{ + rWidth = m_uiWidth; + rHeight = m_uiHeight; + rInputFormat = m_iPixelFormat; + rBitsPerPel = m_uiBitsPerPixel; + rEndianness = m_iEndianness; + rFrameRate = m_dFrameRate; +} + + +UInt64 StreamHandlerLibav::calculateFrameNumber() +{ + UInt64 num_frames; +// if( m_cStream->nb_frames ) +// { * +// num_frames = m_cStream->nb_frames; +// } +// else + if( m_cFmtCtx->duration != AV_NOPTS_VALUE ) + { + Int64 duration = m_cFmtCtx->duration + 5000; + m_uiSecs = duration / AV_TIME_BASE; + num_frames = m_uiSecs * m_dFrameRate; + m_uiMicroSec = duration % AV_TIME_BASE; + } + else + { + num_frames = 0; + } + num_frames = num_frames == 0 ? 1 : num_frames; + return num_frames; +} + +Bool StreamHandlerLibav::decodeVideoPkt() { Int got_frame = 0; Int decResult; - if( pkt.stream_index == video_stream_idx ) + if( pkt.stream_index == m_iStreamIdx ) { - decResult = avcodec_decode_video2( video_dec_ctx, frame, &got_frame, &pkt ); + decResult = avcodec_decode_video2( m_cCodecCtx, m_cFrame, &got_frame, &pkt ); if( decResult < 0 ) { fprintf( stderr, "Error decoding video frame\n" ); @@ -315,7 +331,7 @@ Bool LibAvContextHandle::decodeVideoPkt() return got_frame > 0 ? true : false; } -Bool LibAvContextHandle::decodeAvFormat() +Bool StreamHandlerLibav::read( Byte* pchBuffer ) { Bool bGotFrame = false; AVPacket orig_pkt = pkt; @@ -323,7 +339,7 @@ Bool LibAvContextHandle::decodeAvFormat() bGotFrame |= decodeVideoPkt(); /* read frames from the file */ - while( !bGotFrame && ( av_read_frame( fmt_ctx, &pkt ) >= 0 ) ) + while( !bGotFrame && ( av_read_frame( m_cFmtCtx, &pkt ) >= 0 ) ) { orig_pkt = pkt; do @@ -348,9 +364,10 @@ Bool LibAvContextHandle::decodeAvFormat() 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_image_copy_to_buffer( m_pchFrameBuffer, m_uiFrameBufferSize, m_cFrame->data, m_cFrame->linesize, m_cCodecCtx->pix_fmt, m_cCodecCtx->width, + m_cCodecCtx->height, 1 ); + av_image_copy_to_buffer( pchBuffer, m_uiFrameBufferSize, m_cFrame->data, m_cFrame->linesize, m_cCodecCtx->pix_fmt, m_cCodecCtx->width, + m_cCodecCtx->height, 1 ); if( orig_pkt.size ) av_free_packet( &orig_pkt ); @@ -360,9 +377,15 @@ Bool LibAvContextHandle::decodeAvFormat() return false; } -Void LibAvContextHandle::seekAvFormat( UInt64 frame_num ) +Bool StreamHandlerLibav::write( Byte* pchBuffer ) { - av_seek_frame( fmt_ctx, video_stream_idx, frame_num, AVSEEK_FLAG_FRAME ); + return false; +} + +Bool StreamHandlerLibav::seek( UInt64 iFrameNum ) +{ + av_seek_frame( m_cFmtCtx, m_iStreamIdx, iFrameNum, AVSEEK_FLAG_FRAME ); + return true; } } // NAMESPACE diff --git a/lib/LibAvContextHandle.h b/lib/StreamHandlerLibav.h similarity index 69% rename from lib/LibAvContextHandle.h rename to lib/StreamHandlerLibav.h index 57cbc9f..1b48906 100644 --- a/lib/LibAvContextHandle.h +++ b/lib/StreamHandlerLibav.h @@ -18,7 +18,7 @@ */ /** - * \file LibAvContextHandle.h + * \file StreamHandlerLibav.h * \ingroup PlaYUVerLib * \brief Interface with libav libs */ @@ -49,11 +49,12 @@ extern "C" #include "PlaYUVerDefs.h" #include "PlaYUVerStream.h" +#include "PlaYUVerStreamHandlerIf.h" namespace plaYUVer { -class LibAvContextHandle +class StreamHandlerLibav: public PlaYUVerStreamHandlerIf { public: @@ -61,46 +62,42 @@ public: static std::vector supportedWriteFormats(); static std::vector supportedSaveFormats(); - LibAvContextHandle() : - m_bHasStream( false ) + StreamHandlerLibav() { } - Bool initAvFormat( const char* filename, UInt& width, UInt& height, Int& pixel_format, UInt& bits_pel, Int& endianness, Double& frame_rate, UInt64& num_frames ); - Void closeAvFormat(); - Bool decodeAvFormat(); - Void seekAvFormat( UInt64 frame_num ); + Bool openHandler( std::string strFilename, Bool bInput ); +// Bool initAvFormat( const char* filename, UInt& width, UInt& height, Int& pixel_format, UInt& bits_pel, Int& endianness, Double& frame_rate, UInt64& num_frames ); + Void closeHandler(); + UInt64 calculateFrameNumber(); + Bool seek( UInt64 iFrameNum ); + Bool read( Byte* pchBuffer ); + Bool write( Byte* pchBuffer ); + + Void getFormat( UInt& rWidth, UInt& rHeight, Int& rInputFormat, UInt& rBitsPerPel, Int& rEndianness, Double& rFrameRate ); - Bool getStatus() - { - return m_bHasStream; - } - Char* getFormatName() - { - return m_acFormatName; - } - Char* getCodecName() - { - return m_acCodecName; - } UInt getStreamDuration() { return m_uiSecs; } -// uint8_t *video_dst_data[4]; -// int video_dst_linesize[4]; -// int video_dst_bufsize; - UChar* m_pchFrameBuffer; UInt64 m_uiFrameBufferSize; private: - AVFormatContext *fmt_ctx; - AVCodecContext *video_dec_ctx; - AVStream *video_stream; - Int video_stream_idx; - AVFrame *frame; + + UInt m_uiWidth; + UInt m_uiHeight; + Int m_iPixelFormat; + UInt m_uiBitsPerPixel; + Int m_iEndianness; + Double m_dFrameRate; + + AVFormatContext* m_cFmtCtx; + AVCodecContext* m_cCodecCtx; + AVStream* m_cStream; + Int m_iStreamIdx; + AVFrame* m_cFrame; AVPacket pkt; Bool m_bHasStream; diff --git a/lib/StreamHandlerRaw.h b/lib/StreamHandlerRaw.h new file mode 100644 index 0000000..e1d05f4 --- /dev/null +++ b/lib/StreamHandlerRaw.h @@ -0,0 +1,101 @@ +/* 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 PlaYUVerRawHandler.h + * \brief Abstract class for stream handling + */ + +#ifndef __PLAYUVERRAWHANDLER_H__ +#define __PLAYUVERRAWHANDLER_H__ + +#include "PlaYUVerDefs.h" +#include "PlaYUVerStreamHandlerIf.h" + +namespace plaYUVer +{ + +/** + * \class PlaYUVerRawHandler + * \ingroup PlaYUVerLib PlaYUVerLib_Stream + * \brief Class to handle raw video format + */ +class PlaYUVerRawHandler: public PlaYUVerStreamHandlerIf +{ +private: + FILE* m_pFile; /**< The input file pointer >*/ +public: + + Bool openHandler( std::string strFilename, Bool bInput ) + { + m_bIsInput = bInput; + m_pFile = NULL; + m_pFile = fopen( strFilename.c_str(), bInput ? "rb" : "wb" ); + if( m_pFile == NULL ) + { + return false; + } + m_strFormatName = "YUV"; + m_strCodecName = "Raw Video"; + return true; + } + Void closeHandler() + { + if( m_pFile ) + fclose( m_pFile ); + } + UInt64 calculateFrameNumber() + { + if( !m_pFile || m_uiNBytesPerFrame == 0 ) + return 0; + fseek( m_pFile, 0, SEEK_END ); + UInt64 fileSize = ftell( m_pFile ); + fseek( m_pFile, 0, SEEK_SET ); + return ( fileSize / m_uiNBytesPerFrame ); + } + Bool seek( UInt64 iFrameNum ) + { + if( m_bIsInput && m_pFile ) + { + fseek( m_pFile, iFrameNum >= 0 ? iFrameNum * m_uiNBytesPerFrame : 0, SEEK_SET ); + return true; + } + return false; + } + Bool read( Byte* pchBuffer ) + { + UInt64 processed_bytes = fread( pchBuffer, sizeof( Byte ), m_uiNBytesPerFrame, m_pFile ); + if( processed_bytes != m_uiNBytesPerFrame ) + return false; + return true; + } + Bool write( Byte* pchBuffer ) + { + UInt64 processed_bytes = fwrite( pchBuffer, sizeof( Byte ), m_uiNBytesPerFrame, m_pFile ); + if( processed_bytes != m_uiNBytesPerFrame ) + return false; + return true; + } +}; + + +} // NAMESPACE + +#endif // __PLAYUVERRAWHANDLER_H__ +