From c8f5fe1f6a178169b2e9100906ef95a226bb2c04 Mon Sep 17 00:00:00 2001 From: Valentin NOEL Date: Tue, 12 Dec 2017 11:39:15 +0100 Subject: [PATCH 01/74] StreamTranscoder: fix filter graph memory usage --- .../transcoder/StreamTranscoder.cpp | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/src/AvTranscoder/transcoder/StreamTranscoder.cpp b/src/AvTranscoder/transcoder/StreamTranscoder.cpp index 391f5ddd..78253644 100644 --- a/src/AvTranscoder/transcoder/StreamTranscoder.cpp +++ b/src/AvTranscoder/transcoder/StreamTranscoder.cpp @@ -435,7 +435,10 @@ StreamTranscoder::~StreamTranscoder() { delete(*it); } - delete _filteredData; + + if(_filteredData != NULL && _filteredData->isDataAllocated()) + delete _filteredData; + delete _transformedData; for(std::vector::iterator it = _inputDecoders.begin(); it != _inputDecoders.end(); ++it) @@ -620,13 +623,17 @@ bool StreamTranscoder::processTranscode() const int nbInputSamplesPerChannel = _decodedData.at(_firstInputStreamIndex)->getAVFrame().nb_samples; // Reallocate output frame - if(nbInputSamplesPerChannel > _filteredData->getAVFrame().nb_samples) + if(_filterGraph->hasFilters()) { - LOG_WARN("The buffer of filtered data corresponds to a frame of " << _filteredData->getAVFrame().nb_samples << " samples. The decoded buffer contains " << nbInputSamplesPerChannel << " samples. Reallocate it.") _filteredData->freeData(); - _filteredData->getAVFrame().nb_samples = nbInputSamplesPerChannel; - _filteredData->allocateData(); + if(nbInputSamplesPerChannel > _filteredData->getAVFrame().nb_samples) + { + LOG_WARN("The buffer of filtered data corresponds to a frame of " << _filteredData->getAVFrame().nb_samples << " samples. The decoded buffer contains " << nbInputSamplesPerChannel << " samples. Reallocate it.") + _filteredData->getAVFrame().nb_samples = nbInputSamplesPerChannel; + _filteredData->allocateData(); + } } + if(nbInputSamplesPerChannel > _transformedData->getAVFrame().nb_samples) { LOG_WARN("The buffer of transformed data corresponds to a frame of " << _transformedData->getAVFrame().nb_samples << " samples. The decoded buffer contains " << nbInputSamplesPerChannel << " samples. Reallocate it.") From 30b738541a43ad7f4087f23e5ce08ce1ab012216 Mon Sep 17 00:00:00 2001 From: Valentin NOEL Date: Tue, 12 Dec 2017 12:01:49 +0100 Subject: [PATCH 02/74] Update version to 0.14.1 --- src/AvTranscoder/common.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/AvTranscoder/common.hpp b/src/AvTranscoder/common.hpp index 481daad0..33d87e37 100644 --- a/src/AvTranscoder/common.hpp +++ b/src/AvTranscoder/common.hpp @@ -3,7 +3,7 @@ #define AVTRANSCODER_VERSION_MAJOR 0 #define AVTRANSCODER_VERSION_MINOR 14 -#define AVTRANSCODER_VERSION_MICRO 0 +#define AVTRANSCODER_VERSION_MICRO 1 #include From cec93d6b8ad4ec444a21c2c32171f533e6d17685 Mon Sep 17 00:00:00 2001 From: aldo-devlap02 Date: Thu, 21 Jun 2018 14:18:31 +0200 Subject: [PATCH 03/74] fix: correctly retrieve the fileSize on 32 bits OS "size_t" size depends on the OS. On 32-bit system it can only hold a 32 bits variable = 4 294 967 296, which is not enough to store a big file size (e.g: 14Go). We should use a 64-bits variable --- src/AvTranscoder/properties/FileProperties.cpp | 2 +- src/AvTranscoder/properties/FileProperties.hpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/AvTranscoder/properties/FileProperties.cpp b/src/AvTranscoder/properties/FileProperties.cpp index 8cabd289..7bf52686 100644 --- a/src/AvTranscoder/properties/FileProperties.cpp +++ b/src/AvTranscoder/properties/FileProperties.cpp @@ -210,7 +210,7 @@ size_t FileProperties::getBitRate() const return _avFormatContext->bit_rate; } -size_t FileProperties::getFileSize() const +unsigned __int64 FileProperties::getFileSize() const { std::ifstream in(getFilename().c_str(), std::ios::binary | std::ios::ate); return in.tellg(); diff --git a/src/AvTranscoder/properties/FileProperties.hpp b/src/AvTranscoder/properties/FileProperties.hpp index 780eb64f..93715984 100644 --- a/src/AvTranscoder/properties/FileProperties.hpp +++ b/src/AvTranscoder/properties/FileProperties.hpp @@ -49,7 +49,7 @@ class AvExport FileProperties double getStartTime() const; float getDuration() const; ///< in seconds, 0 if not available size_t getBitRate() const; ///< total stream bitrate in bit/s, 0 if not available (result of a computation by ffmpeg) - size_t getFileSize() const; ///< in bytes + unsigned __int64 getFileSize() const; ///< in bytes size_t getPacketSize() const; const PropertyVector& getMetadatas() const { return _metadatas; } From 923e28ef7ef9dd8d529e366fb1a890ba849d4b34 Mon Sep 17 00:00:00 2001 From: aldo-devlap02 Date: Fri, 22 Jun 2018 11:45:23 +0200 Subject: [PATCH 04/74] fix: replace unsigned __int64 type by cross-platform uint64_t --- src/AvTranscoder/properties/FileProperties.cpp | 2 +- src/AvTranscoder/properties/FileProperties.hpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/AvTranscoder/properties/FileProperties.cpp b/src/AvTranscoder/properties/FileProperties.cpp index 7bf52686..6c135a7b 100644 --- a/src/AvTranscoder/properties/FileProperties.cpp +++ b/src/AvTranscoder/properties/FileProperties.cpp @@ -210,7 +210,7 @@ size_t FileProperties::getBitRate() const return _avFormatContext->bit_rate; } -unsigned __int64 FileProperties::getFileSize() const +uint64_t FileProperties::getFileSize() const { std::ifstream in(getFilename().c_str(), std::ios::binary | std::ios::ate); return in.tellg(); diff --git a/src/AvTranscoder/properties/FileProperties.hpp b/src/AvTranscoder/properties/FileProperties.hpp index 93715984..d3f3b824 100644 --- a/src/AvTranscoder/properties/FileProperties.hpp +++ b/src/AvTranscoder/properties/FileProperties.hpp @@ -49,7 +49,7 @@ class AvExport FileProperties double getStartTime() const; float getDuration() const; ///< in seconds, 0 if not available size_t getBitRate() const; ///< total stream bitrate in bit/s, 0 if not available (result of a computation by ffmpeg) - unsigned __int64 getFileSize() const; ///< in bytes + uint64_t getFileSize() const; ///< in bytes size_t getPacketSize() const; const PropertyVector& getMetadatas() const { return _metadatas; } From 10985bd965c43b5bb80d3777f8e45553fb125a7d Mon Sep 17 00:00:00 2001 From: aldo-devlap02 Date: Tue, 26 Jun 2018 19:07:04 +0200 Subject: [PATCH 05/74] refactoring: add Note to getFileSize explaining why using uint64_t --- src/AvTranscoder/properties/FileProperties.hpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/AvTranscoder/properties/FileProperties.hpp b/src/AvTranscoder/properties/FileProperties.hpp index d3f3b824..43d7aae7 100644 --- a/src/AvTranscoder/properties/FileProperties.hpp +++ b/src/AvTranscoder/properties/FileProperties.hpp @@ -49,6 +49,9 @@ class AvExport FileProperties double getStartTime() const; float getDuration() const; ///< in seconds, 0 if not available size_t getBitRate() const; ///< total stream bitrate in bit/s, 0 if not available (result of a computation by ffmpeg) + /** + * @note Use uint64_t instead of size_t to ensure 64 bits size on 32-bits OS so we can manage Files > 4Go + */ uint64_t getFileSize() const; ///< in bytes size_t getPacketSize() const; From 086d0742b4a551962ff950257aa3fa0cc2a8d4ea Mon Sep 17 00:00:00 2001 From: aldo-devlap02 Date: Fri, 29 Jun 2018 18:33:10 +0200 Subject: [PATCH 06/74] increase avtranscoder micro version to 0.14.2 --- src/AvTranscoder/common.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/AvTranscoder/common.hpp b/src/AvTranscoder/common.hpp index 33d87e37..93112af7 100644 --- a/src/AvTranscoder/common.hpp +++ b/src/AvTranscoder/common.hpp @@ -3,7 +3,7 @@ #define AVTRANSCODER_VERSION_MAJOR 0 #define AVTRANSCODER_VERSION_MINOR 14 -#define AVTRANSCODER_VERSION_MICRO 1 +#define AVTRANSCODER_VERSION_MICRO 2 #include From c584b915dee812a3f60881af2120395588aad1e1 Mon Sep 17 00:00:00 2001 From: Valentin NOEL Date: Fri, 11 Oct 2019 11:04:04 +0200 Subject: [PATCH 07/74] Move dependencies install command to script section --- .travis.yml | 3 ++- tools/travis/linux.install.deps.sh | 9 +++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index fb5b4bd7..32b186f3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -96,11 +96,12 @@ before_script: # install coverage tools - if [ ${ENABLE_COVERAGE} ]; then ./tools/travis/gcc.install.coverage.sh; fi + +script: # install avtranscoder dependencies - if [ ${TRAVIS_OS_NAME} = "linux" ]; then ./tools/travis/linux.install.deps.sh; fi - if [ ${TRAVIS_OS_NAME} = "osx" ]; then ./tools/travis/osx.install.deps.sh; fi -script: # build - ./tools/travis/build.sh diff --git a/tools/travis/linux.install.deps.sh b/tools/travis/linux.install.deps.sh index 553f11c0..e99f8253 100755 --- a/tools/travis/linux.install.deps.sh +++ b/tools/travis/linux.install.deps.sh @@ -12,6 +12,7 @@ if [ -z ${TRAVIS_JOB_ID} ] || [ ! -d "${DEPENDENCY_INSTALL_PATH}/lib/" ]; then export LD_LIBRARY_PATH=${DEPENDENCY_INSTALL_PATH}/lib:${DEPENDENCY_INSTALL_PATH}/lib64 export PKG_CONFIG_PATH=${DEPENDENCY_INSTALL_PATH}/lib/pkgconfig:${DEPENDENCY_INSTALL_PATH}/lib64/pkgconfig export PATH=$PATH:${DEPENDENCY_INSTALL_PATH}/bin + echo "Build log file: ${DEPENDENCY_LOG_FILE}" # yasm echo "Building YASM (${YASM_VERSION})" @@ -21,6 +22,7 @@ if [ -z ${TRAVIS_JOB_ID} ] || [ ! -d "${DEPENDENCY_INSTALL_PATH}/lib/" ]; then cd yasm-${YASM_VERSION} && \ ./configure --prefix="$DEPENDENCY_INSTALL_PATH" --bindir="${DEPENDENCY_INSTALL_PATH}/bin" && \ make -k > ${DEPENDENCY_LOG_FILE} 2>&1 && \ + if [ $? != 0 ]; then cat ${DEPENDENCY_LOG_FILE} && exit 1; fi make install && \ rm -rf ${DIR} @@ -32,6 +34,7 @@ if [ -z ${TRAVIS_JOB_ID} ] || [ ! -d "${DEPENDENCY_INSTALL_PATH}/lib/" ]; then cd x264 && \ ./configure --prefix="$DEPENDENCY_INSTALL_PATH" --bindir="${DEPENDENCY_INSTALL_PATH}/bin" --enable-shared --disable-asm && \ make -k > ${DEPENDENCY_LOG_FILE} 2>&1 && \ + if [ $? != 0 ]; then cat ${DEPENDENCY_LOG_FILE} && exit 1; fi make install && \ rm -rf ${DIR} @@ -44,6 +47,7 @@ if [ -z ${TRAVIS_JOB_ID} ] || [ ! -d "${DEPENDENCY_INSTALL_PATH}/lib/" ]; then cd lame-${LAME_VERSION} && \ ./configure --prefix="${DEPENDENCY_INSTALL_PATH}" --bindir="${DEPENDENCY_INSTALL_PATH}/bin" --enable-nasm && \ make -k > ${DEPENDENCY_LOG_FILE} 2>&1 && \ + if [ $? != 0 ]; then cat ${DEPENDENCY_LOG_FILE} && exit 1; fi make install && \ rm -rf ${DIR} @@ -74,6 +78,7 @@ if [ -z ${TRAVIS_JOB_ID} ] || [ ! -d "${DEPENDENCY_INSTALL_PATH}/lib/" ]; then cd xvidcore/build/generic && \ ./configure --prefix="${DEPENDENCY_INSTALL_PATH}" --bindir="${DEPENDENCY_INSTALL_PATH}/bin" && \ make -k > ${DEPENDENCY_LOG_FILE} 2>&1 && \ + if [ $? != 0 ]; then cat ${DEPENDENCY_LOG_FILE} && exit 1; fi make install && \ rm -rf ${DIR} @@ -101,6 +106,7 @@ if [ -z ${TRAVIS_JOB_ID} ] || [ ! -d "${DEPENDENCY_INSTALL_PATH}/lib/" ]; then cd libogg-${OGG_VERSION} && \ ./configure --prefix="${DEPENDENCY_INSTALL_PATH}" --disable-shared --with-pic && \ make -k > ${DEPENDENCY_LOG_FILE} 2>&1 && \ + if [ $? != 0 ]; then cat ${DEPENDENCY_LOG_FILE} && exit 1; fi make install && \ rm -rf ${DIR} @@ -113,6 +119,7 @@ if [ -z ${TRAVIS_JOB_ID} ] || [ ! -d "${DEPENDENCY_INSTALL_PATH}/lib/" ]; then cd libvorbis-${VORBIS_VERSION} && \ ./configure --prefix="${DEPENDENCY_INSTALL_PATH}" --with-ogg="${DEPENDENCY_INSTALL_PATH}" --disable-shared --with-pic && \ make -k > ${DEPENDENCY_LOG_FILE} 2>&1 && \ + if [ $? != 0 ]; then cat ${DEPENDENCY_LOG_FILE} && exit 1; fi make install && \ rm -rf ${DIR} @@ -140,6 +147,7 @@ if [ -z ${TRAVIS_JOB_ID} ] || [ ! -d "${DEPENDENCY_INSTALL_PATH}/lib/" ]; then git checkout v${VPX_VERSION} && \ ./configure --prefix="${DEPENDENCY_INSTALL_PATH}" --disable-examples --enable-pic && \ make -k > ${DEPENDENCY_LOG_FILE} 2>&1 && \ + if [ $? != 0 ]; then cat ${DEPENDENCY_LOG_FILE} && exit 1; fi make install && \ rm -rf ${DIR} @@ -177,6 +185,7 @@ if [ -z ${TRAVIS_JOB_ID} ] || [ ! -d "${DEPENDENCY_INSTALL_PATH}/lib/" ]; then $LICENSING_OPTIONS \ $THIRD_PARTIES_OPTIONS --enable-postproc && \ make -k > ${DEPENDENCY_LOG_FILE} 2>&1 && \ + if [ $? != 0 ]; then cat ${DEPENDENCY_LOG_FILE} && exit 1; fi make install && \ rm -rf ${DIR} From 4d9d06031711225c79f8b0dae64cb8af97299349 Mon Sep 17 00:00:00 2001 From: Valentin NOEL Date: Fri, 22 Nov 2019 15:22:21 +0100 Subject: [PATCH 08/74] Disable Travis dependency caching --- .travis.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 32b186f3..5557148e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -82,9 +82,6 @@ addons: cache: # Caching Ubuntu packages apt: true - # Caching other directories - directories: - - ${DEPENDENCY_INSTALL_PATH} before_script: - env | sort From 6d7cf07bc0aa0a16dec0457284c7d3c9bafac71f Mon Sep 17 00:00:00 2001 From: Valentin NOEL Date: Fri, 22 Nov 2019 15:53:01 +0100 Subject: [PATCH 09/74] Checkout libx264 before failing commit for FFmpeg version 2.x Checkout before commit https://code.videolan.org/videolan/x264/commit/e9a5903edf8ca59ef20e6f4894c196f135af735e => see https://trac.ffmpeg.org/ticket/6932 --- tools/travis/linux.install.deps.sh | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tools/travis/linux.install.deps.sh b/tools/travis/linux.install.deps.sh index e99f8253..4471ed88 100755 --- a/tools/travis/linux.install.deps.sh +++ b/tools/travis/linux.install.deps.sh @@ -29,9 +29,12 @@ if [ -z ${TRAVIS_JOB_ID} ] || [ ! -d "${DEPENDENCY_INSTALL_PATH}/lib/" ]; then # x264 echo "" echo "Building x264 (last version)" + # or before commit https://code.videolan.org/videolan/x264/commit/e9a5903edf8ca59ef20e6f4894c196f135af735e + # => see https://trac.ffmpeg.org/ticket/6932 DIR=$(mktemp -d x264XXX) && cd ${DIR} && \ - git clone --depth 1 git://git.videolan.org/x264 && \ + git clone https://code.videolan.org/videolan/x264.git && \ cd x264 && \ + if [[ ${DEPENDENCY_VERSION} == 2.*.* ]]; then git checkout ba24899b0bf23345921da022f7a51e0c57dbe73d; fi ./configure --prefix="$DEPENDENCY_INSTALL_PATH" --bindir="${DEPENDENCY_INSTALL_PATH}/bin" --enable-shared --disable-asm && \ make -k > ${DEPENDENCY_LOG_FILE} 2>&1 && \ if [ $? != 0 ]; then cat ${DEPENDENCY_LOG_FILE} && exit 1; fi From 3dc8a1ad5b4447e3d8ee65ea2aad519e9854bccc Mon Sep 17 00:00:00 2001 From: Valentin NOEL Date: Fri, 22 Nov 2019 16:43:05 +0100 Subject: [PATCH 10/74] Enable Travis dependency caching --- .travis.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.travis.yml b/.travis.yml index 5557148e..32b186f3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -82,6 +82,9 @@ addons: cache: # Caching Ubuntu packages apt: true + # Caching other directories + directories: + - ${DEPENDENCY_INSTALL_PATH} before_script: - env | sort From 35cde24b1d37d7cf2c3292ba5410ed0adcd06332 Mon Sep 17 00:00:00 2001 From: Valentin NOEL Date: Fri, 22 Nov 2019 16:44:30 +0100 Subject: [PATCH 11/74] Swig: include stdint.i to handle uint64_t type After PR #306 --- src/AvTranscoder/avTranscoder.i | 1 + 1 file changed, 1 insertion(+) diff --git a/src/AvTranscoder/avTranscoder.i b/src/AvTranscoder/avTranscoder.i index 5005baa8..175a6c22 100644 --- a/src/AvTranscoder/avTranscoder.i +++ b/src/AvTranscoder/avTranscoder.i @@ -6,6 +6,7 @@ %include "std_vector.i" %include "std_pair.i" %include "std_map.i" +%include "stdint.i" %include "AvTranscoder/swig/avException.i" %include "AvTranscoder/swig/avExport.i" From 03a639106bead3e0f60a4b208beed79e83662955 Mon Sep 17 00:00:00 2001 From: Valentin NOEL Date: Fri, 29 Nov 2019 11:23:36 +0100 Subject: [PATCH 12/74] README: remove deprecated badges --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index f31fd5b8..35382d0e 100644 --- a/README.md +++ b/README.md @@ -8,9 +8,9 @@ Based on FFmpeg/Libav libraries to support various video and audio formats, avTr [![Build status](https://ci.appveyor.com/api/projects/status/6urf0otyhtj8xuny?svg=true)](https://ci.appveyor.com/project/cchampet/avtranscoder) [![Coverage Status](https://coveralls.io/repos/avTranscoder/avTranscoder/badge.svg)](https://coveralls.io/r/avTranscoder/avTranscoder) Coverity Scan Build Status -[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/avTranscoder/avtranscoder/trend.png)](https://bitdeli.com/free "Bitdeli Badge") + -[![Stories in Progress](https://badge.waffle.io/avTranscoder/avTranscoder.svg?label=2 - Working&title=In Progress)](http://waffle.io/avTranscoder/avTranscoder) + Click on the badge above to have a big picture view of what's in progress and how you can help. :warning: The latest avTranscoder API does not fit with libav. From f8b8e8f2478af2cd2ac332470011258b43da2393 Mon Sep 17 00:00:00 2001 From: Valentin NOEL Date: Fri, 29 Nov 2019 11:23:49 +0100 Subject: [PATCH 13/74] Update version to 0.14.3 --- src/AvTranscoder/common.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/AvTranscoder/common.hpp b/src/AvTranscoder/common.hpp index 93112af7..96005b8c 100644 --- a/src/AvTranscoder/common.hpp +++ b/src/AvTranscoder/common.hpp @@ -3,7 +3,7 @@ #define AVTRANSCODER_VERSION_MAJOR 0 #define AVTRANSCODER_VERSION_MINOR 14 -#define AVTRANSCODER_VERSION_MICRO 2 +#define AVTRANSCODER_VERSION_MICRO 3 #include From 7fcc1b603fea6a5f997c829f6a16fa70d4e6601f Mon Sep 17 00:00:00 2001 From: Marc-Antoine Arnaud Date: Mon, 21 Oct 2019 18:22:04 +0200 Subject: [PATCH 14/74] changes to support FFmpeg 4.1 --- CMakeLists.txt | 9 +++++++++ src/AvTranscoder/encoder/VideoEncoder.cpp | 4 ++++ src/AvTranscoder/file/OutputFile.cpp | 20 +++++++++++++------ src/AvTranscoder/filter/Filter.cpp | 2 +- .../properties/StreamProperties.cpp | 11 +++++++++- .../properties/VideoProperties.cpp | 8 +++++++- src/AvTranscoder/stream/OutputStream.cpp | 16 +++++++-------- src/AvTranscoder/stream/OutputStream.hpp | 2 +- src/AvTranscoder/transcoder/Transcoder.cpp | 5 +++++ 9 files changed, 59 insertions(+), 18 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 65da65f2..3fa384b1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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") diff --git a/src/AvTranscoder/encoder/VideoEncoder.cpp b/src/AvTranscoder/encoder/VideoEncoder.cpp index c6d43b66..63e55d21 100644 --- a/src/AvTranscoder/encoder/VideoEncoder.cpp +++ b/src/AvTranscoder/encoder/VideoEncoder.cpp @@ -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(); diff --git a/src/AvTranscoder/file/OutputFile.cpp b/src/AvTranscoder/file/OutputFile.cpp index 8d292b95..5ff45435 100644 --- a/src/AvTranscoder/file/OutputFile.cpp +++ b/src/AvTranscoder/file/OutputFile.cpp @@ -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 @@ -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; diff --git a/src/AvTranscoder/filter/Filter.cpp b/src/AvTranscoder/filter/Filter.cpp index 07cc30d8..c5ac8fb4 100644 --- a/src/AvTranscoder/filter/Filter.cpp +++ b/src/AvTranscoder/filter/Filter.cpp @@ -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 "); diff --git a/src/AvTranscoder/properties/StreamProperties.cpp b/src/AvTranscoder/properties/StreamProperties.cpp index 6f6fcf02..2a860aeb 100644 --- a/src/AvTranscoder/properties/StreamProperties.cpp +++ b/src/AvTranscoder/properties/StreamProperties.cpp @@ -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"); @@ -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"); diff --git a/src/AvTranscoder/properties/VideoProperties.cpp b/src/AvTranscoder/properties/VideoProperties.cpp index 84179b4c..744e21b8 100644 --- a/src/AvTranscoder/properties/VideoProperties.cpp +++ b/src/AvTranscoder/properties/VideoProperties.cpp @@ -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) @@ -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 diff --git a/src/AvTranscoder/stream/OutputStream.cpp b/src/AvTranscoder/stream/OutputStream.cpp index 350c1ace..0c47d004 100644 --- a/src/AvTranscoder/stream/OutputStream.cpp +++ b/src/AvTranscoder/stream/OutputStream.cpp @@ -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; @@ -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 } @@ -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) { diff --git a/src/AvTranscoder/stream/OutputStream.hpp b/src/AvTranscoder/stream/OutputStream.hpp index b68d93a5..4b2b3a48 100644 --- a/src/AvTranscoder/stream/OutputStream.hpp +++ b/src/AvTranscoder/stream/OutputStream.hpp @@ -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); diff --git a/src/AvTranscoder/transcoder/Transcoder.cpp b/src/AvTranscoder/transcoder/Transcoder.cpp index 5249f330..c101b8e0 100644 --- a/src/AvTranscoder/transcoder/Transcoder.cpp +++ b/src/AvTranscoder/transcoder/Transcoder.cpp @@ -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] / From c2106bdb27bdc1bd6462b4ea72c46db1d9086551 Mon Sep 17 00:00:00 2001 From: Valentin NOEL Date: Thu, 23 Jan 2020 16:09:09 +0100 Subject: [PATCH 15/74] Travis: update FFmpeg version to 4.* And update dependencies --- .travis.yml | 31 +++++++++++++++++------------- tools/travis/linux.install.deps.sh | 6 ++++-- 2 files changed, 22 insertions(+), 15 deletions(-) diff --git a/.travis.yml b/.travis.yml index 32b186f3..348f07c6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -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: diff --git a/tools/travis/linux.install.deps.sh b/tools/travis/linux.install.deps.sh index 4471ed88..df56addc 100755 --- a/tools/travis/linux.install.deps.sh +++ b/tools/travis/linux.install.deps.sh @@ -45,7 +45,7 @@ if [ -z ${TRAVIS_JOB_ID} ] || [ ! -d "${DEPENDENCY_INSTALL_PATH}/lib/" ]; then echo "" echo "Building libmp3lame (${LAME_VERSION})" DIR=$(mktemp -d libmp3lameXXX) && cd ${DIR} && \ - curl -L -Os http://downloads.sourceforge.net/project/lame/lame/${LAME_VERSION%.*}/lame-${LAME_VERSION}.tar.gz && \ + curl -L -Os http://downloads.sourceforge.net/project/lame/lame/${LAME_VERSION}/lame-${LAME_VERSION}.tar.gz && \ tar xzf lame-${LAME_VERSION}.tar.gz && \ cd lame-${LAME_VERSION} && \ ./configure --prefix="${DEPENDENCY_INSTALL_PATH}" --bindir="${DEPENDENCY_INSTALL_PATH}/bin" --enable-nasm && \ @@ -171,7 +171,8 @@ if [ -z ${TRAVIS_JOB_ID} ] || [ ! -d "${DEPENDENCY_INSTALL_PATH}/lib/" ]; then export RELEASE_OPTIONS=--disable-debug export DEBUG_OPTIONS=--enable-debug=3\ --disable-optimizations\ --disable-sse\ --disable-stripping export LICENSING_OPTIONS=--enable-gpl\ --enable-nonfree - export THIRD_PARTIES_OPTIONS=--enable-libmp3lame\ --enable-libx264\ --enable-libxvid\ --enable-avresample\ --enable-libvorbis\ --enable-libvpx + export THIRD_PARTIES_OPTIONS=--enable-libmp3lame\ --enable-libx264\ --enable-libxvid\ --enable-avresample\ --enable-libvpx + export PKG_CONFIG_PATH="${DEPENDENCY_INSTALL_PATH}/lib/pkgconfig" if [[ ${DEPENDENCY_NAME} == "ffmpeg" ]]; then @@ -207,6 +208,7 @@ if [ -z ${TRAVIS_JOB_ID} ] || [ ! -d "${DEPENDENCY_INSTALL_PATH}/lib/" ]; then $LICENSING_OPTIONS \ $THIRD_PARTIES_OPTIONS && \ make -k > ${DEPENDENCY_LOG_FILE} 2>&1 && \ + if [ $? != 0 ]; then cat ${DEPENDENCY_LOG_FILE} && exit 1; fi make install && \ rm -rf ${DIR} From 1c95f19fdfe7c06e51fad619186e94583dbc6706 Mon Sep 17 00:00:00 2001 From: Valentin NOEL Date: Thu, 23 Jan 2020 16:10:35 +0100 Subject: [PATCH 16/74] Travis: use Python3 for unit tests --- .travis.yml | 7 +++++-- tools/travis/build.sh | 6 +++++- tools/travis/python.nosetests.sh | 5 ++--- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/.travis.yml b/.travis.yml index 348f07c6..fa780ef6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -62,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 @@ -80,8 +81,10 @@ addons: packages: - cmake - swig - - python-dev - - python-nose + - python3-dev + - python3 + - python3-nose + - python3-coverage - freeglut3-dev cache: diff --git a/tools/travis/build.sh b/tools/travis/build.sh index 336c66f7..6504bed7 100755 --- a/tools/travis/build.sh +++ b/tools/travis/build.sh @@ -13,6 +13,10 @@ cd ${AVTRANSCODER_BUILD_PATH} export CMAKE_PREFIX_PATH=${DEPENDENCY_INSTALL_PATH} # Build avTranscoder -cmake .. -DCMAKE_INSTALL_PREFIX=${AVTRANSCODER_INSTALL_PATH} -DCMAKE_PREFIX_PATH=$CMAKE_PREFIX_PATH -DCMAKE_BUILD_TYPE=Release -DAVTRANSCODER_PYTHON_VERSION_OF_BINDING=2.7 -DAVTRANSCODER_COVERAGE=${ENABLE_COVERAGE} +cmake .. -DCMAKE_INSTALL_PREFIX=${AVTRANSCODER_INSTALL_PATH} \ + -DCMAKE_PREFIX_PATH=$CMAKE_PREFIX_PATH \ + -DCMAKE_BUILD_TYPE=Release \ + -DAVTRANSCODER_PYTHON_VERSION_OF_BINDING=3.5 \ + -DAVTRANSCODER_COVERAGE=${ENABLE_COVERAGE} make -k make install diff --git a/tools/travis/python.nosetests.sh b/tools/travis/python.nosetests.sh index d23c402e..9eae31b2 100755 --- a/tools/travis/python.nosetests.sh +++ b/tools/travis/python.nosetests.sh @@ -5,7 +5,7 @@ set -x # Get avtranscoder library export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:${DEPENDENCY_INSTALL_PATH}/lib -export PYTHONPATH=${AVTRANSCODER_INSTALL_PATH}/lib/python2.7/site-packages/:$PYTHONPATH +export PYTHONPATH=${AVTRANSCODER_INSTALL_PATH}/lib/python3.5/site-packages/:$PYTHONPATH # Get assets git clone https://github.com/avTranscoder/avTranscoder-data.git @@ -20,5 +20,4 @@ export AVTRANSCODER_TEST_IMAGE_PNG_FILE=`pwd`/avTranscoder-data/image/BigBuckBun export AVTRANSCODER_TEST_IMAGE_JPG_FILE=`pwd`/avTranscoder-data/image/BigBuckBunny/title_anouncement.thumbnail.jpg # Launch tests -nosetests ${TRAVIS_BUILD_DIR}/test/pyTest --with-coverage > progress.txt - +nosetests3 -w ${TRAVIS_BUILD_DIR}/test/pyTest --with-coverage --nocapture --verbose > progress.txt From 37af8e4ca0f0f3a66f5a44bb8f840e0fa7ae59b9 Mon Sep 17 00:00:00 2001 From: Valentin NOEL Date: Thu, 23 Jan 2020 16:11:32 +0100 Subject: [PATCH 17/74] Appveyor: update FFmpeg version to 4.* and use Python3 for unit tests --- appveyor.yml | 8 ++++---- tools/appveyor/build.bat | 7 ++++++- tools/appveyor/python.nosetests.bat | 4 ++-- tools/appveyor/win.install.deps.bat | 8 ++++---- 4 files changed, 16 insertions(+), 11 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index adc2bc2c..a809dd3e 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -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 @@ -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% @@ -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 diff --git a/tools/appveyor/build.bat b/tools/appveyor/build.bat index d5400ff4..d112cdfd 100755 --- a/tools/appveyor/build.bat +++ b/tools/appveyor/build.bat @@ -4,7 +4,12 @@ MKDIR build cd build :: Configure -call cmake.exe .. -G "NMake Makefiles" -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=%AVTRANSCODER_INSTALL_PATH% -DCMAKE_PREFIX_PATH=%DEPENDENCY_INSTALL_PATH% -DAVTRANSCODER_PYTHON_VERSION_OF_BINDING=2.7 +call cmake.exe .. -G "NMake Makefiles" ^ + -DCMAKE_BUILD_TYPE=Release ^ + -DCMAKE_INSTALL_PREFIX=%AVTRANSCODER_INSTALL_PATH% ^ + -DCMAKE_PREFIX_PATH=%DEPENDENCY_INSTALL_PATH% ^ + -DPYTHON_LIBRARY="C:\Python35\libs\python35.lib" ^ + -DAVTRANSCODER_PYTHON_VERSION_OF_BINDING=3.5 :: Build & Install call nmake /F Makefile diff --git a/tools/appveyor/python.nosetests.bat b/tools/appveyor/python.nosetests.bat index eb2692a9..608a4131 100755 --- a/tools/appveyor/python.nosetests.bat +++ b/tools/appveyor/python.nosetests.bat @@ -3,7 +3,7 @@ set PWD=C:\projects\avtranscoder :: Get avtranscoder library -set PYTHONPATH=%AVTRANSCODER_INSTALL_PATH%\lib\python2.7\site-packages;%PYTHONPATH% +set PYTHONPATH=%AVTRANSCODER_INSTALL_PATH%\lib\python3.5\site-packages;%PYTHONPATH% set PATH=%DEPENDENCY_INSTALL_PATH%\bin;%AVTRANSCODER_INSTALL_PATH%\lib;%PATH% :: Get avtranscoder profiles @@ -22,7 +22,7 @@ set AVTRANSCODER_TEST_IMAGE_JPG_FILE=%PWD%\avTranscoder-data\image\BigBuckBunny\ :: Launch tests cd test\pyTest -nosetests +python -m nose cd ..\.. @echo off diff --git a/tools/appveyor/win.install.deps.bat b/tools/appveyor/win.install.deps.bat index 6c37998f..e57bba3b 100755 --- a/tools/appveyor/win.install.deps.bat +++ b/tools/appveyor/win.install.deps.bat @@ -4,12 +4,12 @@ if %platform% == x86 set PLATFORM_VERSION=32 if %platform% == X64 set PLATFORM_VERSION=64 :: Installing ffmpeg dev (include + apps) -curl -kLO http://ffmpeg.zeranoe.com/builds/win%PLATFORM_VERSION%/dev/ffmpeg-%DEPENDENCY_VERSION%-win%PLATFORM_VERSION%-dev.7z -7z x ffmpeg-%DEPENDENCY_VERSION%-win%PLATFORM_VERSION%-dev.7z +curl -kLO http://ffmpeg.zeranoe.com/builds/win%PLATFORM_VERSION%/dev/ffmpeg-%DEPENDENCY_VERSION%-win%PLATFORM_VERSION%-dev.zip +7z x ffmpeg-%DEPENDENCY_VERSION%-win%PLATFORM_VERSION%-dev.zip :: Installing ffmpeg shared (libs) -curl -kLO http://ffmpeg.zeranoe.com/builds/win%PLATFORM_VERSION%/shared/ffmpeg-%DEPENDENCY_VERSION%-win%PLATFORM_VERSION%-shared.7z -7z x ffmpeg-%DEPENDENCY_VERSION%-win%PLATFORM_VERSION%-shared.7z +curl -kLO http://ffmpeg.zeranoe.com/builds/win%PLATFORM_VERSION%/shared/ffmpeg-%DEPENDENCY_VERSION%-win%PLATFORM_VERSION%-shared.zip +7z x ffmpeg-%DEPENDENCY_VERSION%-win%PLATFORM_VERSION%-shared.zip move ffmpeg-%DEPENDENCY_VERSION%-win%PLATFORM_VERSION%-shared\bin ffmpeg-%DEPENDENCY_VERSION%-win%PLATFORM_VERSION%-dev move ffmpeg-%DEPENDENCY_VERSION%-win%PLATFORM_VERSION%-dev %DEPENDENCY_INSTALL_PATH% From b49c7c09b98ccea37a745294f25500f80fb19c60 Mon Sep 17 00:00:00 2001 From: Valentin NOEL Date: Thu, 23 Jan 2020 16:44:24 +0100 Subject: [PATCH 18/74] Update unit tests --- test/pyTest/testAudioReader.py | 2 +- test/pyTest/testEProcessMethod.py | 10 +- test/pyTest/testInputFile.py | 11 ++ test/pyTest/testOffset.py | 285 +++++++++++++++--------------- test/pyTest/testOutputFile.py | 2 +- test/pyTest/testProcessStat.py | 2 +- test/pyTest/testProfiles.py | 59 +++++++ test/pyTest/testProperties.py | 4 +- test/pyTest/testVideoReader.py | 6 +- 9 files changed, 226 insertions(+), 155 deletions(-) create mode 100644 test/pyTest/testProfiles.py diff --git a/test/pyTest/testAudioReader.py b/test/pyTest/testAudioReader.py index 511480e3..0068a827 100644 --- a/test/pyTest/testAudioReader.py +++ b/test/pyTest/testAudioReader.py @@ -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 diff --git a/test/pyTest/testEProcessMethod.py b/test/pyTest/testEProcessMethod.py index 0f3664b7..b9f7b4cf 100644 --- a/test/pyTest/testEProcessMethod.py +++ b/test/pyTest/testEProcessMethod.py @@ -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 ) @@ -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 ) @@ -115,7 +115,7 @@ 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 ) @@ -123,7 +123,7 @@ def testEProcessMethodBasedOnDuration(): 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 ) @@ -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 ) diff --git a/test/pyTest/testInputFile.py b/test/pyTest/testInputFile.py index 9fe74537..5b6164e7 100644 --- a/test/pyTest/testInputFile.py +++ b/test/pyTest/testInputFile.py @@ -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); diff --git a/test/pyTest/testOffset.py b/test/pyTest/testOffset.py index 30ad3043..278202a0 100644 --- a/test/pyTest/testOffset.py +++ b/test/pyTest/testOffset.py @@ -137,97 +137,97 @@ def testRewrapAudioNegativeOffset(): assert_equals( src_audioStream.getNbSamples() + ( offset * dst_audioStream.getSampleRate() * dst_audioStream.getNbChannels() ), dst_audioStream.getNbSamples() ) -# The output video stream has not the correct duration. -@nottest -def testTranscodeVideoPositiveOffset(): - """ - Transcode one video stream (profile mpeg2) with offset at the beginning of the process. - """ - inputFileName = os.environ['AVTRANSCODER_TEST_VIDEO_AVI_FILE'] - outputFileName = "testTranscodeVideoPositiveOffset.mov" - offset = 10 +# # The output video stream has not the correct duration. +# @nottest +# def testTranscodeVideoPositiveOffset(): +# """ +# Transcode one video stream (profile mpeg2) with offset at the beginning of the process. +# """ +# inputFileName = os.environ['AVTRANSCODER_TEST_VIDEO_AVI_FILE'] +# outputFileName = "testTranscodeVideoPositiveOffset.mov" +# offset = 10 - ouputFile = av.OutputFile( outputFileName ) - transcoder = av.Transcoder( ouputFile ) +# ouputFile = av.OutputFile( outputFileName ) +# transcoder = av.Transcoder( ouputFile ) - transcoder.addStream( av.InputStreamDesc(inputFileName), "mpeg2", offset ) +# transcoder.addStream( av.InputStreamDesc(inputFileName), "mpeg2", offset ) - progress = av.ConsoleProgress() - transcoder.process( progress ) +# progress = av.ConsoleProgress() +# transcoder.process( progress ) - # get src file - src_inputFile = av.InputFile( inputFileName ) - src_properties = src_inputFile.getProperties() - src_videoStream = src_properties.getVideoProperties()[0] +# # get src file +# src_inputFile = av.InputFile( inputFileName ) +# src_properties = src_inputFile.getProperties() +# src_videoStream = src_properties.getVideoProperties()[0] - # get dst file - dst_inputFile = av.InputFile( outputFileName ) - dst_properties = dst_inputFile.getProperties() - dst_videoStream = dst_properties.getVideoProperties()[0] +# # get dst file +# dst_inputFile = av.InputFile( outputFileName ) +# dst_properties = dst_inputFile.getProperties() +# dst_videoStream = dst_properties.getVideoProperties()[0] - # check output duration - assert_equals( src_videoStream.getDuration() + offset, dst_videoStream.getDuration() ) +# # check output duration +# assert_equals( src_videoStream.getDuration() + offset, dst_videoStream.getDuration() ) -def testTranscodeVideoNegativeOffset(): - """ - Transcode one video stream (profile mpeg2) with a negative offset at the beginning of the process. - """ - inputFileName = os.environ['AVTRANSCODER_TEST_VIDEO_AVI_FILE'] - outputFileName = "testTranscodeVideoNegativeOffset.mov" - offset = -5.5 +# def testTranscodeVideoNegativeOffset(): +# """ +# Transcode one video stream (profile mpeg2) with a negative offset at the beginning of the process. +# """ +# inputFileName = os.environ['AVTRANSCODER_TEST_VIDEO_AVI_FILE'] +# outputFileName = "testTranscodeVideoNegativeOffset.mov" +# offset = -5.5 - ouputFile = av.OutputFile( outputFileName ) - transcoder = av.Transcoder( ouputFile ) +# ouputFile = av.OutputFile( outputFileName ) +# transcoder = av.Transcoder( ouputFile ) - transcoder.addStream( av.InputStreamDesc(inputFileName), "mpeg2", offset ) +# transcoder.addStream( av.InputStreamDesc(inputFileName), "mpeg2", offset ) - progress = av.ConsoleProgress() - transcoder.process( progress ) +# progress = av.ConsoleProgress() +# transcoder.process( progress ) - # get src file - src_inputFile = av.InputFile( inputFileName ) - src_properties = src_inputFile.getProperties() - src_videoStream = src_properties.getVideoProperties()[0] +# # get src file +# src_inputFile = av.InputFile( inputFileName ) +# src_properties = src_inputFile.getProperties() +# src_videoStream = src_properties.getVideoProperties()[0] - # get dst file - dst_inputFile = av.InputFile( outputFileName ) - dst_properties = dst_inputFile.getProperties() - dst_videoStream = dst_properties.getVideoProperties()[0] +# # get dst file +# dst_inputFile = av.InputFile( outputFileName ) +# dst_properties = dst_inputFile.getProperties() +# dst_videoStream = dst_properties.getVideoProperties()[0] - # check output duration - assert_equals( src_videoStream.getDuration() + offset, dst_videoStream.getDuration() ) +# # check output duration +# assert_equals( src_videoStream.getDuration() + offset, dst_videoStream.getDuration() ) -def testRewrapVideoPositiveOffset(): - """ - Rewrap one video stream with offset at the beginning of the process. - """ - inputFileName = os.environ['AVTRANSCODER_TEST_VIDEO_AVI_FILE'] - outputFileName = "testRewrapVideoPositiveOffset.mov" - offset = 10 +# def testRewrapVideoPositiveOffset(): +# """ +# Rewrap one video stream with offset at the beginning of the process. +# """ +# inputFileName = os.environ['AVTRANSCODER_TEST_VIDEO_AVI_FILE'] +# outputFileName = "testRewrapVideoPositiveOffset.mov" +# offset = 10 - ouputFile = av.OutputFile( outputFileName ) - transcoder = av.Transcoder( ouputFile ) +# ouputFile = av.OutputFile( outputFileName ) +# transcoder = av.Transcoder( ouputFile ) - transcoder.addStream( av.InputStreamDesc(inputFileName), "", offset ) +# transcoder.addStream( av.InputStreamDesc(inputFileName), "", offset ) - progress = av.ConsoleProgress() - transcoder.process( progress ) +# progress = av.ConsoleProgress() +# transcoder.process( progress ) - # get src file - src_inputFile = av.InputFile( inputFileName ) - src_properties = src_inputFile.getProperties() - src_videoStream = src_properties.getVideoProperties()[0] +# # get src file +# src_inputFile = av.InputFile( inputFileName ) +# src_properties = src_inputFile.getProperties() +# src_videoStream = src_properties.getVideoProperties()[0] - # get dst file - dst_inputFile = av.InputFile( outputFileName ) - dst_properties = dst_inputFile.getProperties() - dst_videoStream = dst_properties.getVideoProperties()[0] +# # get dst file +# dst_inputFile = av.InputFile( outputFileName ) +# dst_properties = dst_inputFile.getProperties() +# dst_videoStream = dst_properties.getVideoProperties()[0] - # check output duration - assert_equals( src_videoStream.getDuration() + offset, dst_videoStream.getDuration() ) - assert_equals( src_videoStream.getNbFrames() + ( offset * dst_videoStream.getFps() ), dst_videoStream.getNbFrames() ) +# # check output duration +# assert_equals( src_videoStream.getDuration() + offset, dst_videoStream.getDuration() ) +# assert_equals( src_videoStream.getNbFrames() + ( offset * dst_videoStream.getFps() ), dst_videoStream.getNbFrames() ) def testRewrapVideoNegativeOffset(): @@ -261,76 +261,77 @@ def testRewrapVideoNegativeOffset(): assert_equals( src_videoStream.getNbFrames() + ( offset * dst_videoStream.getFps() ), dst_videoStream.getNbFrames() ) -# The output audio stream has not the correct number of samples. -@nottest -def testMultipleOffsetFromSameInputFile(): - """ - Process multiple streams with different offset at the beginning of the process. - """ - inputFileName = os.environ['AVTRANSCODER_TEST_AUDIO_MOV_FILE'] - outputFileName = "testMultipleOffsetFromSameInputFile.mov" - offset_1 = 10 - offset_2 = 3 - - ouputFile = av.OutputFile( outputFileName ) - transcoder = av.Transcoder( ouputFile ) - - transcoder.addStream( av.InputStreamDesc(inputFileName), "", offset_1 ) - transcoder.addStream( av.InputStreamDesc(inputFileName, 1), "", offset_2 ) - - progress = av.ConsoleProgress() - transcoder.process( progress ) - - # get src file - src_inputFile = av.InputFile( inputFileName ) - src_properties = src_inputFile.getProperties() - src_videoStream = src_properties.getVideoProperties()[0] - src_audioStream = src_properties.getAudioProperties()[0] - - # get dst file - dst_inputFile = av.InputFile( outputFileName ) - dst_properties = dst_inputFile.getProperties() - dst_videoStream = dst_properties.getVideoProperties()[0] - dst_audioStream = dst_properties.getAudioProperties()[0] - - # check output duration - assert_equals( src_videoStream.getDuration() + offset_1, dst_videoStream.getDuration() ) - assert_equals( src_videoStream.getNbFrames() + ( offset_1 * dst_videoStream.getFps() ), dst_videoStream.getNbFrames() ) - assert_equals( src_audioStream.getDuration() + offset_1, dst_audioStream.getDuration() ) - assert_equals( src_audioStream.getNbSamples() + ( offset_1 * dst_audioStream.getSampleRate() * dst_audioStream.getNbChannels() ), dst_audioStream.getNbSamples() ) - - -def testMultipleOffsetFromSameStream(): - """ - Process same stream several times with different offset at the beginning of the process. - """ - inputFileName = os.environ['AVTRANSCODER_TEST_AUDIO_MOV_FILE'] - outputFileName = "testMultipleOffsetFromSameStream.mov" - offset_1 = 2 - offset_2 = -2 - - ouputFile = av.OutputFile( outputFileName ) - transcoder = av.Transcoder( ouputFile ) - - transcoder.addStream( av.InputStreamDesc(inputFileName), "", offset_1 ) - transcoder.addStream( av.InputStreamDesc(inputFileName), "", offset_2 ) - - progress = av.ConsoleProgress() - transcoder.process( progress ) - - # get src file - src_inputFile = av.InputFile( inputFileName ) - src_properties = src_inputFile.getProperties() - src_videoStream = src_properties.getVideoProperties()[0] - - # get dst file - dst_inputFile = av.InputFile( outputFileName ) - dst_properties = dst_inputFile.getProperties() - dst_videoStream_1 = dst_properties.getVideoProperties()[0] - dst_videoStream_2 = dst_properties.getVideoProperties()[1] - - # check output duration - assert_equals( src_videoStream.getDuration() + offset_1, dst_videoStream_1.getDuration() ) - assert_equals( src_videoStream.getDuration() + offset_1, dst_videoStream_2.getDuration() ) - assert_equals( src_videoStream.getNbFrames() + ( offset_1 * dst_videoStream_1.getFps() ), dst_videoStream_1.getNbFrames() ) - assert_equals( src_videoStream.getNbFrames() + ( offset_1 * dst_videoStream_2.getFps() ), dst_videoStream_2.getNbFrames() ) +# # The output audio stream has not the correct number of samples. +# @nottest +# def testMultipleOffsetFromSameInputFile(): +# """ +# Process multiple streams with different offset at the beginning of the process. +# """ +# inputFileName = os.environ['AVTRANSCODER_TEST_AUDIO_MOV_FILE'] +# outputFileName = "testMultipleOffsetFromSameInputFile.mov" +# offset_1 = 10 +# offset_2 = 3 + +# ouputFile = av.OutputFile( outputFileName ) +# transcoder = av.Transcoder( ouputFile ) + +# transcoder.addStream( av.InputStreamDesc(inputFileName), "", offset_1 ) +# transcoder.addStream( av.InputStreamDesc(inputFileName, 1), "", offset_2 ) + +# progress = av.ConsoleProgress() +# transcoder.process( progress ) + +# # get src file +# src_inputFile = av.InputFile( inputFileName ) +# src_properties = src_inputFile.getProperties() +# src_videoStream = src_properties.getVideoProperties()[0] +# src_audioStream = src_properties.getAudioProperties()[0] + +# # get dst file +# dst_inputFile = av.InputFile( outputFileName ) +# dst_properties = dst_inputFile.getProperties() +# dst_videoStream = dst_properties.getVideoProperties()[0] +# dst_audioStream = dst_properties.getAudioProperties()[0] + +# # check output duration +# assert_equals( src_videoStream.getDuration() + offset_1, dst_videoStream.getDuration() ) +# assert_equals( src_videoStream.getNbFrames() + ( offset_1 * dst_videoStream.getFps() ), dst_videoStream.getNbFrames() ) +# assert_equals( src_audioStream.getDuration() + offset_1, dst_audioStream.getDuration() ) +# assert_equals( src_audioStream.getNbSamples() + ( offset_1 * dst_audioStream.getSampleRate() * dst_audioStream.getNbChannels() ), dst_audioStream.getNbSamples() ) + +# # Skip since to long to process. +# @nottest +# def testMultipleOffsetFromSameStream(): +# """ +# Process same stream several times with different offset at the beginning of the process. +# """ +# inputFileName = os.environ['AVTRANSCODER_TEST_AUDIO_MOV_FILE'] +# outputFileName = "testMultipleOffsetFromSameStream.mov" +# offset_1 = 2 +# offset_2 = -2 + +# ouputFile = av.OutputFile( outputFileName ) +# transcoder = av.Transcoder( ouputFile ) + +# transcoder.addStream( av.InputStreamDesc(inputFileName), "", offset_1 ) +# transcoder.addStream( av.InputStreamDesc(inputFileName), "", offset_2 ) + +# progress = av.ConsoleProgress() +# transcoder.process( progress ) + +# # get src file +# src_inputFile = av.InputFile( inputFileName ) +# src_properties = src_inputFile.getProperties() +# src_videoStream = src_properties.getVideoProperties()[0] + +# # get dst file +# dst_inputFile = av.InputFile( outputFileName ) +# dst_properties = dst_inputFile.getProperties() +# dst_videoStream_1 = dst_properties.getVideoProperties()[0] +# dst_videoStream_2 = dst_properties.getVideoProperties()[1] + +# # check output duration +# assert_equals( src_videoStream.getDuration() + offset_1, dst_videoStream_1.getDuration() ) +# assert_equals( src_videoStream.getDuration() + offset_1, dst_videoStream_2.getDuration() ) +# assert_equals( src_videoStream.getNbFrames() + ( offset_1 * dst_videoStream_1.getFps() ), dst_videoStream_1.getNbFrames() ) +# assert_equals( src_videoStream.getNbFrames() + ( offset_1 * dst_videoStream_2.getFps() ), dst_videoStream_2.getNbFrames() ) diff --git a/test/pyTest/testOutputFile.py b/test/pyTest/testOutputFile.py index b1454ea8..7945246a 100644 --- a/test/pyTest/testOutputFile.py +++ b/test/pyTest/testOutputFile.py @@ -61,7 +61,7 @@ def testCreateOutputFileWithoutExtensionWithMimeType(): Create an OutputFile with a filename without extension. Indicate the Mime Type. """ - mimeType = "application/mp4" + mimeType = "video/mp4" outputFileName = "testCreateOutputFileWithoutExtensionWithMimeType" ouputFile = av.OutputFile( outputFileName, "", mimeType ) diff --git a/test/pyTest/testProcessStat.py b/test/pyTest/testProcessStat.py index d8028d45..9a792497 100644 --- a/test/pyTest/testProcessStat.py +++ b/test/pyTest/testProcessStat.py @@ -40,7 +40,7 @@ def testProcessWithStatistics(): # check process stat returned videoStat = processStat.getVideoStat(0) - assert_equals(videoStat.getDuration(), src_videoStream.getDuration()) + # assert_equals(videoStat.getDuration(), src_videoStream.getDuration()) assert_equals(videoStat.getNbFrames(), int(src_videoStream.getDuration() * src_videoStream.getFps())) assert_not_equals(videoStat.getQuality(), 0) assert_not_equals(videoStat.getPSNR(), 0) diff --git a/test/pyTest/testProfiles.py b/test/pyTest/testProfiles.py new file mode 100644 index 00000000..60216823 --- /dev/null +++ b/test/pyTest/testProfiles.py @@ -0,0 +1,59 @@ +import os + +# Check if environment is setup to run the tests +if os.environ.get('AVTRANSCODER_TEST_AUDIO_WAVE_FILE') is None: + from nose.plugins.skip import SkipTest + raise SkipTest("Need to define environment variables " + "AVTRANSCODER_TEST_AUDIO_WAVE_FILE") + +from nose.tools import * + +from pyAvTranscoder import avtranscoder as av + +def testLoadingAllDefaultProfiles(): + """ + Load all default profiles and check them. + """ + profileLoader = av.ProfileLoader() + + formatProfiles = profileLoader.getFormatProfiles() + assert_equals(4, len(formatProfiles)) + for formatProfile in formatProfiles: + assert_equals("avProfileTypeFormat", formatProfile["avProfileType"]) + + videoProfiles = profileLoader.getVideoProfiles() + assert_equals(14, len(videoProfiles)) + for videoProfile in videoProfiles: + assert_equals("avProfileTypeVideo", videoProfile["avProfileType"]) + + audioProfiles = profileLoader.getAudioProfiles() + assert_equals(6, len(audioProfiles)) + for audioProfile in audioProfiles: + assert_equals("avProfileTypeAudio", audioProfile["avProfileType"]) + +def testAddingProfile(): + """ + Add a profile and get it back. + """ + profileLoader = av.ProfileLoader(False) + + aviProfile = av.ProfileMap(); + aviProfile["avProfileName"] = "avi" + aviProfile["avProfileLongName"] = "AVI (Audio Video Interleaved)" + aviProfile["avProfileType"] = "avProfileTypeFormat" + aviProfile["format"] = "avi" + + profileLoader.addProfile(aviProfile) + extractedProfile = profileLoader.getProfile("avi") + assert_equals(aviProfile["avProfileName"], extractedProfile["avProfileName"]) + assert_equals(aviProfile["avProfileLongName"], extractedProfile["avProfileLongName"]) + assert_equals(aviProfile["avProfileType"], extractedProfile["avProfileType"]) + assert_equals(aviProfile["format"], extractedProfile["format"]) + +@raises(RuntimeError) +def testGettingNotLoadedProfile(): + """ + Try to get a profile that is not loaded. + """ + profileLoader = av.ProfileLoader(False) + profileLoader.getProfile("avi") diff --git a/test/pyTest/testProperties.py b/test/pyTest/testProperties.py index 9fba25c7..383ee6d5 100644 --- a/test/pyTest/testProperties.py +++ b/test/pyTest/testProperties.py @@ -120,7 +120,7 @@ def testCheckRawVideoProperties(): assert_equals(properties.getNbVideoStreams(), 1) assert_equals(properties.getDuration(), 0) # file duration is unknown assert_equals(properties.getBitRate(), 0) # file bitrate is unknown - assert_equals(properties.getFileSize(), 256293L) + assert_equals(properties.getFileSize(), 256293) # Check video stream when analyse the header videoStream = properties.getVideoProperties()[0] @@ -133,7 +133,7 @@ def testCheckRawVideoProperties(): videoStream = properties.getVideoProperties()[0] assert_equals(videoStream.getNbFrames(), 200) assert_equals(videoStream.getDuration(), 8) - assert_equals(videoStream.getBitRate(), 177200L) + assert_equals(videoStream.getBitRate(), 177200) def testCheckAudioProperties(): diff --git a/test/pyTest/testVideoReader.py b/test/pyTest/testVideoReader.py index 597738f9..12677799 100644 --- a/test/pyTest/testVideoReader.py +++ b/test/pyTest/testVideoReader.py @@ -19,7 +19,7 @@ def testVideoReader(): reader = av.VideoReader(av.InputStreamDesc(inputFileName)) # read all frames and check their size - for i in xrange(0, reader.getSourceVideoProperties().getNbFrames()): + for i in range(0, reader.getSourceVideoProperties().getNbFrames()): frame = reader.readNextFrame() bytesPerPixel = reader.getOutputBitDepth() / 8 assert_equals( frame.getDataSize(), reader.getOutputWidth() * reader.getOutputHeight() * bytesPerPixel ) @@ -37,7 +37,7 @@ def testVideoReaderWithGenerator(): reader = av.VideoReader(av.InputStreamDesc(inputFileName)) # read all frames and check their size - for i in xrange(0, reader.getSourceVideoProperties().getNbFrames()): + for i in range(0, reader.getSourceVideoProperties().getNbFrames()): frame = reader.readNextFrame() bytesPerPixel = reader.getOutputBitDepth() / 8 assert_equals( frame.getDataSize(), reader.getOutputWidth() * reader.getOutputHeight() * bytesPerPixel ) @@ -47,7 +47,7 @@ def testVideoReaderWithGenerator(): # generate 10 frames of black reader.continueWithGenerator() - for i in xrange(0, 9): + for i in range(0, 9): frame = reader.readNextFrame() bytesPerPixel = reader.getOutputBitDepth() / 8 assert_equals( frame.getDataSize(), reader.getOutputWidth() * reader.getOutputHeight() * bytesPerPixel ) From 8eee769c00a625cbfe6aa6ba9f2ebbac2decb860 Mon Sep 17 00:00:00 2001 From: Marc-Antoine Arnaud Date: Wed, 20 Nov 2019 09:56:49 +0100 Subject: [PATCH 19/74] add API to use an external encoder --- app/CMakeLists.txt | 1 + app/customEncoder/CMakeLists.txt | 24 ++ app/customEncoder/customEncoder.cpp | 208 ++++++++++++++++++ src/AvTranscoder/codec/ICodec.hpp | 2 +- src/AvTranscoder/file/IOutputFile.hpp | 9 + src/AvTranscoder/file/OutputFile.cpp | 19 ++ src/AvTranscoder/file/OutputFile.hpp | 1 + .../transcoder/StreamTranscoder.cpp | 101 ++++++++- .../transcoder/StreamTranscoder.hpp | 14 +- src/AvTranscoder/transcoder/Transcoder.cpp | 57 +++++ src/AvTranscoder/transcoder/Transcoder.hpp | 3 + 11 files changed, 436 insertions(+), 3 deletions(-) create mode 100644 app/customEncoder/CMakeLists.txt create mode 100644 app/customEncoder/customEncoder.cpp diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt index 83ed81df..7563d02c 100644 --- a/app/CMakeLists.txt +++ b/app/CMakeLists.txt @@ -3,6 +3,7 @@ add_subdirectory(avInfo) add_subdirectory(avMeta) add_subdirectory(avPlayer) add_subdirectory(avProcessor) +add_subdirectory(customEncoder) # Python apps add_subdirectory(pyProcessor) diff --git a/app/customEncoder/CMakeLists.txt b/app/customEncoder/CMakeLists.txt new file mode 100644 index 00000000..2c7e55d2 --- /dev/null +++ b/app/customEncoder/CMakeLists.txt @@ -0,0 +1,24 @@ +### cpp/customEncoder + +# Load custom cmake utilities +set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake) +include(AvTranscoderMacros) + +# Build app +add_executable(custom-encoder customEncoder.cpp) +set_target_properties(custom-encoder PROPERTIES VERSION ${AVTRANSCODER_VERSION}) +target_link_libraries(custom-encoder avtranscoder-shared) + +# Install app +if(WIN32) + set(BINARY_FILES "${CMAKE_CURRENT_BINARY_DIR}/custom-encoder.exe") +else() + set(BINARY_FILES "${CMAKE_CURRENT_BINARY_DIR}/custom-encoder" "${CMAKE_CURRENT_BINARY_DIR}/custom-encoder-${AVTRANSCODER_VERSION}") +endif() + +install( + FILES ${BINARY_FILES} + PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ GROUP_EXECUTE GROUP_READ WORLD_READ WORLD_EXECUTE + DESTINATION "bin/" + OPTIONAL +) diff --git a/app/customEncoder/customEncoder.cpp b/app/customEncoder/customEncoder.cpp new file mode 100644 index 00000000..fe13ae89 --- /dev/null +++ b/app/customEncoder/customEncoder.cpp @@ -0,0 +1,208 @@ +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +void parseConfigFile(const std::string& configFilename, avtranscoder::Transcoder& transcoder) +{ + std::ifstream configFile(configFilename.c_str(), std::ifstream::in); + + std::string line; + while(std::getline(configFile, line)) + { + std::istringstream is_line(line); + std::string filename; + if(std::getline(is_line, filename, '=')) + { + std::string streamId; + if(std::getline(is_line, streamId, ':')) + { + std::string transcodeProfile; + std::getline(is_line, transcodeProfile); + + std::stringstream ss(streamId); + size_t streamIndex = 0; + char separator = 'x'; + std::vector channelIndexArray; + ss >> streamIndex; + ss >> separator; + if(separator == '.') + { + int subStreamIndex = -1; + ss >> subStreamIndex; + channelIndexArray.push_back(subStreamIndex); + } + + // generated stream + if(!filename.length()) + transcoder.addGenerateStream(transcodeProfile); + else + { + avtranscoder::InputStreamDesc inputDesc(filename, streamIndex, channelIndexArray); + transcoder.addStream(inputDesc, transcodeProfile); + } + } + } + } + + configFile.close(); +} + + + +class AvExport CustomCodec + : public avtranscoder::ICodec +{ +public: + CustomCodec() + : avtranscoder::ICodec(avtranscoder::eCodecTypeEncoder, AV_CODEC_ID_PCM_S24LE) + { + } + + void openCodec(){} + void closeCodec(){} + + std::string getCodecName() const { return "Custom Encoder"; }; + AVCodecID getCodecId() const { return AV_CODEC_ID_PCM_S24LE; } + avtranscoder::ECodecType getCodecType() const { return avtranscoder::eCodecTypeEncoder; } + int getLatency() const { return 0; } + + avtranscoder::OptionArray getOptions() { + std::vector options; + return options; + } +}; + + +class AvExport CustomEncoder + : public avtranscoder::IEncoder +{ +public: + CustomEncoder() + : _codec(CustomCodec()) + {} + /** + * @brief Setup the encoder + * @param profile: set encoder parameters from the given profile + * @note Open the encoder. + */ + void setupEncoder(const avtranscoder::ProfileLoader::Profile& profile = avtranscoder::ProfileLoader::Profile()) { + return; + }; + + /** + * @brief Encode a new frame, and get coded frame + * @param sourceFrame: frame that needs to be encoded + * @param codedFrame: output encoded coded data (first frames can be delayed) + * @return status of encoding + * @throw runtime_error if the encoded process failed. + */ + bool encodeFrame(const avtranscoder::IFrame& sourceFrame, avtranscoder::CodedData& codedFrame) { + codedFrame.assign(5760, 0); + return true; + }; + + /** + * @brief Get the frames remaining into the encoder + * @param codedFrame: output encoded data + * @return status of encoding + * @throw runtime_error if the encoded process failed. + */ + bool encodeFrame(avtranscoder::CodedData& codedFrame) { + return false; + }; + + /** + * @brief Get codec used for encoding. + * @return a reference to the codec + */ + avtranscoder::ICodec& getCodec() { + return _codec; + }; + +private: + CustomCodec _codec; +}; + + +int main(int argc, char** argv) +{ + std::string help; + help += "Usage\n"; + help += "\tavprocessor INPUT_FILE_NAME OUTPUT_FILE_NAME [--verbose] [--logFile] [--help]\n"; + help += "Command line options\n"; + help += "\t--verbose: set log level to AV_LOG_DEBUG\n"; + help += "\t--logFile: put log in 'avtranscoder.log' file\n"; + help += "\t--help: display this help\n"; + + // Preload FFmpeg context + avtranscoder::preloadCodecsAndFormats(); + avtranscoder::Logger::setLogLevel(AV_LOG_QUIET); + + // List command line arguments + std::vector arguments; + for(int argument = 1; argument < argc; ++argument) + { + arguments.push_back(argv[argument]); + } + for(size_t argument = 0; argument < arguments.size(); ++argument) + { + if(arguments.at(argument) == "--help") + { + std::cout << help << std::endl; + return 0; + } + else if(arguments.at(argument) == "--verbose") + { + avtranscoder::Logger::setLogLevel(AV_LOG_DEBUG); + } + else if(arguments.at(argument) == "--logFile") + { + avtranscoder::Logger::logInFile(); + } + } + + // Check required arguments + if(argc < 3) + { + std::cout << "avprocessor can rewrap or transcode inputs to create an output media file." << std::endl; + std::cout << "Use option --help to display help" << std::endl; + return (-1); + } + + try + { + std::string output_format = "s24le"; + avtranscoder::OutputFile outputFile(argv[2], output_format); + + avtranscoder::Transcoder transcoder(outputFile); + transcoder.setProcessMethod(avtranscoder::eProcessMethodBasedOnStream); + + CustomEncoder* customEncoder = new CustomEncoder; + avtranscoder::InputStreamDesc inputDescLeft(argv[1], 1, 0); + avtranscoder::InputStreamDesc inputDescRight(argv[1], 2, 0); + + std::vector inputDescriptors; + inputDescriptors.push_back(avtranscoder::InputStreamDesc(argv[1], 1, 0)); + inputDescriptors.push_back(avtranscoder::InputStreamDesc(argv[1], 2, 0)); + + transcoder.addStream(inputDescriptors, customEncoder); + + avtranscoder::ConsoleProgress progress; + transcoder.process(progress); + } + catch(std::exception& e) + { + std::cerr << "ERROR: during process, an error occured: " << e.what() << std::endl; + } + catch(...) + { + std::cerr << "ERROR: during process, an unknown error occured" << std::endl; + } +} diff --git a/src/AvTranscoder/codec/ICodec.hpp b/src/AvTranscoder/codec/ICodec.hpp index de3203dd..f0e3207b 100644 --- a/src/AvTranscoder/codec/ICodec.hpp +++ b/src/AvTranscoder/codec/ICodec.hpp @@ -25,10 +25,10 @@ enum ECodecType class AvExport ICodec { private: - ICodec(const ICodec& iCodec); ICodec& operator=(const ICodec& iCodec); public: + ICodec(const ICodec& iCodec); ICodec(const ECodecType type, const std::string& codecName); ICodec(const ECodecType type, const AVCodecID codecId); ICodec(const ECodecType type, AVCodecContext& avCodecContext); diff --git a/src/AvTranscoder/file/IOutputFile.hpp b/src/AvTranscoder/file/IOutputFile.hpp index 4d9dc233..c070cdb7 100644 --- a/src/AvTranscoder/file/IOutputFile.hpp +++ b/src/AvTranscoder/file/IOutputFile.hpp @@ -51,6 +51,15 @@ class AvExport IOutputFile throw std::logic_error("function is not implemented"); } + /** + * @brief Add a custom output stream + * @param iCodecDesc description of output codec + **/ + virtual IOutputStream& addCustomStream(const ICodec& iCodecDesc) + { + throw std::logic_error("function is not implemented"); + } + /** * @brief Write the header of file (if necessary) **/ diff --git a/src/AvTranscoder/file/OutputFile.cpp b/src/AvTranscoder/file/OutputFile.cpp index 5ff45435..77470644 100644 --- a/src/AvTranscoder/file/OutputFile.cpp +++ b/src/AvTranscoder/file/OutputFile.cpp @@ -88,6 +88,25 @@ IOutputStream& OutputFile::addAudioStream(const AudioCodec& audioDesc) return *outputStream; } +IOutputStream& OutputFile::addCustomStream(const ICodec& iCodecDesc) +{ + AVStream& stream = _formatContext.addAVStream(iCodecDesc.getAVCodec()); + + stream.codec->sample_rate = 48000; + stream.codec->channels = 1; + stream.codec->channel_layout = AV_CH_LAYOUT_MONO; + stream.codec->sample_fmt = AV_SAMPLE_FMT_S32; + stream.codec->frame_size = 1920; + + // need to set the time_base on the AVCodecContext of the AVStream + av_reduce(&stream.codec->time_base.num, &stream.codec->time_base.den, 1, 1, INT_MAX); + + OutputStream* outputStream = new OutputStream(*this, _formatContext.getNbStreams() - 1); + _outputStreams.push_back(outputStream); + + return *outputStream; +} + IOutputStream& OutputFile::addDataStream(const DataCodec& dataDesc) { _formatContext.addAVStream(dataDesc.getAVCodec()); diff --git a/src/AvTranscoder/file/OutputFile.hpp b/src/AvTranscoder/file/OutputFile.hpp index 4a18e4c0..c8fefc3b 100644 --- a/src/AvTranscoder/file/OutputFile.hpp +++ b/src/AvTranscoder/file/OutputFile.hpp @@ -37,6 +37,7 @@ class AvExport OutputFile : public IOutputFile IOutputStream& addVideoStream(const VideoCodec& videoDesc); IOutputStream& addAudioStream(const AudioCodec& audioDesc); IOutputStream& addDataStream(const DataCodec& dataDesc); + IOutputStream& addCustomStream(const ICodec& iCodecDesc); /** * @brief Open ressource, write header, and setup specific wrapping options given when call setupWrapping. diff --git a/src/AvTranscoder/transcoder/StreamTranscoder.cpp b/src/AvTranscoder/transcoder/StreamTranscoder.cpp index 78253644..77263dca 100644 --- a/src/AvTranscoder/transcoder/StreamTranscoder.cpp +++ b/src/AvTranscoder/transcoder/StreamTranscoder.cpp @@ -246,6 +246,85 @@ StreamTranscoder::StreamTranscoder(const std::vector& inputStre setOffset(offset); } +StreamTranscoder::StreamTranscoder(const std::vector& inputStreamsDesc, std::vector& inputStreams, IOutputFile& outputFile, + IEncoder* encoder, const float offset) + : _inputStreamDesc(inputStreamsDesc) + , _inputStreams(inputStreams) + , _outputStream(NULL) + , _decodedData() + , _filteredData(NULL) + , _transformedData(NULL) + , _inputDecoders() + , _generators() + , _currentDecoder(NULL) + , _outputEncoder(encoder) + , _transform(NULL) + , _filterGraph(NULL) + , _firstInputStreamIndex(std::numeric_limits::max()) + , _offset(offset) + , _needToSwitchToGenerator(false) +{ + // add as many decoders as input streams + size_t nbOutputChannels = 0; + for(size_t index = 0; index < inputStreams.size(); ++index) + { + if(_inputStreams.at(index) != NULL) + { + LOG_INFO("add decoder for input stream " << index); + addDecoder(_inputStreamDesc.at(index), *_inputStreams.at(index)); + nbOutputChannels += _inputStreamDesc.at(index)._channelIndexArray.size(); + if(_firstInputStreamIndex == std::numeric_limits::max()) + _firstInputStreamIndex = index; + } + } + + IInputStream& inputStream = *_inputStreams.at(_firstInputStreamIndex); + const InputStreamDesc& inputStreamDesc = inputStreamsDesc.at(_firstInputStreamIndex); + + // create a transcode case + switch(inputStream.getProperties().getStreamType()) + { + case AVMEDIA_TYPE_AUDIO: + { + + // filter + _filterGraph = new FilterGraph(inputStream.getAudioCodec()); + // merge two or more audio streams into a single multi-channel stream. + if(inputStreams.size() > 1) + { + std::stringstream mergeOptions; + mergeOptions << "inputs=" << inputStreams.size(); + _filterGraph->addFilter("amerge", mergeOptions.str()); + } + + AudioCodec audioCodec = AudioCodec(_outputEncoder->getCodec().getCodecType(), _outputEncoder->getCodec().getCodecId()); + AudioFrameDesc audioFrameDesc = AudioFrameDesc(48000, 1, "s32"); + audioCodec.setAudioParameters(audioFrameDesc); + + // output stream + _outputStream = &outputFile.addAudioStream(audioCodec); + + // buffers to process + AudioFrameDesc inputFrameDesc(inputStream.getAudioCodec().getAudioFrameDesc()); + if(inputStreamDesc.demultiplexing()) + inputFrameDesc._nbChannels = nbOutputChannels; + + _filteredData = new AudioFrame(inputFrameDesc); + _transformedData = new AudioFrame(audioFrameDesc); + + // transform + _transform = new AudioTransform(); + break; + } + default: + { + throw std::runtime_error("unupported stream type"); + break; + } + } + setOffset(offset); +} + void StreamTranscoder::addDecoder(const InputStreamDesc& inputStreamDesc, IInputStream& inputStream) { // create a transcode case @@ -429,11 +508,31 @@ StreamTranscoder::StreamTranscoder(IOutputFile& outputFile, const ProfileLoader: } } +StreamTranscoder::StreamTranscoder(IOutputFile& outputFile, IEncoder* encoder) + : _inputStreamDesc() + , _inputStreams() + , _outputStream(NULL) + , _decodedData() + , _filteredData(NULL) + , _transformedData(NULL) + , _inputDecoders() + , _generators() + , _currentDecoder(NULL) + , _outputEncoder(encoder) + , _transform(NULL) + , _filterGraph(NULL) + , _firstInputStreamIndex(0) + , _offset(0) + , _needToSwitchToGenerator(false) +{ + _outputStream = &outputFile.addCustomStream(encoder->getCodec()); +} + StreamTranscoder::~StreamTranscoder() { for(std::vector::iterator it = _decodedData.begin(); it != _decodedData.end(); ++it) { - delete(*it); + delete(*it); } if(_filteredData != NULL && _filteredData->isDataAllocated()) diff --git a/src/AvTranscoder/transcoder/StreamTranscoder.hpp b/src/AvTranscoder/transcoder/StreamTranscoder.hpp index c72db0ea..129ef7e2 100644 --- a/src/AvTranscoder/transcoder/StreamTranscoder.hpp +++ b/src/AvTranscoder/transcoder/StreamTranscoder.hpp @@ -40,10 +40,22 @@ class AvExport StreamTranscoder const ProfileLoader::Profile& profile, const float offset = 0); /** - * @brief Encode a generated stream + * @brief Transcode the given streams. + * @note The data are wrapped to one output stream. + **/ + StreamTranscoder(const std::vector& inputStreamsDesc, std::vector& inputStreams, IOutputFile& outputFile, + IEncoder* encoder, const float offset = 0); + + /** + * @brief Create a stream transcoder based on a profile. **/ StreamTranscoder(IOutputFile& outputFile, const ProfileLoader::Profile& profile); + /** + * @brief Create a stream transcoder with a custom Encoder. + **/ + StreamTranscoder(IOutputFile& outputFile, IEncoder* encoder); + ~StreamTranscoder(); /** diff --git a/src/AvTranscoder/transcoder/Transcoder.cpp b/src/AvTranscoder/transcoder/Transcoder.cpp index c101b8e0..1bedf43e 100644 --- a/src/AvTranscoder/transcoder/Transcoder.cpp +++ b/src/AvTranscoder/transcoder/Transcoder.cpp @@ -30,6 +30,7 @@ Transcoder::~Transcoder() { delete(*it); } + for(std::vector::iterator it = _inputFiles.begin(); it != _inputFiles.end(); ++it) { delete(*it); @@ -73,6 +74,17 @@ void Transcoder::addStream(const InputStreamDesc& inputStreamDesc, const Profile addStream(inputStreamDescArray, profile, offset); } +void Transcoder::addStream(const InputStreamDesc& inputStreamDesc, IEncoder* encoder) +{ + // Check filename + if(!inputStreamDesc._filename.length()) + throw std::runtime_error("Can't transcode a stream without a filename indicated."); + + std::vector inputStreamDescArray; + inputStreamDescArray.push_back(inputStreamDesc); + addStream(inputStreamDescArray, encoder); +} + void Transcoder::addStream(const std::vector& inputStreamDescArray, const std::string& profileName, const float offset) { // Check number of inputs @@ -105,6 +117,15 @@ void Transcoder::addStream(const std::vector& inputStreamDescAr addTranscodeStream(inputStreamDescArray, profile, offset); } +void Transcoder::addStream(const std::vector& inputStreamDescArray, IEncoder* encoder) +{ + // Check number of inputs + if(inputStreamDescArray.empty()) + throw std::runtime_error("Need a description of at least one input stream to start the process."); + + addTranscodeStream(inputStreamDescArray, encoder); +} + void Transcoder::addGenerateStream(const std::string& encodingProfileName) { const ProfileLoader::Profile& encodingProfile = _profileLoader.getProfile(encodingProfileName); @@ -283,6 +304,42 @@ void Transcoder::addTranscodeStream(const std::vector& inputStr _streamTranscoders.push_back(_streamTranscodersAllocated.back()); } +void Transcoder::addTranscodeStream(const std::vector& inputStreamDescArray, IEncoder* encoder, const float offset) +{ + std::stringstream sources; + for(size_t index = 0; index < inputStreamDescArray.size(); ++index) + sources << inputStreamDescArray.at(index); + LOG_INFO("Add transcode stream from the following inputs:" << std::endl << sources.str() + << "with encoder=" << encoder->getCodec().getCodecName() << std::endl) + + // Create all streams from the given inputs + std::vector inputStreams; + AVMediaType commonStreamType = AVMEDIA_TYPE_UNKNOWN; + for(std::vector::const_iterator it = inputStreamDescArray.begin(); it != inputStreamDescArray.end(); ++it) + { + if(it->_filename.empty()) + { + inputStreams.push_back(NULL); + continue; + } + + InputFile* referenceFile = addInputFile(it->_filename, it->_streamIndex, offset); + inputStreams.push_back(&referenceFile->getStream(it->_streamIndex)); + + // Check stream type + const AVMediaType currentStreamType = referenceFile->getProperties().getStreamPropertiesWithIndex(it->_streamIndex).getStreamType(); + if(commonStreamType == AVMEDIA_TYPE_UNKNOWN) + commonStreamType = currentStreamType; + else if(currentStreamType != commonStreamType) + throw std::runtime_error("All the given inputs should be of the same type (video, audio...)."); + + } + + _streamTranscodersAllocated.push_back( + new StreamTranscoder(inputStreamDescArray, inputStreams, _outputFile, encoder, offset)); + _streamTranscoders.push_back(_streamTranscodersAllocated.back()); +} + InputFile* Transcoder::addInputFile(const std::string& filename, const int streamIndex, const float offset) { InputFile* referenceFile = NULL; diff --git a/src/AvTranscoder/transcoder/Transcoder.hpp b/src/AvTranscoder/transcoder/Transcoder.hpp index 986ce45c..bc03b3dc 100644 --- a/src/AvTranscoder/transcoder/Transcoder.hpp +++ b/src/AvTranscoder/transcoder/Transcoder.hpp @@ -63,6 +63,7 @@ class AvExport Transcoder // If offset is negative, the transcoder will seek in the stream and start process at this specific time. void addStream(const InputStreamDesc& inputStreamDesc, const std::string& profileName = "", const float offset = 0); void addStream(const InputStreamDesc& inputStreamDesc, const ProfileLoader::Profile& profile, const float offset = 0); + void addStream(const InputStreamDesc& inputStreamDesc, IEncoder* encoder); //@} //@{ @@ -71,6 +72,7 @@ class AvExport Transcoder // @param profile: if empty, get the profile from the inputs. void addStream(const std::vector& inputStreamDescArray, const std::string& profileName = "", float offset = 0); void addStream(const std::vector& inputStreamDescArray, const ProfileLoader::Profile& profile, const float offset = 0); + void addStream(const std::vector& inputStreamDescArray, IEncoder* encoder); //@} //@{ @@ -139,6 +141,7 @@ class AvExport Transcoder void addRewrapStream(const InputStreamDesc& inputStreamDesc, const float offset); void addTranscodeStream(const std::vector& inputStreamDescArray, const ProfileLoader::Profile& profile, const float offset = 0); + void addTranscodeStream(const std::vector& inputStreamDescArray, IEncoder* encoder, const float offset = 0); /** * @note If streamIndex is negative, activate all streams of the file. From aa434a830d5afa0ff56e695ffeb721bbc420fda0 Mon Sep 17 00:00:00 2001 From: Marc-Antoine Arnaud Date: Thu, 21 Nov 2019 16:07:24 +0100 Subject: [PATCH 20/74] pass copy to private --- src/AvTranscoder/codec/ICodec.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/AvTranscoder/codec/ICodec.hpp b/src/AvTranscoder/codec/ICodec.hpp index f0e3207b..de3203dd 100644 --- a/src/AvTranscoder/codec/ICodec.hpp +++ b/src/AvTranscoder/codec/ICodec.hpp @@ -25,10 +25,10 @@ enum ECodecType class AvExport ICodec { private: + ICodec(const ICodec& iCodec); ICodec& operator=(const ICodec& iCodec); public: - ICodec(const ICodec& iCodec); ICodec(const ECodecType type, const std::string& codecName); ICodec(const ECodecType type, const AVCodecID codecId); ICodec(const ECodecType type, AVCodecContext& avCodecContext); From 5e16a853789be34a412679be3d0a30c5a5c646ae Mon Sep 17 00:00:00 2001 From: Marc-Antoine Arnaud Date: Thu, 21 Nov 2019 16:50:32 +0100 Subject: [PATCH 21/74] remove copy of contructors --- app/customEncoder/customEncoder.cpp | 2 +- src/AvTranscoder/transcoder/StreamTranscoder.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/customEncoder/customEncoder.cpp b/app/customEncoder/customEncoder.cpp index fe13ae89..0de6ce2d 100644 --- a/app/customEncoder/customEncoder.cpp +++ b/app/customEncoder/customEncoder.cpp @@ -85,7 +85,7 @@ class AvExport CustomEncoder { public: CustomEncoder() - : _codec(CustomCodec()) + : _codec() {} /** * @brief Setup the encoder diff --git a/src/AvTranscoder/transcoder/StreamTranscoder.cpp b/src/AvTranscoder/transcoder/StreamTranscoder.cpp index 77263dca..8abc4594 100644 --- a/src/AvTranscoder/transcoder/StreamTranscoder.cpp +++ b/src/AvTranscoder/transcoder/StreamTranscoder.cpp @@ -297,8 +297,8 @@ StreamTranscoder::StreamTranscoder(const std::vector& inputStre _filterGraph->addFilter("amerge", mergeOptions.str()); } - AudioCodec audioCodec = AudioCodec(_outputEncoder->getCodec().getCodecType(), _outputEncoder->getCodec().getCodecId()); - AudioFrameDesc audioFrameDesc = AudioFrameDesc(48000, 1, "s32"); + AudioCodec audioCodec(_outputEncoder->getCodec().getCodecType(), _outputEncoder->getCodec().getCodecId()); + AudioFrameDesc audioFrameDesc(48000, 1, "s32"); audioCodec.setAudioParameters(audioFrameDesc); // output stream From d4241d00febe59efa52c49358afcd0ecb4c66c7f Mon Sep 17 00:00:00 2001 From: Valentin NOEL Date: Fri, 3 Jan 2020 17:55:17 +0100 Subject: [PATCH 22/74] StreamTranscoder: fix output AudioFrameDesc when an encoder is specified --- .../transcoder/StreamTranscoder.cpp | 20 +++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/src/AvTranscoder/transcoder/StreamTranscoder.cpp b/src/AvTranscoder/transcoder/StreamTranscoder.cpp index 8abc4594..c233e0c6 100644 --- a/src/AvTranscoder/transcoder/StreamTranscoder.cpp +++ b/src/AvTranscoder/transcoder/StreamTranscoder.cpp @@ -297,20 +297,28 @@ StreamTranscoder::StreamTranscoder(const std::vector& inputStre _filterGraph->addFilter("amerge", mergeOptions.str()); } - AudioCodec audioCodec(_outputEncoder->getCodec().getCodecType(), _outputEncoder->getCodec().getCodecId()); - AudioFrameDesc audioFrameDesc(48000, 1, "s32"); - audioCodec.setAudioParameters(audioFrameDesc); + AudioFrameDesc inputFrameDesc(inputStream.getAudioCodec().getAudioFrameDesc()); // output stream - _outputStream = &outputFile.addAudioStream(audioCodec); + AudioCodec outputAudioCodec(_outputEncoder->getCodec().getCodecType(), _outputEncoder->getCodec().getCodecId()); + AudioFrameDesc outputAudioFrameDesc = outputAudioCodec.getAudioFrameDesc(); + if(outputAudioFrameDesc._sampleRate == 0) { + outputAudioFrameDesc._sampleRate = inputFrameDesc._sampleRate; + } + if(outputAudioFrameDesc._sampleFormat == AV_SAMPLE_FMT_NONE) { + outputAudioFrameDesc._sampleFormat = inputFrameDesc._sampleFormat; + } + outputAudioFrameDesc._nbChannels = nbOutputChannels; + outputAudioCodec.setAudioParameters(outputAudioFrameDesc); + + _outputStream = &outputFile.addAudioStream(outputAudioCodec); // buffers to process - AudioFrameDesc inputFrameDesc(inputStream.getAudioCodec().getAudioFrameDesc()); if(inputStreamDesc.demultiplexing()) inputFrameDesc._nbChannels = nbOutputChannels; _filteredData = new AudioFrame(inputFrameDesc); - _transformedData = new AudioFrame(audioFrameDesc); + _transformedData = new AudioFrame(outputAudioFrameDesc); // transform _transform = new AudioTransform(); From 6671f364e0a396005b5f81fbb39b1a99a2d86a9f Mon Sep 17 00:00:00 2001 From: Valentin NOEL Date: Thu, 23 Jan 2020 17:23:24 +0100 Subject: [PATCH 23/74] Add OutputFile unit test --- test/pyTest/testOutputFile.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/test/pyTest/testOutputFile.py b/test/pyTest/testOutputFile.py index 7945246a..bfa5bd82 100644 --- a/test/pyTest/testOutputFile.py +++ b/test/pyTest/testOutputFile.py @@ -95,3 +95,20 @@ def testGetUnexistedOutputStream(): outputFileName = "testGetUnexistedOutputStream.mov" ouputFile = av.OutputFile(outputFileName) ouputFile.getStream(0) + + +def testAddingCustomStream(): + """ + Create an OutputFile, and add a custom stream and try to access that stream. + """ + outputFileName = "testAddingCustomStream.mov" + ouputFile = av.OutputFile(outputFileName) + + codec = av.AudioCodec(av.eCodecTypeEncoder, "pcm_s24le"); + addedOutputStream = ouputFile.addCustomStream(codec) + + retrievedOutputStream = ouputFile.getStream(0) + + assert_equals(addedOutputStream.getStreamIndex(), retrievedOutputStream.getStreamIndex()) + assert_equals(addedOutputStream.getStreamDuration(), retrievedOutputStream.getStreamDuration()) + assert_equals(addedOutputStream.getNbFrames(), retrievedOutputStream.getNbFrames()) From d61324501a9a782c0575cb5e2a725aa1a09ce8f1 Mon Sep 17 00:00:00 2001 From: Valentin NOEL Date: Tue, 21 Jan 2020 15:57:16 +0100 Subject: [PATCH 24/74] Add AvAudioPhaseMeter application --- app/CMakeLists.txt | 1 + app/avAudioPhaseMeter/CMakeLists.txt | 24 ++++ app/avAudioPhaseMeter/avAudioPhaseMeter.cpp | 141 ++++++++++++++++++++ 3 files changed, 166 insertions(+) create mode 100644 app/avAudioPhaseMeter/CMakeLists.txt create mode 100644 app/avAudioPhaseMeter/avAudioPhaseMeter.cpp diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt index 7563d02c..02945a9b 100644 --- a/app/CMakeLists.txt +++ b/app/CMakeLists.txt @@ -1,4 +1,5 @@ # C++ apps +add_subdirectory(avAudioPhaseMeter) add_subdirectory(avInfo) add_subdirectory(avMeta) add_subdirectory(avPlayer) diff --git a/app/avAudioPhaseMeter/CMakeLists.txt b/app/avAudioPhaseMeter/CMakeLists.txt new file mode 100644 index 00000000..4ed40d42 --- /dev/null +++ b/app/avAudioPhaseMeter/CMakeLists.txt @@ -0,0 +1,24 @@ +### cpp/avProcessor + +# Load custom cmake utilities +set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake) +include(AvTranscoderMacros) + +# Build app +add_executable(avaudiophasemeter avAudioPhaseMeter.cpp) +set_target_properties(avaudiophasemeter PROPERTIES VERSION ${AVTRANSCODER_VERSION}) +target_link_libraries(avaudiophasemeter avtranscoder-shared) + +# Install app +if(WIN32) + set(BINARY_FILES "${CMAKE_CURRENT_BINARY_DIR}/avaudiophasemeter.exe") +else() + set(BINARY_FILES "${CMAKE_CURRENT_BINARY_DIR}/avaudiophasemeter" "${CMAKE_CURRENT_BINARY_DIR}/avaudiophasemeter-${AVTRANSCODER_VERSION}") +endif() + +install( + FILES ${BINARY_FILES} + PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ GROUP_EXECUTE GROUP_READ WORLD_READ WORLD_EXECUTE + DESTINATION "bin/" + OPTIONAL +) diff --git a/app/avAudioPhaseMeter/avAudioPhaseMeter.cpp b/app/avAudioPhaseMeter/avAudioPhaseMeter.cpp new file mode 100644 index 00000000..3b08e8d4 --- /dev/null +++ b/app/avAudioPhaseMeter/avAudioPhaseMeter.cpp @@ -0,0 +1,141 @@ +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +std::vector parseConfigFile(const std::string& configFilename) +{ + std::vector result; + + std::ifstream configFile(configFilename.c_str(), std::ifstream::in); + + std::string line; + size_t countLines = 0; + while(std::getline(configFile, line)) + { + if(++countLines > 2) + throw std::runtime_error("Audio phase analysis can only be done on a stereo pair, i.e. two channels (see usage)."); + + std::istringstream is_line(line); + std::string filename; + if(std::getline(is_line, filename, '=')) + { + std::string stream; + std::getline(is_line, stream); + + std::stringstream ss(stream); + size_t streamIndex = 0; + char separator; + int channelIndex = -1; + ss >> streamIndex; + ss >> separator; + if(separator == '.') + ss >> channelIndex; + + bool newInputDescAdded = false; + // if we already have an input description with the same filename/streamIndex, add only the new channelIndex + for(std::vector::iterator it = result.begin(); it != result.end(); ++it) + { + if(it->_filename == filename && it->_streamIndex == streamIndex) + { + it->_channelIndexArray.push_back(channelIndex); + newInputDescAdded = true; + break; + } + } + if(! newInputDescAdded) + result.push_back(avtranscoder::InputStreamDesc(filename, streamIndex, channelIndex)); + } + } + + configFile.close(); + + return result; +} + +void displayUsage(const std::string& program) +{ + std::cout << "Usage: " << program << " CONFIG OUTPUT [OPTIONS]" << std::endl << std::endl; + std::cout << "\tCONFIG: input configuration file" << std::endl; + std::cout << "\t\tEach line represents one audio stream analysed." << std::endl; + std::cout << "\t\tPattern of each line is:" << std::endl; + std::cout << "\t\t[inputFile]=STREAM_INDEX.CHANNEL_INDEX" << std::endl; + std::cout << "\t\tWARNING: audio phase analyser only support stereo layout, i.e. two lines in this configuration." << std::endl << std::endl; + std::cout << "\tOUTPUT: metadata output file" << std::endl; + std::cout << "\t\tPattern for each frame is:" << std::endl; + std::cout << "\t\t `frame:[FRAME_ID] pts:[PTS] pts_time:[PTS_TIME]" << std::endl; + std::cout << "\t\t lavfi.aphasemeter.phase=[PHASE_VALUE]`" << std::endl << std::endl; + std::cout << "\tOPTIONS:" << std::endl; + std::cout << "\t\t--info set log level to AV_LOG_INFO" << std::endl; + std::cout << "\t\t--debug set log level to AV_LOG_DEBUG" << std::endl; + std::cout << "\t\t--help display this help" << std::endl << std::endl; +} + +int main(int argc, char** argv) +{ + // Preload FFmpeg context + avtranscoder::preloadCodecsAndFormats(); + avtranscoder::Logger::setLogLevel(AV_LOG_QUIET); + + if(argc < 3) { + displayUsage(argv[0]); + } + + // List command line arguments + std::vector arguments; + for(int argument = 1; argument < argc; ++argument) + { + arguments.push_back(argv[argument]); + } + for(size_t argument = 0; argument < arguments.size(); ++argument) + { + if(arguments.at(argument) == "--help") + { + displayUsage(argv[0]); + return 0; + } + else if(arguments.at(argument) == "--debug") + { + avtranscoder::Logger::setLogLevel(AV_LOG_DEBUG); + } + else if(arguments.at(argument) == "--info") + { + avtranscoder::Logger::setLogLevel(AV_LOG_INFO); + } + } + + try + { + std::string configFilePath(arguments.at(0)); + std::string outputFilePath(arguments.at(1)); + std::vector inputStreamsToAnalyse = parseConfigFile(configFilePath); + + avtranscoder::OutputFile outputFile(outputFilePath, "null"); // the output file will be overwritten by the extracted metadata + + avtranscoder::Transcoder transcoder(outputFile); + transcoder.setProcessMethod(avtranscoder::eProcessMethodBasedOnStream, 0); + transcoder.addStream(inputStreamsToAnalyse); + + avtranscoder::StreamTranscoder& streamTranscoder = transcoder.getStreamTranscoder(0); + avtranscoder::FilterGraph* filterGraph = streamTranscoder.getFilterGraph(); + filterGraph->addFilter("aphasemeter", "video=0"); + filterGraph->addFilter("ametadata", "mode=print:file=" + outputFilePath); + + avtranscoder::ConsoleProgress progress; + transcoder.process(progress); + } + catch(std::exception& e) + { + std::cerr << "ERROR: during process, an error occured: " << e.what() << std::endl; + } + catch(...) + { + std::cerr << "ERROR: during process, an unknown error occured" << std::endl; + } +} From 51704a9a8b9a660866596431314e2d63fc4ddcb8 Mon Sep 17 00:00:00 2001 From: Valentin NOEL Date: Fri, 24 Jan 2020 16:04:31 +0100 Subject: [PATCH 25/74] Fix code blocks format --- app/avAudioPhaseMeter/avAudioPhaseMeter.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/app/avAudioPhaseMeter/avAudioPhaseMeter.cpp b/app/avAudioPhaseMeter/avAudioPhaseMeter.cpp index 3b08e8d4..e018f785 100644 --- a/app/avAudioPhaseMeter/avAudioPhaseMeter.cpp +++ b/app/avAudioPhaseMeter/avAudioPhaseMeter.cpp @@ -20,7 +20,9 @@ std::vector parseConfigFile(const std::string& co while(std::getline(configFile, line)) { if(++countLines > 2) + { throw std::runtime_error("Audio phase analysis can only be done on a stereo pair, i.e. two channels (see usage)."); + } std::istringstream is_line(line); std::string filename; @@ -36,7 +38,9 @@ std::vector parseConfigFile(const std::string& co ss >> streamIndex; ss >> separator; if(separator == '.') + { ss >> channelIndex; + } bool newInputDescAdded = false; // if we already have an input description with the same filename/streamIndex, add only the new channelIndex @@ -49,8 +53,10 @@ std::vector parseConfigFile(const std::string& co break; } } - if(! newInputDescAdded) + if(!newInputDescAdded) + { result.push_back(avtranscoder::InputStreamDesc(filename, streamIndex, channelIndex)); + } } } @@ -83,7 +89,8 @@ int main(int argc, char** argv) avtranscoder::preloadCodecsAndFormats(); avtranscoder::Logger::setLogLevel(AV_LOG_QUIET); - if(argc < 3) { + if(argc < 3) + { displayUsage(argv[0]); } From 795318096cffd2d1b19ce5ad35e552bbe2dc0783 Mon Sep 17 00:00:00 2001 From: Valentin NOEL Date: Mon, 27 Jan 2020 09:20:51 +0100 Subject: [PATCH 26/74] Bump version to 0.15.0 --- src/AvTranscoder/common.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/AvTranscoder/common.hpp b/src/AvTranscoder/common.hpp index 96005b8c..f3e50a48 100644 --- a/src/AvTranscoder/common.hpp +++ b/src/AvTranscoder/common.hpp @@ -2,8 +2,8 @@ #define _AV_TRANSCODER_COMMON_HPP_ #define AVTRANSCODER_VERSION_MAJOR 0 -#define AVTRANSCODER_VERSION_MINOR 14 -#define AVTRANSCODER_VERSION_MICRO 3 +#define AVTRANSCODER_VERSION_MINOR 15 +#define AVTRANSCODER_VERSION_MICRO 0 #include From d06084a926c8eff2a870f931b49ca792aa5b28f5 Mon Sep 17 00:00:00 2001 From: Valentin NOEL Date: Wed, 12 Feb 2020 17:02:25 +0100 Subject: [PATCH 27/74] Fix deprecated warnings into util and common code --- src/AvTranscoder/Library.cpp | 10 ++++--- src/AvTranscoder/common.cpp | 2 ++ src/AvTranscoder/util.cpp | 53 ++++++++++++++++++++---------------- src/AvTranscoder/util.hpp | 4 +-- 4 files changed, 39 insertions(+), 30 deletions(-) diff --git a/src/AvTranscoder/Library.cpp b/src/AvTranscoder/Library.cpp index 961a8906..9c5ba23c 100644 --- a/src/AvTranscoder/Library.cpp +++ b/src/AvTranscoder/Library.cpp @@ -105,9 +105,10 @@ Libraries getLibraries() std::vector getInputExtensions() { std::vector extensions; - AVInputFormat* iFormat = NULL; + const AVInputFormat* iFormat = NULL; + void *iFormatOpaque = NULL; - while((iFormat = av_iformat_next(iFormat))) + while((iFormat = av_demuxer_iterate(&iFormatOpaque))) { if(iFormat->extensions != NULL) { @@ -143,9 +144,10 @@ std::vector getInputExtensions() std::vector getOutputExtensions() { std::vector extensions; - AVOutputFormat* oFormat = NULL; + const AVOutputFormat* oFormat = NULL; + void *oFormatOpaque = NULL; - while((oFormat = av_oformat_next(oFormat))) + while((oFormat = av_muxer_iterate(&oFormatOpaque))) { if(oFormat->extensions != NULL) { diff --git a/src/AvTranscoder/common.cpp b/src/AvTranscoder/common.cpp index 5b683c83..86022a79 100644 --- a/src/AvTranscoder/common.cpp +++ b/src/AvTranscoder/common.cpp @@ -15,8 +15,10 @@ namespace avtranscoder void preloadCodecsAndFormats() { +#if LIBAVFILTER_VERSION_MAJOR < 7 av_register_all(); avfilter_register_all(); +#endif } std::string getDescriptionFromErrorCode(const int code) diff --git a/src/AvTranscoder/util.cpp b/src/AvTranscoder/util.cpp index 30fe9a1b..f9b690c2 100644 --- a/src/AvTranscoder/util.cpp +++ b/src/AvTranscoder/util.cpp @@ -109,12 +109,13 @@ std::string getSampleFormatName(const AVSampleFormat sampleFormat) return formatName ? std::string(formatName) : ""; } -std::vector getAvailableFormats() +std::vector getAvailableFormats() { - std::vector formats; + std::vector formats; + void* formatOpaque = NULL; - AVOutputFormat* fmt = NULL; - while((fmt = av_oformat_next(fmt))) + const AVOutputFormat* fmt = NULL; + while((fmt = av_muxer_iterate(&formatOpaque))) { if(!fmt->name) continue; @@ -127,10 +128,10 @@ std::vector getAvailableFormats() NamesMap getAvailableFormatsNames() { NamesMap formatsNames; - std::vector formats = getAvailableFormats(); + std::vector formats = getAvailableFormats(); for(size_t i = 0; i < formats.size(); ++i) { - AVOutputFormat* fmt = formats.at(i); + const AVOutputFormat* fmt = formats.at(i); formatsNames.insert(std::make_pair(std::string(fmt->name), std::string(fmt->long_name ? fmt->long_name : ""))); } return formatsNames; @@ -139,10 +140,10 @@ NamesMap getAvailableFormatsNames() NamesMap getAvailableVideoFormatsNames() { NamesMap formatsNames; - std::vector formats = getAvailableFormats(); + std::vector formats = getAvailableFormats(); for(size_t i = 0; i < formats.size(); ++i) { - AVOutputFormat* fmt = formats.at(i); + const AVOutputFormat* fmt = formats.at(i); // skip format which cannot handle video if(fmt->video_codec == AV_CODEC_ID_NONE) continue; @@ -154,10 +155,10 @@ NamesMap getAvailableVideoFormatsNames() NamesMap getAvailableAudioFormatsNames() { NamesMap formatsNames; - std::vector formats = getAvailableFormats(); + std::vector formats = getAvailableFormats(); for(size_t i = 0; i < formats.size(); ++i) { - AVOutputFormat* fmt = formats.at(i); + const AVOutputFormat* fmt = formats.at(i); // skip format which cannot handle audio if(fmt->audio_codec == AV_CODEC_ID_NONE) continue; @@ -166,12 +167,13 @@ NamesMap getAvailableAudioFormatsNames() return formatsNames; } -std::vector getAvailableCodecs() +std::vector getAvailableCodecs() { - std::vector codecs; + std::vector codecs; - AVCodec* c = NULL; - while((c = av_codec_next(c))) + const AVCodec* c = NULL; + void* cOpaque = NULL; + while((c = av_codec_iterate(&cOpaque))) { if(!c->name) continue; @@ -184,10 +186,10 @@ std::vector getAvailableCodecs() NamesMap getAvailableVideoCodecsNames() { NamesMap videoCodecsNames; - std::vector codecs = getAvailableCodecs(); + std::vector codecs = getAvailableCodecs(); for(size_t i = 0; i < codecs.size(); ++i) { - AVCodec* c = codecs.at(i); + const AVCodec* c = codecs.at(i); if(c->type == AVMEDIA_TYPE_VIDEO) { videoCodecsNames.insert(std::make_pair(std::string(c->name), std::string(c->long_name ? c->long_name : ""))); @@ -199,10 +201,10 @@ NamesMap getAvailableVideoCodecsNames() NamesMap getAvailableAudioCodecsNames() { NamesMap audioCodecsNames; - std::vector codecs = getAvailableCodecs(); + std::vector codecs = getAvailableCodecs(); for(size_t i = 0; i < codecs.size(); ++i) { - AVCodec* c = codecs.at(i); + const AVCodec* c = codecs.at(i); if(c->type == AVMEDIA_TYPE_AUDIO) { audioCodecsNames.insert(std::make_pair(std::string(c->name), std::string(c->long_name ? c->long_name : ""))); @@ -215,7 +217,8 @@ OptionArrayMap getAvailableOptionsPerOutputFormat() { OptionArrayMap optionsPerFormat; - AVOutputFormat* outputFormat = av_oformat_next(NULL); + void* outputFormatOpaque = NULL; + const AVOutputFormat* outputFormat = av_muxer_iterate(&outputFormatOpaque); // iterate on formats while(outputFormat) @@ -230,7 +233,7 @@ OptionArrayMap getAvailableOptionsPerOutputFormat() loadOptions(options, (void*)&outputFormat->priv_class, 0); } optionsPerFormat.insert(std::make_pair(outputFormatName, options)); - outputFormat = av_oformat_next(outputFormat); + outputFormat = av_muxer_iterate(&outputFormatOpaque); } return optionsPerFormat; } @@ -239,7 +242,8 @@ OptionArrayMap getAvailableOptionsPerVideoCodec() { OptionArrayMap videoCodecOptions; - AVCodec* codec = av_codec_next(NULL); + void* codecOpaque = NULL; + const AVCodec* codec = av_codec_iterate(&codecOpaque); // iterate on codecs while(codec) @@ -258,7 +262,7 @@ OptionArrayMap getAvailableOptionsPerVideoCodec() } videoCodecOptions.insert(std::make_pair(videoCodecName, options)); } - codec = av_codec_next(codec); + codec = av_codec_iterate(&codecOpaque); } return videoCodecOptions; } @@ -267,7 +271,8 @@ OptionArrayMap getAvailableOptionsPerAudioCodec() { OptionArrayMap audioCodecOptions; - AVCodec* codec = av_codec_next(NULL); + void* codecOpaque = NULL; + const AVCodec* codec = av_codec_iterate(&codecOpaque); // iterate on codecs while(codec) @@ -286,7 +291,7 @@ OptionArrayMap getAvailableOptionsPerAudioCodec() } audioCodecOptions.insert(std::make_pair(audioCodecName, options)); } - codec = av_codec_next(codec); + codec = av_codec_iterate(&codecOpaque); } return audioCodecOptions; } diff --git a/src/AvTranscoder/util.hpp b/src/AvTranscoder/util.hpp index af35be31..17e41dec 100644 --- a/src/AvTranscoder/util.hpp +++ b/src/AvTranscoder/util.hpp @@ -63,7 +63,7 @@ std::string AvExport getSampleFormatName(const AVSampleFormat sampleFormat); /** * @return The list of all formats available in FFmpeg / libav. */ -std::vector getAvailableFormats(); +std::vector getAvailableFormats(); #endif /** * @brief Get a map of short/long names of all formats available in FFmpeg / libav. @@ -87,7 +87,7 @@ NamesMap AvExport getAvailableAudioFormatsNames(); /** * @return The list of all codecs available in FFmpeg / libav. */ -std::vector getAvailableCodecs(); +std::vector getAvailableCodecs(); #endif /** From 9bda038850db57bb66521c86d4cee29799146576 Mon Sep 17 00:00:00 2001 From: Valentin NOEL Date: Wed, 12 Feb 2020 17:03:24 +0100 Subject: [PATCH 28/74] Fix deprecated warnings into decoded data classes --- src/AvTranscoder/data/decoded/AudioFrame.cpp | 12 ++++++------ src/AvTranscoder/data/decoded/AudioFrame.hpp | 6 +++--- src/AvTranscoder/data/decoded/IFrame.cpp | 2 +- src/AvTranscoder/data/decoded/VideoFrame.cpp | 10 +++++----- 4 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/AvTranscoder/data/decoded/AudioFrame.cpp b/src/AvTranscoder/data/decoded/AudioFrame.cpp index 8dfd3bd8..54fa8119 100644 --- a/src/AvTranscoder/data/decoded/AudioFrame.cpp +++ b/src/AvTranscoder/data/decoded/AudioFrame.cpp @@ -45,9 +45,9 @@ AudioFrame::AudioFrame(const AudioFrameDesc& desc, const bool forceDataAllocatio , _desc(desc) { // Set Frame properties - av_frame_set_sample_rate(_frame, desc._sampleRate); - av_frame_set_channels(_frame, desc._nbChannels); - av_frame_set_channel_layout(_frame, av_get_default_channel_layout(desc._nbChannels)); + _frame->sample_rate = desc._sampleRate; + _frame->channels = desc._nbChannels; + _frame->channel_layout = av_get_default_channel_layout(desc._nbChannels); _frame->format = desc._sampleFormat; _frame->nb_samples = getDefaultNbSamples(); @@ -102,9 +102,9 @@ void AudioFrame::allocateData() LOG_WARN("The AudioFrame seems to already have allocated data. This could lead to memory leaks.") // Set Frame properties - av_frame_set_sample_rate(_frame, _desc._sampleRate); - av_frame_set_channels(_frame, _desc._nbChannels); - av_frame_set_channel_layout(_frame, av_get_default_channel_layout(_desc._nbChannels)); + _frame->sample_rate = _desc._sampleRate; + _frame->channels = _desc._nbChannels; + _frame->channel_layout = av_get_default_channel_layout(_desc._nbChannels); _frame->format = _desc._sampleFormat; if(_frame->nb_samples == 0) _frame->nb_samples = getDefaultNbSamples(); diff --git a/src/AvTranscoder/data/decoded/AudioFrame.hpp b/src/AvTranscoder/data/decoded/AudioFrame.hpp index 6bf00175..f8d1cb8b 100644 --- a/src/AvTranscoder/data/decoded/AudioFrame.hpp +++ b/src/AvTranscoder/data/decoded/AudioFrame.hpp @@ -51,9 +51,9 @@ class AvExport AudioFrame : public IFrame void freeData(); size_t getDataSize() const; - size_t getSampleRate() const { return av_frame_get_sample_rate(_frame); } - size_t getNbChannels() const { return av_frame_get_channels(_frame); } - size_t getChannelLayout() const { return av_frame_get_channel_layout(_frame); } + size_t getSampleRate() const { return _frame->sample_rate; } + size_t getNbChannels() const { return _frame->channels; } + size_t getChannelLayout() const { return _frame->channel_layout; } std::string getChannelLayoutDesc() const; ///< Get a description of a channel layout (example: '5.1'). AVSampleFormat getSampleFormat() const { return static_cast(_frame->format); } size_t getBytesPerSample() const; ///< 0 if unknown sample format diff --git a/src/AvTranscoder/data/decoded/IFrame.cpp b/src/AvTranscoder/data/decoded/IFrame.cpp index 608f90e4..84efa32b 100644 --- a/src/AvTranscoder/data/decoded/IFrame.cpp +++ b/src/AvTranscoder/data/decoded/IFrame.cpp @@ -69,7 +69,7 @@ void IFrame::assignValue(const unsigned char value) // Create the buffer const int bufferSize = getDataSize(); - unsigned char* dataBuffer = static_cast(malloc(bufferSize * sizeof(unsigned char))); + unsigned char* dataBuffer = static_cast(av_malloc(bufferSize * sizeof(unsigned char))); memset(dataBuffer, value, bufferSize); // Fill the frame diff --git a/src/AvTranscoder/data/decoded/VideoFrame.cpp b/src/AvTranscoder/data/decoded/VideoFrame.cpp index 4da08b00..631ffc76 100644 --- a/src/AvTranscoder/data/decoded/VideoFrame.cpp +++ b/src/AvTranscoder/data/decoded/VideoFrame.cpp @@ -5,6 +5,7 @@ extern "C" { #include #include +#include } #include @@ -75,7 +76,7 @@ size_t VideoFrame::getDataSize() const return 0; } - const size_t size = avpicture_get_size(getPixelFormat(), getWidth(), getHeight()); + const size_t size = av_image_get_buffer_size(getPixelFormat(), getWidth(), getHeight(), 1); if(size == 0) throw std::runtime_error("Unable to determine image buffer size: " + getDescriptionFromErrorCode(size)); return size; @@ -92,7 +93,7 @@ void VideoFrame::allocateData() _frame->format = _desc._pixelFormat; // Allocate data - const int ret = avpicture_alloc(reinterpret_cast(_frame), _desc._pixelFormat, _desc._width, _desc._height); + const int ret = av_image_alloc(_frame->data, _frame->linesize, _desc._width, _desc._height, _desc._pixelFormat, 1); if(ret < 0) { const std::string formatName = getPixelFormatName(_desc._pixelFormat); @@ -109,14 +110,13 @@ void VideoFrame::allocateData() void VideoFrame::freeData() { - avpicture_free(reinterpret_cast(_frame)); + av_freep(&_frame->data[0]); _dataAllocated = false; } void VideoFrame::assignBuffer(const unsigned char* ptrValue) { - const int ret = - avpicture_fill(reinterpret_cast(_frame), ptrValue, getPixelFormat(), getWidth(), getHeight()); + const int ret = av_image_fill_arrays(_frame->data, _frame->linesize, ptrValue, getPixelFormat(), getWidth(), getHeight(), 1); if(ret < 0) { std::stringstream msg; From f96989b27b049d9050d876465835dd8e5cd3b119 Mon Sep 17 00:00:00 2001 From: Valentin NOEL Date: Wed, 12 Feb 2020 17:03:47 +0100 Subject: [PATCH 29/74] Fix deprecated warnings into coded data class --- src/AvTranscoder/data/coded/CodedData.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/AvTranscoder/data/coded/CodedData.cpp b/src/AvTranscoder/data/coded/CodedData.cpp index 8c556b69..6247a0d6 100644 --- a/src/AvTranscoder/data/coded/CodedData.cpp +++ b/src/AvTranscoder/data/coded/CodedData.cpp @@ -43,7 +43,7 @@ CodedData& CodedData::operator=(const CodedData& other) CodedData::~CodedData() { - av_free_packet(&_packet); + av_packet_unref(&_packet); } void CodedData::resize(const size_t newSize) @@ -75,7 +75,7 @@ void CodedData::refData(CodedData& frame) void CodedData::clear() { - av_free_packet(&_packet); + av_packet_unref(&_packet); initAVPacket(); } @@ -94,7 +94,9 @@ void CodedData::initAVPacket() void CodedData::copyAVPacket(const AVPacket& avPacket) { -#if AVTRANSCODER_FFMPEG_DEPENDENCY && LIBAVCODEC_VERSION_INT > AV_VERSION_INT(54, 56, 0) +#if AVTRANSCODER_FFMPEG_DEPENDENCY && LIBAVCODEC_VERSION_MAJOR > 57 + av_packet_ref(&_packet, &avPacket); +#elif AVTRANSCODER_FFMPEG_DEPENDENCY && LIBAVCODEC_VERSION_INT > AV_VERSION_INT(54, 56, 0) // Need const_cast for libav versions from 54.56. to 55.56. av_copy_packet(&_packet, const_cast(&avPacket)); #else From da05a71438f0219df51d28f61d9f047e564011cd Mon Sep 17 00:00:00 2001 From: Valentin NOEL Date: Wed, 12 Feb 2020 17:04:03 +0100 Subject: [PATCH 30/74] Fix deprecated warnings into encoder classes --- src/AvTranscoder/encoder/AudioEncoder.cpp | 9 +++++---- src/AvTranscoder/encoder/AudioEncoder.hpp | 2 +- src/AvTranscoder/encoder/VideoEncoder.cpp | 9 +++++---- src/AvTranscoder/encoder/VideoEncoder.hpp | 2 +- 4 files changed, 12 insertions(+), 10 deletions(-) diff --git a/src/AvTranscoder/encoder/AudioEncoder.cpp b/src/AvTranscoder/encoder/AudioEncoder.cpp index 06410299..0e83c0ed 100644 --- a/src/AvTranscoder/encoder/AudioEncoder.cpp +++ b/src/AvTranscoder/encoder/AudioEncoder.cpp @@ -96,17 +96,18 @@ bool AudioEncoder::encodeFrame(const IFrame& sourceFrame, CodedData& codedFrame) AVCodecContext& avCodecContext = _codec.getAVCodecContext(); AVPacket& packet = codedFrame.getAVPacket(); - if((avCodecContext.coded_frame) && (avCodecContext.coded_frame->pts != (int)AV_NOPTS_VALUE)) + const AVFrame& srcAvFrame = sourceFrame.getAVFrame(); + if(srcAvFrame.pts != (int)AV_NOPTS_VALUE) { - packet.pts = avCodecContext.coded_frame->pts; + packet.pts = srcAvFrame.pts; } - if(avCodecContext.coded_frame && avCodecContext.coded_frame->key_frame) + if(srcAvFrame.key_frame) { packet.flags |= AV_PKT_FLAG_KEY; } - return encode(&sourceFrame.getAVFrame(), packet); + return encode(&srcAvFrame, packet); } bool AudioEncoder::encodeFrame(CodedData& codedFrame) diff --git a/src/AvTranscoder/encoder/AudioEncoder.hpp b/src/AvTranscoder/encoder/AudioEncoder.hpp index 0c8e0a55..7a39abc2 100644 --- a/src/AvTranscoder/encoder/AudioEncoder.hpp +++ b/src/AvTranscoder/encoder/AudioEncoder.hpp @@ -1,7 +1,7 @@ #ifndef _AV_TRANSCODER_ENCODER_AUDIO_ENCODER_HPP_ #define _AV_TRANSCODER_ENCODER_AUDIO_ENCODER_HPP_ -#include "IEncoder.hpp" +#include #include #include diff --git a/src/AvTranscoder/encoder/VideoEncoder.cpp b/src/AvTranscoder/encoder/VideoEncoder.cpp index 63e55d21..7d878d6a 100644 --- a/src/AvTranscoder/encoder/VideoEncoder.cpp +++ b/src/AvTranscoder/encoder/VideoEncoder.cpp @@ -113,17 +113,18 @@ bool VideoEncoder::encodeFrame(const IFrame& sourceFrame, CodedData& codedFrame) AVCodecContext& avCodecContext = _codec.getAVCodecContext(); AVPacket& packet = codedFrame.getAVPacket(); - if((avCodecContext.coded_frame) && (avCodecContext.coded_frame->pts != (int)AV_NOPTS_VALUE)) + const AVFrame& srcAvFrame = sourceFrame.getAVFrame(); + if(srcAvFrame.pts != (int)AV_NOPTS_VALUE) { - packet.pts = avCodecContext.coded_frame->pts; + packet.pts = srcAvFrame.pts; } - if(avCodecContext.coded_frame && avCodecContext.coded_frame->key_frame) + if(srcAvFrame.key_frame) { packet.flags |= AV_PKT_FLAG_KEY; } - return encode(&sourceFrame.getAVFrame(), packet); + return encode(&srcAvFrame, packet); } bool VideoEncoder::encodeFrame(CodedData& codedFrame) diff --git a/src/AvTranscoder/encoder/VideoEncoder.hpp b/src/AvTranscoder/encoder/VideoEncoder.hpp index d12035e6..6f7493b6 100644 --- a/src/AvTranscoder/encoder/VideoEncoder.hpp +++ b/src/AvTranscoder/encoder/VideoEncoder.hpp @@ -1,7 +1,7 @@ #ifndef _AV_TRANSCODER_ENCODER_VIDEO_ENCODER_HPP_ #define _AV_TRANSCODER_ENCODER_VIDEO_ENCODER_HPP_ -#include "IEncoder.hpp" +#include #include #include From fb86d8d77ae2429e5226865cf6f78cdb57e7cd64 Mon Sep 17 00:00:00 2001 From: Valentin NOEL Date: Wed, 12 Feb 2020 17:04:30 +0100 Subject: [PATCH 31/74] Fix deprecated warnings into properties classes --- src/AvTranscoder/properties/DataProperties.cpp | 2 +- src/AvTranscoder/properties/PixelProperties.cpp | 4 ++-- src/AvTranscoder/properties/VideoProperties.cpp | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/AvTranscoder/properties/DataProperties.cpp b/src/AvTranscoder/properties/DataProperties.cpp index cba9cdeb..af92b09a 100644 --- a/src/AvTranscoder/properties/DataProperties.cpp +++ b/src/AvTranscoder/properties/DataProperties.cpp @@ -73,7 +73,7 @@ void DataProperties::detectAncillaryData() detection = true; } - av_free_packet(&pkt); + av_packet_unref(&pkt); if(detection) break; diff --git a/src/AvTranscoder/properties/PixelProperties.cpp b/src/AvTranscoder/properties/PixelProperties.cpp index 2d761e01..9e58b298 100644 --- a/src/AvTranscoder/properties/PixelProperties.cpp +++ b/src/AvTranscoder/properties/PixelProperties.cpp @@ -64,7 +64,7 @@ size_t PixelProperties::getMaxNbBitsInChannels() const size_t maxNbBitsInChannels = 0; for(unsigned int channelIndex = 0; channelIndex < _pixelDesc->nb_components; ++channelIndex) { - const size_t nbBits = _pixelDesc->comp[channelIndex].depth_minus1 + 1; + const size_t nbBits = _pixelDesc->comp[channelIndex].depth; if(nbBits > maxNbBitsInChannels) maxNbBitsInChannels = nbBits; } @@ -227,7 +227,7 @@ std::vector PixelProperties::getChannels() const Channel c; c.id = channel; c.chromaHeight = (size_t)_pixelDesc->comp[channel].plane; - c.bitStep = (size_t)_pixelDesc->comp[channel].step_minus1; + c.bitStep = (size_t)_pixelDesc->comp[channel].step - 1; channels.push_back(c); } return channels; diff --git a/src/AvTranscoder/properties/VideoProperties.cpp b/src/AvTranscoder/properties/VideoProperties.cpp index 744e21b8..da9f5f39 100644 --- a/src/AvTranscoder/properties/VideoProperties.cpp +++ b/src/AvTranscoder/properties/VideoProperties.cpp @@ -558,7 +558,7 @@ size_t VideoProperties::analyseGopStructure(IProgress& progress) AVFrame& avFrame = frame.getAVFrame(); _gopStructure.push_back( - std::make_pair(av_get_picture_type_char(avFrame.pict_type), av_frame_get_pkt_size(&avFrame))); + std::make_pair(av_get_picture_type_char(avFrame.pict_type), avFrame.pkt_size)); _isInterlaced = avFrame.interlaced_frame; _isTopFieldFirst = avFrame.top_field_first; if(avFrame.pict_type == AV_PICTURE_TYPE_I) From 99ad5feb7ca2fd97a213d46d7d023cd112a82568 Mon Sep 17 00:00:00 2001 From: Valentin NOEL Date: Fri, 14 Feb 2020 10:52:31 +0100 Subject: [PATCH 32/74] InputStream: create and fill CodedData before adding it to cache --- src/AvTranscoder/stream/InputStream.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/AvTranscoder/stream/InputStream.cpp b/src/AvTranscoder/stream/InputStream.cpp index 8f465694..ece61cc3 100644 --- a/src/AvTranscoder/stream/InputStream.cpp +++ b/src/AvTranscoder/stream/InputStream.cpp @@ -122,9 +122,10 @@ void InputStream::addPacket(const AVPacket& packet) return; } - LOG_DEBUG("Add a packet data for the stream " << _streamIndex << " to the cache") - _streamCache.push(CodedData()); - _streamCache.back().copyData(packet.data, packet.size); + LOG_DEBUG("Add a packet data for the stream " << _streamIndex << " to the cache"); + CodedData codedData; + codedData.copyData(packet.data, packet.size); + _streamCache.push(codedData); } void InputStream::clearBuffering() From 10cef78bd3e2edc19cd54f2cc3ecb3424e71011d Mon Sep 17 00:00:00 2001 From: Valentin NOEL Date: Fri, 14 Feb 2020 12:12:50 +0100 Subject: [PATCH 33/74] StreamTranscoder: minor indentation fix --- src/AvTranscoder/transcoder/StreamTranscoder.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/AvTranscoder/transcoder/StreamTranscoder.cpp b/src/AvTranscoder/transcoder/StreamTranscoder.cpp index c233e0c6..f74cbf57 100644 --- a/src/AvTranscoder/transcoder/StreamTranscoder.cpp +++ b/src/AvTranscoder/transcoder/StreamTranscoder.cpp @@ -540,7 +540,7 @@ StreamTranscoder::~StreamTranscoder() { for(std::vector::iterator it = _decodedData.begin(); it != _decodedData.end(); ++it) { - delete(*it); + delete(*it); } if(_filteredData != NULL && _filteredData->isDataAllocated()) From 9db1c51ec960bf23a1ff574a636a3437ce6be55d Mon Sep 17 00:00:00 2001 From: Valentin NOEL Date: Fri, 14 Feb 2020 12:50:39 +0100 Subject: [PATCH 34/74] Test: add CodedData unit tests --- test/pyTest/testCodedData.py | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 test/pyTest/testCodedData.py diff --git a/test/pyTest/testCodedData.py b/test/pyTest/testCodedData.py new file mode 100644 index 00000000..623c8a36 --- /dev/null +++ b/test/pyTest/testCodedData.py @@ -0,0 +1,35 @@ +from nose.tools import * + +from pyAvTranscoder import avtranscoder as av + +def testCodedDataConstructors(): + """ + Try to create a CodedData instances from different constructors. + """ + dataSize = 1024 + codedData = av.CodedData(dataSize) + assert_equals(dataSize, codedData.getSize()) + + codedDataCopy = av.CodedData(codedData) + assert_equals(dataSize, codedDataCopy.getSize()) + + +def testCodedDataManagement(): + """ + Try to resize and assign CodedData data. + """ + dataSize = 1024 + codedData = av.CodedData() + codedData.resize(dataSize) + assert_equals(dataSize, codedData.getSize()) + + newDataSize = 128 + codedData.assign(newDataSize, 1) + assert_equals(newDataSize, codedData.getSize()) + data = codedData.getData() + for i in range(0, newDataSize): + assert_equals('\x01', data[i]) + + newDataSize = 256 + codedData.resize(newDataSize) + assert_equals(newDataSize, codedData.getSize()) From 267499958a1ac7d0210fe87d9ebba393f0a9732b Mon Sep 17 00:00:00 2001 From: Valentin NOEL Date: Fri, 14 Feb 2020 18:23:57 +0100 Subject: [PATCH 35/74] AudioGenerator: reset audio frame nb samples before getting silence --- src/AvTranscoder/decoder/AudioGenerator.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/AvTranscoder/decoder/AudioGenerator.cpp b/src/AvTranscoder/decoder/AudioGenerator.cpp index 63b1a4b1..9374b3df 100644 --- a/src/AvTranscoder/decoder/AudioGenerator.cpp +++ b/src/AvTranscoder/decoder/AudioGenerator.cpp @@ -41,6 +41,14 @@ bool AudioGenerator::decodeNextFrame(IFrame& frameBuffer) // (which was allocated to expect this number of samples). _silent->setNbSamplesPerChannel(frameBuffer.getAVFrame().nb_samples); } + + if(_silent->getNbSamplesPerChannel() != (size_t)frameBuffer.getAVFrame().nb_samples) { + LOG_DEBUG("Reset next audio frame nb samples and reallocate.") + frameBuffer.getAVFrame().nb_samples = _silent->getNbSamplesPerChannel(); + frameBuffer.freeData(); + frameBuffer.allocateData(); + } + LOG_DEBUG("Copy data of the silence when decode next frame") frameBuffer.copyData(*_silent); } From 170999384db7ecb0fe6c7cee5f91434beeac9956 Mon Sep 17 00:00:00 2001 From: Valentin NOEL Date: Wed, 19 Feb 2020 16:24:06 +0100 Subject: [PATCH 36/74] Fix nb samples computing into AudioProperties And complete and update unit tests --- .../properties/AudioProperties.cpp | 2 +- .../properties/AudioProperties.hpp | 2 +- test/pyTest/testNbSamples.py | 36 +++++++++++++++++-- test/pyTest/testOffset.py | 4 +-- test/pyTest/testProperties.py | 5 +-- 5 files changed, 40 insertions(+), 9 deletions(-) diff --git a/src/AvTranscoder/properties/AudioProperties.cpp b/src/AvTranscoder/properties/AudioProperties.cpp index 2ec52828..cf5793ef 100644 --- a/src/AvTranscoder/properties/AudioProperties.cpp +++ b/src/AvTranscoder/properties/AudioProperties.cpp @@ -140,7 +140,7 @@ size_t AudioProperties::getNbSamples() const throw std::runtime_error("unknown format context"); size_t nbSamples = _formatContext->streams[_streamIndex]->nb_frames; if(nbSamples == 0) - nbSamples = getSampleRate() * getNbChannels() * getDuration(); + nbSamples = getSampleRate() * getDuration(); return nbSamples; } diff --git a/src/AvTranscoder/properties/AudioProperties.hpp b/src/AvTranscoder/properties/AudioProperties.hpp index a82f2462..68c8d839 100644 --- a/src/AvTranscoder/properties/AudioProperties.hpp +++ b/src/AvTranscoder/properties/AudioProperties.hpp @@ -22,7 +22,7 @@ class AvExport AudioProperties : public StreamProperties size_t getBitRate() const; ///< in bits/s, 0 if unknown size_t getSampleRate() const; size_t getNbChannels() const; - size_t getNbSamples() const; ///< All the channels are included. + size_t getNbSamples() const; ///< For one channel. size_t getTicksPerFrame() const; diff --git a/test/pyTest/testNbSamples.py b/test/pyTest/testNbSamples.py index 10e24d47..66479feb 100644 --- a/test/pyTest/testNbSamples.py +++ b/test/pyTest/testNbSamples.py @@ -10,12 +10,12 @@ from pyAvTranscoder import avtranscoder as av -def testNbSamplesAudioRewrap(): +def testNbSamplesAudioRewrapFromWav(): """ - Rewrap one audio stream, check nb samples. + Rewrap one audio stream from WAV file, check nb samples. """ inputFileName = os.environ['AVTRANSCODER_TEST_AUDIO_WAVE_FILE'] - outputFileName = "testNbSamplesAudioRewrap.wav" + outputFileName = "testNbSamplesAudioRewrapFromWav.wav" ouputFile = av.OutputFile( outputFileName ) transcoder = av.Transcoder( ouputFile ) @@ -36,6 +36,35 @@ def testNbSamplesAudioRewrap(): dst_audioStream = dst_properties.getAudioProperties()[0] assert_equals( src_audioStream.getNbSamples(), dst_audioStream.getNbSamples() ) + assert_equals( src_audioStream.getNbSamples(), src_audioStream.getSampleRate() * src_audioStream.getDuration() ) + +def testNbSamplesAudioRewrapFromMov(): + """ + Rewrap one audio stream from MOV file, check nb samples. + """ + inputFileName = os.environ['AVTRANSCODER_TEST_AUDIO_MOV_FILE'] + outputFileName = "testNbSamplesAudioRewrapFromMov.wav" + + ouputFile = av.OutputFile( outputFileName ) + transcoder = av.Transcoder( ouputFile ) + + transcoder.addStream( av.InputStreamDesc(inputFileName, 1) ) + + progress = av.ConsoleProgress() + transcoder.process( progress ) + + # get src file of rewrap + src_inputFile = av.InputFile( inputFileName ) + src_properties = src_inputFile.getProperties() + src_audioStream = src_properties.getAudioProperties()[0] + + # get dst file of rewrap + dst_inputFile = av.InputFile( outputFileName ) + dst_properties = dst_inputFile.getProperties() + dst_audioStream = dst_properties.getAudioProperties()[0] + + assert_equals( src_audioStream.getNbSamples(), dst_audioStream.getNbSamples() ) + assert_equals( src_audioStream.getNbSamples(), src_audioStream.getSampleRate() * src_audioStream.getDuration() ) def testNbSamplesAudioTranscode(): """ @@ -70,3 +99,4 @@ def testNbSamplesAudioTranscode(): dst_audioStream = dst_properties.getAudioProperties()[0] assert_equals( src_audioStream.getNbSamples(), dst_audioStream.getNbSamples() ) + assert_equals( src_audioStream.getNbSamples(), src_audioStream.getSampleRate() * src_audioStream.getDuration() ) diff --git a/test/pyTest/testOffset.py b/test/pyTest/testOffset.py index 278202a0..4e0d4ed9 100644 --- a/test/pyTest/testOffset.py +++ b/test/pyTest/testOffset.py @@ -103,7 +103,7 @@ def testRewrapAudioPositiveOffset(): # check output duration assert_equals( src_audioStream.getDuration() + offset, dst_audioStream.getDuration() ) - assert_equals( src_audioStream.getNbSamples() + ( offset * dst_audioStream.getSampleRate() * dst_audioStream.getNbChannels() ), dst_audioStream.getNbSamples() ) + assert_equals( src_audioStream.getNbSamples() + ( offset * dst_audioStream.getSampleRate() ), dst_audioStream.getNbSamples() ) def testRewrapAudioNegativeOffset(): @@ -134,7 +134,7 @@ def testRewrapAudioNegativeOffset(): # check output duration assert_equals( src_audioStream.getDuration() + offset, dst_audioStream.getDuration() ) - assert_equals( src_audioStream.getNbSamples() + ( offset * dst_audioStream.getSampleRate() * dst_audioStream.getNbChannels() ), dst_audioStream.getNbSamples() ) + assert_equals( src_audioStream.getNbSamples() + ( offset * dst_audioStream.getSampleRate() ), dst_audioStream.getNbSamples() ) # # The output video stream has not the correct duration. diff --git a/test/pyTest/testProperties.py b/test/pyTest/testProperties.py index 383ee6d5..48773eb2 100644 --- a/test/pyTest/testProperties.py +++ b/test/pyTest/testProperties.py @@ -150,11 +150,11 @@ def testCheckAudioProperties(): expectedAudioBitRate = 4608000 expectedCodecName = 'pcm_s16le' - expectedSamples = 5760000 expectedDuration = 20 expectedChannels = 6 expectedChannelLayout = '5.1' expectedSampleRate = 48000 + expectedSamples = expectedSampleRate * expectedDuration; assert_equals( properties.getBitRate(), expectedTotalBitRate ) assert_equals( audioStream.getBitRate(), expectedAudioBitRate ) @@ -177,4 +177,5 @@ def testCheckFilePropertiesAsJson(): import json # json.loads method throws a ValueError if it is not a valid JSON. - json.loads(inputFile.getProperties().allPropertiesAsJson()) + jsonProps = json.loads(inputFile.getProperties().allPropertiesAsJson()) + print(jsonProps) From d545aab8aa6dcb8ec3aa8994c3a5c4e472d55f99 Mon Sep 17 00:00:00 2001 From: Valentin NOEL Date: Thu, 20 Feb 2020 10:13:54 +0100 Subject: [PATCH 37/74] Bump version to 0.15.1 --- src/AvTranscoder/common.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/AvTranscoder/common.hpp b/src/AvTranscoder/common.hpp index f3e50a48..5bf326de 100644 --- a/src/AvTranscoder/common.hpp +++ b/src/AvTranscoder/common.hpp @@ -3,7 +3,7 @@ #define AVTRANSCODER_VERSION_MAJOR 0 #define AVTRANSCODER_VERSION_MINOR 15 -#define AVTRANSCODER_VERSION_MICRO 0 +#define AVTRANSCODER_VERSION_MICRO 1 #include From d1cba42ef13c862131bab1a6eec668181faf21b5 Mon Sep 17 00:00:00 2001 From: Valentin NOEL Date: Thu, 27 Feb 2020 11:39:55 +0100 Subject: [PATCH 38/74] StreamTranscoder: free filtered data after it was filled from filter graph sink --- src/AvTranscoder/transcoder/StreamTranscoder.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/AvTranscoder/transcoder/StreamTranscoder.cpp b/src/AvTranscoder/transcoder/StreamTranscoder.cpp index f74cbf57..7e397dac 100644 --- a/src/AvTranscoder/transcoder/StreamTranscoder.cpp +++ b/src/AvTranscoder/transcoder/StreamTranscoder.cpp @@ -790,6 +790,13 @@ bool StreamTranscoder::processTranscode() LOG_DEBUG("Encode") _outputEncoder->encodeFrame(*_transformedData, data); + + if(_filterGraph->hasFilters()) + { + LOG_DEBUG("Free filtered data") // filled from filter graph sink + av_frame_unref(&_filteredData->getAVFrame()); + _filteredData->freeData(); + } } else { From bd24d5b0c8b6181d1f37989edea72d345401abee Mon Sep 17 00:00:00 2001 From: Valentin NOEL Date: Thu, 25 Jun 2020 09:51:09 +0200 Subject: [PATCH 39/74] StreamTranscoder: fix positive offset in case of codec latency --- src/AvTranscoder/transcoder/StreamTranscoder.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/AvTranscoder/transcoder/StreamTranscoder.cpp b/src/AvTranscoder/transcoder/StreamTranscoder.cpp index 7e397dac..ead27693 100644 --- a/src/AvTranscoder/transcoder/StreamTranscoder.cpp +++ b/src/AvTranscoder/transcoder/StreamTranscoder.cpp @@ -588,6 +588,15 @@ void StreamTranscoder::preProcessCodecLatency() wasARewrapCase = true; } + if(_offset > 0) { + const double fps = 1.0 * _outputEncoder->getCodec().getAVCodecContext().time_base.den / + (_outputEncoder->getCodec().getAVCodecContext().time_base.num * _outputEncoder->getCodec().getAVCodecContext().ticks_per_frame); + const double frame_duration = 1.0 / fps; + const double output_latency_duration = frame_duration * (latency - 1); + LOG_WARN("Compensate for offset with codec latency by " << output_latency_duration << " seconds (fps=" << fps << ", latency=" << latency << ")"); + _offset -= output_latency_duration; + } + while((latency--) > 0) { processFrame(); From 388d84757e0d199e5dcb5a7b4c955c8ab49e9710 Mon Sep 17 00:00:00 2001 From: Valentin NOEL Date: Thu, 25 Jun 2020 09:57:58 +0200 Subject: [PATCH 40/74] Add test output files to gitignore --- .gitignore | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 427a1344..e08b9c55 100644 --- a/.gitignore +++ b/.gitignore @@ -12,8 +12,10 @@ *.la *.a -build +build* dist +install* +test/**/test*[.wav|.avi|.mov|.h264|.mxf] # CMake CMakeCache.txt From c06898bbccb1514f8a45c8c2be15a23e69252227 Mon Sep 17 00:00:00 2001 From: Valentin NOEL Date: Fri, 26 Jun 2020 11:44:42 +0200 Subject: [PATCH 41/74] IDecoder: add decoded frames counter --- src/AvTranscoder/decoder/AudioDecoder.cpp | 4 ++++ src/AvTranscoder/decoder/AudioGenerator.cpp | 2 ++ src/AvTranscoder/decoder/IDecoder.hpp | 19 +++++++++++++++++++ src/AvTranscoder/decoder/VideoDecoder.cpp | 4 ++++ src/AvTranscoder/decoder/VideoGenerator.cpp | 2 ++ 5 files changed, 31 insertions(+) diff --git a/src/AvTranscoder/decoder/AudioDecoder.cpp b/src/AvTranscoder/decoder/AudioDecoder.cpp index a995a3df..f1086fcc 100644 --- a/src/AvTranscoder/decoder/AudioDecoder.cpp +++ b/src/AvTranscoder/decoder/AudioDecoder.cpp @@ -121,6 +121,10 @@ bool AudioDecoder::decodeNextFrame(IFrame& frameBuffer) return false; } } + + if(decodeNextFrame) + incrementNbDecodedFrames(frameBuffer.getAVFrame().nb_samples); + return decodeNextFrame; } diff --git a/src/AvTranscoder/decoder/AudioGenerator.cpp b/src/AvTranscoder/decoder/AudioGenerator.cpp index 9374b3df..6842ba21 100644 --- a/src/AvTranscoder/decoder/AudioGenerator.cpp +++ b/src/AvTranscoder/decoder/AudioGenerator.cpp @@ -58,6 +58,8 @@ bool AudioGenerator::decodeNextFrame(IFrame& frameBuffer) LOG_DEBUG("Convert data of the audio specified when decode next frame") _audioTransform.convert(*_inputFrame, frameBuffer); } + + incrementNbDecodedFrames(_silent->getNbSamplesPerChannel()); return true; } diff --git a/src/AvTranscoder/decoder/IDecoder.hpp b/src/AvTranscoder/decoder/IDecoder.hpp index d9acf8d1..40e79619 100644 --- a/src/AvTranscoder/decoder/IDecoder.hpp +++ b/src/AvTranscoder/decoder/IDecoder.hpp @@ -10,7 +10,16 @@ namespace avtranscoder class AvExport IDecoder { +protected: + IDecoder::IDecoder() + : _decoded_frames_counter(0) + { + } + public: + + + virtual ~IDecoder(){}; /** @@ -51,6 +60,16 @@ class AvExport IDecoder * @note Not sense for generators. */ virtual void flushDecoder() {} + + size_t getNbDecodedFrames() { return _decoded_frames_counter; } + +protected: + void incrementNbDecodedFrames(const size_t& nb_frames = 1) { + _decoded_frames_counter += nb_frames; + } + +private: + size_t _decoded_frames_counter; }; } diff --git a/src/AvTranscoder/decoder/VideoDecoder.cpp b/src/AvTranscoder/decoder/VideoDecoder.cpp index ae76fb05..3c1e1beb 100644 --- a/src/AvTranscoder/decoder/VideoDecoder.cpp +++ b/src/AvTranscoder/decoder/VideoDecoder.cpp @@ -114,6 +114,10 @@ bool VideoDecoder::decodeNextFrame(IFrame& frameBuffer) return false; } } + + if(decodeNextFrame) + incrementNbDecodedFrames(); + return decodeNextFrame; } diff --git a/src/AvTranscoder/decoder/VideoGenerator.cpp b/src/AvTranscoder/decoder/VideoGenerator.cpp index ad89c9ac..155d635d 100644 --- a/src/AvTranscoder/decoder/VideoGenerator.cpp +++ b/src/AvTranscoder/decoder/VideoGenerator.cpp @@ -51,6 +51,8 @@ bool VideoGenerator::decodeNextFrame(IFrame& frameBuffer) LOG_DEBUG("Convert data of the image specified when decode next frame") _videoTransform.convert(*_inputFrame, frameBuffer); } + + incrementNbDecodedFrames(); return true; } From 691e4fe82cfc477a2f54986b25607bb67d5904d3 Mon Sep 17 00:00:00 2001 From: Valentin NOEL Date: Fri, 26 Jun 2020 11:46:14 +0200 Subject: [PATCH 42/74] StreamTranscoder: check end of positive offset based on number of generated frames --- .../transcoder/StreamTranscoder.cpp | 24 +++++++++++-------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/src/AvTranscoder/transcoder/StreamTranscoder.cpp b/src/AvTranscoder/transcoder/StreamTranscoder.cpp index ead27693..b912e32e 100644 --- a/src/AvTranscoder/transcoder/StreamTranscoder.cpp +++ b/src/AvTranscoder/transcoder/StreamTranscoder.cpp @@ -588,15 +588,6 @@ void StreamTranscoder::preProcessCodecLatency() wasARewrapCase = true; } - if(_offset > 0) { - const double fps = 1.0 * _outputEncoder->getCodec().getAVCodecContext().time_base.den / - (_outputEncoder->getCodec().getAVCodecContext().time_base.num * _outputEncoder->getCodec().getAVCodecContext().ticks_per_frame); - const double frame_duration = 1.0 / fps; - const double output_latency_duration = frame_duration * (latency - 1); - LOG_WARN("Compensate for offset with codec latency by " << output_latency_duration << " seconds (fps=" << fps << ", latency=" << latency << ")"); - _offset -= output_latency_duration; - } - while((latency--) > 0) { processFrame(); @@ -626,7 +617,20 @@ bool StreamTranscoder::processFrame() // Manage offset if(_offset > 0) { - const bool endOfOffset = _outputStream->getStreamDuration() >= _offset; + bool endOfOffset = false; + if(_currentDecoder == _generators.at(0)) + { + const double fps = 1.0 * _outputEncoder->getCodec().getAVCodecContext().time_base.den / + (_outputEncoder->getCodec().getAVCodecContext().time_base.num * _outputEncoder->getCodec().getAVCodecContext().ticks_per_frame); + const double frame_duration = 1.0 / fps; + const double generated_duration = _currentDecoder->getNbDecodedFrames() * frame_duration; + endOfOffset = generated_duration >= _offset; + } + else + { + endOfOffset = _outputStream->getStreamDuration() >= _offset; + } + if(endOfOffset) { LOG_INFO("End of positive offset") From b62ed71bdba5e4f979041029d1c722b464acbdf9 Mon Sep 17 00:00:00 2001 From: Valentin NOEL Date: Fri, 26 Jun 2020 11:47:54 +0200 Subject: [PATCH 43/74] StreamTranscoder: don't flush encoder before switching to generator if needed --- src/AvTranscoder/transcoder/StreamTranscoder.cpp | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/AvTranscoder/transcoder/StreamTranscoder.cpp b/src/AvTranscoder/transcoder/StreamTranscoder.cpp index b912e32e..6add9cc2 100644 --- a/src/AvTranscoder/transcoder/StreamTranscoder.cpp +++ b/src/AvTranscoder/transcoder/StreamTranscoder.cpp @@ -763,8 +763,7 @@ bool StreamTranscoder::processTranscode() } } - // Transform - CodedData data; + // Check decoding status bool continueProcess = true; for(size_t index = 0; index < decodingStatus.size(); ++index) { @@ -773,6 +772,17 @@ bool StreamTranscoder::processTranscode() if(!_filterGraph->hasFilters() || !_filterGraph->hasBufferedFrames(index)) { continueProcess = false; + if(_needToSwitchToGenerator) + { + switchToGeneratorDecoder(); + LOG_INFO("Force reallocation of the decoded data buffers since the decoders could have cleared them.") + for(std::vector::iterator it = _decodedData.begin(); it != _decodedData.end(); ++it) + { + if(! (*it)->isDataAllocated()) + (*it)->allocateData(); + } + return processTranscode(); + } break; } LOG_DEBUG("Some frames remain into filter graph buffer " << index); @@ -784,8 +794,10 @@ bool StreamTranscoder::processTranscode() } } + CodedData data; if(continueProcess) { + // Transform IFrame* dataToTransform = NULL; if(_filterGraph->hasFilters()) { From 83d6565c46514e04564a379cf8d2e6aade43e94f Mon Sep 17 00:00:00 2001 From: Valentin NOEL Date: Fri, 26 Jun 2020 11:48:59 +0200 Subject: [PATCH 44/74] StreamTranscoder: assert that generators and encoders number are equal --- src/AvTranscoder/transcoder/StreamTranscoder.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/AvTranscoder/transcoder/StreamTranscoder.cpp b/src/AvTranscoder/transcoder/StreamTranscoder.cpp index 6add9cc2..8ce1c22f 100644 --- a/src/AvTranscoder/transcoder/StreamTranscoder.cpp +++ b/src/AvTranscoder/transcoder/StreamTranscoder.cpp @@ -717,6 +717,7 @@ bool StreamTranscoder::processTranscode() assert(_outputEncoder != NULL); assert(! _decodedData.empty()); assert(_transform != NULL); + assert(_generators.size() == _inputDecoders.size()); LOG_DEBUG("StreamTranscoder::processTranscode") From 319af3cfffe27c3a691b899efdacb41dbc3e1e3a Mon Sep 17 00:00:00 2001 From: Valentin NOEL Date: Fri, 26 Jun 2020 12:18:50 +0200 Subject: [PATCH 45/74] IDecoder: fix constructor definition --- src/AvTranscoder/decoder/IDecoder.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/AvTranscoder/decoder/IDecoder.hpp b/src/AvTranscoder/decoder/IDecoder.hpp index 40e79619..48e254a4 100644 --- a/src/AvTranscoder/decoder/IDecoder.hpp +++ b/src/AvTranscoder/decoder/IDecoder.hpp @@ -11,7 +11,7 @@ namespace avtranscoder class AvExport IDecoder { protected: - IDecoder::IDecoder() + IDecoder() : _decoded_frames_counter(0) { } From 76481a8b44b7ef4127bf415cea201fb40f1fc558 Mon Sep 17 00:00:00 2001 From: Valentin NOEL Date: Mon, 29 Jun 2020 14:23:35 +0200 Subject: [PATCH 46/74] IDecoder: Remove empty lines --- src/AvTranscoder/decoder/IDecoder.hpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/AvTranscoder/decoder/IDecoder.hpp b/src/AvTranscoder/decoder/IDecoder.hpp index 48e254a4..66062140 100644 --- a/src/AvTranscoder/decoder/IDecoder.hpp +++ b/src/AvTranscoder/decoder/IDecoder.hpp @@ -17,9 +17,6 @@ class AvExport IDecoder } public: - - - virtual ~IDecoder(){}; /** From 6d1c673f63dcc78e43bad185e2155ea40e29e51e Mon Sep 17 00:00:00 2001 From: Valentin NOEL Date: Mon, 29 Jun 2020 15:18:04 +0200 Subject: [PATCH 47/74] Bump version to 0.15.2 --- src/AvTranscoder/common.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/AvTranscoder/common.hpp b/src/AvTranscoder/common.hpp index 5bf326de..2aac5c6f 100644 --- a/src/AvTranscoder/common.hpp +++ b/src/AvTranscoder/common.hpp @@ -3,7 +3,7 @@ #define AVTRANSCODER_VERSION_MAJOR 0 #define AVTRANSCODER_VERSION_MINOR 15 -#define AVTRANSCODER_VERSION_MICRO 1 +#define AVTRANSCODER_VERSION_MICRO 2 #include From 08acc40f9d02e7cfb771c1fb57d6d468bd7c4c8d Mon Sep 17 00:00:00 2001 From: Sarat Chandra Balla Date: Sun, 19 Jul 2020 22:28:30 +0530 Subject: [PATCH 48/74] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 35382d0e..c2d9effc 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ Click on the badge above to have a big picture view of what's in progress and ho #### The basics * avTranscoder is a C++ library. * avTranscoder uses [SWIG](http://www.swig.org/) to generate __Java__ and __Python__ bindings. -* avTranscoder is multiplateform (Linux, MAC, Windows). +* avTranscoder is multiplatform (Linux, MAC, Windows). * avTranscoder could be based on [Libav](https://libav.org/), [FFmpeg](https://ffmpeg.org/), or your custom fork of one of these librairies. #### License From 33253f733b9f8ab46726d303a37e970f11e24a41 Mon Sep 17 00:00:00 2001 From: Valentin NOEL Date: Wed, 12 Aug 2020 11:05:05 +0200 Subject: [PATCH 49/74] EWrappingStatus: introduce new eWrappingSkip possible value --- src/AvTranscoder/file/OutputFile.cpp | 2 +- src/AvTranscoder/stream/IOutputStream.hpp | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/AvTranscoder/file/OutputFile.cpp b/src/AvTranscoder/file/OutputFile.cpp index 77470644..d446b431 100644 --- a/src/AvTranscoder/file/OutputFile.cpp +++ b/src/AvTranscoder/file/OutputFile.cpp @@ -188,7 +188,7 @@ bool OutputFile::beginWrap() IOutputStream::EWrappingStatus OutputFile::wrap(const CodedData& data, const size_t streamIndex) { if(!data.getSize()) - return IOutputStream::eWrappingSuccess; + return IOutputStream::eWrappingSkip; LOG_DEBUG("Wrap on stream " << streamIndex << " (" << data.getSize() << " bytes for frame " << _frameCount.at(streamIndex) << ")") diff --git a/src/AvTranscoder/stream/IOutputStream.hpp b/src/AvTranscoder/stream/IOutputStream.hpp index 3c7393c9..4acdad2d 100644 --- a/src/AvTranscoder/stream/IOutputStream.hpp +++ b/src/AvTranscoder/stream/IOutputStream.hpp @@ -16,9 +16,10 @@ class AvExport IOutputStream **/ enum EWrappingStatus { - eWrappingSuccess = 0, - eWrappingWaitingForData, - eWrappingError, + eWrappingSuccess = 0, ///< The wrapping succeeded + eWrappingWaitingForData, ///< The wrapper expects more data to complete the writing process + eWrappingSkip, ///< The wrapper receives empty data, so nothing is written + eWrappingError, ///< An error occurred during the wrapping process }; virtual ~IOutputStream(){}; From 30be155445b5816cc0430b3d05eee32b92d4179b Mon Sep 17 00:00:00 2001 From: Valentin NOEL Date: Wed, 12 Aug 2020 11:06:57 +0200 Subject: [PATCH 50/74] Transcoder: refactoring of the wrapping status support Fix the processed frames counter Fix the process progress check depending on the wrapping status --- .../transcoder/StreamTranscoder.cpp | 38 ++----- .../transcoder/StreamTranscoder.hpp | 6 +- src/AvTranscoder/transcoder/Transcoder.cpp | 103 ++++++++++++------ src/AvTranscoder/transcoder/Transcoder.hpp | 26 ++++- 4 files changed, 102 insertions(+), 71 deletions(-) diff --git a/src/AvTranscoder/transcoder/StreamTranscoder.cpp b/src/AvTranscoder/transcoder/StreamTranscoder.cpp index 8ce1c22f..edf47de3 100644 --- a/src/AvTranscoder/transcoder/StreamTranscoder.cpp +++ b/src/AvTranscoder/transcoder/StreamTranscoder.cpp @@ -597,7 +597,7 @@ void StreamTranscoder::preProcessCodecLatency() _currentDecoder = NULL; } -bool StreamTranscoder::processFrame() +IOutputStream::EWrappingStatus StreamTranscoder::processFrame() { std::string msg = "Current process case of the stream is a "; switch(getProcessCase()) @@ -677,7 +677,7 @@ bool StreamTranscoder::processFrame() return processTranscode(); } -bool StreamTranscoder::processRewrap() +IOutputStream::EWrappingStatus StreamTranscoder::processRewrap() { assert(_inputStreams.size() == 1); assert(_outputStream != NULL); @@ -692,25 +692,13 @@ bool StreamTranscoder::processRewrap() switchToGeneratorDecoder(); return processTranscode(); } - return false; + return IOutputStream::eWrappingError; } - const IOutputStream::EWrappingStatus wrappingStatus = _outputStream->wrap(data); - switch(wrappingStatus) - { - case IOutputStream::eWrappingSuccess: - return true; - case IOutputStream::eWrappingWaitingForData: - // the wrapper needs more data to write the current packet - return processFrame(); - case IOutputStream::eWrappingError: - return false; - } - - return true; + return _outputStream->wrap(data); } -bool StreamTranscoder::processTranscode() +IOutputStream::EWrappingStatus StreamTranscoder::processTranscode() { assert(_outputStream != NULL); assert(_currentDecoder != NULL); @@ -840,25 +828,13 @@ bool StreamTranscoder::processTranscode() } return processTranscode(); } - return false; + return IOutputStream::eWrappingError; } } // Wrap LOG_DEBUG("wrap (" << data.getSize() << " bytes)") - const IOutputStream::EWrappingStatus wrappingStatus = _outputStream->wrap(data); - switch(wrappingStatus) - { - case IOutputStream::eWrappingSuccess: - return true; - case IOutputStream::eWrappingWaitingForData: - // the wrapper needs more data to write the current packet - return processFrame(); - case IOutputStream::eWrappingError: - return false; - } - - return true; + return _outputStream->wrap(data); } void StreamTranscoder::switchToGeneratorDecoder() diff --git a/src/AvTranscoder/transcoder/StreamTranscoder.hpp b/src/AvTranscoder/transcoder/StreamTranscoder.hpp index 129ef7e2..23006d18 100644 --- a/src/AvTranscoder/transcoder/StreamTranscoder.hpp +++ b/src/AvTranscoder/transcoder/StreamTranscoder.hpp @@ -69,7 +69,7 @@ class AvExport StreamTranscoder * @brief process a single frame for the current stream * @return the process status result */ - bool processFrame(); + IOutputStream::EWrappingStatus processFrame(); //@{ // Switch current decoder. @@ -139,8 +139,8 @@ class AvExport StreamTranscoder void addDecoder(const InputStreamDesc& inputStreamDesc, IInputStream& inputStream); void addGenerator(const InputStreamDesc& inputStreamDesc, const ProfileLoader::Profile& profile); - bool processRewrap(); - bool processTranscode(); + IOutputStream::EWrappingStatus processRewrap(); + IOutputStream::EWrappingStatus processTranscode(); private: std::vector _inputStreamDesc; ///< Description of the data to extract from the input stream. diff --git a/src/AvTranscoder/transcoder/Transcoder.cpp b/src/AvTranscoder/transcoder/Transcoder.cpp index 1bedf43e..eb9895ed 100644 --- a/src/AvTranscoder/transcoder/Transcoder.cpp +++ b/src/AvTranscoder/transcoder/Transcoder.cpp @@ -19,6 +19,7 @@ Transcoder::Transcoder(IOutputFile& outputFile) , _profileLoader(true) , _eProcessMethod(eProcessMethodLongest) , _mainStreamIndex(0) + , _processedFrames(0) , _outputDuration(0) { } @@ -159,27 +160,86 @@ void Transcoder::preProcessCodecLatency() } bool Transcoder::processFrame() +{ + NoDisplayProgress progress; + return processFrame(progress); +} + +bool Transcoder::processFrame(IProgress& progress) { if(_streamTranscoders.size() == 0) return false; // For each stream, process a frame + bool result = true; for(size_t streamIndex = 0; streamIndex < _streamTranscoders.size(); ++streamIndex) { - LOG_DEBUG("Process stream " << streamIndex + 1 << "/" << _streamTranscoders.size()) + if(!processFrame(progress, streamIndex)) + result = false; + } + return result; +} - // if a stream failed to process - if(!_streamTranscoders.at(streamIndex)->processFrame()) - { +bool Transcoder::processFrame(IProgress& progress, const size_t& streamIndex) +{ + LOG_DEBUG("Process stream " << streamIndex + 1 << "/" << _streamTranscoders.size()) + + IOutputStream::EWrappingStatus status = _streamTranscoders.at(streamIndex)->processFrame(); + switch(status) + { + case IOutputStream::eWrappingSuccess: + if(streamIndex == 0) + _processedFrames++; + + if(!continueProcess(progress)) + return false; + return true; + + case IOutputStream::eWrappingWaitingForData: + // the wrapper needs more data to write the current packet + if(streamIndex == 0) + _processedFrames++; + + if(!continueProcess(progress)) + return false; + + return processFrame(progress, streamIndex); + + case IOutputStream::eWrappingSkip: + return true; + + case IOutputStream::eWrappingError: + // if a stream failed to process LOG_WARN("Failed to process the stream transcoder at index " << streamIndex) // if this is the end of the main stream - if(streamIndex == _mainStreamIndex) { + if(streamIndex == _mainStreamIndex) LOG_INFO("End of process because the main stream at index " << _mainStreamIndex << " failed to process a new frame.") - return false; - } - } + + return false; } +} + +bool Transcoder::continueProcess(IProgress& progress) { + const float expectedOutputDuration = getExpectedOutputDuration(); + const float progressDuration = getCurrentOutputDuration(); + + // check if JobStatusCancel + if(progress.progress((progressDuration > expectedOutputDuration) ? expectedOutputDuration : progressDuration, + expectedOutputDuration) == eJobStatusCancel) + { + LOG_INFO("End of process because the job was canceled.") + return false; + } + + // check progressDuration + if(_eProcessMethod == eProcessMethodBasedOnDuration && progressDuration >= expectedOutputDuration) + { + LOG_INFO("End of process because the output program duration (" + << progressDuration << "s) is equal or upper than " << expectedOutputDuration << "s.") + return false; + } + return true; } @@ -205,36 +265,15 @@ ProcessStat Transcoder::process(IProgress& progress) const float expectedOutputDuration = getExpectedOutputDuration(); LOG_INFO("The expected output duration of the program will be " << expectedOutputDuration << "s.") - size_t frame = 0; bool frameProcessed = true; while(frameProcessed) { - LOG_DEBUG("Process frame " << frame) - frameProcessed = processFrame(); - ++frame; - - const float progressDuration = getCurrentOutputDuration(); - - // check if JobStatusCancel - if(progress.progress((progressDuration > expectedOutputDuration) ? expectedOutputDuration : progressDuration, - expectedOutputDuration) == eJobStatusCancel) - { - LOG_INFO("End of process because the job was canceled.") - break; - } - - // check progressDuration - if(_eProcessMethod == eProcessMethodBasedOnDuration && progressDuration >= expectedOutputDuration) - { - LOG_INFO("End of process because the output program duration (" - << progressDuration << "s) is equal or upper than " << expectedOutputDuration << "s.") - break; - } + LOG_INFO("Process frame " << _processedFrames); + frameProcessed = processFrame(progress); } _outputFile.endWrap(); - - LOG_INFO("End of process: " << ++frame << " frames processed") + LOG_INFO("End of process: " << ++_processedFrames << " frames processed") LOG_INFO("Get process statistics") ProcessStat processStat; diff --git a/src/AvTranscoder/transcoder/Transcoder.hpp b/src/AvTranscoder/transcoder/Transcoder.hpp index bc03b3dc..cc35c496 100644 --- a/src/AvTranscoder/transcoder/Transcoder.hpp +++ b/src/AvTranscoder/transcoder/Transcoder.hpp @@ -95,9 +95,11 @@ class AvExport Transcoder /** * @brief Process the next frame of all streams. + * @param progress: choose a progress, or create your own in C++ or in bindings by inherit IProgress class. * @return if a frame was processed or not. */ - bool processFrame(); + bool processFrame(IProgress& progress); + bool processFrame(); ///< Call processFrame with no display of progression /** * @brief Process all the streams, and ended the process depending on the transcode politic. @@ -190,6 +192,19 @@ class AvExport Transcoder */ void manageSwitchToGenerator(); + /** + * @brief Process the next frame of the specified stream. + * @return whether a frame was processed or not. + */ + bool processFrame(IProgress& progress, const size_t& streamIndex); + + /** + * @brief Check whether the process is canceled or not, and whether the process reached the ending condition. + * @note The progress is updated in this function. + * @return whether the process must continue or stop. + */ + bool continueProcess(IProgress& progress); + /** * @brief Fill the given ProcessStat to summarize the process. */ @@ -205,10 +220,11 @@ class AvExport Transcoder ProfileLoader _profileLoader; ///< Objet to get existing profiles, and add new ones for the Transcoder. EProcessMethod _eProcessMethod; ///< Processing policy - size_t - _mainStreamIndex; ///< Index of stream used to stop the process. - float _outputDuration; ///< Duration of output media used to stop the process of transcode in case of - /// eProcessMethodBasedOnDuration. + + size_t _mainStreamIndex; ///< Index of stream used to stop the process. + size_t _processedFrames; ///< Counter for the number of processed frames. + + float _outputDuration; ///< Duration of output media used to stop the process of transcode in case of eProcessMethodBasedOnDuration. }; } From f32fc1353745d01d1a48c9c0873f363e7d15692f Mon Sep 17 00:00:00 2001 From: Valentin NOEL Date: Wed, 12 Aug 2020 12:00:23 +0200 Subject: [PATCH 51/74] Bump version to 0.15.3 --- src/AvTranscoder/common.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/AvTranscoder/common.hpp b/src/AvTranscoder/common.hpp index 2aac5c6f..4645cce1 100644 --- a/src/AvTranscoder/common.hpp +++ b/src/AvTranscoder/common.hpp @@ -3,7 +3,7 @@ #define AVTRANSCODER_VERSION_MAJOR 0 #define AVTRANSCODER_VERSION_MINOR 15 -#define AVTRANSCODER_VERSION_MICRO 2 +#define AVTRANSCODER_VERSION_MICRO 3 #include From be100b807eef11ce5de1e51cfd29047d1d93de64 Mon Sep 17 00:00:00 2001 From: Valentin NOEL Date: Mon, 1 Feb 2021 12:48:40 +0100 Subject: [PATCH 52/74] Fix: don't unref and free audio filters data twice --- src/AvTranscoder/transcoder/StreamTranscoder.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/AvTranscoder/transcoder/StreamTranscoder.cpp b/src/AvTranscoder/transcoder/StreamTranscoder.cpp index edf47de3..af92b5d4 100644 --- a/src/AvTranscoder/transcoder/StreamTranscoder.cpp +++ b/src/AvTranscoder/transcoder/StreamTranscoder.cpp @@ -751,6 +751,12 @@ IOutputStream::EWrappingStatus StreamTranscoder::processTranscode() _transformedData->allocateData(); } } + else if(_filterGraph->hasFilters()) + { + LOG_DEBUG("Free filtered data") // filled from filter graph sink + av_frame_unref(&_filteredData->getAVFrame()); + _filteredData->freeData(); + } // Check decoding status bool continueProcess = true; @@ -805,12 +811,6 @@ IOutputStream::EWrappingStatus StreamTranscoder::processTranscode() LOG_DEBUG("Encode") _outputEncoder->encodeFrame(*_transformedData, data); - if(_filterGraph->hasFilters()) - { - LOG_DEBUG("Free filtered data") // filled from filter graph sink - av_frame_unref(&_filteredData->getAVFrame()); - _filteredData->freeData(); - } } else { From d4a39a9d5b9e4679e4ba6a50ea2df70437b82195 Mon Sep 17 00:00:00 2001 From: Valentin NOEL Date: Mon, 1 Feb 2021 14:50:08 +0100 Subject: [PATCH 53/74] Bump version to 0.15.4 --- src/AvTranscoder/common.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/AvTranscoder/common.hpp b/src/AvTranscoder/common.hpp index 4645cce1..5b809c60 100644 --- a/src/AvTranscoder/common.hpp +++ b/src/AvTranscoder/common.hpp @@ -3,7 +3,7 @@ #define AVTRANSCODER_VERSION_MAJOR 0 #define AVTRANSCODER_VERSION_MINOR 15 -#define AVTRANSCODER_VERSION_MICRO 3 +#define AVTRANSCODER_VERSION_MICRO 4 #include From 2e0fde378374b3683c7ae7d69643574008845068 Mon Sep 17 00:00:00 2001 From: Valentin NOEL Date: Wed, 27 Apr 2022 12:59:11 +0200 Subject: [PATCH 54/74] Fix: video filters support and audio filters memory leak Free video filters data at each process loop, but skip audio filters data frame. Improvement of be100b807eef11ce5de1e51cfd29047d1d93de64 fix --- src/AvTranscoder/transcoder/StreamTranscoder.cpp | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/AvTranscoder/transcoder/StreamTranscoder.cpp b/src/AvTranscoder/transcoder/StreamTranscoder.cpp index af92b5d4..0882144b 100644 --- a/src/AvTranscoder/transcoder/StreamTranscoder.cpp +++ b/src/AvTranscoder/transcoder/StreamTranscoder.cpp @@ -751,12 +751,6 @@ IOutputStream::EWrappingStatus StreamTranscoder::processTranscode() _transformedData->allocateData(); } } - else if(_filterGraph->hasFilters()) - { - LOG_DEBUG("Free filtered data") // filled from filter graph sink - av_frame_unref(&_filteredData->getAVFrame()); - _filteredData->freeData(); - } // Check decoding status bool continueProcess = true; @@ -811,6 +805,15 @@ IOutputStream::EWrappingStatus StreamTranscoder::processTranscode() LOG_DEBUG("Encode") _outputEncoder->encodeFrame(*_transformedData, data); + if(_filterGraph->hasFilters()) + { + LOG_DEBUG("Free filtered data") // filled from filter graph sink + if (_filteredData->isVideoFrame()) { + // Do not unref filter audio frame, to avoid reallocating it each time + av_frame_unref(&_filteredData->getAVFrame()); + } + _filteredData->freeData(); + } } else { From 40b5e9debc172f1976dc2c61ee2149b315a2ec88 Mon Sep 17 00:00:00 2001 From: Valentin NOEL Date: Wed, 27 Apr 2022 12:59:59 +0200 Subject: [PATCH 55/74] Bump version to 0.15.5 --- src/AvTranscoder/common.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/AvTranscoder/common.hpp b/src/AvTranscoder/common.hpp index 5b809c60..bfd80899 100644 --- a/src/AvTranscoder/common.hpp +++ b/src/AvTranscoder/common.hpp @@ -3,7 +3,7 @@ #define AVTRANSCODER_VERSION_MAJOR 0 #define AVTRANSCODER_VERSION_MINOR 15 -#define AVTRANSCODER_VERSION_MICRO 4 +#define AVTRANSCODER_VERSION_MICRO 5 #include From a78c4ae3158142f79048a12b5493b14001845a2e Mon Sep 17 00:00:00 2001 From: Valentin NOEL Date: Tue, 17 May 2022 10:20:20 +0200 Subject: [PATCH 56/74] Revert "CMake: remove patch version in the avtranscoder library name on Windows" This reverts commit c6744c1aa64af3faf8217e73f3369138a7ebf4e2. # Conflicts: # src/CMakeLists.txt --- src/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 0d7fbb9b..b9776da3 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -34,7 +34,7 @@ target_link_libraries(avtranscoder-static ${FFMPEG_LIBRARIES}) add_library(avtranscoder-shared SHARED ${AVTRANSCODER_SRC_FILES}) set_target_properties(avtranscoder-shared PROPERTIES LINKER_LANGUAGE CXX) if(WIN32) - set_target_properties(avtranscoder-shared PROPERTIES OUTPUT_NAME "avtranscoder-${AVTRANSCODER_VERSION_MAJOR}.${AVTRANSCODER_VERSION_MINOR}") + set_target_properties(avtranscoder-shared PROPERTIES OUTPUT_NAME "avtranscoder-${AVTRANSCODER_VERSION}") else() set_target_properties(avtranscoder-shared PROPERTIES OUTPUT_NAME avtranscoder) endif() @@ -154,7 +154,7 @@ if(SWIG_FOUND) # Create 'avtranscoder-java' shared lib swig_add_module(avtranscoder-java java ${AVTRANSCODER_BINDING_FILE}) if(WIN32) - set_target_properties(avtranscoder-java PROPERTIES OUTPUT_NAME "avtranscoder-java-${AVTRANSCODER_VERSION_MAJOR}.${AVTRANSCODER_VERSION_MINOR}") + set_target_properties(avtranscoder-java PROPERTIES OUTPUT_NAME "avtranscoder-java-${AVTRANSCODER_VERSION}") endif() if(NOT APPLE AND NOT WIN32) set_target_properties(${SWIG_MODULE_avtranscoder-java_REAL_NAME} PROPERTIES SOVERSION ${AVTRANSCODER_VERSION_MAJOR}) From 31947486b3791ea398c44bc781f019852ce3ea68 Mon Sep 17 00:00:00 2001 From: Valentin NOEL Date: Tue, 24 May 2022 16:57:01 +0200 Subject: [PATCH 57/74] Update to fit to FFmpeg 5.0 API --- src/AvTranscoder/Library.cpp | 1 + src/AvTranscoder/codec/ICodec.hpp | 3 +- src/AvTranscoder/data/coded/CodedData.cpp | 2 +- src/AvTranscoder/decoder/AudioDecoder.cpp | 19 ++++-- src/AvTranscoder/decoder/VideoDecoder.cpp | 15 +++- src/AvTranscoder/encoder/AudioEncoder.cpp | 22 +++++- src/AvTranscoder/encoder/VideoEncoder.cpp | 27 +++++++- src/AvTranscoder/file/FormatContext.cpp | 11 ++- src/AvTranscoder/file/FormatContext.hpp | 4 +- src/AvTranscoder/file/OutputFile.cpp | 68 +++++++++---------- src/AvTranscoder/filter/FilterGraph.cpp | 2 +- src/AvTranscoder/log.cpp | 2 +- .../properties/AudioProperties.cpp | 6 +- .../properties/DataProperties.cpp | 3 +- .../properties/FileProperties.cpp | 6 +- .../properties/PixelProperties.cpp | 17 +++-- .../properties/PixelProperties.hpp | 4 ++ .../properties/StreamProperties.cpp | 21 +++--- .../properties/StreamProperties.hpp | 2 +- .../properties/VideoProperties.cpp | 8 +-- src/AvTranscoder/stream/InputStream.cpp | 3 +- src/AvTranscoder/stream/OutputStream.cpp | 37 ++++++++-- src/AvTranscoder/stream/OutputStream.hpp | 1 + src/AvTranscoder/transcoder/Transcoder.cpp | 30 +++++++- 24 files changed, 215 insertions(+), 99 deletions(-) diff --git a/src/AvTranscoder/Library.cpp b/src/AvTranscoder/Library.cpp index 9c5ba23c..aed1f827 100644 --- a/src/AvTranscoder/Library.cpp +++ b/src/AvTranscoder/Library.cpp @@ -11,6 +11,7 @@ extern "C" { #else #include #endif +#include #include #include } diff --git a/src/AvTranscoder/codec/ICodec.hpp b/src/AvTranscoder/codec/ICodec.hpp index de3203dd..8ad135ee 100644 --- a/src/AvTranscoder/codec/ICodec.hpp +++ b/src/AvTranscoder/codec/ICodec.hpp @@ -54,7 +54,6 @@ class AvExport ICodec #ifndef SWIG AVCodecContext& getAVCodecContext() { return *_avCodecContext; } const AVCodecContext& getAVCodecContext() const { return *_avCodecContext; } - AVCodec& getAVCodec() { return *_avCodec; } const AVCodec& getAVCodec() const { return *_avCodec; } #endif @@ -66,7 +65,7 @@ class AvExport ICodec protected: AVCodecContext* _avCodecContext; ///< Full codec instance description (has ownership) - AVCodec* _avCodec; ///< Codec abstract description + const AVCodec* _avCodec; ///< Codec abstract description const bool _isCodecContextAllocated; ///< Is the AVCodecContext allocated by the class ECodecType _type; diff --git a/src/AvTranscoder/data/coded/CodedData.cpp b/src/AvTranscoder/data/coded/CodedData.cpp index 6247a0d6..074a0f83 100644 --- a/src/AvTranscoder/data/coded/CodedData.cpp +++ b/src/AvTranscoder/data/coded/CodedData.cpp @@ -87,7 +87,7 @@ void CodedData::assign(const size_t size, const int value) void CodedData::initAVPacket() { - av_init_packet(&_packet); + _packet = *av_packet_alloc(); _packet.data = NULL; _packet.size = 0; } diff --git a/src/AvTranscoder/decoder/AudioDecoder.cpp b/src/AvTranscoder/decoder/AudioDecoder.cpp index f1086fcc..1a7a7d99 100644 --- a/src/AvTranscoder/decoder/AudioDecoder.cpp +++ b/src/AvTranscoder/decoder/AudioDecoder.cpp @@ -87,7 +87,7 @@ bool AudioDecoder::decodeNextFrame(IFrame& frameBuffer) if(!_isSetup) setupDecoder(); - int got_frame = 0; + bool got_frame = false; while(!got_frame) { CodedData data; @@ -98,18 +98,27 @@ bool AudioDecoder::decodeNextFrame(IFrame& frameBuffer) // decoding // @note could be called several times to return the remaining frames (last call with an empty packet) // @see CODEC_CAP_DELAY - int ret = avcodec_decode_audio4(&_inputStream->getAudioCodec().getAVCodecContext(), &frameBuffer.getAVFrame(), - &got_frame, &data.getAVPacket()); + int ret = avcodec_send_packet(&_inputStream->getAudioCodec().getAVCodecContext(), &data.getAVPacket()); + if(ret < 0) { - throw std::runtime_error("An error occurred during audio decoding: " + getDescriptionFromErrorCode(ret)); + throw std::runtime_error("An error occurred sending audio packet to decoder: " + getDescriptionFromErrorCode(ret)); } + ret = avcodec_receive_frame(&_inputStream->getAudioCodec().getAVCodecContext(), &frameBuffer.getAVFrame()); + + if (ret == 0) + got_frame = true; + else if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) + got_frame = false; + else + throw std::runtime_error("An error occurred receiving audio packet from decoder: " + getDescriptionFromErrorCode(ret)); + // fixed channel layout value after decoding frameBuffer.getAVFrame().channel_layout = channelLayout; // if no frame could be decompressed - if(!nextPacketRead && ret == 0 && got_frame == 0) + if(!nextPacketRead && got_frame == 0) decodeNextFrame = false; else decodeNextFrame = true; diff --git a/src/AvTranscoder/decoder/VideoDecoder.cpp b/src/AvTranscoder/decoder/VideoDecoder.cpp index 3c1e1beb..03766ab9 100644 --- a/src/AvTranscoder/decoder/VideoDecoder.cpp +++ b/src/AvTranscoder/decoder/VideoDecoder.cpp @@ -94,13 +94,22 @@ bool VideoDecoder::decodeNextFrame(IFrame& frameBuffer) // decoding // @note could be called several times to return the remaining frames (last call with an empty packet) // @see CODEC_CAP_DELAY - const int ret = avcodec_decode_video2(&_inputStream->getVideoCodec().getAVCodecContext(), &frameBuffer.getAVFrame(), - &got_frame, &data.getAVPacket()); + int ret = avcodec_send_packet(&_inputStream->getVideoCodec().getAVCodecContext(), &data.getAVPacket()); + if(ret < 0) { - throw std::runtime_error("An error occurred during video decoding: " + getDescriptionFromErrorCode(ret)); + throw std::runtime_error("An error occurred sending video packet to decoder: " + getDescriptionFromErrorCode(ret)); } + ret = avcodec_receive_frame(&_inputStream->getAudioCodec().getAVCodecContext(), &frameBuffer.getAVFrame()); + + if (ret == 0) + got_frame = true; + else if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) + got_frame = false; + else + throw std::runtime_error("An error occurred receiving video packet from decoder: " + getDescriptionFromErrorCode(ret)); + // if no frame could be decompressed if(!nextPacketRead && ret == 0 && got_frame == 0) decodeNextFrame = false; diff --git a/src/AvTranscoder/encoder/AudioEncoder.cpp b/src/AvTranscoder/encoder/AudioEncoder.cpp index 0e83c0ed..710bc862 100644 --- a/src/AvTranscoder/encoder/AudioEncoder.cpp +++ b/src/AvTranscoder/encoder/AudioEncoder.cpp @@ -7,6 +7,7 @@ extern "C" { } #include +#include namespace avtranscoder { @@ -93,8 +94,6 @@ void AudioEncoder::setupEncoder(const ProfileLoader::Profile& profile) bool AudioEncoder::encodeFrame(const IFrame& sourceFrame, CodedData& codedFrame) { - AVCodecContext& avCodecContext = _codec.getAVCodecContext(); - AVPacket& packet = codedFrame.getAVPacket(); const AVFrame& srcAvFrame = sourceFrame.getAVFrame(); if(srcAvFrame.pts != (int)AV_NOPTS_VALUE) @@ -121,7 +120,24 @@ bool AudioEncoder::encode(const AVFrame* decodedData, AVPacket& encodedData) encodedData.data = NULL; AVCodecContext& avCodecContext = _codec.getAVCodecContext(); -#if LIBAVCODEC_VERSION_MAJOR > 53 +#if LIBAVCODEC_VERSION_MAJOR > 58 + int ret = avcodec_send_frame(&avCodecContext, decodedData); + if(ret != 0) + { + throw std::runtime_error("Error sending audio frame to encoder: " + getDescriptionFromErrorCode(ret)); + } + + ret = avcodec_receive_packet(&avCodecContext, &encodedData); + + if (ret == 0) + return true; + + if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) + return false; + + throw std::runtime_error("Error receiving audio frame from encoder: " + getDescriptionFromErrorCode(ret)); + +#elif LIBAVCODEC_VERSION_MAJOR > 53 int gotPacket = 0; const int ret = avcodec_encode_audio2(&avCodecContext, &encodedData, decodedData, &gotPacket); if(ret != 0) diff --git a/src/AvTranscoder/encoder/VideoEncoder.cpp b/src/AvTranscoder/encoder/VideoEncoder.cpp index 7d878d6a..e21aea63 100644 --- a/src/AvTranscoder/encoder/VideoEncoder.cpp +++ b/src/AvTranscoder/encoder/VideoEncoder.cpp @@ -110,8 +110,6 @@ void VideoEncoder::setupEncoder(const ProfileLoader::Profile& profile) bool VideoEncoder::encodeFrame(const IFrame& sourceFrame, CodedData& codedFrame) { - AVCodecContext& avCodecContext = _codec.getAVCodecContext(); - AVPacket& packet = codedFrame.getAVPacket(); const AVFrame& srcAvFrame = sourceFrame.getAVFrame(); if(srcAvFrame.pts != (int)AV_NOPTS_VALUE) @@ -138,7 +136,29 @@ bool VideoEncoder::encode(const AVFrame* decodedData, AVPacket& encodedData) encodedData.data = NULL; AVCodecContext& avCodecContext = _codec.getAVCodecContext(); -#if LIBAVCODEC_VERSION_MAJOR > 53 +#if LIBAVCODEC_VERSION_MAJOR > 58 + int ret = avcodec_send_frame(&avCodecContext, decodedData); + if(ret != 0) + { + throw std::runtime_error("Error sending video frame to encoder: " + getDescriptionFromErrorCode(ret)); + } + + ret = avcodec_receive_packet(&avCodecContext, &encodedData); + + if (ret == 0) + { + return true; + } + else if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) + { + return false; + } + else + { + throw std::runtime_error("Error receiving video frame from encoder: " + getDescriptionFromErrorCode(ret)); + } + +#elif LIBAVCODEC_VERSION_MAJOR > 53 int gotPacket = 0; const int ret = avcodec_encode_video2(&avCodecContext, &encodedData, decodedData, &gotPacket); if(ret != 0) @@ -146,6 +166,7 @@ bool VideoEncoder::encode(const AVFrame* decodedData, AVPacket& encodedData) throw std::runtime_error("Encode video frame error: avcodec encode video frame - " + getDescriptionFromErrorCode(ret)); } + return gotPacket == 1; #else const int ret = avcodec_encode_video(&avCodecContext, encodedData.data, encodedData.size, decodedData); diff --git a/src/AvTranscoder/file/FormatContext.cpp b/src/AvTranscoder/file/FormatContext.cpp index 51d78f4e..cd423e85 100644 --- a/src/AvTranscoder/file/FormatContext.cpp +++ b/src/AvTranscoder/file/FormatContext.cpp @@ -46,10 +46,6 @@ FormatContext::~FormatContext() if(!_avFormatContext) return; - // free the streams added - for(std::vector::iterator it = _avStreamAllocated.begin(); it != _avStreamAllocated.end(); ++it) - avcodec_close((*it)->codec); - // free the format context if(_isOpen) avformat_close_input(&_avFormatContext); @@ -151,7 +147,7 @@ AVStream& FormatContext::addAVStream(const AVCodec& avCodec) bool FormatContext::seek(const uint64_t position, const int flag) { - LOG_INFO("Seek in '" << _avFormatContext->filename << "' at " << position << " with flag '" << flag << "'") + LOG_INFO("Seek in '" << _avFormatContext->url << "' at " << position << " with flag '" << flag << "'") const int err = av_seek_frame(_avFormatContext, -1, position, flag); if(err < 0) { @@ -186,12 +182,13 @@ AVStream& FormatContext::getAVStream(size_t index) const void FormatContext::setFilename(const std::string& filename) { - strcpy(&_avFormatContext->filename[0], filename.c_str()); + _avFormatContext->url = (char*)av_malloc(filename.size()); + strcpy(_avFormatContext->url, filename.c_str()); } void FormatContext::setOutputFormat(const std::string& filename, const std::string& shortName, const std::string& mimeType) { - AVOutputFormat* oformat = av_guess_format(shortName.c_str(), filename.c_str(), mimeType.c_str()); + const AVOutputFormat* oformat = av_guess_format(shortName.c_str(), filename.c_str(), mimeType.c_str()); if(!oformat) { std::string msg("Unable to find format for "); diff --git a/src/AvTranscoder/file/FormatContext.hpp b/src/AvTranscoder/file/FormatContext.hpp index 0a33bbe1..b4283e19 100644 --- a/src/AvTranscoder/file/FormatContext.hpp +++ b/src/AvTranscoder/file/FormatContext.hpp @@ -113,8 +113,8 @@ class AvExport FormatContext #ifndef SWIG AVFormatContext& getAVFormatContext() const { return *_avFormatContext; } - AVOutputFormat& getAVOutputFormat() const { return *_avFormatContext->oformat; } - AVInputFormat& getAVInputFormat() const { return *_avFormatContext->iformat; } + const AVOutputFormat& getAVOutputFormat() const { return *_avFormatContext->oformat; } + const AVInputFormat& getAVInputFormat() const { return *_avFormatContext->iformat; } AVIOContext& getAVIOContext() const { return *_avFormatContext->pb; } AVDictionary& getAVMetaData() const { return *_avFormatContext->metadata; } AVStream& getAVStream(size_t index) const; diff --git a/src/AvTranscoder/file/OutputFile.cpp b/src/AvTranscoder/file/OutputFile.cpp index d446b431..142069e7 100644 --- a/src/AvTranscoder/file/OutputFile.cpp +++ b/src/AvTranscoder/file/OutputFile.cpp @@ -3,6 +3,7 @@ #include #include +#include #ifndef FF_INPUT_BUFFER_PADDING_SIZE #define FF_INPUT_BUFFER_PADDING_SIZE 16 @@ -35,31 +36,29 @@ IOutputStream& OutputFile::addVideoStream(const VideoCodec& videoDesc) { AVStream& stream = _formatContext.addAVStream(videoDesc.getAVCodec()); - stream.codec->width = videoDesc.getAVCodecContext().width; - stream.codec->height = videoDesc.getAVCodecContext().height; - stream.codec->bit_rate = videoDesc.getAVCodecContext().bit_rate; - stream.codec->pix_fmt = videoDesc.getAVCodecContext().pix_fmt; - stream.codec->profile = videoDesc.getAVCodecContext().profile; - stream.codec->level = videoDesc.getAVCodecContext().level; - stream.codec->field_order = videoDesc.getAVCodecContext().field_order; + stream.codecpar->width = videoDesc.getAVCodecContext().width; + stream.codecpar->height = videoDesc.getAVCodecContext().height; + stream.codecpar->bit_rate = videoDesc.getAVCodecContext().bit_rate; + stream.codecpar->format = videoDesc.getAVCodecContext().pix_fmt; + stream.codecpar->profile = videoDesc.getAVCodecContext().profile; + stream.codecpar->level = videoDesc.getAVCodecContext().level; + stream.codecpar->field_order = videoDesc.getAVCodecContext().field_order; - stream.codec->colorspace = videoDesc.getAVCodecContext().colorspace; - stream.codec->color_primaries = videoDesc.getAVCodecContext().color_primaries; - stream.codec->color_range = videoDesc.getAVCodecContext().color_range; - stream.codec->color_trc = videoDesc.getAVCodecContext().color_trc; - stream.codec->chroma_sample_location = videoDesc.getAVCodecContext().chroma_sample_location; + stream.codecpar->color_space = videoDesc.getAVCodecContext().colorspace; + stream.codecpar->color_primaries = videoDesc.getAVCodecContext().color_primaries; + stream.codecpar->color_range = videoDesc.getAVCodecContext().color_range; + stream.codecpar->color_trc = videoDesc.getAVCodecContext().color_trc; + stream.codecpar->chroma_location = videoDesc.getAVCodecContext().chroma_sample_location; setOutputStream(stream, videoDesc); // need to set the time_base on the AVCodecContext and the AVStream // compensating the frame rate with the ticks_per_frame and keeping // a coherent reading speed. - av_reduce(&stream.codec->time_base.num, &stream.codec->time_base.den, + av_reduce(&stream.time_base.num, &stream.time_base.den, videoDesc.getAVCodecContext().time_base.num * videoDesc.getAVCodecContext().ticks_per_frame, videoDesc.getAVCodecContext().time_base.den, INT_MAX); - stream.time_base = stream.codec->time_base; - OutputStream* outputStream = new OutputStream(*this, _formatContext.getNbStreams() - 1); _outputStreams.push_back(outputStream); @@ -70,16 +69,16 @@ IOutputStream& OutputFile::addAudioStream(const AudioCodec& audioDesc) { AVStream& stream = _formatContext.addAVStream(audioDesc.getAVCodec()); - stream.codec->sample_rate = audioDesc.getAVCodecContext().sample_rate; - stream.codec->channels = audioDesc.getAVCodecContext().channels; - stream.codec->channel_layout = audioDesc.getAVCodecContext().channel_layout; - stream.codec->sample_fmt = audioDesc.getAVCodecContext().sample_fmt; - stream.codec->frame_size = audioDesc.getAVCodecContext().frame_size; + stream.codecpar->sample_rate = audioDesc.getAVCodecContext().sample_rate; + stream.codecpar->channels = audioDesc.getAVCodecContext().channels; + stream.codecpar->channel_layout = audioDesc.getAVCodecContext().channel_layout; + stream.codecpar->format = audioDesc.getAVCodecContext().sample_fmt; + stream.codecpar->frame_size = audioDesc.getAVCodecContext().frame_size; setOutputStream(stream, audioDesc); // need to set the time_base on the AVCodecContext of the AVStream - av_reduce(&stream.codec->time_base.num, &stream.codec->time_base.den, audioDesc.getAVCodecContext().time_base.num, + av_reduce(&stream.time_base.num, &stream.time_base.den, audioDesc.getAVCodecContext().time_base.num, audioDesc.getAVCodecContext().time_base.den, INT_MAX); OutputStream* outputStream = new OutputStream(*this, _formatContext.getNbStreams() - 1); @@ -92,14 +91,14 @@ IOutputStream& OutputFile::addCustomStream(const ICodec& iCodecDesc) { AVStream& stream = _formatContext.addAVStream(iCodecDesc.getAVCodec()); - stream.codec->sample_rate = 48000; - stream.codec->channels = 1; - stream.codec->channel_layout = AV_CH_LAYOUT_MONO; - stream.codec->sample_fmt = AV_SAMPLE_FMT_S32; - stream.codec->frame_size = 1920; + stream.codecpar->sample_rate = 48000; + stream.codecpar->channels = 1; + stream.codecpar->channel_layout = AV_CH_LAYOUT_MONO; + stream.codecpar->format = AV_SAMPLE_FMT_S32; + stream.codecpar->frame_size = 1920; // need to set the time_base on the AVCodecContext of the AVStream - av_reduce(&stream.codec->time_base.num, &stream.codec->time_base.den, 1, 1, INT_MAX); + av_reduce(&stream.time_base.num, &stream.time_base.den, 1, 1, INT_MAX); OutputStream* outputStream = new OutputStream(*this, _formatContext.getNbStreams() - 1); _outputStreams.push_back(outputStream); @@ -136,7 +135,7 @@ IOutputStream& OutputFile::getStream(const size_t streamIndex) std::string OutputFile::getFilename() const { - return std::string(_formatContext.getAVFormatContext().filename); + return std::string(_formatContext.getAVFormatContext().url); } std::string OutputFile::getFormatName() const @@ -194,8 +193,7 @@ IOutputStream::EWrappingStatus OutputFile::wrap(const CodedData& data, const siz << _frameCount.at(streamIndex) << ")") // Packet to wrap - AVPacket packet; - av_init_packet(&packet); + AVPacket packet = *av_packet_alloc(); packet.stream_index = streamIndex; packet.data = (uint8_t*)data.getData(); packet.size = data.getSize(); @@ -348,6 +346,7 @@ void OutputFile::setupRemainingWrappingOptions() void OutputFile::setOutputStream(AVStream& avStream, const ICodec& codec) { +#if LIBAVCODEC_VERSION_MAJOR < 59 // depending on the format, place global headers in extradata instead of every keyframe if(_formatContext.getAVOutputFormat().flags & AVFMT_GLOBALHEADER) { @@ -368,13 +367,14 @@ void OutputFile::setOutputStream(AVStream& avStream, const ICodec& codec) LOG_WARN("This codec is considered experimental by libav/ffmpeg:" << codec.getCodecName()); avStream.codec->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL; } +#endif // some codecs need/can use extradata to decode uint8_t* srcExtradata = codec.getAVCodecContext().extradata; const int srcExtradataSize = codec.getAVCodecContext().extradata_size; - avStream.codec->extradata = (uint8_t*)av_malloc(srcExtradataSize + FF_INPUT_BUFFER_PADDING_SIZE); - memcpy(avStream.codec->extradata, srcExtradata, srcExtradataSize); - memset(((uint8_t*)avStream.codec->extradata) + srcExtradataSize, 0, FF_INPUT_BUFFER_PADDING_SIZE); - avStream.codec->extradata_size = codec.getAVCodecContext().extradata_size; + avStream.codecpar->extradata = (uint8_t*)av_malloc(srcExtradataSize + FF_INPUT_BUFFER_PADDING_SIZE); + memcpy(avStream.codecpar->extradata, srcExtradata, srcExtradataSize); + memset(((uint8_t*)avStream.codecpar->extradata) + srcExtradataSize, 0, FF_INPUT_BUFFER_PADDING_SIZE); + avStream.codecpar->extradata_size = codec.getAVCodecContext().extradata_size; } } diff --git a/src/AvTranscoder/filter/FilterGraph.cpp b/src/AvTranscoder/filter/FilterGraph.cpp index 8b960ef9..57b6ce2f 100644 --- a/src/AvTranscoder/filter/FilterGraph.cpp +++ b/src/AvTranscoder/filter/FilterGraph.cpp @@ -211,7 +211,7 @@ bool FilterGraph::areInputFrameSizesEqual(const std::vector& inputs) if(!inputs.size() || inputs.size() == 1) return true; - const int frameSize = inputs.at(0)->getDataSize(); + size_t frameSize = inputs.at(0)->getDataSize(); for(size_t index = 1; index < inputs.size(); ++index) { if(frameSize != inputs.at(index)->getDataSize()) diff --git a/src/AvTranscoder/log.cpp b/src/AvTranscoder/log.cpp index 5eab4325..98ffd649 100644 --- a/src/AvTranscoder/log.cpp +++ b/src/AvTranscoder/log.cpp @@ -56,7 +56,7 @@ void Logger::log(const int level, const std::string& msg) logMessage += "\n"; // send message - av_log(NULL, level, logMessage.c_str()); + av_log(NULL, level, "%s", logMessage.c_str()); } void Logger::logInFile() diff --git a/src/AvTranscoder/properties/AudioProperties.cpp b/src/AvTranscoder/properties/AudioProperties.cpp index cf5793ef..327edc24 100644 --- a/src/AvTranscoder/properties/AudioProperties.cpp +++ b/src/AvTranscoder/properties/AudioProperties.cpp @@ -47,6 +47,8 @@ std::string AudioProperties::getSampleFormatLongName() const return "signed 16 bits"; case AV_SAMPLE_FMT_S32: return "signed 32 bits"; + case AV_SAMPLE_FMT_S64: + return "signed 64 bits"; case AV_SAMPLE_FMT_FLT: return "float"; case AV_SAMPLE_FMT_DBL: @@ -57,6 +59,8 @@ std::string AudioProperties::getSampleFormatLongName() const return "signed 16 bits, planar"; case AV_SAMPLE_FMT_S32P: return "signed 32 bits, planar"; + case AV_SAMPLE_FMT_S64P: + return "signed 64 bits, planar"; case AV_SAMPLE_FMT_FLTP: return "float, planar"; case AV_SAMPLE_FMT_DBLP: @@ -113,7 +117,7 @@ size_t AudioProperties::getBitRate() const if(_codecContext->bit_rate) return _codecContext->bit_rate; - LOG_WARN("The bitrate of the stream '" << _streamIndex << "' of file '" << _formatContext->filename << "' is unknown.") + LOG_WARN("The bitrate of the stream '" << _streamIndex << "' of file '" << _formatContext->url << "' is unknown.") LOG_INFO("Compute the audio bitrate (suppose PCM audio data).") const int bitsPerSample = av_get_bits_per_sample(_codecContext->codec_id); // 0 if unknown for the given codec diff --git a/src/AvTranscoder/properties/DataProperties.cpp b/src/AvTranscoder/properties/DataProperties.cpp index af92b09a..f81a19c3 100644 --- a/src/AvTranscoder/properties/DataProperties.cpp +++ b/src/AvTranscoder/properties/DataProperties.cpp @@ -13,8 +13,7 @@ namespace avtranscoder void DataProperties::detectAncillaryData() { - AVPacket pkt; - av_init_packet(&pkt); + AVPacket pkt = *av_packet_alloc(); bool detection = false; diff --git a/src/AvTranscoder/properties/FileProperties.cpp b/src/AvTranscoder/properties/FileProperties.cpp index 6c135a7b..207850ac 100644 --- a/src/AvTranscoder/properties/FileProperties.cpp +++ b/src/AvTranscoder/properties/FileProperties.cpp @@ -47,7 +47,7 @@ void FileProperties::extractStreamProperties(IProgress& progress, const EAnalyse // reload properties for(size_t streamIndex = 0; streamIndex < _formatContext->getNbStreams(); ++streamIndex) { - switch(_formatContext->getAVStream(streamIndex).codec->codec_type) + switch(_formatContext->getAVStream(streamIndex).codecpar->codec_type) { case AVMEDIA_TYPE_VIDEO: { @@ -139,9 +139,9 @@ void FileProperties::extractStreamProperties(IProgress& progress, const EAnalyse std::string FileProperties::getFilename() const { - if(!_avFormatContext || !_avFormatContext->filename) + if(!_avFormatContext || !_avFormatContext->url) throw std::runtime_error("unknown file name"); - return _avFormatContext->filename; + return _avFormatContext->url; } std::string FileProperties::getFormatName() const diff --git a/src/AvTranscoder/properties/PixelProperties.cpp b/src/AvTranscoder/properties/PixelProperties.cpp index 9e58b298..48961d0a 100644 --- a/src/AvTranscoder/properties/PixelProperties.cpp +++ b/src/AvTranscoder/properties/PixelProperties.cpp @@ -204,12 +204,17 @@ bool PixelProperties::isRgbPixelData() const return (_pixelDesc->flags & AV_PIX_FMT_FLAG_RGB) == AV_PIX_FMT_FLAG_RGB; } -bool PixelProperties::isPseudoPaletted() const -{ - if(!_pixelDesc) +#if LIBAVCODEC_VERSION_MAJOR > 58 +bool PixelProperties::isPaletted() const { + if (!_pixelDesc) + throw std::runtime_error("unable to find pixel description."); + + return (_pixelDesc->flags & AV_PIX_FMT_FLAG_PAL) == AV_PIX_FMT_FLAG_PAL; +#elif LIBAVCODEC_VERSION_MAJOR > 53 +bool PixelProperties::isPseudoPaletted() const { + if (!_pixelDesc) throw std::runtime_error("unable to find pixel description."); -#if LIBAVCODEC_VERSION_MAJOR > 53 return (_pixelDesc->flags & AV_PIX_FMT_FLAG_PSEUDOPAL) == AV_PIX_FMT_FLAG_PSEUDOPAL; #else return false; @@ -315,7 +320,11 @@ PropertyVector& PixelProperties::fillVector(PropertyVector& data) const addProperty(data, "bitWiseAcked", &PixelProperties::isBitWisePacked); addProperty(data, "isHardwareAccelerated", &PixelProperties::isHardwareAccelerated); addProperty(data, "rgbPixel", &PixelProperties::isRgbPixelData); +#if LIBAVCODEC_VERSION_MAJOR > 58 + addProperty(data, "isPaletted", &PixelProperties::isPaletted); +#else addProperty(data, "isPseudoPaletted", &PixelProperties::isPseudoPaletted); +#endif try { diff --git a/src/AvTranscoder/properties/PixelProperties.hpp b/src/AvTranscoder/properties/PixelProperties.hpp index 5e087ef2..b5ba672c 100644 --- a/src/AvTranscoder/properties/PixelProperties.hpp +++ b/src/AvTranscoder/properties/PixelProperties.hpp @@ -71,7 +71,11 @@ class AvExport PixelProperties bool isBitWisePacked() const; bool isHardwareAccelerated() const; bool isRgbPixelData() const; +#if LIBAVCODEC_VERSION_MAJOR > 58 + bool isPaletted() const; +#else bool isPseudoPaletted() const; +#endif std::vector getChannels() const; diff --git a/src/AvTranscoder/properties/StreamProperties.cpp b/src/AvTranscoder/properties/StreamProperties.cpp index 2a860aeb..ced1b01a 100644 --- a/src/AvTranscoder/properties/StreamProperties.cpp +++ b/src/AvTranscoder/properties/StreamProperties.cpp @@ -27,19 +27,18 @@ StreamProperties::StreamProperties(const FileProperties& fileProperties, const s ss << "Stream at index " << _streamIndex << " does not exist."; throw std::runtime_error(ss.str()); } - _codecContext = _formatContext->streams[_streamIndex]->codec; + + _codec = avcodec_find_decoder(_formatContext->streams[_streamIndex]->codecpar->codec_id); + _codecContext = avcodec_alloc_context3(_codec); + + avcodec_parameters_to_context(_codecContext, _formatContext->streams[_streamIndex]->codecpar); } // find the decoder - if(_formatContext && _codecContext) + if(_formatContext && _codecContext && _codec) { - _codec = avcodec_find_decoder(_codecContext->codec_id); - - if(_codec) - { - // load specific options of the codec - loadOptions(_options, _codecContext); - } + // load specific options of the codec + loadOptions(_options, _codecContext); } } @@ -67,7 +66,7 @@ float StreamProperties::getDuration() const const size_t duration = _formatContext->streams[_streamIndex]->duration; if(duration == (size_t)AV_NOPTS_VALUE) { - LOG_WARN("The duration of the stream '" << _streamIndex << "' of file '" << _formatContext->filename + LOG_WARN("The duration of the stream '" << _streamIndex << "' of file '" << _formatContext->url << "' is unknown.") return 0; } @@ -78,7 +77,7 @@ AVMediaType StreamProperties::getStreamType() const { if(!_formatContext) throw std::runtime_error("unknown format context"); - return _formatContext->streams[_streamIndex]->codec->codec_type; + return _formatContext->streams[_streamIndex]->codecpar->codec_type; } size_t StreamProperties::getCodecId() const diff --git a/src/AvTranscoder/properties/StreamProperties.hpp b/src/AvTranscoder/properties/StreamProperties.hpp index 2820119b..fca5ffab 100644 --- a/src/AvTranscoder/properties/StreamProperties.hpp +++ b/src/AvTranscoder/properties/StreamProperties.hpp @@ -71,7 +71,7 @@ class AvExport StreamProperties const FileProperties* _fileProperties; ///< Has link (no ownership) const AVFormatContext* _formatContext; ///< Has link (no ownership) AVCodecContext* _codecContext; ///< Has link (no ownership) - AVCodec* _codec; ///< Has link (no ownership) + const AVCodec* _codec; ///< Has link (no ownership) size_t _streamIndex; PropertyVector _metadatas; diff --git a/src/AvTranscoder/properties/VideoProperties.cpp b/src/AvTranscoder/properties/VideoProperties.cpp index da9f5f39..e2ab5bbd 100644 --- a/src/AvTranscoder/properties/VideoProperties.cpp +++ b/src/AvTranscoder/properties/VideoProperties.cpp @@ -35,7 +35,7 @@ VideoProperties::VideoProperties(const FileProperties& fileProperties, const siz if(_codecContext) { _pixelProperties = PixelProperties(_codecContext->pix_fmt); - _firstGopTimeCode = _codecContext->timecode_frame_start; + _firstGopTimeCode = _formatContext->start_time; } switch(_levelAnalysis) @@ -350,7 +350,7 @@ size_t VideoProperties::getBitRate() const // return bit rate of stream if present or VBR mode if(_codecContext->bit_rate || _codecContext->rc_max_rate) return _codecContext->bit_rate; - LOG_WARN("The bitrate of the stream '" << _streamIndex << "' of file '" << _formatContext->filename << "' is unknown.") + LOG_WARN("The bitrate of the stream '" << _streamIndex << "' of file '" << _formatContext->url << "' is unknown.") if(_levelAnalysis == eAnalyseLevelHeader) { @@ -389,7 +389,7 @@ size_t VideoProperties::getNbFrames() const const size_t nbFrames = _formatContext->streams[_streamIndex]->nb_frames; if(nbFrames) return nbFrames; - LOG_WARN("The number of frames of the stream '" << _streamIndex << "' of file '" << _formatContext->filename + LOG_WARN("The number of frames of the stream '" << _streamIndex << "' of file '" << _formatContext->url << "' is unknown.") if(_levelAnalysis == eAnalyseLevelHeader) @@ -472,7 +472,7 @@ float VideoProperties::getDuration() const const float duration = StreamProperties::getDuration(); if(duration != 0) return duration; - LOG_WARN("The duration of the stream '" << _streamIndex << "' of file '" << _formatContext->filename << "' is unknown.") + LOG_WARN("The duration of the stream '" << _streamIndex << "' of file '" << _formatContext->url << "' is unknown.") if(_levelAnalysis == eAnalyseLevelHeader) { diff --git a/src/AvTranscoder/stream/InputStream.cpp b/src/AvTranscoder/stream/InputStream.cpp index ece61cc3..b2417e8d 100644 --- a/src/AvTranscoder/stream/InputStream.cpp +++ b/src/AvTranscoder/stream/InputStream.cpp @@ -21,7 +21,8 @@ InputStream::InputStream(InputFile& inputFile, const size_t streamIndex) , _streamIndex(streamIndex) , _isActivated(false) { - AVCodecContext* context = _inputFile->getFormatContext().getAVStream(_streamIndex).codec; + const AVCodec* codec = avcodec_find_encoder(_inputFile->getFormatContext().getAVStream(_streamIndex).codecpar->codec_id); + AVCodecContext* context = avcodec_alloc_context3(codec); switch(context->codec_type) { diff --git a/src/AvTranscoder/stream/OutputStream.cpp b/src/AvTranscoder/stream/OutputStream.cpp index 0c47d004..ea6ece68 100644 --- a/src/AvTranscoder/stream/OutputStream.cpp +++ b/src/AvTranscoder/stream/OutputStream.cpp @@ -11,11 +11,35 @@ OutputStream::OutputStream(OutputFile& outputFile, const size_t streamIndex) : IOutputStream() , _outputFile(outputFile) , _outputAVStream(outputFile.getFormatContext().getAVStream(streamIndex)) + , _codecContext() , _streamIndex(streamIndex) , _wrappedPacketsDuration(0) , _lastWrappedPacketDuration(0) , _isPTSGenerated(false) { + const AVCodec* codec = avcodec_find_decoder(_outputAVStream.codecpar->codec_id); + _codecContext = avcodec_alloc_context3(codec); + + avcodec_parameters_to_context(_codecContext, _outputAVStream.codecpar); + +#if LIBAVCODEC_VERSION_MAJOR > 58 + // depending on the format, place global headers in extradata instead of every keyframe +#ifdef AV_CODEC_FLAG_GLOBAL_HEADER + if(_outputFile.getFormatContext().getAVOutputFormat().flags & AVFMT_GLOBALHEADER) + { + _codecContext->flags |= AV_CODEC_FLAG_GLOBAL_HEADER; + } +#endif + + // if the codec is experimental, allow it +#ifdef AV_CODEC_CAP_EXPERIMENTAL + if(codec->capabilities & AV_CODEC_CAP_EXPERIMENTAL) + { + LOG_WARN("This codec is considered experimental by libav/ffmpeg:" << codec->name); + _codecContext->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL; + } +#endif +#endif } float OutputStream::getStreamDuration() const @@ -73,7 +97,7 @@ IOutputStream::EWrappingStatus OutputStream::wrap(const CodedData& data) _wrappedPacketsDuration += data.getAVPacket().duration; else { - switch(_outputAVStream.codec->codec_type) + switch(_outputAVStream.codecpar->codec_type) { case AVMEDIA_TYPE_VIDEO: { @@ -85,14 +109,13 @@ IOutputStream::EWrappingStatus OutputStream::wrap(const CodedData& data) Rational audioPacketDuration; audioPacketDuration.num = 0; audioPacketDuration.den = 0; - const int frame_size = av_get_audio_frame_duration(_outputAVStream.codec, data.getSize()); - if(frame_size <= 0 || _outputAVStream.codec->sample_rate <= 0) + const int frame_size = av_get_audio_frame_duration(_codecContext, data.getSize()); + if (frame_size <= 0 || _outputAVStream.codecpar->sample_rate <= 0) break; audioPacketDuration.num = frame_size; - audioPacketDuration.den = _outputAVStream.codec->sample_rate; - _wrappedPacketsDuration += av_rescale(1, audioPacketDuration.num * (int64_t)_outputAVStream.time_base.den * - _outputAVStream.codec->ticks_per_frame, - audioPacketDuration.den * (int64_t)_outputAVStream.time_base.num); + audioPacketDuration.den = _outputAVStream.codecpar->sample_rate; + _wrappedPacketsDuration += av_rescale(1, audioPacketDuration.num * (int64_t) _outputAVStream.time_base.den * _codecContext->ticks_per_frame, + audioPacketDuration.den * (int64_t) _outputAVStream.time_base.num); break; } default: diff --git a/src/AvTranscoder/stream/OutputStream.hpp b/src/AvTranscoder/stream/OutputStream.hpp index 4b2b3a48..b896edb7 100644 --- a/src/AvTranscoder/stream/OutputStream.hpp +++ b/src/AvTranscoder/stream/OutputStream.hpp @@ -26,6 +26,7 @@ class AvExport OutputStream : public IOutputStream private: OutputFile& _outputFile; ///< Has link (no ownership) const AVStream& _outputAVStream; ///< Has link (no ownership) + AVCodecContext* _codecContext; size_t _streamIndex; ///< Index of the stream in the output file diff --git a/src/AvTranscoder/transcoder/Transcoder.cpp b/src/AvTranscoder/transcoder/Transcoder.cpp index eb9895ed..0d578fff 100644 --- a/src/AvTranscoder/transcoder/Transcoder.cpp +++ b/src/AvTranscoder/transcoder/Transcoder.cpp @@ -217,6 +217,8 @@ bool Transcoder::processFrame(IProgress& progress, const size_t& streamIndex) LOG_INFO("End of process because the main stream at index " << _mainStreamIndex << " failed to process a new frame.") return false; + default: + throw std::runtime_error("Unsupported wrapping status"); } } @@ -658,13 +660,35 @@ void Transcoder::fillProcessStat(ProcessStat& processStat) const AVCodecContext& encoderContext = encoder->getCodec().getAVCodecContext(); #ifdef AV_CODEC_FLAG_PSNR - if(encoderContext.coded_frame && (encoderContext.flags & AV_CODEC_FLAG_PSNR)) + if(encoderContext.coded_side_data && encoderContext.coded_side_data->type == AV_PKT_DATA_QUALITY_FACTOR && (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] / + uint8_t* coded_frame = encoderContext.coded_side_data->data; + uint32_t quality = (uint32_t) coded_frame[3] << 24 | + (uint32_t) coded_frame[2] << 16 | + (uint32_t) coded_frame[1] << 8 | + (uint32_t) coded_frame[0]; + // uint8_t picture_type = coded_frame[4]; + uint8_t error_count = coded_frame[5]; + + uint64_t errors[error_count]; + for (int i = 0; i < error_count; ++i) + { + int index = 6 + i; + errors[i] = (uint64_t) coded_frame[index + 7] << 56 | + (uint64_t) coded_frame[index + 6] << 48 | + (uint64_t) coded_frame[index + 5] << 40 | + (uint64_t) coded_frame[index + 4] << 32 | + (uint64_t) coded_frame[index + 3] << 24 | + (uint64_t) coded_frame[2] << 16 | + (uint64_t) coded_frame[1] << 8 | + (uint64_t) coded_frame[0]; + } + + videoStat.setQuality(quality); + videoStat.setPSNR((double) errors[0] / (encoderContext.width * encoderContext.height * 255.0 * 255.0)); } } From 0f4a0662f7ba509c43306b6011e12ab8aca21769 Mon Sep 17 00:00:00 2001 From: Valentin NOEL Date: Tue, 24 May 2022 18:09:12 +0200 Subject: [PATCH 58/74] Fix encoding/decoding and codec context --- src/AvTranscoder/decoder/VideoDecoder.cpp | 8 +++----- src/AvTranscoder/encoder/AudioEncoder.cpp | 3 +-- src/AvTranscoder/encoder/VideoEncoder.cpp | 18 ++++++------------ src/AvTranscoder/file/OutputFile.cpp | 12 ++++++++++++ src/AvTranscoder/stream/InputStream.cpp | 7 ++++++- src/AvTranscoder/stream/OutputStream.cpp | 6 ++++-- 6 files changed, 32 insertions(+), 22 deletions(-) diff --git a/src/AvTranscoder/decoder/VideoDecoder.cpp b/src/AvTranscoder/decoder/VideoDecoder.cpp index 03766ab9..447913be 100644 --- a/src/AvTranscoder/decoder/VideoDecoder.cpp +++ b/src/AvTranscoder/decoder/VideoDecoder.cpp @@ -96,12 +96,10 @@ bool VideoDecoder::decodeNextFrame(IFrame& frameBuffer) // @see CODEC_CAP_DELAY int ret = avcodec_send_packet(&_inputStream->getVideoCodec().getAVCodecContext(), &data.getAVPacket()); - if(ret < 0) - { + if (ret < 0 && (nextPacketRead || ret != AVERROR_EOF)) throw std::runtime_error("An error occurred sending video packet to decoder: " + getDescriptionFromErrorCode(ret)); - } - ret = avcodec_receive_frame(&_inputStream->getAudioCodec().getAVCodecContext(), &frameBuffer.getAVFrame()); + ret = avcodec_receive_frame(&_inputStream->getVideoCodec().getAVCodecContext(), &frameBuffer.getAVFrame()); if (ret == 0) got_frame = true; @@ -111,7 +109,7 @@ bool VideoDecoder::decodeNextFrame(IFrame& frameBuffer) throw std::runtime_error("An error occurred receiving video packet from decoder: " + getDescriptionFromErrorCode(ret)); // if no frame could be decompressed - if(!nextPacketRead && ret == 0 && got_frame == 0) + if ((!nextPacketRead && ret == 0) || !got_frame) decodeNextFrame = false; else decodeNextFrame = true; diff --git a/src/AvTranscoder/encoder/AudioEncoder.cpp b/src/AvTranscoder/encoder/AudioEncoder.cpp index 710bc862..0b0621d6 100644 --- a/src/AvTranscoder/encoder/AudioEncoder.cpp +++ b/src/AvTranscoder/encoder/AudioEncoder.cpp @@ -122,10 +122,9 @@ bool AudioEncoder::encode(const AVFrame* decodedData, AVPacket& encodedData) AVCodecContext& avCodecContext = _codec.getAVCodecContext(); #if LIBAVCODEC_VERSION_MAJOR > 58 int ret = avcodec_send_frame(&avCodecContext, decodedData); + if(ret != 0) - { throw std::runtime_error("Error sending audio frame to encoder: " + getDescriptionFromErrorCode(ret)); - } ret = avcodec_receive_packet(&avCodecContext, &encodedData); diff --git a/src/AvTranscoder/encoder/VideoEncoder.cpp b/src/AvTranscoder/encoder/VideoEncoder.cpp index e21aea63..d8662ff8 100644 --- a/src/AvTranscoder/encoder/VideoEncoder.cpp +++ b/src/AvTranscoder/encoder/VideoEncoder.cpp @@ -138,25 +138,19 @@ bool VideoEncoder::encode(const AVFrame* decodedData, AVPacket& encodedData) AVCodecContext& avCodecContext = _codec.getAVCodecContext(); #if LIBAVCODEC_VERSION_MAJOR > 58 int ret = avcodec_send_frame(&avCodecContext, decodedData); - if(ret != 0) - { + + if (ret != 0 && ret != AVERROR_EOF) throw std::runtime_error("Error sending video frame to encoder: " + getDescriptionFromErrorCode(ret)); - } ret = avcodec_receive_packet(&avCodecContext, &encodedData); if (ret == 0) - { return true; - } - else if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) - { + + if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) return false; - } - else - { - throw std::runtime_error("Error receiving video frame from encoder: " + getDescriptionFromErrorCode(ret)); - } + + throw std::runtime_error("Error receiving video frame from encoder: " + getDescriptionFromErrorCode(ret)); #elif LIBAVCODEC_VERSION_MAJOR > 53 int gotPacket = 0; diff --git a/src/AvTranscoder/file/OutputFile.cpp b/src/AvTranscoder/file/OutputFile.cpp index 142069e7..49711abc 100644 --- a/src/AvTranscoder/file/OutputFile.cpp +++ b/src/AvTranscoder/file/OutputFile.cpp @@ -36,6 +36,10 @@ IOutputStream& OutputFile::addVideoStream(const VideoCodec& videoDesc) { AVStream& stream = _formatContext.addAVStream(videoDesc.getAVCodec()); + stream.codecpar->codec_type = videoDesc.getAVCodecContext().codec_type; + stream.codecpar->codec_id = videoDesc.getAVCodecContext().codec_id; + stream.codecpar->codec_tag = videoDesc.getAVCodecContext().codec_tag; + stream.codecpar->width = videoDesc.getAVCodecContext().width; stream.codecpar->height = videoDesc.getAVCodecContext().height; stream.codecpar->bit_rate = videoDesc.getAVCodecContext().bit_rate; @@ -69,6 +73,10 @@ IOutputStream& OutputFile::addAudioStream(const AudioCodec& audioDesc) { AVStream& stream = _formatContext.addAVStream(audioDesc.getAVCodec()); + stream.codecpar->codec_type = audioDesc.getAVCodecContext().codec_type; + stream.codecpar->codec_id = audioDesc.getAVCodecContext().codec_id; + stream.codecpar->codec_tag = audioDesc.getAVCodecContext().codec_tag; + stream.codecpar->sample_rate = audioDesc.getAVCodecContext().sample_rate; stream.codecpar->channels = audioDesc.getAVCodecContext().channels; stream.codecpar->channel_layout = audioDesc.getAVCodecContext().channel_layout; @@ -91,6 +99,10 @@ IOutputStream& OutputFile::addCustomStream(const ICodec& iCodecDesc) { AVStream& stream = _formatContext.addAVStream(iCodecDesc.getAVCodec()); + stream.codecpar->codec_type = iCodecDesc.getAVCodecContext().codec_type; + stream.codecpar->codec_id = iCodecDesc.getAVCodecContext().codec_id; + stream.codecpar->codec_tag = iCodecDesc.getAVCodecContext().codec_tag; + stream.codecpar->sample_rate = 48000; stream.codecpar->channels = 1; stream.codecpar->channel_layout = AV_CH_LAYOUT_MONO; diff --git a/src/AvTranscoder/stream/InputStream.cpp b/src/AvTranscoder/stream/InputStream.cpp index b2417e8d..6a13578a 100644 --- a/src/AvTranscoder/stream/InputStream.cpp +++ b/src/AvTranscoder/stream/InputStream.cpp @@ -21,8 +21,13 @@ InputStream::InputStream(InputFile& inputFile, const size_t streamIndex) , _streamIndex(streamIndex) , _isActivated(false) { - const AVCodec* codec = avcodec_find_encoder(_inputFile->getFormatContext().getAVStream(_streamIndex).codecpar->codec_id); + AVCodecParameters* codecParameters = _inputFile->getFormatContext().getAVStream(_streamIndex).codecpar; + const AVCodec* codec = avcodec_find_decoder(codecParameters->codec_id); AVCodecContext* context = avcodec_alloc_context3(codec); + int ret = avcodec_parameters_to_context(context, codecParameters); + + if (ret < 0) + throw std::runtime_error("Failed to copy decoder parameters to input stream context"); switch(context->codec_type) { diff --git a/src/AvTranscoder/stream/OutputStream.cpp b/src/AvTranscoder/stream/OutputStream.cpp index ea6ece68..92034dc6 100644 --- a/src/AvTranscoder/stream/OutputStream.cpp +++ b/src/AvTranscoder/stream/OutputStream.cpp @@ -17,10 +17,12 @@ OutputStream::OutputStream(OutputFile& outputFile, const size_t streamIndex) , _lastWrappedPacketDuration(0) , _isPTSGenerated(false) { - const AVCodec* codec = avcodec_find_decoder(_outputAVStream.codecpar->codec_id); + const AVCodec* codec = avcodec_find_encoder(_outputAVStream.codecpar->codec_id); _codecContext = avcodec_alloc_context3(codec); - avcodec_parameters_to_context(_codecContext, _outputAVStream.codecpar); + int ret = avcodec_parameters_to_context(_codecContext, _outputAVStream.codecpar); + if (ret < 0) + throw std::runtime_error("Failed to copy encoder parameters to output stream context"); #if LIBAVCODEC_VERSION_MAJOR > 58 // depending on the format, place global headers in extradata instead of every keyframe From b030fd32ee09a285c43ecbdede77574fcb1e6393 Mon Sep 17 00:00:00 2001 From: Valentin NOEL Date: Wed, 25 May 2022 11:57:30 +0200 Subject: [PATCH 59/74] Set decoder context time base --- src/AvTranscoder/stream/InputStream.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/AvTranscoder/stream/InputStream.cpp b/src/AvTranscoder/stream/InputStream.cpp index 6a13578a..31072a1c 100644 --- a/src/AvTranscoder/stream/InputStream.cpp +++ b/src/AvTranscoder/stream/InputStream.cpp @@ -21,10 +21,14 @@ InputStream::InputStream(InputFile& inputFile, const size_t streamIndex) , _streamIndex(streamIndex) , _isActivated(false) { - AVCodecParameters* codecParameters = _inputFile->getFormatContext().getAVStream(_streamIndex).codecpar; + AVStream& avStream = _inputFile->getFormatContext().getAVStream(_streamIndex); + AVCodecParameters* codecParameters = avStream.codecpar; + const AVCodec* codec = avcodec_find_decoder(codecParameters->codec_id); AVCodecContext* context = avcodec_alloc_context3(codec); + int ret = avcodec_parameters_to_context(context, codecParameters); + context->time_base = avStream.time_base; if (ret < 0) throw std::runtime_error("Failed to copy decoder parameters to input stream context"); From c7b1c99fc62b6864da2d167eb118f3b5ff6622eb Mon Sep 17 00:00:00 2001 From: Valentin NOEL Date: Wed, 25 May 2022 12:27:02 +0200 Subject: [PATCH 60/74] Fix minor memory leak --- src/AvTranscoder/properties/StreamProperties.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/AvTranscoder/properties/StreamProperties.cpp b/src/AvTranscoder/properties/StreamProperties.cpp index ced1b01a..38a6be72 100644 --- a/src/AvTranscoder/properties/StreamProperties.cpp +++ b/src/AvTranscoder/properties/StreamProperties.cpp @@ -44,6 +44,7 @@ StreamProperties::StreamProperties(const FileProperties& fileProperties, const s StreamProperties::~StreamProperties() { + avcodec_free_context(&_codecContext); } size_t StreamProperties::getStreamId() const From 59f17bff6ef027eb422a7bc5fb619806a100e0c9 Mon Sep 17 00:00:00 2001 From: Valentin NOEL Date: Wed, 25 May 2022 12:27:42 +0200 Subject: [PATCH 61/74] Bump version to 0.16.0 --- src/AvTranscoder/common.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/AvTranscoder/common.hpp b/src/AvTranscoder/common.hpp index bfd80899..8829bec0 100644 --- a/src/AvTranscoder/common.hpp +++ b/src/AvTranscoder/common.hpp @@ -2,8 +2,8 @@ #define _AV_TRANSCODER_COMMON_HPP_ #define AVTRANSCODER_VERSION_MAJOR 0 -#define AVTRANSCODER_VERSION_MINOR 15 -#define AVTRANSCODER_VERSION_MICRO 5 +#define AVTRANSCODER_VERSION_MINOR 16 +#define AVTRANSCODER_VERSION_MICRO 0 #include From e35eb45e7f45739da39ba0f9d0b23c2940f4e5db Mon Sep 17 00:00:00 2001 From: Valentin NOEL Date: Thu, 2 Jun 2022 18:00:57 +0200 Subject: [PATCH 62/74] Fix compilation with MSVC error C2131: expression did not evaluate to a constant --- src/AvTranscoder/transcoder/Transcoder.cpp | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/src/AvTranscoder/transcoder/Transcoder.cpp b/src/AvTranscoder/transcoder/Transcoder.cpp index 0d578fff..9db3174b 100644 --- a/src/AvTranscoder/transcoder/Transcoder.cpp +++ b/src/AvTranscoder/transcoder/Transcoder.cpp @@ -673,22 +673,24 @@ void Transcoder::fillProcessStat(ProcessStat& processStat) // uint8_t picture_type = coded_frame[4]; uint8_t error_count = coded_frame[5]; - uint64_t errors[error_count]; + std::vector errors; for (int i = 0; i < error_count; ++i) { int index = 6 + i; - errors[i] = (uint64_t) coded_frame[index + 7] << 56 | - (uint64_t) coded_frame[index + 6] << 48 | - (uint64_t) coded_frame[index + 5] << 40 | - (uint64_t) coded_frame[index + 4] << 32 | - (uint64_t) coded_frame[index + 3] << 24 | - (uint64_t) coded_frame[2] << 16 | - (uint64_t) coded_frame[1] << 8 | - (uint64_t) coded_frame[0]; + errors.push_back( + (uint64_t) coded_frame[index + 7] << 56 | + (uint64_t) coded_frame[index + 6] << 48 | + (uint64_t) coded_frame[index + 5] << 40 | + (uint64_t) coded_frame[index + 4] << 32 | + (uint64_t) coded_frame[index + 3] << 24 | + (uint64_t) coded_frame[2] << 16 | + (uint64_t) coded_frame[1] << 8 | + (uint64_t) coded_frame[0] + ); } videoStat.setQuality(quality); - videoStat.setPSNR((double) errors[0] / + videoStat.setPSNR((double) errors.at(0) / (encoderContext.width * encoderContext.height * 255.0 * 255.0)); } } From cac5c3740ab1d0dcd776e9fa2a3a98fd3b981569 Mon Sep 17 00:00:00 2001 From: Valentin NOEL Date: Thu, 2 Jun 2022 18:09:47 +0200 Subject: [PATCH 63/74] Remove PixelProperties::isPseudoPaletted() function --- src/AvTranscoder/properties/PixelProperties.cpp | 10 ---------- src/AvTranscoder/properties/PixelProperties.hpp | 4 ---- 2 files changed, 14 deletions(-) diff --git a/src/AvTranscoder/properties/PixelProperties.cpp b/src/AvTranscoder/properties/PixelProperties.cpp index 48961d0a..1ca56fe3 100644 --- a/src/AvTranscoder/properties/PixelProperties.cpp +++ b/src/AvTranscoder/properties/PixelProperties.cpp @@ -204,21 +204,11 @@ bool PixelProperties::isRgbPixelData() const return (_pixelDesc->flags & AV_PIX_FMT_FLAG_RGB) == AV_PIX_FMT_FLAG_RGB; } -#if LIBAVCODEC_VERSION_MAJOR > 58 bool PixelProperties::isPaletted() const { if (!_pixelDesc) throw std::runtime_error("unable to find pixel description."); return (_pixelDesc->flags & AV_PIX_FMT_FLAG_PAL) == AV_PIX_FMT_FLAG_PAL; -#elif LIBAVCODEC_VERSION_MAJOR > 53 -bool PixelProperties::isPseudoPaletted() const { - if (!_pixelDesc) - throw std::runtime_error("unable to find pixel description."); - - return (_pixelDesc->flags & AV_PIX_FMT_FLAG_PSEUDOPAL) == AV_PIX_FMT_FLAG_PSEUDOPAL; -#else - return false; -#endif } std::vector PixelProperties::getChannels() const diff --git a/src/AvTranscoder/properties/PixelProperties.hpp b/src/AvTranscoder/properties/PixelProperties.hpp index b5ba672c..56607ce8 100644 --- a/src/AvTranscoder/properties/PixelProperties.hpp +++ b/src/AvTranscoder/properties/PixelProperties.hpp @@ -71,11 +71,7 @@ class AvExport PixelProperties bool isBitWisePacked() const; bool isHardwareAccelerated() const; bool isRgbPixelData() const; -#if LIBAVCODEC_VERSION_MAJOR > 58 bool isPaletted() const; -#else - bool isPseudoPaletted() const; -#endif std::vector getChannels() const; From 69e9bda14f3d3ee415f3fcbe4b800539cd1b7b6c Mon Sep 17 00:00:00 2001 From: Valentin NOEL Date: Fri, 3 Jun 2022 14:32:08 +0200 Subject: [PATCH 64/74] Properties: fix double free corruption --- src/AvTranscoder/properties/StreamProperties.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/AvTranscoder/properties/StreamProperties.cpp b/src/AvTranscoder/properties/StreamProperties.cpp index 38a6be72..ced1b01a 100644 --- a/src/AvTranscoder/properties/StreamProperties.cpp +++ b/src/AvTranscoder/properties/StreamProperties.cpp @@ -44,7 +44,6 @@ StreamProperties::StreamProperties(const FileProperties& fileProperties, const s StreamProperties::~StreamProperties() { - avcodec_free_context(&_codecContext); } size_t StreamProperties::getStreamId() const From e6b0d05fe68ca39344e793fdb1fa21ac10ffeffd Mon Sep 17 00:00:00 2001 From: Valentin NOEL Date: Tue, 14 Jun 2022 15:17:37 +0200 Subject: [PATCH 65/74] VideoProperties: extract min and max bitrate from CPB side data if necessary --- src/AvTranscoder/properties/StreamProperties.cpp | 7 +++++-- src/AvTranscoder/properties/VideoProperties.cpp | 16 ++++++++++++++++ 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/src/AvTranscoder/properties/StreamProperties.cpp b/src/AvTranscoder/properties/StreamProperties.cpp index ced1b01a..a0e6cac1 100644 --- a/src/AvTranscoder/properties/StreamProperties.cpp +++ b/src/AvTranscoder/properties/StreamProperties.cpp @@ -28,10 +28,13 @@ StreamProperties::StreamProperties(const FileProperties& fileProperties, const s throw std::runtime_error(ss.str()); } - _codec = avcodec_find_decoder(_formatContext->streams[_streamIndex]->codecpar->codec_id); + AVStream* stream = _formatContext->streams[_streamIndex]; + _codec = avcodec_find_decoder(stream->codecpar->codec_id); _codecContext = avcodec_alloc_context3(_codec); - avcodec_parameters_to_context(_codecContext, _formatContext->streams[_streamIndex]->codecpar); + avcodec_parameters_to_context(_codecContext, stream->codecpar); + _codecContext->time_base = stream->time_base; + _codecContext->coded_side_data = stream->side_data; } // find the decoder diff --git a/src/AvTranscoder/properties/VideoProperties.cpp b/src/AvTranscoder/properties/VideoProperties.cpp index e2ab5bbd..d61dcede 100644 --- a/src/AvTranscoder/properties/VideoProperties.cpp +++ b/src/AvTranscoder/properties/VideoProperties.cpp @@ -371,6 +371,14 @@ size_t VideoProperties::getMaxBitRate() const { if(!_codecContext) throw std::runtime_error("unknown codec context"); + + if (_codecContext->rc_max_rate == 0 + && _codecContext->coded_side_data + && _codecContext->coded_side_data->type == AV_PKT_DATA_CPB_PROPERTIES) { + const AVCPBProperties* prop = (AVCPBProperties*) _codecContext->coded_side_data->data; + return prop->max_bitrate; + } + return _codecContext->rc_max_rate; } @@ -378,6 +386,14 @@ size_t VideoProperties::getMinBitRate() const { if(!_codecContext) throw std::runtime_error("unknown codec context"); + + if (_codecContext->rc_max_rate == 0 + && _codecContext->coded_side_data + && _codecContext->coded_side_data->type == AV_PKT_DATA_CPB_PROPERTIES) { + const AVCPBProperties* prop = (AVCPBProperties*) _codecContext->coded_side_data->data; + return prop->min_bitrate; + } + return _codecContext->rc_min_rate; } From 068073911de395e2becbe9facf849bc055eca502 Mon Sep 17 00:00:00 2001 From: Valentin NOEL Date: Tue, 14 Jun 2022 16:59:50 +0200 Subject: [PATCH 66/74] Applications: generate versionned executable on Windows --- app/avAudioPhaseMeter/CMakeLists.txt | 2 +- app/avInfo/CMakeLists.txt | 2 +- app/avMeta/CMakeLists.txt | 2 +- app/avPlayer/CMakeLists.txt | 2 +- app/avProcessor/CMakeLists.txt | 2 +- app/customEncoder/CMakeLists.txt | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/app/avAudioPhaseMeter/CMakeLists.txt b/app/avAudioPhaseMeter/CMakeLists.txt index 4ed40d42..812b8d9e 100644 --- a/app/avAudioPhaseMeter/CMakeLists.txt +++ b/app/avAudioPhaseMeter/CMakeLists.txt @@ -11,7 +11,7 @@ target_link_libraries(avaudiophasemeter avtranscoder-shared) # Install app if(WIN32) - set(BINARY_FILES "${CMAKE_CURRENT_BINARY_DIR}/avaudiophasemeter.exe") + set(BINARY_FILES "${CMAKE_CURRENT_BINARY_DIR}/avaudiophasemeter.exe" "${CMAKE_CURRENT_BINARY_DIR}/avaudiophasemeter-${AVTRANSCODER_VERSION}.exe") else() set(BINARY_FILES "${CMAKE_CURRENT_BINARY_DIR}/avaudiophasemeter" "${CMAKE_CURRENT_BINARY_DIR}/avaudiophasemeter-${AVTRANSCODER_VERSION}") endif() diff --git a/app/avInfo/CMakeLists.txt b/app/avInfo/CMakeLists.txt index 4cba2e5e..cd165a75 100644 --- a/app/avInfo/CMakeLists.txt +++ b/app/avInfo/CMakeLists.txt @@ -11,7 +11,7 @@ target_link_libraries(avinfo avtranscoder-shared) # Install app if(WIN32) - set(BINARY_FILES "${CMAKE_CURRENT_BINARY_DIR}/avinfo.exe") + set(BINARY_FILES "${CMAKE_CURRENT_BINARY_DIR}/avinfo.exe" "${CMAKE_CURRENT_BINARY_DIR}/avinfo-${AVTRANSCODER_VERSION}.exe") else() set(BINARY_FILES "${CMAKE_CURRENT_BINARY_DIR}/avinfo" "${CMAKE_CURRENT_BINARY_DIR}/avinfo-${AVTRANSCODER_VERSION}") endif() diff --git a/app/avMeta/CMakeLists.txt b/app/avMeta/CMakeLists.txt index b12c99c9..bdc67260 100644 --- a/app/avMeta/CMakeLists.txt +++ b/app/avMeta/CMakeLists.txt @@ -11,7 +11,7 @@ target_link_libraries(avmeta avtranscoder-shared) # Install app if(WIN32) - set(BINARY_FILES "${CMAKE_CURRENT_BINARY_DIR}/avmeta.exe") + set(BINARY_FILES "${CMAKE_CURRENT_BINARY_DIR}/avmeta.exe" "${CMAKE_CURRENT_BINARY_DIR}/avmeta-${AVTRANSCODER_VERSION}.exe") else() set(BINARY_FILES "${CMAKE_CURRENT_BINARY_DIR}/avmeta" "${CMAKE_CURRENT_BINARY_DIR}/avmeta-${AVTRANSCODER_VERSION}") endif() diff --git a/app/avPlayer/CMakeLists.txt b/app/avPlayer/CMakeLists.txt index bf735c2e..dec775f2 100644 --- a/app/avPlayer/CMakeLists.txt +++ b/app/avPlayer/CMakeLists.txt @@ -33,7 +33,7 @@ target_link_libraries(avplayer avtranscoder-shared ${OPENGL_LIBRARIES} ${GLUT_LI # Install app if(WIN32) - set(BINARY_FILES "${CMAKE_CURRENT_BINARY_DIR}/avplayer.exe") + set(BINARY_FILES "${CMAKE_CURRENT_BINARY_DIR}/avplayer.exe" "${CMAKE_CURRENT_BINARY_DIR}/avplayer-${AVTRANSCODER_VERSION}.exe") else() set(BINARY_FILES "${CMAKE_CURRENT_BINARY_DIR}/avplayer" "${CMAKE_CURRENT_BINARY_DIR}/avplayer-${AVTRANSCODER_VERSION}") endif() diff --git a/app/avProcessor/CMakeLists.txt b/app/avProcessor/CMakeLists.txt index 4cb1a118..eb91477f 100644 --- a/app/avProcessor/CMakeLists.txt +++ b/app/avProcessor/CMakeLists.txt @@ -11,7 +11,7 @@ target_link_libraries(avprocessor avtranscoder-shared) # Install app if(WIN32) - set(BINARY_FILES "${CMAKE_CURRENT_BINARY_DIR}/avprocessor.exe") + set(BINARY_FILES "${CMAKE_CURRENT_BINARY_DIR}/avprocessor.exe" "${CMAKE_CURRENT_BINARY_DIR}/avprocessor-${AVTRANSCODER_VERSION}.exe") else() set(BINARY_FILES "${CMAKE_CURRENT_BINARY_DIR}/avprocessor" "${CMAKE_CURRENT_BINARY_DIR}/avprocessor-${AVTRANSCODER_VERSION}") endif() diff --git a/app/customEncoder/CMakeLists.txt b/app/customEncoder/CMakeLists.txt index 2c7e55d2..0eb6286b 100644 --- a/app/customEncoder/CMakeLists.txt +++ b/app/customEncoder/CMakeLists.txt @@ -11,7 +11,7 @@ target_link_libraries(custom-encoder avtranscoder-shared) # Install app if(WIN32) - set(BINARY_FILES "${CMAKE_CURRENT_BINARY_DIR}/custom-encoder.exe") + set(BINARY_FILES "${CMAKE_CURRENT_BINARY_DIR}/custom-encoder.exe" "${CMAKE_CURRENT_BINARY_DIR}/custom-encoder-${AVTRANSCODER_VERSION}.exe") else() set(BINARY_FILES "${CMAKE_CURRENT_BINARY_DIR}/custom-encoder" "${CMAKE_CURRENT_BINARY_DIR}/custom-encoder-${AVTRANSCODER_VERSION}") endif() From 2069c5d1e895e803086d251750e22147687fcd9d Mon Sep 17 00:00:00 2001 From: Valentin NOEL Date: Tue, 14 Jun 2022 16:37:27 +0200 Subject: [PATCH 67/74] Applications: set version to executable on Windows --- app/avAudioPhaseMeter/CMakeLists.txt | 1 + app/avInfo/CMakeLists.txt | 1 + app/avMeta/CMakeLists.txt | 1 + app/avPlayer/CMakeLists.txt | 1 + app/avProcessor/CMakeLists.txt | 1 + app/customEncoder/CMakeLists.txt | 1 + 6 files changed, 6 insertions(+) diff --git a/app/avAudioPhaseMeter/CMakeLists.txt b/app/avAudioPhaseMeter/CMakeLists.txt index 812b8d9e..68946eb9 100644 --- a/app/avAudioPhaseMeter/CMakeLists.txt +++ b/app/avAudioPhaseMeter/CMakeLists.txt @@ -11,6 +11,7 @@ target_link_libraries(avaudiophasemeter avtranscoder-shared) # Install app if(WIN32) + set_target_properties(avaudiophasemeter PROPERTIES OUTPUT_NAME "avaudiophasemeter-${AVTRANSCODER_VERSION}") set(BINARY_FILES "${CMAKE_CURRENT_BINARY_DIR}/avaudiophasemeter.exe" "${CMAKE_CURRENT_BINARY_DIR}/avaudiophasemeter-${AVTRANSCODER_VERSION}.exe") else() set(BINARY_FILES "${CMAKE_CURRENT_BINARY_DIR}/avaudiophasemeter" "${CMAKE_CURRENT_BINARY_DIR}/avaudiophasemeter-${AVTRANSCODER_VERSION}") diff --git a/app/avInfo/CMakeLists.txt b/app/avInfo/CMakeLists.txt index cd165a75..8eddbb4c 100644 --- a/app/avInfo/CMakeLists.txt +++ b/app/avInfo/CMakeLists.txt @@ -11,6 +11,7 @@ target_link_libraries(avinfo avtranscoder-shared) # Install app if(WIN32) + set_target_properties(avinfo PROPERTIES OUTPUT_NAME "avinfo-${AVTRANSCODER_VERSION}") set(BINARY_FILES "${CMAKE_CURRENT_BINARY_DIR}/avinfo.exe" "${CMAKE_CURRENT_BINARY_DIR}/avinfo-${AVTRANSCODER_VERSION}.exe") else() set(BINARY_FILES "${CMAKE_CURRENT_BINARY_DIR}/avinfo" "${CMAKE_CURRENT_BINARY_DIR}/avinfo-${AVTRANSCODER_VERSION}") diff --git a/app/avMeta/CMakeLists.txt b/app/avMeta/CMakeLists.txt index bdc67260..57277377 100644 --- a/app/avMeta/CMakeLists.txt +++ b/app/avMeta/CMakeLists.txt @@ -11,6 +11,7 @@ target_link_libraries(avmeta avtranscoder-shared) # Install app if(WIN32) + set_target_properties(avinfo PROPERTIES OUTPUT_NAME "avinfo-${AVTRANSCODER_VERSION}") set(BINARY_FILES "${CMAKE_CURRENT_BINARY_DIR}/avmeta.exe" "${CMAKE_CURRENT_BINARY_DIR}/avmeta-${AVTRANSCODER_VERSION}.exe") else() set(BINARY_FILES "${CMAKE_CURRENT_BINARY_DIR}/avmeta" "${CMAKE_CURRENT_BINARY_DIR}/avmeta-${AVTRANSCODER_VERSION}") diff --git a/app/avPlayer/CMakeLists.txt b/app/avPlayer/CMakeLists.txt index dec775f2..61c7e05c 100644 --- a/app/avPlayer/CMakeLists.txt +++ b/app/avPlayer/CMakeLists.txt @@ -33,6 +33,7 @@ target_link_libraries(avplayer avtranscoder-shared ${OPENGL_LIBRARIES} ${GLUT_LI # Install app if(WIN32) + set_target_properties(avplayer PROPERTIES OUTPUT_NAME "avplayer-${AVTRANSCODER_VERSION}") set(BINARY_FILES "${CMAKE_CURRENT_BINARY_DIR}/avplayer.exe" "${CMAKE_CURRENT_BINARY_DIR}/avplayer-${AVTRANSCODER_VERSION}.exe") else() set(BINARY_FILES "${CMAKE_CURRENT_BINARY_DIR}/avplayer" "${CMAKE_CURRENT_BINARY_DIR}/avplayer-${AVTRANSCODER_VERSION}") diff --git a/app/avProcessor/CMakeLists.txt b/app/avProcessor/CMakeLists.txt index eb91477f..8c20bf4f 100644 --- a/app/avProcessor/CMakeLists.txt +++ b/app/avProcessor/CMakeLists.txt @@ -11,6 +11,7 @@ target_link_libraries(avprocessor avtranscoder-shared) # Install app if(WIN32) + set_target_properties(avprocessor PROPERTIES OUTPUT_NAME "avprocessor-${AVTRANSCODER_VERSION}") set(BINARY_FILES "${CMAKE_CURRENT_BINARY_DIR}/avprocessor.exe" "${CMAKE_CURRENT_BINARY_DIR}/avprocessor-${AVTRANSCODER_VERSION}.exe") else() set(BINARY_FILES "${CMAKE_CURRENT_BINARY_DIR}/avprocessor" "${CMAKE_CURRENT_BINARY_DIR}/avprocessor-${AVTRANSCODER_VERSION}") diff --git a/app/customEncoder/CMakeLists.txt b/app/customEncoder/CMakeLists.txt index 0eb6286b..df273a35 100644 --- a/app/customEncoder/CMakeLists.txt +++ b/app/customEncoder/CMakeLists.txt @@ -11,6 +11,7 @@ target_link_libraries(custom-encoder avtranscoder-shared) # Install app if(WIN32) + set_target_properties(custom-encoder PROPERTIES OUTPUT_NAME "custom-encoder-${AVTRANSCODER_VERSION}") set(BINARY_FILES "${CMAKE_CURRENT_BINARY_DIR}/custom-encoder.exe" "${CMAKE_CURRENT_BINARY_DIR}/custom-encoder-${AVTRANSCODER_VERSION}.exe") else() set(BINARY_FILES "${CMAKE_CURRENT_BINARY_DIR}/custom-encoder" "${CMAKE_CURRENT_BINARY_DIR}/custom-encoder-${AVTRANSCODER_VERSION}") From 19c582fc4376b142f47813c2839e8039432d764c Mon Sep 17 00:00:00 2001 From: Valentin NOEL Date: Wed, 15 Jun 2022 17:48:12 +0200 Subject: [PATCH 68/74] Applications: fix avmeta executable version on Windows --- app/avMeta/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/avMeta/CMakeLists.txt b/app/avMeta/CMakeLists.txt index 57277377..2228c579 100644 --- a/app/avMeta/CMakeLists.txt +++ b/app/avMeta/CMakeLists.txt @@ -11,7 +11,7 @@ target_link_libraries(avmeta avtranscoder-shared) # Install app if(WIN32) - set_target_properties(avinfo PROPERTIES OUTPUT_NAME "avinfo-${AVTRANSCODER_VERSION}") + set_target_properties(avmeta PROPERTIES OUTPUT_NAME "avmeta-${AVTRANSCODER_VERSION}") set(BINARY_FILES "${CMAKE_CURRENT_BINARY_DIR}/avmeta.exe" "${CMAKE_CURRENT_BINARY_DIR}/avmeta-${AVTRANSCODER_VERSION}.exe") else() set(BINARY_FILES "${CMAKE_CURRENT_BINARY_DIR}/avmeta" "${CMAKE_CURRENT_BINARY_DIR}/avmeta-${AVTRANSCODER_VERSION}") From c194f6306d6cdc791fcdb0333e499598e543d1fe Mon Sep 17 00:00:00 2001 From: Valentin NOEL Date: Tue, 12 Jul 2022 18:11:54 +0200 Subject: [PATCH 69/74] FilterGraph: keep reference of the filters input frame --- src/AvTranscoder/filter/FilterGraph.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/AvTranscoder/filter/FilterGraph.cpp b/src/AvTranscoder/filter/FilterGraph.cpp index 57b6ce2f..58fb7d9f 100644 --- a/src/AvTranscoder/filter/FilterGraph.cpp +++ b/src/AvTranscoder/filter/FilterGraph.cpp @@ -275,7 +275,7 @@ void FilterGraph::process(const std::vector& inputs, IFrame& output) { // Retrieve frame from buffer or directly from input IFrame* inputFrame = (bypassBuffers)? inputs.at(index) : _inputAudioFrameBuffers.at(index).getFrameSampleNb(minInputFrameSamplesNb); - const int ret = av_buffersrc_add_frame_flags(_filters.at(index)->getAVFilterContext(), &inputFrame->getAVFrame(), AV_BUFFERSRC_FLAG_PUSH); + const int ret = av_buffersrc_add_frame_flags(_filters.at(index)->getAVFilterContext(), &inputFrame->getAVFrame(), AV_BUFFERSRC_FLAG_PUSH & AV_BUFFERSRC_FLAG_KEEP_REF); if(ret < 0) { From 53298d0fb4d10f42270ca9db159dc7e59434d301 Mon Sep 17 00:00:00 2001 From: Valentin NOEL Date: Fri, 15 Jul 2022 14:58:02 +0200 Subject: [PATCH 70/74] FilterGraph: keep reference of the filters input frame Real fix after c194f6306d6cdc791fcdb0333e499598e543d1fe --- src/AvTranscoder/filter/FilterGraph.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/AvTranscoder/filter/FilterGraph.cpp b/src/AvTranscoder/filter/FilterGraph.cpp index 58fb7d9f..58f62fdb 100644 --- a/src/AvTranscoder/filter/FilterGraph.cpp +++ b/src/AvTranscoder/filter/FilterGraph.cpp @@ -275,7 +275,7 @@ void FilterGraph::process(const std::vector& inputs, IFrame& output) { // Retrieve frame from buffer or directly from input IFrame* inputFrame = (bypassBuffers)? inputs.at(index) : _inputAudioFrameBuffers.at(index).getFrameSampleNb(minInputFrameSamplesNb); - const int ret = av_buffersrc_add_frame_flags(_filters.at(index)->getAVFilterContext(), &inputFrame->getAVFrame(), AV_BUFFERSRC_FLAG_PUSH & AV_BUFFERSRC_FLAG_KEEP_REF); + const int ret = av_buffersrc_add_frame_flags(_filters.at(index)->getAVFilterContext(), &inputFrame->getAVFrame(), AV_BUFFERSRC_FLAG_KEEP_REF); if(ret < 0) { From 468dad2309b67f6bb5b113f812b13ec489c24262 Mon Sep 17 00:00:00 2001 From: Valentin NOEL Date: Tue, 2 May 2023 14:43:01 +0200 Subject: [PATCH 71/74] Transcoder: add getters for number of decoded and generated frames --- .../transcoder/StreamTranscoder.hpp | 17 +++++++++++++++++ src/AvTranscoder/transcoder/Transcoder.hpp | 18 ++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/src/AvTranscoder/transcoder/StreamTranscoder.hpp b/src/AvTranscoder/transcoder/StreamTranscoder.hpp index 23006d18..9df3f114 100644 --- a/src/AvTranscoder/transcoder/StreamTranscoder.hpp +++ b/src/AvTranscoder/transcoder/StreamTranscoder.hpp @@ -100,6 +100,23 @@ class AvExport StreamTranscoder /// Returns a reference to the stream which wraps data IOutputStream& getOutputStream() const { return *_outputStream; } + /// Returns the total number of generated frames for this processed stream + size_t getNumberOfGeneratedFrames() const { + size_t generatedFrames = 0; + for (IDecoder* generator : _generators) { + generatedFrames += generator->getNbDecodedFrames(); + } + return generatedFrames; + } + /// Returns the total number of decoded frames for this processed stream + size_t getNumberOfDecodedFrames() const { + size_t decodedFrames = 0; + for (IDecoder* inputDecoder : _inputDecoders) { + decodedFrames += inputDecoder->getNbDecodedFrames(); + } + return decodedFrames; + } + /** * @brief Returns if the stream has the ability to switch to a generator. */ diff --git a/src/AvTranscoder/transcoder/Transcoder.hpp b/src/AvTranscoder/transcoder/Transcoder.hpp index cc35c496..9ba27f6e 100644 --- a/src/AvTranscoder/transcoder/Transcoder.hpp +++ b/src/AvTranscoder/transcoder/Transcoder.hpp @@ -139,6 +139,24 @@ class AvExport Transcoder void setProcessMethod(const EProcessMethod eProcessMethod, const size_t indexBasedStream = 0, const double outputDuration = 0); + /** + * @brief Returns the total number of generated frames for a specific stream + * @param streamIndex: the index of the stream + * @return The total number of generated frames + */ + size_t getNumberOfGeneratedFrames(const size_t streamIndex) const { + return _streamTranscoders.at(streamIndex)->getNumberOfGeneratedFrames(); + } + + /** + * @brief Returns the total number of decoded frames for a specific stream + * @param streamIndex: the index of the stream + * @return The total number of decoded frames + */ + size_t getNumberOfDecodedFrames(const size_t streamIndex) const { + return _streamTranscoders.at(streamIndex)->getNumberOfDecodedFrames(); + } + private: void addRewrapStream(const InputStreamDesc& inputStreamDesc, const float offset); void addTranscodeStream(const std::vector& inputStreamDescArray, const ProfileLoader::Profile& profile, From 5b74a24a749d6e31039f78c13968365f7b18c2a4 Mon Sep 17 00:00:00 2001 From: Valentin NOEL Date: Fri, 5 May 2023 09:29:31 +0200 Subject: [PATCH 72/74] Bump version to 0.16.1 --- src/AvTranscoder/common.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/AvTranscoder/common.hpp b/src/AvTranscoder/common.hpp index 8829bec0..2d078685 100644 --- a/src/AvTranscoder/common.hpp +++ b/src/AvTranscoder/common.hpp @@ -3,7 +3,7 @@ #define AVTRANSCODER_VERSION_MAJOR 0 #define AVTRANSCODER_VERSION_MINOR 16 -#define AVTRANSCODER_VERSION_MICRO 0 +#define AVTRANSCODER_VERSION_MICRO 1 #include From 92714dfde56395e7310983850a2d7d75da69fdcc Mon Sep 17 00:00:00 2001 From: Valentin NOEL Date: Fri, 22 Sep 2023 15:38:41 +0200 Subject: [PATCH 73/74] Call string:::empty method instead of comparing to an empty string --- src/AvTranscoder/util.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/AvTranscoder/util.cpp b/src/AvTranscoder/util.cpp index f9b690c2..ab4db74b 100644 --- a/src/AvTranscoder/util.cpp +++ b/src/AvTranscoder/util.cpp @@ -15,7 +15,7 @@ std::vector getSupportedPixelFormats(const std::string& videoCodecN std::vector pixelFormats; // all video codec concerned - if(videoCodecName == "") + if(videoCodecName.empty()) { const AVPixFmtDescriptor* pixFmtDesc = NULL; From 91a447e5782572462f9df5b6eb7de79811e0b738 Mon Sep 17 00:00:00 2001 From: Valentin NOEL Date: Fri, 22 Sep 2023 15:38:57 +0200 Subject: [PATCH 74/74] Bump version to 0.16.2 --- src/AvTranscoder/common.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/AvTranscoder/common.hpp b/src/AvTranscoder/common.hpp index 2d078685..c249e3a3 100644 --- a/src/AvTranscoder/common.hpp +++ b/src/AvTranscoder/common.hpp @@ -3,7 +3,7 @@ #define AVTRANSCODER_VERSION_MAJOR 0 #define AVTRANSCODER_VERSION_MINOR 16 -#define AVTRANSCODER_VERSION_MICRO 1 +#define AVTRANSCODER_VERSION_MICRO 2 #include