diff --git a/lib/StreamHandlerLibav.cpp b/lib/StreamHandlerLibav.cpp index 8e7c72f..4cbb36e 100644 --- a/lib/StreamHandlerLibav.cpp +++ b/lib/StreamHandlerLibav.cpp @@ -32,6 +32,10 @@ #define FF_USER_CODEC_PARAM #endif +//#if( ( LIBAVCODEC_VERSION_MAJOR >= 57 ) && ( LIBAVCODEC_VERSION_MINOR >= 37 ) ) +//#define FF_SEND_RECEIVE_API +//#endif + std::vector StreamHandlerLibav::supportedReadFormats() { INI_REGIST_PLAYUVER_SUPPORTED_FMT; @@ -141,39 +145,20 @@ Bool StreamHandlerLibav::openHandler( String strFilename, Bool bInput ) #ifdef FF_USER_CODEC_PARAM m_uiFrameBufferSize = av_image_get_buffer_size( AVPixelFormat( codec_param->format ), codec_param->width, codec_param->height, 1 ); + + Int pix_fmt = codec_param->format; + m_uiWidth = codec_param->width; + m_uiHeight = codec_param->height; #else - m_uiFrameBufferSize = - av_image_get_buffer_size( m_cCodedCtx->pix_fmt, m_cCodedCtx->width, m_cCodedCtx->height, 1 ); + m_uiFrameBufferSize = av_image_get_buffer_size( + m_cStream->codec->pix_fmt, m_cStream->codec->width, m_cStream->codec->height, 1 ); + + Int pix_fmt = m_cStream->codec->pix_fmt; + m_uiWidth = m_cStream->codec->width; + m_uiHeight = m_cStream->codec->height; + #endif - m_uiFrameBufferSize = - av_image_get_buffer_size( m_cCodedCtx->pix_fmt, m_cCodedCtx->width, m_cCodedCtx->height, 1 ); - getMem1D( &m_pchFrameBuffer, m_uiFrameBufferSize ); - - m_strFormatName = uppercase( strFilename.substr( strFilename.find_last_of( "." ) + 1 ) ); - const char* name = avcodec_get_name( m_cCodedCtx->codec_id ); - // sprintf( m_acCodecName, "%s", name ); - m_strCodecName = name; - - Double fr = 30; - 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( m_cStream->r_frame_rate.den && m_cStream->r_frame_rate.num ) - fr = av_q2d( m_cStream->r_frame_rate ); -#endif - else if( m_cStream->time_base.den && m_cStream->time_base.num ) - fr = 1 / av_q2d( m_cStream->time_base ); - else if( m_cCodedCtx->time_base.den && m_cCodedCtx->time_base.num ) - fr = 1 / av_q2d( m_cCodedCtx->time_base ); - - m_dFrameRate = fr; - - Int pix_fmt = m_cCodedCtx->pix_fmt; - - // Set bits per pixel to default (8 bits) - m_uiBitsPerPixel = 8; - /** * Auxiliar conversation to re-use similar pixfmt */ @@ -199,8 +184,29 @@ Bool StreamHandlerLibav::openHandler( String strFilename, Bool bInput ) pix_fmt = AV_PIX_FMT_GRAY8; } - m_uiWidth = m_cCodedCtx->width; - m_uiHeight = m_cCodedCtx->height; + m_strFormatName = uppercase( strFilename.substr( strFilename.find_last_of( "." ) + 1 ) ); + const char* name = avcodec_get_name( m_cCodedCtx->codec_id ); + // sprintf( m_acCodecName, "%s", name ); + m_strCodecName = name; + + Double fr = 30; + 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( m_cStream->r_frame_rate.den && m_cStream->r_frame_rate.num ) + fr = av_q2d( m_cStream->r_frame_rate ); +#endif + else if( m_cStream->time_base.den && m_cStream->time_base.num ) + fr = 1 / av_q2d( m_cStream->time_base ); +#ifndef FF_USER_CODEC_PARAM + else if( m_cStream->codec->time_base.den && m_cStream->codec->time_base.num ) + fr = 1 / av_q2d( m_cStream->codec->time_base ); +#endif + + m_dFrameRate = fr; + + // Set bits per pixel to default (8 bits) + m_uiBitsPerPixel = 8; m_iPixelFormat = PlaYUVerFrame::NO_FMT; for( Int i = 0; i < PlaYUVerFrame::NUMBER_PEL_FORMATS; i++ ) @@ -239,9 +245,9 @@ Bool StreamHandlerLibav::openHandler( String strFilename, Bool bInput ) } /* initialize packet, set data to NULL, let the demuxer fill it */ - av_init_packet( &pkt ); - pkt.data = NULL; - pkt.size = 0; + av_init_packet( &m_cPacket ); + m_cPacket.data = NULL; + m_cPacket.size = 0; m_bHasStream = true; @@ -294,45 +300,68 @@ UInt64 StreamHandlerLibav::calculateFrameNumber() return num_frames; } -Bool StreamHandlerLibav::decodeVideoPkt() +#ifdef FF_SEND_RECEIVE_API +// The flush packet is a non-NULL packet with size 0 and data NULL +Int StreamHandlerLibav::decodeVideoPkt( Bool& gotFrame ) { - Int got_frame = 0; + int ret; + + ret = avcodec_send_packet( m_cCodedCtx, &m_cPacket ); + // // In particular, we don't expect AVERROR(EAGAIN), because we read all + // // decoded frames with avcodec_receive_frame() until done. + // if( ret < 0 ) + // return ret == AVERROR_EOF ? 0 : ret; + + ret = avcodec_receive_frame( m_cCodedCtx, m_cFrame ); + if( ret < 0 && ret != AVERROR( EAGAIN ) && ret != AVERROR_EOF ) + return ret; + if( ret >= 0 ) + gotFrame = true; + + return ret; +} +#else +Int StreamHandlerLibav::decodeVideoPkt( Bool& gotFrame ) +{ + Int got_frame = false; Int decResult; - if( pkt.stream_index == m_iStreamIdx ) + if( m_cPacket.stream_index == m_iStreamIdx ) { - decResult = avcodec_decode_video2( m_cCodedCtx, m_cFrame, &got_frame, &pkt ); + decResult = avcodec_decode_video2( m_cCodedCtx, m_cFrame, &got_frame, &m_cPacket ); if( decResult < 0 ) { fprintf( stderr, "Error decoding video frame\n" ); - return false; + return decResult; } - pkt.data += decResult; - pkt.size -= decResult; + m_cPacket.data += decResult; + m_cPacket.size -= decResult; } else { - pkt.size = 0; + m_cPacket.size = 0; } - return got_frame > 0 ? true : false; + gotFrame = got_frame > 0 ? true : false; + return decResult; } +#endif Bool StreamHandlerLibav::read( PlaYUVerFrame* pcFrame ) { Bool bGotFrame = false; - AVPacket orig_pkt = pkt; + AVPacket orig_pkt = m_cPacket; - bGotFrame |= decodeVideoPkt(); + decodeVideoPkt( bGotFrame ); /* read frames from the file */ - while( !bGotFrame && ( av_read_frame( m_cFmtCtx, &pkt ) >= 0 ) ) + while( !bGotFrame && ( av_read_frame( m_cFmtCtx, &m_cPacket ) >= 0 ) ) { - orig_pkt = pkt; + orig_pkt = m_cPacket; do { - bGotFrame |= decodeVideoPkt(); + decodeVideoPkt( bGotFrame ); if( bGotFrame ) break; - } while( pkt.size > 0 ); + } while( m_cPacket.size > 0 ); if( bGotFrame ) { @@ -343,7 +372,7 @@ Bool StreamHandlerLibav::read( PlaYUVerFrame* pcFrame ) /*! Try flush existing packets */ if( !bGotFrame ) { - bGotFrame |= decodeVideoPkt(); + decodeVideoPkt( bGotFrame ); } if( bGotFrame ) @@ -359,14 +388,15 @@ Bool StreamHandlerLibav::read( PlaYUVerFrame* pcFrame ) m_cCodedCtx->height, 1 ); #endif + +#ifndef FF_SEND_RECEIVE_API if( orig_pkt.size ) av_free_packet( &orig_pkt ); +#endif pcFrame->frameFromBuffer( m_pStreamBuffer, m_iEndianness ); - return true; } - return false; } diff --git a/lib/StreamHandlerLibav.h b/lib/StreamHandlerLibav.h index 9b8eb28..6406dfe 100644 --- a/lib/StreamHandlerLibav.h +++ b/lib/StreamHandlerLibav.h @@ -84,14 +84,14 @@ class StreamHandlerLibav : public PlaYUVerStreamHandlerIf AVCodecContext* m_cCodedCtx; AVFrame* m_cFrame; - AVPacket pkt; + AVPacket m_cPacket; Bool m_bHasStream; UInt64 m_uiSecs; UInt64 m_uiMicroSec; - Bool decodeVideoPkt(); + Int decodeVideoPkt( Bool& gotFrame ); }; #endif // __LIBAVCONTEXTHANDLE_H__