4646#include < sstream>
4747#include < stdexcept>
4848
49+ #define USE_NEW_FFMPEG_API (LIBAVCODEC_VERSION_MAJOR >= 57 )
50+
4951FFMPEGVideoStream::FFMPEGVideoStream ( AVFormatContext& avFormatContext )
5052 : _avFormatContext( avFormatContext )
51- , _videoCodecContext( 0 ) // shortcut to _videoStream->codec; don't free
53+ , _videoCodecContext( 0 ) // allocated if USE_NEW_FFMPEG_API, else shortcut
5254 , _videoStream( 0 ) // shortcut to _avFormatContext->streams[i]; don't free
5355 // Seeking parameters
5456 , _numFrames( 0 )
@@ -66,7 +68,9 @@ FFMPEGVideoStream::FFMPEGVideoStream( AVFormatContext& avFormatContext )
6668
6769FFMPEGVideoStream::~FFMPEGVideoStream ()
6870{
69- avcodec_close ( _videoCodecContext );
71+ #if USE_NEW_FFMPEG_API
72+ avcodec_free_context ( &_videoCodecContext );
73+ #endif
7074}
7175
7276PicturePtr FFMPEGVideoStream::decode ( AVPacket& packet )
@@ -95,11 +99,37 @@ bool FFMPEGVideoStream::_isVideoPacket( const AVPacket& packet ) const
9599 return packet.stream_index == _videoStream->index ;
96100}
97101
102+ std::string _getAvError ( const int errorCode )
103+ {
104+ char errbuf[256 ];
105+ av_strerror ( errorCode, errbuf, 256 );
106+ return std::string ( errbuf );
107+ }
108+
98109bool FFMPEGVideoStream::_decodeToAvFrame ( AVPacket& packet )
99110{
100111 if ( !_isVideoPacket ( packet ))
101112 return false ;
102113
114+ #if USE_NEW_FFMPEG_API
115+ int errCode = avcodec_send_packet ( _videoCodecContext, &packet );
116+ if ( errCode < 0 )
117+ {
118+ put_flog ( LOG_ERROR, " avcodec_send_packet returned error code '%i' : "
119+ " '%s' in '%s'" , errCode, _getAvError ( errCode ).c_str (),
120+ _avFormatContext.filename );
121+ return false ;
122+ }
123+
124+ errCode = avcodec_receive_frame ( _videoCodecContext, &_frame->getAVFrame ());
125+ if ( errCode < 0 )
126+ {
127+ put_flog ( LOG_ERROR, " avcodec_receive_frame returned error code '%i' : "
128+ " '%s' in '%s'" , errCode, _getAvError ( errCode ).c_str (),
129+ _avFormatContext.filename );
130+ return false ;
131+ }
132+ #else
103133 int frameDecodingComplete = 0 ;
104134 const int errCode = avcodec_decode_video2 ( _videoCodecContext,
105135 &_frame->getAVFrame (),
@@ -121,7 +151,7 @@ bool FFMPEGVideoStream::_decodeToAvFrame( AVPacket& packet )
121151 _avFormatContext.filename );
122152 return false ;
123153 }
124-
154+ # endif
125155 return true ;
126156}
127157
@@ -223,7 +253,11 @@ void FFMPEGVideoStream::_findVideoStream()
223253 for ( unsigned int i = 0 ; i < _avFormatContext.nb_streams ; ++i )
224254 {
225255 AVStream* stream = _avFormatContext.streams [i];
256+ #if USE_NEW_FFMPEG_API
257+ if ( stream->codecpar ->codec_type == AVMEDIA_TYPE_VIDEO )
258+ #else
226259 if ( stream->codec ->codec_type == AVMEDIA_TYPE_VIDEO )
260+ #endif
227261 {
228262 _videoStream = stream; // Shortcut pointer - don't free
229263 return ;
@@ -235,23 +269,36 @@ void FFMPEGVideoStream::_findVideoStream()
235269
236270void FFMPEGVideoStream::_openVideoStreamDecoder ()
237271{
272+ AVCodec* codec = nullptr ;
273+
274+ #if USE_NEW_FFMPEG_API
275+ if ( !( codec = avcodec_find_decoder ( _videoStream->codecpar ->codec_id )))
276+ throw std::runtime_error ( " No decoder found for video stream" );
277+
278+ _videoCodecContext = avcodec_alloc_context3 ( codec );
279+ if ( !_videoCodecContext )
280+ throw std::runtime_error ( " Could not allocate a decoding context" );
281+
282+ const int error = avcodec_parameters_to_context ( _videoCodecContext,
283+ _videoStream->codecpar );
284+ if ( error < 0 )
285+ throw std::runtime_error ( " Could not init context from parameters" );
286+ #else
238287 // Contains information about the codec that the stream is using
239288 _videoCodecContext = _videoStream->codec ; // Shortcut - don't free
240289
241- AVCodec* codec = avcodec_find_decoder ( _videoCodecContext->codec_id );
290+ codec = avcodec_find_decoder ( _videoCodecContext->codec_id );
242291 if ( !codec )
243292 throw std::runtime_error ( " No decoder found for video stream" );
293+ #endif
244294
245295 // open codec
246296 const int ret = avcodec_open2 ( _videoCodecContext, codec, NULL );
247-
248297 if ( ret < 0 )
249298 {
250- char errbuf[256 ];
251- av_strerror ( ret, errbuf, 256 );
252-
253299 std::stringstream message;
254- message << " Could not open codec, error code " << ret << " : " << errbuf;
300+ message << " Could not open codec, error code " << ret << " : " <<
301+ _getAvError ( ret );
255302
256303 throw std::runtime_error ( message.str ( ));
257304 }
0 commit comments