Skip to content

Commit 28f96da

Browse files
author
Raphael Dumusc
committed
Support new FFMPEG 3.1 AVCodec API [DISCL-372]
1 parent 321ac65 commit 28f96da

4 files changed

Lines changed: 60 additions & 10 deletions

File tree

.travis.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ before_install:
2525
- brew update
2626
- brew outdated cmake || brew upgrade cmake
2727
- brew install cppcheck doxygen ninja
28-
- brew install homebrew/versions/ffmpeg28 jpeg-turbo mpich qt5
28+
- brew install ffmpeg jpeg-turbo mpich qt5
2929
- brew install poppler --with-qt5
3030
script:
3131
- mkdir $BUILD_TYPE

doc/Changelog.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ Changelog {#Changelog}
33

44
# Release 1.2 (git master)
55

6+
* [56](https://github.com/BlueBrain/Tide/pull/56):
7+
Support new FFMPEG 3.1 AVCodec API
68
* [55](https://github.com/BlueBrain/Tide/pull/55):
79
Fix potentially [serious bug](https://github.com/BlueBrain/Deflect/pull/115)
810
in Deflect server.

tide/core/FFMPEGMovie.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ bool FFMPEGMovie::_open( const QString& uri )
7979
{
8080
put_flog( LOG_FATAL, "Error opening file %s : '%s'",
8181
uri.toLocal8Bit().constData(), e.what( ));
82+
_releaseAvFormatContext();
8283
return false;
8384
}
8485

tide/core/FFMPEGVideoStream.cpp

Lines changed: 56 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -46,9 +46,11 @@
4646
#include <sstream>
4747
#include <stdexcept>
4848

49+
#define USE_NEW_FFMPEG_API (LIBAVCODEC_VERSION_MAJOR >= 57)
50+
4951
FFMPEGVideoStream::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

6769
FFMPEGVideoStream::~FFMPEGVideoStream()
6870
{
69-
avcodec_close( _videoCodecContext );
71+
#if USE_NEW_FFMPEG_API
72+
avcodec_free_context( &_videoCodecContext );
73+
#endif
7074
}
7175

7276
PicturePtr 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+
98109
bool 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

236270
void 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

Comments
 (0)