From 366d69b5c974e157e52d1e6dfcd3f4b13a427213 Mon Sep 17 00:00:00 2001 From: Joao Carreira Date: Sun, 10 Oct 2021 23:04:39 +0100 Subject: [PATCH] Always use RAW format if first try to open file fails --- app/VideoStreamSubWindow.cpp | 9 +- lib/CalypStream.cpp | 253 +++++++++++++++++++---------------- lib/CalypStream.h | 34 ++++- lib/CalypStreamHandlerIf.h | 1 - lib/StreamHandlerOpenCV.cpp | 24 ++-- lib/StreamHandlerOpenCV.h | 3 +- 6 files changed, 190 insertions(+), 134 deletions(-) diff --git a/app/VideoStreamSubWindow.cpp b/app/VideoStreamSubWindow.cpp index ac8198b..61fa6ca 100644 --- a/app/VideoStreamSubWindow.cpp +++ b/app/VideoStreamSubWindow.cpp @@ -200,15 +200,20 @@ bool VideoStreamSubWindow::loadFile( QString cFilename, bool bForceDialog ) } try { - bRet = m_pCurrStream->open( cFilename.toStdString(), Width, Height, InputFormat, BitsPel, Endianness, FrameRate, true ); + bRet = m_pCurrStream->open( cFilename.toStdString(), Width, Height, InputFormat, BitsPel, Endianness, FrameRate, true, iPass == 1 ); } catch( CalypFailure& e ) { - if( iPass == 1 ) + if( iPass > 0 ) throw( e ); } } + if( !bRet ) + { + return false; + } + m_sStreamInfo.m_cFilename = cFilename; m_sStreamInfo.m_uiWidth = Width; m_sStreamInfo.m_uiHeight = Height; diff --git a/lib/CalypStream.cpp b/lib/CalypStream.cpp index 57d3a9a..1579749 100644 --- a/lib/CalypStream.cpp +++ b/lib/CalypStream.cpp @@ -48,7 +48,7 @@ constexpr auto kDefaultBitsPerPixel = 8; constexpr auto kDefaultFrameRate = 30; -auto find_stream_handler( std::string strFilename, bool bRead ) -> CalypStreamFormat::CreateStreamHandlerFn; +auto find_stream_handler( const std::string& strFilename, bool bRead ) -> CalypStreamFormat::CreateStreamHandlerFn; std::vector CalypStream::supportedReadFormats() { @@ -192,7 +192,6 @@ public: isInit = false; bLoadAll = false; iCurrFrameNum = -1; - cFilename = ""; } ~CalypStreamPrivate() @@ -200,6 +199,109 @@ public: close(); } + bool open( std::string filename, unsigned int width, unsigned int height, int input_format, unsigned int bitsPel, int endianness, bool hasNegative, + unsigned int frame_rate, bool bInput, bool forceRaw ) + { + if( isInit ) + { + close(); + } + isInit = false; + isInput = bInput; + + if( forceRaw ) + { + handler = StreamHandlerRaw::Create(); + } + else + { + auto createHandlerFct = find_stream_handler( filename, isInput ); + if( !createHandlerFct ) + { + throw CalypFailure( "CalypStream", "Invalid handler" ); + } + + handler = createHandlerFct(); + } + + if( !handler ) + { + throw CalypFailure( "CalypStream", "Cannot create handler" ); + } + + cFilename = std::move( filename ); + + handler->m_uiWidth = width; + handler->m_uiHeight = height; + handler->m_iPixelFormat = input_format; + handler->m_uiBitsPerPixel = bitsPel; + handler->m_iEndianness = endianness; + handler->m_dFrameRate = frame_rate; + + if( !handler->openHandler( cFilename, isInput ) ) + { + close(); + throw CalypFailure( "CalypStream", "Cannot create the stream handler" ); + return isInit; + } + + if( handler->m_uiWidth <= 0 || handler->m_uiHeight <= 0 || handler->m_iPixelFormat < 0 ) + { + close(); + throw CalypFailure( "CalypStream", "Incorrect configuration: width, height or pixel format" ); + return isInit; + } + + frameFifo.clear(); + + // Keep past, current and future frames + std::size_t bufferSize = isInput ? 6 : 1; + try + { + frameBuffer = std::make_shared( bufferSize, + handler->m_uiWidth, + handler->m_uiHeight, + handler->m_iPixelFormat, + handler->m_uiBitsPerPixel, + hasNegative ); + } + catch( CalypFailure& e ) + { + close(); + throw CalypFailure( "CalypStream", "Cannot allocated frame buffer" ); + return isInit; + } + + const CalypFrame* refFrame = frameBuffer->ref(); + + handler->m_uiNBytesPerFrame = refFrame->getBytesPerFrame(); + + // Some handlers need to know how long is a frame to get frame number + handler->calculateFrameNumber(); + + if( isInput && handler->m_uiTotalNumberFrames == 0 ) + { + close(); + throw CalypFailure( "CalypStream", "Incorrect configuration: less than one frame" ); + return isInit; + } + + if( !handler->configureBuffer( *refFrame ) ) + { + close(); + throw CalypFailure( "CalypStream", "Cannot allocated buffers" ); + return isInit; + } + + iCurrFrameNum = -1; + isInit = true; + + seekInput( 0 ); + + isInit = true; + return isInit; + } + void close() { if( handler ) @@ -211,6 +313,30 @@ public: isInit = false; } + bool seekInput( unsigned long new_frame_num ) + { + const std::lock_guard lock( stream_mutex ); + + if( !isInit || new_frame_num >= handler->m_uiTotalNumberFrames || long( new_frame_num ) == iCurrFrameNum ) + return false; + + iCurrFrameNum = new_frame_num; + + if( bLoadAll ) + return true; + + frameFifo.clear(); + if( !handler->seek( iCurrFrameNum ) ) + { + throw CalypFailure( "CalypStream", "Cannot seek file into desired position" ); + } + + readNextFrame(); + if( handler->m_uiTotalNumberFrames > 1 ) + readNextFrame(); + return true; + } + bool readNextFrame( bool fillRgbBuffer = false ) { const std::lock_guard lock( stream_mutex ); @@ -291,109 +417,25 @@ bool CalypStream::open( std::string filename, std::string resolution, std::strin break; } } - return open( filename, width, height, input_format, bitsPel, endianness, hasNegative, frame_rate, bInput ); + return d->open( std::move( filename ), width, height, input_format, bitsPel, endianness, hasNegative, frame_rate, bInput, false ); } bool CalypStream::open( std::string filename, unsigned int width, unsigned int height, int input_format, unsigned int bitsPel, int endianness, unsigned int frame_rate, bool bInput ) { - return open( filename, width, height, input_format, bitsPel, endianness, false, frame_rate, bInput ); + return d->open( std::move( filename ), width, height, input_format, bitsPel, endianness, false, frame_rate, bInput, false ); } bool CalypStream::open( std::string filename, unsigned int width, unsigned int height, int input_format, unsigned int bitsPel, int endianness, bool hasNegative, unsigned int frame_rate, bool bInput ) { - if( d->isInit ) - { - d->close(); - } - d->isInit = false; - d->isInput = bInput; + return d->open( std::move( filename ), width, height, input_format, bitsPel, endianness, hasNegative, frame_rate, bInput, false ); +} - auto createHandlerFct = find_stream_handler( filename, d->isInput ); - if( !createHandlerFct ) - { - throw CalypFailure( "CalypStream", "Invalid handler" ); - } - - d->handler = createHandlerFct(); - - if( !d->handler ) - { - throw CalypFailure( "CalypStream", "Cannot create handler" ); - } - - d->cFilename = filename; - - d->handler->m_cFilename = filename; - d->handler->m_uiWidth = width; - d->handler->m_uiHeight = height; - d->handler->m_iPixelFormat = input_format; - d->handler->m_uiBitsPerPixel = bitsPel; - d->handler->m_iEndianness = endianness; - d->handler->m_dFrameRate = frame_rate; - - if( !d->handler->openHandler( d->cFilename, d->isInput ) ) - { - d->close(); - return d->isInit; - } - - if( d->handler->m_uiWidth <= 0 || d->handler->m_uiHeight <= 0 || d->handler->m_iPixelFormat < 0 ) - { - d->close(); - //throw CalypFailure( "CalypStream", "Incorrect configuration: width, height or pixel format" ); - return d->isInit; - } - - d->frameFifo.clear(); - - // Keep past, current and future frames - std::size_t bufferSize = d->isInput ? 6 : 1; - try - { - d->frameBuffer = std::make_shared( bufferSize, - d->handler->m_uiWidth, - d->handler->m_uiHeight, - d->handler->m_iPixelFormat, - d->handler->m_uiBitsPerPixel, - hasNegative ); - } - catch( CalypFailure& e ) - { - d->close(); - throw CalypFailure( "CalypStream", "Cannot allocated frame buffer" ); - return d->isInit; - } - - const CalypFrame* refFrame = d->frameBuffer->ref(); - - d->handler->m_uiNBytesPerFrame = refFrame->getBytesPerFrame(); - - // Some handlers need to know how long is a frame to get frame number - d->handler->calculateFrameNumber(); - - if( d->isInput && d->handler->m_uiTotalNumberFrames == 0 ) - { - d->close(); - throw CalypFailure( "CalypStream", "Incorrect configuration: less than one frame" ); - return d->isInit; - } - - if( !d->handler->configureBuffer( *refFrame ) ) - { - d->close(); - throw CalypFailure( "CalypStream", "Cannot allocated buffers" ); - return d->isInit; - } - - d->iCurrFrameNum = -1; - d->isInit = true; - - seekInput( 0 ); - - d->isInit = true; - return d->isInit; +bool CalypStream::open( std::string filename, unsigned int width, unsigned int height, int input_format, unsigned int bitsPel, int endianness, + unsigned int frame_rate, bool bInput, bool forceRaw ) +{ + return d->open( std::move( filename ), width, height, input_format, bitsPel, endianness, false, frame_rate, bInput, forceRaw ); } bool CalypStream::supportsFormatConfiguration() @@ -643,29 +685,10 @@ bool CalypStream::seekInputRelative( bool bIsFoward ) bool CalypStream::seekInput( unsigned long new_frame_num ) { - const std::lock_guard lock( d->stream_mutex ); - - if( !d->isInit || new_frame_num >= d->handler->m_uiTotalNumberFrames || long( new_frame_num ) == d->iCurrFrameNum ) - return false; - - d->iCurrFrameNum = new_frame_num; - - if( d->bLoadAll ) - return true; - - d->frameFifo.clear(); - if( !d->handler->seek( d->iCurrFrameNum ) ) - { - throw CalypFailure( "CalypStream", "Cannot seek file into desired position" ); - } - - d->readNextFrame(); - if( d->handler->m_uiTotalNumberFrames > 1 ) - d->readNextFrame(); - return true; + return d->seekInput( new_frame_num ); } -auto find_stream_handler( std::string strFilename, bool bRead ) -> CalypStreamFormat::CreateStreamHandlerFn +auto find_stream_handler( const std::string& strFilename, bool bRead ) -> CalypStreamFormat::CreateStreamHandlerFn { std::string currExt = strFilename.substr( strFilename.find_last_of( "." ) + 1 ); currExt = clpLowercase( currExt ); diff --git a/lib/CalypStream.h b/lib/CalypStream.h index 7492e5d..e542aee 100644 --- a/lib/CalypStream.h +++ b/lib/CalypStream.h @@ -82,12 +82,40 @@ public: std::string getFormatName() const; std::string getCodecName() const; - bool open( std::string filename, std::string resolution, std::string input_format, unsigned int bitsPel, int endianness, bool hasNegative, unsigned int frame_rate, + bool open( std::string filename, + std::string resolution, + std::string input_format, + unsigned int bitsPel, + int endianness, + bool hasNegative, + unsigned int frame_rate, bool bInput ); - bool open( std::string filename, unsigned int width, unsigned int height, int input_format, unsigned int bitsPel, int endianness, unsigned int frame_rate, + bool open( std::string filename, + unsigned int width, + unsigned int height, + int input_format, + unsigned int bitsPel, + int endianness, + unsigned int frame_rate, bool bInput ); - bool open( std::string filename, unsigned int width, unsigned int height, int input_format, unsigned int bitsPel, int endianness, bool hasNegative, unsigned int frame_rate, + bool open( std::string filename, + unsigned int width, + unsigned int height, + int input_format, + unsigned int bitsPel, + int endianness, + bool hasNegative, + unsigned int frame_rate, bool bInput ); + bool open( std::string filename, + unsigned int width, + unsigned int height, + int input_format, + unsigned int bitsPel, + int endianness, + unsigned int frame_rate, + bool bInput, + bool forceRaw ); bool supportsFormatConfiguration(); bool reload(); diff --git a/lib/CalypStreamHandlerIf.h b/lib/CalypStreamHandlerIf.h index ff4b518..3bf89d7 100644 --- a/lib/CalypStreamHandlerIf.h +++ b/lib/CalypStreamHandlerIf.h @@ -103,7 +103,6 @@ protected: std::string m_strCodecName; bool m_bIsInput{ true }; bool m_bNative{ true }; - std::string m_cFilename; unsigned int m_uiWidth{ 0 }; unsigned int m_uiHeight{ 0 }; int m_iPixelFormat{ -1 }; diff --git a/lib/StreamHandlerOpenCV.cpp b/lib/StreamHandlerOpenCV.cpp index d9530c3..17e30b5 100644 --- a/lib/StreamHandlerOpenCV.cpp +++ b/lib/StreamHandlerOpenCV.cpp @@ -60,12 +60,12 @@ std::vector StreamHandlerOpenCV::supportedWriteFormats() StreamHandlerOpenCV::StreamHandlerOpenCV() { m_pchHandlerName = "OpenCV"; - pcVideoCapture = NULL; + m_pcVideoCapture = NULL; } bool StreamHandlerOpenCV::openHandler( std::string strFilename, bool bInput ) { - m_cFilename = strFilename; + m_cFilename = std::move( strFilename ); if( bInput ) { #if( CV_VERSION_MAJOR >= 3 ) @@ -82,10 +82,10 @@ bool StreamHandlerOpenCV::openHandler( std::string strFilename, bool bInput ) m_strFormatName = "DEV"; m_strCodecName = "Raw Video"; - pcVideoCapture = new VideoCapture( iDeviceId ); + m_pcVideoCapture = new VideoCapture( iDeviceId ); #if CV_MAJOR_VERSION >= 4 - m_uiWidth = pcVideoCapture->get( cv::CAP_PROP_FRAME_WIDTH ); - m_uiHeight = pcVideoCapture->get( cv::CAP_PROP_FRAME_HEIGHT ); + m_uiWidth = m_pcVideoCapture->get( cv::CAP_PROP_FRAME_WIDTH ); + m_uiHeight = m_pcVideoCapture->get( cv::CAP_PROP_FRAME_HEIGHT ); #else m_uiWidth = pcVideoCapture->get( CV_CAP_PROP_FRAME_WIDTH ); m_uiHeight = pcVideoCapture->get( CV_CAP_PROP_FRAME_HEIGHT ); @@ -106,7 +106,7 @@ bool StreamHandlerOpenCV::openHandler( std::string strFilename, bool bInput ) m_iPixelFormat = CalypFrame::findPixelFormat( "BGR" ); m_uiTotalNumberFrames = 1; - if( pcVideoCapture ) + if( m_pcVideoCapture ) { m_uiTotalNumberFrames = 2; } @@ -117,11 +117,11 @@ bool StreamHandlerOpenCV::openHandler( std::string strFilename, bool bInput ) void StreamHandlerOpenCV::closeHandler() { - if( pcVideoCapture ) + if( m_pcVideoCapture ) { - pcVideoCapture->release(); - delete pcVideoCapture; - pcVideoCapture = NULL; + m_pcVideoCapture->release(); + delete m_pcVideoCapture; + m_pcVideoCapture = NULL; } } @@ -139,10 +139,10 @@ bool StreamHandlerOpenCV::seek( std::uint64_t iFrameNum ) bool StreamHandlerOpenCV::read( CalypFrame& pcFrame ) { bool bRet = false; - if( pcVideoCapture ) + if( m_pcVideoCapture ) { Mat cvMat; - bRet = pcVideoCapture->read( cvMat ); + bRet = m_pcVideoCapture->read( cvMat ); if( bRet ) bRet = pcFrame.fromMat( cvMat ); } diff --git a/lib/StreamHandlerOpenCV.h b/lib/StreamHandlerOpenCV.h index 14c407b..055c586 100644 --- a/lib/StreamHandlerOpenCV.h +++ b/lib/StreamHandlerOpenCV.h @@ -48,7 +48,8 @@ public: bool write( const CalypFrame& pcFrame ); private: - cv::VideoCapture* pcVideoCapture; + std::string m_cFilename; + cv::VideoCapture* m_pcVideoCapture; }; #endif // __STREAMHANDLEROPENCV_H__