Skip to content

FFmpeg 4.* support #312

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Jan 23, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 23 additions & 15 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,23 +25,28 @@ env:
- DEPENDENCY_LOG_FILE=${TRAVIS_BUILD_DIR}/build-dependencies-log.txt

- YASM_VERSION=1.3.0
- LAME_VERSION=3.99.5
- FAAC_VERSION=1.28
- LAME_VERSION=3.100
# - FAAC_VERSION=1.28
- XVID_VERSION=1.3.3
- FDKAAC_VERSION=0.1.3
# - FDKAAC_VERSION=0.1.3
- OGG_VERSION=1.3.2
- VORBIS_VERSION=1.3.4
- THEORA_VERSION=1.1.1
- VORBIS_VERSION=1.3.6
# - THEORA_VERSION=1.1.1
- VPX_VERSION=1.4.0
matrix:
- DEPENDENCY_NAME=libav DEPENDENCY_VERSION=11.3 ENABLE_COVERAGE=true
- DEPENDENCY_NAME=libav DEPENDENCY_VERSION=11.3 ENABLE_COVERAGE=false
- DEPENDENCY_NAME=ffmpeg DEPENDENCY_VERSION=2.4.2 ENABLE_COVERAGE=true
- DEPENDENCY_NAME=ffmpeg DEPENDENCY_VERSION=2.4.2 ENABLE_COVERAGE=false
- DEPENDENCY_NAME=ffmpeg DEPENDENCY_VERSION=2.5.7 ENABLE_COVERAGE=false
- DEPENDENCY_NAME=ffmpeg DEPENDENCY_VERSION=2.6.8 ENABLE_COVERAGE=false
- DEPENDENCY_NAME=ffmpeg DEPENDENCY_VERSION=2.7.6 ENABLE_COVERAGE=false
- DEPENDENCY_NAME=ffmpeg DEPENDENCY_VERSION=2.8.6 ENABLE_COVERAGE=false
# - DEPENDENCY_NAME=libav DEPENDENCY_VERSION=11.12 ENABLE_COVERAGE=true
# - DEPENDENCY_NAME=libav DEPENDENCY_VERSION=11.12 ENABLE_COVERAGE=false
# - DEPENDENCY_NAME=libav DEPENDENCY_VERSION=12.3 ENABLE_COVERAGE=true
# - DEPENDENCY_NAME=libav DEPENDENCY_VERSION=12.3 ENABLE_COVERAGE=false
# - DEPENDENCY_NAME=ffmpeg DEPENDENCY_VERSION=2.4.2 ENABLE_COVERAGE=true
# - DEPENDENCY_NAME=ffmpeg DEPENDENCY_VERSION=2.4.2 ENABLE_COVERAGE=false
# - DEPENDENCY_NAME=ffmpeg DEPENDENCY_VERSION=2.5.7 ENABLE_COVERAGE=false
# - DEPENDENCY_NAME=ffmpeg DEPENDENCY_VERSION=2.6.8 ENABLE_COVERAGE=false
# - DEPENDENCY_NAME=ffmpeg DEPENDENCY_VERSION=2.7.6 ENABLE_COVERAGE=false
# - DEPENDENCY_NAME=ffmpeg DEPENDENCY_VERSION=2.8.6 ENABLE_COVERAGE=false
# - DEPENDENCY_NAME=ffmpeg DEPENDENCY_VERSION=4.0 ENABLE_COVERAGE=false
- DEPENDENCY_NAME=ffmpeg DEPENDENCY_VERSION=4.1 ENABLE_COVERAGE=false
- DEPENDENCY_NAME=ffmpeg DEPENDENCY_VERSION=4.2 ENABLE_COVERAGE=true

matrix:
exclude:
Expand All @@ -57,6 +62,7 @@ matrix:
env: DEPENDENCY_NAME=ffmpeg DEPENDENCY_VERSION=2.4.2 ENABLE_COVERAGE=true
allow_failures:
# build with libav
- os: osx
- env: DEPENDENCY_NAME=libav DEPENDENCY_VERSION=11.3 ENABLE_COVERAGE=true
- env: DEPENDENCY_NAME=libav DEPENDENCY_VERSION=11.3 ENABLE_COVERAGE=false
# build with ffmpeg-2.8.6
Expand All @@ -75,8 +81,10 @@ addons:
packages:
- cmake
- swig
- python-dev
- python-nose
- python3-dev
- python3
- python3-nose
- python3-coverage
- freeglut3-dev

cache:
Expand Down
9 changes: 9 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,15 @@ cmake_minimum_required(VERSION 2.8.11)

project(AvTranscoder)

