diff --git a/source/InputStream.cpp b/source/InputStream.cpp index 860147b..23403da 100755 --- a/source/InputStream.cpp +++ b/source/InputStream.cpp @@ -126,6 +126,8 @@ Bool InputStream::needFormatDialog( QString filename ) Void InputStream::init( QString filename, UInt width, UInt height, Int input_format, UInt frame_rate ) { + Bool avStatus; + m_uiWidth = width; m_uiHeight = height; m_uiFrameRate = frame_rate; @@ -134,7 +136,7 @@ Void InputStream::init( QString filename, UInt width, UInt height, Int input_for m_iPixelFormat = input_format; #ifdef USE_FFMPEG - Bool avStatus = m_cLibAvContext.initAvFormat( filename, m_uiWidth, m_uiHeight, m_iPixelFormat, m_uiFrameRate ); + avStatus = m_cLibAvContext.initAvFormat( filename, m_uiWidth, m_uiHeight, m_iPixelFormat, m_uiFrameRate ); #endif if( m_uiWidth <= 0 || m_uiHeight <= 0 ) @@ -147,7 +149,7 @@ Void InputStream::init( QString filename, UInt width, UInt height, Int input_for UInt64 frame_bytes_input = m_cCurrFrame->getBytesPerFrame(); - if( m_iFileFormat == YUVFormat ) + if( avStatus ) { m_cFilename = filename; m_pFile = fopen( m_cFilename.toLocal8Bit().data(), "rb" ); @@ -182,16 +184,6 @@ Void InputStream::readFrame() { return; } - UInt64 frame_bytes_input = m_cCurrFrame->getBytesPerFrame(); - -#ifdef USE_FFMPEG - if( m_cLibAvContext.getStatus() ) - { - m_cLibAvContext.decodeAvFormat(); - m_cCurrFrame->FrameFromBuffer( m_cLibAvContext.video_dst_data[0], m_iPixelFormat ); - return; - } -#endif if( m_uiCurrFrameNum < m_uiTotalFrameNum ) { @@ -203,6 +195,17 @@ Void InputStream::readFrame() m_uiCurrFrameNum = 0; seekInput( m_uiCurrFrameNum ); } + +#ifdef USE_FFMPEG + if( m_cLibAvContext.getStatus() ) + { + m_cLibAvContext.decodeAvFormat(); + m_cCurrFrame->FrameFromBuffer( m_cLibAvContext.video_dst_data[0], m_iPixelFormat ); + return; + } +#endif + + UInt64 frame_bytes_input = m_cCurrFrame->getBytesPerFrame(); bytes_read = fread( m_pInputBuffer, sizeof(Pel), frame_bytes_input, m_pFile ); if( bytes_read != frame_bytes_input ) { @@ -255,10 +258,19 @@ cv::Mat InputStream::getFrameCvMat() Void InputStream::seekInput( Int new_frame_num ) { - UInt64 frame_bytes_input = m_uiWidth * m_uiHeight * 1.5; - UInt64 nbytes_seek = frame_bytes_input * new_frame_num; - fseek( m_pFile, nbytes_seek, SEEK_SET ); - m_uiCurrFrameNum = new_frame_num; +#ifdef USE_FFMPEG + if( m_cLibAvContext.getStatus() ) + { + m_cLibAvContext.seekAvFormat( new_frame_num ); + } + else +#endif + { + UInt64 frame_bytes_input = m_uiWidth * m_uiHeight * 1.5; + UInt64 nbytes_seek = frame_bytes_input * new_frame_num; + fseek( m_pFile, nbytes_seek, SEEK_SET ); + m_uiCurrFrameNum = new_frame_num; + } } Bool InputStream::checkErrors( Int error_type ) diff --git a/source/LibAvContextHandle.cpp b/source/LibAvContextHandle.cpp index 9c7dd19..92055fe 100755 --- a/source/LibAvContextHandle.cpp +++ b/source/LibAvContextHandle.cpp @@ -29,8 +29,8 @@ #include -#include "InputStream.h" #include "LibMemAlloc.h" +#include "PlaYUVerFrame.h" namespace plaYUVer { @@ -73,13 +73,18 @@ static int open_codec_context( int *stream_idx, AVFormatContext *fmt_ctx, enum A Void LibAvContextHandle::closeAvFormat() { - if( video_dec_ctx ) - avcodec_close( video_dec_ctx ); + if( m_bHasStream ) + { + if( video_dec_ctx ) + avcodec_close( video_dec_ctx ); - avformat_close_input( &fmt_ctx ); + if( fmt_ctx ) + avformat_close_input( &fmt_ctx ); - av_free( frame ); - av_free( video_dst_data[0] ); + av_free( frame ); + av_free( video_dst_data[0] ); + } + m_bHasStream = false; } Bool LibAvContextHandle::initAvFormat( QString filename, UInt& width, UInt& height, Int& pixel_format, UInt& frame_rate ) @@ -99,14 +104,31 @@ Bool LibAvContextHandle::initAvFormat( QString filename, UInt& width, UInt& heig m_bHasStream = false; char *src_filename = filename.toLocal8Bit().data(); - - FILE *video_dst_file = NULL; + AVDictionary *format_opts = NULL; /* 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 ); + } + switch( pixel_format ) + { + case PlaYUVerFrame::NO_FMT: + break; + case PlaYUVerFrame::YUV420: + av_dict_set( &format_opts, "pixel_format", av_get_pix_fmt_name( AV_PIX_FMT_YUV420P ), 0 ); + break; + case PlaYUVerFrame::YUV400: + av_dict_set( &format_opts, "pixel_format", av_get_pix_fmt_name( AV_PIX_FMT_GRAY8 ), 0 ); + break; + } + /* open input file, and allocate format context */ - if( avformat_open_input( &fmt_ctx, src_filename, NULL, NULL ) < 0 ) + if( avformat_open_input( &fmt_ctx, src_filename, NULL, &format_opts ) < 0 ) { qDebug( ) << " Could not open source file %s !!!" << filename << endl; return false; @@ -135,6 +157,20 @@ Bool LibAvContextHandle::initAvFormat( QString filename, UInt& width, UInt& heig video_dst_bufsize = ret; } + 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 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 ); +#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 ); + + frame_rate = ( UInt )fr; + width = video_dec_ctx->width; height = video_dec_ctx->height; switch( video_dec_ctx->pix_fmt ) @@ -220,6 +256,11 @@ Bool LibAvContextHandle::decodeAvFormat() true; } +Void LibAvContextHandle::seekAvFormat( UInt frame_num ) +{ + av_seek_frame( fmt_ctx, video_stream_idx, frame_num, AVSEEK_FLAG_ANY ); +} + } // NAMESPACE #endif diff --git a/source/LibAvContextHandle.h b/source/LibAvContextHandle.h index 5a7e065..c361bdf 100755 --- a/source/LibAvContextHandle.h +++ b/source/LibAvContextHandle.h @@ -50,6 +50,8 @@ public: Void closeAvFormat(); Bool decodeAvFormat(); + Void seekAvFormat( UInt frame_num ); + Bool getStatus() { return m_bHasStream; diff --git a/source/PlaYUVerFrame.h b/source/PlaYUVerFrame.h index 2e9ed47..0cf6f06 100755 --- a/source/PlaYUVerFrame.h +++ b/source/PlaYUVerFrame.h @@ -44,7 +44,7 @@ public: enum InputStreamColorSpace { - YUV420, YUV400, YUV422, RGB, + NO_FMT = -1, YUV420, YUV400, YUV422, RGB, }; UInt64 getBytesPerFrame();