From 2a43b5262a2be84398cc28d260215f537c36c978 Mon Sep 17 00:00:00 2001 From: Joao Carreira Date: Fri, 6 Mar 2015 01:50:59 +0000 Subject: [PATCH] Try fix detection of number of frames (detected problem within the libavs). Use double for frame rate --- app/VideoHandle.cpp | 2 +- lib/LibAvContextHandle.cpp | 122 ++++++++++++++++++------------------- lib/LibAvContextHandle.h | 8 ++- lib/PlaYUVerStream.cpp | 13 ++-- lib/PlaYUVerStream.h | 6 +- 5 files changed, 76 insertions(+), 75 deletions(-) diff --git a/app/VideoHandle.cpp b/app/VideoHandle.cpp index d6a9a46..7951d6d 100644 --- a/app/VideoHandle.cpp +++ b/app/VideoHandle.cpp @@ -427,7 +427,7 @@ Void VideoHandle::play() if( !m_pcCurrentVideoSubWindow->isPlaying() ) // Not playing { - UInt frameRate; + Double frameRate; UInt timeInterval; if( m_acPlayingSubWindows.size() < 2 ) { diff --git a/lib/LibAvContextHandle.cpp b/lib/LibAvContextHandle.cpp index 0d66a7d..6ef2101 100644 --- a/lib/LibAvContextHandle.cpp +++ b/lib/LibAvContextHandle.cpp @@ -133,7 +133,7 @@ Void LibAvContextHandle::closeAvFormat() m_bHasStream = false; } -Bool LibAvContextHandle::initAvFormat( const char* filename, UInt& width, UInt& height, Int& pixel_format, UInt& frame_rate, UInt64& num_frames ) +Bool LibAvContextHandle::initAvFormat( const char* filename, UInt& width, UInt& height, Int& pixel_format, Double& frame_rate, UInt64& num_frames ) { fmt_ctx = NULL; video_dec_ctx = NULL; @@ -212,9 +212,13 @@ Bool LibAvContextHandle::initAvFormat( const char* filename, UInt& width, UInt& else if( video_stream->codec->time_base.den && video_stream->codec->time_base.num ) fr = 1 / av_q2d( video_stream->codec->time_base ); - frame_rate = ( UInt )fr; + frame_rate = fr; - if( fmt_ctx->duration != AV_NOPTS_VALUE ) + /*if( video_stream->nb_frames ) + { + num_frames = video_stream->nb_frames; + } + else*/ if( fmt_ctx->duration != AV_NOPTS_VALUE ) { Int64 duration = fmt_ctx->duration + 5000; m_uiSecs = duration / AV_TIME_BASE; @@ -292,77 +296,71 @@ Bool LibAvContextHandle::initAvFormat( const char* filename, UInt& width, UInt& return true; } +Bool LibAvContextHandle::decodeVideoPkt() +{ + Int got_frame = 0; + Int decResult; + if( pkt.stream_index == video_stream_idx ) + { + decResult = avcodec_decode_video2( video_dec_ctx, frame, &got_frame, &pkt ); + if( decResult < 0 ) + { + fprintf( stderr, "Error decoding video frame\n" ); + return false; + } + pkt.data += decResult; + pkt.size -= decResult; + } + else + { + pkt.size = 0; + } + Bool bRet = got_frame > 0 ? true : false; + return bRet; +} + Bool LibAvContextHandle::decodeAvFormat() { - Int got_frame; - Int decResult; + Bool bGotFrame = false; + AVPacket orig_pkt = pkt; + + bGotFrame |= decodeVideoPkt(); + /* read frames from the file */ - while( av_read_frame( fmt_ctx, &pkt ) >= 0 ) + while( !bGotFrame && ( av_read_frame( fmt_ctx, &pkt ) >= 0 ) ) { - AVPacket orig_pkt = pkt; + orig_pkt = pkt; do { - if( pkt.stream_index == video_stream_idx ) - { - /* decode video frame */ - decResult = avcodec_decode_video2( video_dec_ctx, frame, &got_frame, &pkt ); - if( decResult < 0 ) - { - fprintf( stderr, "Error decoding video frame\n" ); - return false; - } - - if( got_frame ) - { - av_image_copy_to_buffer( m_pchFrameBuffer, m_uiFrameBufferSize, frame->data, frame->linesize, video_dec_ctx->pix_fmt, video_dec_ctx->width, - video_dec_ctx->height, 1 ); - } - } - pkt.data += decResult; - pkt.size -= decResult; + bGotFrame |= decodeVideoPkt(); + if( bGotFrame ) + break; } while( pkt.size > 0 ); + + if( bGotFrame ) + { + break; + } + } + + /*! Try flush existing packets */ + if( !bGotFrame ) + { + bGotFrame |= decodeVideoPkt(); + } + + if( bGotFrame ) + { + av_image_copy_to_buffer( m_pchFrameBuffer, m_uiFrameBufferSize, frame->data, frame->linesize, video_dec_ctx->pix_fmt, video_dec_ctx->width, + video_dec_ctx->height, 1 ); + av_free_packet( &orig_pkt ); -// /* read frames from the file */ -// while( av_read_frame( fmt_ctx, &pkt ) >= 0 ) -// { -// if( pkt.stream_index == video_stream_idx ) -// { -// /* decode video frame */ -// Int ret = avcodec_decode_video2( video_dec_ctx, frame, &got_frame, &pkt ); -// if( ret < 0 ) -// { -// fprintf( stderr, "Error decoding video frame\n" ); -// return false; -// } -// -// if( got_frame ) -// { -// av_image_copy_to_buffer( m_pchFrameBuffer, m_uiFrameBufferSize, frame->data, frame->linesize, video_dec_ctx->pix_fmt, video_dec_ctx->width, -// video_dec_ctx->height, 1 ); -// -// /* copy decoded frame to destination buffer: -// * this is required since rawvideo expects non aligned data */ -// // av_image_copy( video_dst_data, video_dst_linesize, ( const uint8_t ** )( frame->data ), frame->linesize, video_dec_ctx->pix_fmt, video_dec_ctx->width, -// // video_dec_ctx->height ); -// } -// } -// av_free_packet( &pkt ); - if( got_frame ) - return true; + return true; } - return false; -// /* flush cached frames */ -// pkt.data = NULL; -// pkt.size = 0; -// do -// { -// decode_packet( &got_frame, 1 ); -// } -// while( got_frame ); - return true; + return false; } Void LibAvContextHandle::seekAvFormat( UInt64 frame_num ) diff --git a/lib/LibAvContextHandle.h b/lib/LibAvContextHandle.h index 1a2e977..bf51225 100644 --- a/lib/LibAvContextHandle.h +++ b/lib/LibAvContextHandle.h @@ -66,7 +66,7 @@ public: m_bHasStream( false ) { } - Bool initAvFormat( const char* filename, UInt& width, UInt& height, Int& pixel_format, UInt& frame_rate, UInt64& num_frames ); + Bool initAvFormat( const char* filename, UInt& width, UInt& height, Int& pixel_format, Double& frame_rate, UInt64& num_frames ); Void closeAvFormat(); Bool decodeAvFormat(); @@ -103,8 +103,10 @@ private: Bool m_bHasStream; Char m_acCodecName[20]; - UInt m_uiSecs; - UInt m_uiMicroSec; + UInt64 m_uiSecs; + UInt64 m_uiMicroSec; + + Bool decodeVideoPkt(); }; } // NAMESPACE diff --git a/lib/PlaYUVerStream.cpp b/lib/PlaYUVerStream.cpp index 25514a8..95390cf 100644 --- a/lib/PlaYUVerStream.cpp +++ b/lib/PlaYUVerStream.cpp @@ -148,7 +148,7 @@ PlaYUVerStream::PlaYUVerStream() m_uiTotalFrameNum = 0; m_iCurrFrameNum = -1; m_iPixelFormat = -1; - m_uiFrameRate = 30; + m_dFrameRate = 30; m_iFileFormat = -1; m_pStreamBuffer = NULL; m_cFilename = ""; @@ -205,7 +205,7 @@ Bool PlaYUVerStream::open( std::string filename, UInt width, UInt height, Int in m_uiWidth = width; m_uiHeight = height; m_iPixelFormat = input_format; - m_uiFrameRate = frame_rate; + m_dFrameRate = frame_rate; m_pchFilename = new Char[m_cFilename.size() + 1]; std::copy( m_cFilename.begin(), m_cFilename.end(), m_pchFilename ); @@ -271,7 +271,7 @@ Bool PlaYUVerStream::open( std::string filename, UInt width, UInt height, Int in #ifdef USE_FFMPEG if( m_uiStreamHandler == FFMPEG ) { - if( !m_cLibAvContext->initAvFormat( m_pchFilename, m_uiWidth, m_uiHeight, m_iPixelFormat, m_uiFrameRate, m_uiTotalFrameNum ) ) + if( !m_cLibAvContext->initAvFormat( m_pchFilename, m_uiWidth, m_uiHeight, m_iPixelFormat, m_dFrameRate, m_uiTotalFrameNum ) ) { throw "Cannot open file using FFmpeg libs"; } @@ -442,7 +442,7 @@ Void PlaYUVerStream::getFormat( UInt& rWidth, UInt& rHeight, Int& rInputFormat, rWidth = m_uiWidth; rHeight = m_uiHeight; rInputFormat = m_iPixelFormat; - rFrameRate = m_uiFrameRate; + rFrameRate = m_dFrameRate; } else { @@ -506,7 +506,7 @@ Void PlaYUVerStream::getDuration( Int* duration_array ) else #endif { - secs = m_uiTotalFrameNum / m_uiFrameRate; + secs = m_uiTotalFrameNum / m_dFrameRate; } mins = secs / 60; secs %= 60; @@ -520,7 +520,8 @@ Void PlaYUVerStream::getDuration( Int* duration_array ) Void PlaYUVerStream::readFrameFillRGBBuffer() { readFrame(); - m_pcNextFrame->fillRGBBuffer(); + if( m_pcNextFrame ) + m_pcNextFrame->fillRGBBuffer(); return; } diff --git a/lib/PlaYUVerStream.h b/lib/PlaYUVerStream.h index 6519b0b..0db4a24 100644 --- a/lib/PlaYUVerStream.h +++ b/lib/PlaYUVerStream.h @@ -90,7 +90,7 @@ private: UInt m_uiWidth; UInt m_uiHeight; - UInt m_uiFrameRate; + Double m_dFrameRate; UInt64 m_uiTotalFrameNum; Int64 m_iCurrFrameNum; @@ -181,9 +181,9 @@ public: { return m_iCurrFrameNum; } - UInt getFrameRate() + Double getFrameRate() { - return m_uiFrameRate; + return m_dFrameRate; } Void getDuration( Int* duration_array );