# All libraries will be put in INSTALL_PREFIX/lib
# RPATH of host points INSTALL_PREFIX/lib
# see: http://www.cmake.org/Wiki/CMake_RPATH_handling
set(CMAKE_MACOSX_RPATH 1)
set(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE)
set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib")
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)


# Define AvTranscoder default path to profiles
add_definitions(-DAVTRANSCODER_DEFAULT_AVPROFILES="${CMAKE_INSTALL_PREFIX}/share/avprofiles")

Expand Down
8 changes: 4 additions & 4 deletions appveyor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ platform:
environment:
global:
DEPENDENCY_NAME: ffmpeg
DEPENDENCY_VERSION: 2.4.5
DEPENDENCY_VERSION: 4.2.1
DEPENDENCY_INSTALL_PATH: C:\ProgramData\install-dependency
AVTRANSCODER_INSTALL_PATH: C:\projects\avtranscoder\build\install-avtranscoder

Expand All @@ -25,10 +25,10 @@ install:

# Get the correct python version
- ps: if($env:platform -eq 'x86') {
$env:PYTHON = "C:\Python27";
$env:PYTHON = "C:\Python35";
}
else {
$env:PYTHON = "C:\Python27-x64";
$env:PYTHON = "C:\Python35-x64";
}
# Prepend newly installed Python to the PATH of this build
- cmd: set PATH=%PYTHON%;%PYTHON%\Scripts;%PATH%
Expand All @@ -37,7 +37,7 @@ install:
- "python --version"
- "python -c \"import struct; print(struct.calcsize('P') * 8)\""
# Upgrade to the latest version of pip to avoid it displaying warnings about it being out of date.
- pip install --disable-pip-version-check --user --upgrade pip
- "python -m pip install --disable-pip-version-check --user --upgrade pip"

# Install tests dependencies
- pip install nose
Expand Down
4 changes: 4 additions & 0 deletions src/AvTranscoder/encoder/VideoEncoder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,11 @@ void VideoEncoder::setupEncoder(const ProfileLoader::Profile& profile)
if(profile.count(constants::avProfileProcessStat))
{
LOG_INFO("SetUp video encoder to compute statistics during process")
#ifdef AV_CODEC_FLAG_PSNR
encoderFlags |= AV_CODEC_FLAG_PSNR;
#else
encoderFlags |= CODEC_FLAG_PSNR;
#endif
}
_codec.getAVCodecContext().flags |= encoderFlags;
_codec.openCodec();
Expand Down
20 changes: 14 additions & 6 deletions src/AvTranscoder/file/OutputFile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -200,12 +200,12 @@ IOutputStream::EWrappingStatus OutputFile::wrap(const CodedData& data, const siz
packet.dts = av_rescale_q(data.getAVPacket().dts, srcTimeBase, dstTimeBase);
}
// add stream PTS if already incremented
const int currentStreamPTS = _outputStreams.at(streamIndex)->getStreamPTS();
if(packet.pts != AV_NOPTS_VALUE && packet.pts < currentStreamPTS)
{
packet.pts += currentStreamPTS;
packet.dts += currentStreamPTS;
}
// const int currentStreamPTS = _outputStreams.at(streamIndex)->getStreamPTS();
// if(packet.pts != AV_NOPTS_VALUE && packet.pts < currentStreamPTS)
// {
// packet.pts += currentStreamPTS;
// packet.dts += currentStreamPTS;
// }
}

// copy duration of packet wrapped
Expand Down Expand Up @@ -332,11 +332,19 @@ void OutputFile::setOutputStream(AVStream& avStream, const ICodec& codec)
// depending on the format, place global headers in extradata instead of every keyframe
if(_formatContext.getAVOutputFormat().flags & AVFMT_GLOBALHEADER)
{
#ifdef AV_CODEC_FLAG_GLOBAL_HEADER
avStream.codec->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
#else
avStream.codec->flags |= CODEC_FLAG_GLOBAL_HEADER;
#endif
}

// if the codec is experimental, allow it
#ifdef AV_CODEC_CAP_EXPERIMENTAL
if(codec.getAVCodec().capabilities & AV_CODEC_CAP_EXPERIMENTAL)
#else
if(codec.getAVCodec().capabilities & CODEC_CAP_EXPERIMENTAL)
#endif
{
LOG_WARN("This codec is considered experimental by libav/ffmpeg:" << codec.getCodecName());
avStream.codec->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL;
Expand Down
2 changes: 1 addition & 1 deletion src/AvTranscoder/filter/Filter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ Filter::Filter(const std::string& name, const std::string& options, const std::s
, _options(options)
, _instanceName(instanceName.empty() ? name : instanceName)
{
_filter = avfilter_get_by_name(name.c_str());
_filter = (AVFilter*)avfilter_get_by_name(name.c_str());
if(!_filter)
{
std::string msg("Cannot find filter ");
Expand Down
11 changes: 10 additions & 1 deletion src/AvTranscoder/properties/StreamProperties.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -93,8 +93,13 @@ std::string StreamProperties::getCodecName() const
if(!_codecContext || !_codec)
throw std::runtime_error("unknown codec");

#ifdef AV_CODEC_CAP_TRUNCATED
if(_codec->capabilities & AV_CODEC_CAP_TRUNCATED)
_codecContext->flags |= AV_CODEC_FLAG_TRUNCATED;
#else
if(_codec->capabilities & CODEC_CAP_TRUNCATED)
_codecContext->flags |= CODEC_FLAG_TRUNCATED;
#endif

if(!_codec->name)
throw std::runtime_error("unknown codec name");
Expand All @@ -107,9 +112,13 @@ std::string StreamProperties::getCodecLongName() const
if(!_codecContext || !_codec)
throw std::runtime_error("unknown codec");

#ifdef AV_CODEC_CAP_TRUNCATED
if(_codec->capabilities & AV_CODEC_CAP_TRUNCATED)
_codecContext->flags |= AV_CODEC_FLAG_TRUNCATED;
#else
if(_codec->capabilities & CODEC_CAP_TRUNCATED)
_codecContext->flags |= CODEC_FLAG_TRUNCATED;

#endif
if(!_codec->long_name)
throw std::runtime_error("unknown codec long name");

Expand Down
8 changes: 7 additions & 1 deletion src/AvTranscoder/properties/VideoProperties.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,13 @@ std::string VideoProperties::getProfileName() const
if(!_codecContext || !_codec)
throw std::runtime_error("unknown codec");

#ifdef AV_CODEC_CAP_TRUNCATED
if(_codec->capabilities & AV_CODEC_CAP_TRUNCATED)
_codecContext->flags |= AV_CODEC_FLAG_TRUNCATED;
#else
if(_codec->capabilities & CODEC_CAP_TRUNCATED)
_codecContext->flags |= CODEC_FLAG_TRUNCATED;
#endif

const char* profile = NULL;
if((profile = av_get_profile_name(_codec, getProfile())) == NULL)
Expand Down Expand Up @@ -427,7 +432,8 @@ size_t VideoProperties::getDtgActiveFormat() const
{
if(!_codecContext)
throw std::runtime_error("unknown codec context");
return _codecContext->dtg_active_format;
// return _codecContext->dtg_active_format;
return 0;
}

size_t VideoProperties::getReferencesFrames() const
Expand Down
16 changes: 8 additions & 8 deletions src/AvTranscoder/stream/OutputStream.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,10 @@ OutputStream::OutputStream(OutputFile& outputFile, const size_t streamIndex)

float OutputStream::getStreamDuration() const
{
const AVFrac& outputPTS = _outputAVStream.pts;
const AVRational& outputTimeBase = _outputAVStream.time_base;

// check floating point exception
if(outputTimeBase.den == 0 || outputPTS.den == 0)
if(outputTimeBase.den == 0)
{
LOG_WARN("Cannot compute stream duration of output stream at index " << _streamIndex)
return 0.f;
Expand All @@ -36,7 +35,7 @@ float OutputStream::getStreamDuration() const
// returns the pts of the last muxed packet, converted from timebase to seconds
return av_q2d(outputTimeBase) * av_stream_get_end_pts(&_outputAVStream);
#else
return av_q2d(outputTimeBase) * (outputPTS.val + (outputPTS.num / outputPTS.den));
return av_q2d(outputTimeBase) * _outputAVStream.pts;
#endif
}

Expand All @@ -45,11 +44,12 @@ size_t OutputStream::getNbFrames() const
return _outputAVStream.nb_frames;
}

int OutputStream::getStreamPTS() const
{
const AVFrac& outputPTS = _outputAVStream.pts;
return (outputPTS.val + (outputPTS.num / outputPTS.den));
}
// int OutputStream::getStreamPTS() const
// {
// // const AVFrac& outputPTS = _outputAVStream.pts;
// // return (outputPTS.val + (outputPTS.num / outputPTS.den));
// return _outputAVStream.pts;
// }

IOutputStream::EWrappingStatus OutputStream::wrap(const CodedData& data)
{
Expand Down
2 changes: 1 addition & 1 deletion src/AvTranscoder/stream/OutputStream.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ class AvExport OutputStream : public IOutputStream
size_t getStreamIndex() const { return _streamIndex; }
float getStreamDuration() const;
size_t getNbFrames() const; ///< If audio stream, returns number of packets
int getStreamPTS() const; ///< Get current AVStream PTS
// int getStreamPTS() const; ///< Get current AVStream PTS

bool isPTSGenerated() const { return _isPTSGenerated; }
IOutputStream::EWrappingStatus wrap(const CodedData& data);
Expand Down
5 changes: 5 additions & 0 deletions src/AvTranscoder/transcoder/Transcoder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -560,7 +560,12 @@ void Transcoder::fillProcessStat(ProcessStat& processStat)
if(encoder)
{
const AVCodecContext& encoderContext = encoder->getCodec().getAVCodecContext();

#ifdef AV_CODEC_FLAG_PSNR
if(encoderContext.coded_frame && (encoderContext.flags & AV_CODEC_FLAG_PSNR))
#else
if(encoderContext.coded_frame && (encoderContext.flags & CODEC_FLAG_PSNR))
#endif
{
videoStat.setQuality(encoderContext.coded_frame->quality);
videoStat.setPSNR(encoderContext.coded_frame->error[0] /
Expand Down
2 changes: 1 addition & 1 deletion test/pyTest/testAudioReader.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ def testAudioReaderWithGenerator():

# generate 10 frames of silence
reader.continueWithGenerator()
for i in xrange(0, 9):
for i in range(0, 9):
frame = reader.readNextFrame()
# assuming we generate data of 1920 samples of 2 bytes
nbSamplesPerChannel = 1920
Expand Down
10 changes: 5 additions & 5 deletions test/pyTest/testEProcessMethod.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ def testEProcessMethodLongest():
transcoder.setProcessMethod( av.eProcessMethodLongest )

transcoder.addStream( av.InputStreamDesc(inputFileName_longest, 0) )
transcoder.addStream( av.InputStreamDesc(inputFileName_shortest, 0) )
transcoder.addStream( av.InputStreamDesc(inputFileName_shortest, 1) )

progress = av.ConsoleProgress()
transcoder.process( progress )
Expand Down Expand Up @@ -90,7 +90,7 @@ def testEProcessMethodBasedOnStream():

transcoder.addStream( av.InputStreamDesc(inputFileName_first, 0) )
transcoder.addStream( av.InputStreamDesc(inputFileName_second, 0) )
transcoder.addStream( av.InputStreamDesc(inputFileName_third, 0) )
transcoder.addStream( av.InputStreamDesc(inputFileName_third, 1) )

progress = av.ConsoleProgress()
transcoder.process( progress )
Expand All @@ -115,15 +115,15 @@ def testEProcessMethodBasedOnDuration():
inputFileName_second = os.environ['AVTRANSCODER_TEST_AUDIO_WAVE_FILE']
inputFileName_third = os.environ['AVTRANSCODER_TEST_AUDIO_MOV_FILE']
outputFileName = "testEProcessMethodBasedOnDuration.mov"
outputDuration = 50
outputDuration = 10

ouputFile = av.OutputFile( outputFileName )
transcoder = av.Transcoder( ouputFile )
transcoder.setProcessMethod( av.eProcessMethodBasedOnDuration, 0, outputDuration )

transcoder.addStream( av.InputStreamDesc(inputFileName_first, 0) )
transcoder.addStream( av.InputStreamDesc(inputFileName_second, 0) )
transcoder.addStream( av.InputStreamDesc(inputFileName_third, 0) )
transcoder.addStream( av.InputStreamDesc(inputFileName_third, 1) )

progress = av.ConsoleProgress()
transcoder.process( progress )
Expand All @@ -133,5 +133,5 @@ def testEProcessMethodBasedOnDuration():
dst_properties = dst_inputFile.getProperties()

for dst_stream_properties in dst_properties.getStreamProperties():
assert_almost_equals( dst_stream_properties.getDuration(), outputDuration, delta=0.05 )
assert_almost_equals( dst_stream_properties.getDuration(), outputDuration, delta=0.1 )

11 changes: 11 additions & 0 deletions test/pyTest/testInputFile.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,3 +120,14 @@ def testInputFileAnalyseFull():
assert_not_equals(videoProperties.getDuration(), 0)
assert_not_equals(videoProperties.getBitRate(), 0)
assert_not_equals(videoProperties.getNbFrames(), 0)

@raises(RuntimeError)
def testInputFileSetupInvalidUnwrappingProfile():
"""
Analyse only header of an InputFile, and try to access a properties computed when access the first GOP.
"""
inputFileName = os.environ['AVTRANSCODER_TEST_VIDEO_MOV_FILE']

emptyUnwrappingProfile = av.ProfileMap()
inputFile = av.InputFile(inputFileName)
inputFile.setupUnwrapping(emptyUnwrappingProfile);
Loading