From fa1b5c872693432600c9136914697ae50b008fbe Mon Sep 17 00:00:00 2001 From: Clement Champetier Date: Mon, 11 Jul 2016 21:10:02 +0200 Subject: [PATCH 01/12] decoders: updated exception message in case of error while decoding --- src/AvTranscoder/decoder/AudioDecoder.cpp | 2 +- src/AvTranscoder/decoder/VideoDecoder.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/AvTranscoder/decoder/AudioDecoder.cpp b/src/AvTranscoder/decoder/AudioDecoder.cpp index 3b20e8bc..31cf94ac 100644 --- a/src/AvTranscoder/decoder/AudioDecoder.cpp +++ b/src/AvTranscoder/decoder/AudioDecoder.cpp @@ -97,7 +97,7 @@ bool AudioDecoder::decodeNextFrame(Frame& frameBuffer) &got_frame, &data.getAVPacket()); if(ret < 0) { - throw std::runtime_error("an error occured during audio decoding" + getDescriptionFromErrorCode(ret)); + throw std::runtime_error("An error occured during audio decoding: " + getDescriptionFromErrorCode(ret)); } // if no frame could be decompressed diff --git a/src/AvTranscoder/decoder/VideoDecoder.cpp b/src/AvTranscoder/decoder/VideoDecoder.cpp index 51363466..9e69eed3 100644 --- a/src/AvTranscoder/decoder/VideoDecoder.cpp +++ b/src/AvTranscoder/decoder/VideoDecoder.cpp @@ -95,7 +95,7 @@ bool VideoDecoder::decodeNextFrame(Frame& frameBuffer) &got_frame, &data.getAVPacket()); if(ret < 0) { - throw std::runtime_error("an error occured during video decoding - " + getDescriptionFromErrorCode(ret)); + throw std::runtime_error("An error occured during video decoding: " + getDescriptionFromErrorCode(ret)); } // if no frame could be decompressed From 66a7b4312d9d190bb48673d99eb2a169e859a244 Mon Sep 17 00:00:00 2001 From: Clement Champetier Date: Mon, 11 Jul 2016 21:12:07 +0200 Subject: [PATCH 02/12] VideoProperties: added doc about possible estimate properties --- src/AvTranscoder/properties/VideoProperties.hpp | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/AvTranscoder/properties/VideoProperties.hpp b/src/AvTranscoder/properties/VideoProperties.hpp index 433c8cd4..0da11713 100644 --- a/src/AvTranscoder/properties/VideoProperties.hpp +++ b/src/AvTranscoder/properties/VideoProperties.hpp @@ -40,10 +40,18 @@ class AvExport VideoProperties : public StreamProperties Rational getSar() const; // sample/pixel aspect ratio Rational getDar() const; // display aspect ratio - size_t getBitRate() const; ///< in bits/s, 0 if unknown + /** + * @return The video bitrate in bits/s. + * @warning If there is no such info available in the container, this data is estimate by decoding the first GOP. + */ + size_t getBitRate() const; size_t getMaxBitRate() const; size_t getMinBitRate() const; - size_t getNbFrames() const; ///< 0 if unknown + /** + * @note 0 if unknown. + * @warning In case of a raw format, this data is estimate from the fps and the duration. + */ + size_t getNbFrames() const; size_t getTicksPerFrame() const; size_t getWidth() const; size_t getHeight() const; @@ -63,7 +71,8 @@ class AvExport VideoProperties : public StreamProperties /** * @brief Override method. - * @return the stream duration in seconds, 0 if not available + * @return The stream duration in seconds, 0 if not available. + * @warning In case of a raw format, this data is estimate from the file size. */ float getDuration() const; From 046f6db9586974470eecefffb00cadf89655dd68 Mon Sep 17 00:00:00 2001 From: Clement Champetier Date: Mon, 11 Jul 2016 21:37:39 +0200 Subject: [PATCH 03/12] Transcoder: removed check of progress duration as a stop condition Use _mainStreamIndex attribute in all process methods to stop the process. --- src/AvTranscoder/transcoder/Transcoder.cpp | 41 +++++++++++++--------- src/AvTranscoder/transcoder/Transcoder.hpp | 14 ++++---- 2 files changed, 33 insertions(+), 22 deletions(-) diff --git a/src/AvTranscoder/transcoder/Transcoder.cpp b/src/AvTranscoder/transcoder/Transcoder.cpp index 247fc5b2..caed8479 100644 --- a/src/AvTranscoder/transcoder/Transcoder.cpp +++ b/src/AvTranscoder/transcoder/Transcoder.cpp @@ -243,6 +243,12 @@ bool Transcoder::processFrame() { LOG_WARN("Failed to process stream " << streamIndex) ++nbStreamProcessStatusFailed; + + // if this is the end of the main stream + if(streamIndex == _mainStreamIndex) { + LOG_INFO("End of process because the main stream at index " << _mainStreamIndex << " failed to process a new frame.") + return false; + } } } @@ -302,14 +308,6 @@ ProcessStat Transcoder::process(IProgress& progress) LOG_INFO("End of process because the job was canceled.") break; } - - // check progressDuration - if(progressDuration >= expectedOutputDuration) - { - LOG_INFO("End of process because the output program duration (" - << progressDuration << "s) is equal or upper than " << expectedOutputDuration << "s.") - break; - } } _outputFile.endWrap(); @@ -498,32 +496,43 @@ ProfileLoader::Profile Transcoder::getProfileFromFile(InputFile& inputFile, cons return profile; } -float Transcoder::getStreamDuration(size_t indexStream) const +float Transcoder::getStreamDuration(const size_t indexStream) const { return _streamTranscoders.at(indexStream)->getDuration(); } -float Transcoder::getMinTotalDuration() const +float Transcoder::getMinTotalDuration() { float minTotalDuration = std::numeric_limits::max(); - for(size_t i = 0; i < _streamTranscoders.size(); ++i) + for(size_t streamIndex = 0; streamIndex < _streamTranscoders.size(); ++streamIndex) { - minTotalDuration = std::min(getStreamDuration(i), minTotalDuration); + const float streamDuration = getStreamDuration(streamIndex); + if(std::min(streamDuration, minTotalDuration) == streamDuration) + { + minTotalDuration = streamDuration; + _mainStreamIndex = streamIndex; + } + } return minTotalDuration; } -float Transcoder::getMaxTotalDuration() const +float Transcoder::getMaxTotalDuration() { float maxTotalDuration = 0; - for(size_t i = 0; i < _streamTranscoders.size(); ++i) + for(size_t streamIndex = 0; streamIndex < _streamTranscoders.size(); ++streamIndex) { - maxTotalDuration = std::max(getStreamDuration(i), maxTotalDuration); + const float streamDuration = getStreamDuration(streamIndex); + if(std::max(streamDuration, maxTotalDuration) == streamDuration) + { + maxTotalDuration = streamDuration; + _mainStreamIndex = streamIndex; + } } return maxTotalDuration; } -float Transcoder::getExpectedOutputDuration() const +float Transcoder::getExpectedOutputDuration() { switch(_eProcessMethod) { diff --git a/src/AvTranscoder/transcoder/Transcoder.hpp b/src/AvTranscoder/transcoder/Transcoder.hpp index 289db061..08f1654b 100644 --- a/src/AvTranscoder/transcoder/Transcoder.hpp +++ b/src/AvTranscoder/transcoder/Transcoder.hpp @@ -197,20 +197,22 @@ class AvExport Transcoder float getStreamDuration(size_t indexStream) const; /** - * @brief Get the duration of the shortest stream, in seconds - */ - float getMinTotalDuration() const; + * @brief Get the duration of the shortest stream, in seconds + * @note Set the index of the main stream to stop the process at the end of the shortest stream. + */ + float getMinTotalDuration(); /** * @brief Get the duration of the longest stream, in seconds + * @note Set the index of the main stream to stop the process at the end of the longest stream. */ - float getMaxTotalDuration() const; + float getMaxTotalDuration(); /** * @brief Get the expected duration of the output program * @note Depends on the streams, the process method, and the main stream index. */ - float getExpectedOutputDuration() const; + float getExpectedOutputDuration(); /** * @brief Get the current duration of the output program @@ -240,7 +242,7 @@ class AvExport Transcoder EProcessMethod _eProcessMethod; ///< Processing policy size_t - _mainStreamIndex; ///< Index of stream used to stop the process of transcode in case of eProcessMethodBasedOnStream. + _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. }; From fb3c87aed9169d69d06f1805ab81e100233eaf7f Mon Sep 17 00:00:00 2001 From: Clement Champetier Date: Mon, 11 Jul 2016 21:42:26 +0200 Subject: [PATCH 04/12] Transcoder: removed unnecessary code Never reach. --- src/AvTranscoder/transcoder/Transcoder.cpp | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/src/AvTranscoder/transcoder/Transcoder.cpp b/src/AvTranscoder/transcoder/Transcoder.cpp index caed8479..c1bb8f6f 100644 --- a/src/AvTranscoder/transcoder/Transcoder.cpp +++ b/src/AvTranscoder/transcoder/Transcoder.cpp @@ -235,14 +235,12 @@ bool Transcoder::processFrame() return false; // For each stream, process a frame - size_t nbStreamProcessStatusFailed = 0; for(size_t streamIndex = 0; streamIndex < _streamTranscoders.size(); ++streamIndex) { LOG_DEBUG("Process stream " << streamIndex << "/" << (_streamTranscoders.size() - 1)) if(!_streamTranscoders.at(streamIndex)->processFrame()) { LOG_WARN("Failed to process stream " << streamIndex) - ++nbStreamProcessStatusFailed; // if this is the end of the main stream if(streamIndex == _mainStreamIndex) { @@ -251,21 +249,6 @@ bool Transcoder::processFrame() } } } - - // Get the number of streams without the generators (they always succeed) - size_t nbStreamsWithoutGenerator = _streamTranscoders.size(); - for(size_t streamIndex = 0; streamIndex < _streamTranscoders.size(); ++streamIndex) - { - if(_streamTranscoders.at(streamIndex)->getProcessCase() == StreamTranscoder::eProcessCaseGenerator) - --nbStreamsWithoutGenerator; - } - - // If all streams failed to process a new frame - if(nbStreamsWithoutGenerator != 0 && nbStreamsWithoutGenerator == nbStreamProcessStatusFailed) - { - LOG_INFO("End of process because all streams (except generators) failed to process a new frame.") - return false; - } return true; } From 119731c53ea3e400a01f8e4aa5d516062f874463 Mon Sep 17 00:00:00 2001 From: Clement Champetier Date: Tue, 12 Jul 2016 10:26:48 +0200 Subject: [PATCH 05/12] Transcoder: check output duration when the process method is based on duration --- src/AvTranscoder/transcoder/Transcoder.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/AvTranscoder/transcoder/Transcoder.cpp b/src/AvTranscoder/transcoder/Transcoder.cpp index c1bb8f6f..dce025b3 100644 --- a/src/AvTranscoder/transcoder/Transcoder.cpp +++ b/src/AvTranscoder/transcoder/Transcoder.cpp @@ -238,6 +238,8 @@ bool Transcoder::processFrame() for(size_t streamIndex = 0; streamIndex < _streamTranscoders.size(); ++streamIndex) { LOG_DEBUG("Process stream " << streamIndex << "/" << (_streamTranscoders.size() - 1)) + + // if a stream failed to process if(!_streamTranscoders.at(streamIndex)->processFrame()) { LOG_WARN("Failed to process stream " << streamIndex) @@ -291,6 +293,14 @@ ProcessStat Transcoder::process(IProgress& progress) 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; + } } _outputFile.endWrap(); From 54e966a90baa2c027913736b6e50e12fd23c6406 Mon Sep 17 00:00:00 2001 From: Clement Champetier Date: Tue, 12 Jul 2016 12:40:43 +0200 Subject: [PATCH 06/12] StreamTranscoder: fixed end of process in case of offset --- src/AvTranscoder/transcoder/StreamTranscoder.cpp | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/src/AvTranscoder/transcoder/StreamTranscoder.cpp b/src/AvTranscoder/transcoder/StreamTranscoder.cpp index 67f3e8a4..b4777a4d 100644 --- a/src/AvTranscoder/transcoder/StreamTranscoder.cpp +++ b/src/AvTranscoder/transcoder/StreamTranscoder.cpp @@ -355,9 +355,8 @@ void StreamTranscoder::preProcessCodecLatency() bool StreamTranscoder::processFrame() { - const EProcessCase processCase = getProcessCase(); std::string msg = "Current process case of the stream is a "; - switch(processCase) + switch(getProcessCase()) { case eProcessCaseTranscode: msg += "transcode."; @@ -371,9 +370,6 @@ bool StreamTranscoder::processFrame() } LOG_DEBUG(msg) - if(processCase == eProcessCaseGenerator) - return processTranscode(); - // Manage offset if(_offset > 0) { @@ -382,7 +378,7 @@ bool StreamTranscoder::processFrame() { LOG_INFO("End of positive offset") - if(getProcessCase() == eProcessCaseTranscode) + if(_inputDecoder) switchToInputDecoder(); else _currentDecoder = NULL; @@ -392,9 +388,7 @@ bool StreamTranscoder::processFrame() { // process generator if(_currentDecoder != _generator) - { switchToGeneratorDecoder(); - } } } else if(_offset < 0) @@ -405,14 +399,14 @@ bool StreamTranscoder::processFrame() { LOG_INFO("End of negative offset") - switchToGeneratorDecoder(); + if(_needToSwitchToGenerator) + switchToGeneratorDecoder(); _offset = 0; } } - if(processCase == eProcessCaseRewrap) + if(getProcessCase() == eProcessCaseRewrap) return processRewrap(); - return processTranscode(_subStreamIndex); } From 614eab5c355f1ac596a79f3ac6060831a946ab27 Mon Sep 17 00:00:00 2001 From: Clement Champetier Date: Tue, 12 Jul 2016 12:41:07 +0200 Subject: [PATCH 07/12] StreamTranscoder: added doc to getProcessCase private method --- src/AvTranscoder/transcoder/StreamTranscoder.hpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/AvTranscoder/transcoder/StreamTranscoder.hpp b/src/AvTranscoder/transcoder/StreamTranscoder.hpp index 7c8a8c5d..92c0fdb8 100644 --- a/src/AvTranscoder/transcoder/StreamTranscoder.hpp +++ b/src/AvTranscoder/transcoder/StreamTranscoder.hpp @@ -106,7 +106,8 @@ class AvExport StreamTranscoder void setOffset(const float offset); //@{ - // Get the current process case. + // @brief Get the current process case. + // @warning Could vary during the process. enum EProcessCase { eProcessCaseTranscode, From 6cf1b2a1551400611197ffd7e6a1cfd7445f16e8 Mon Sep 17 00:00:00 2001 From: Clement Champetier Date: Tue, 12 Jul 2016 12:45:32 +0200 Subject: [PATCH 08/12] Transcoder: updated log in processFrame method --- src/AvTranscoder/transcoder/Transcoder.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/AvTranscoder/transcoder/Transcoder.cpp b/src/AvTranscoder/transcoder/Transcoder.cpp index dce025b3..81e9ab60 100644 --- a/src/AvTranscoder/transcoder/Transcoder.cpp +++ b/src/AvTranscoder/transcoder/Transcoder.cpp @@ -237,12 +237,12 @@ bool Transcoder::processFrame() // For each stream, process a frame for(size_t streamIndex = 0; streamIndex < _streamTranscoders.size(); ++streamIndex) { - LOG_DEBUG("Process stream " << streamIndex << "/" << (_streamTranscoders.size() - 1)) + LOG_DEBUG("Process stream " << streamIndex + 1 << "/" << _streamTranscoders.size()) // if a stream failed to process if(!_streamTranscoders.at(streamIndex)->processFrame()) { - LOG_WARN("Failed to process stream " << streamIndex) + LOG_WARN("Failed to process stream at index " << streamIndex) // if this is the end of the main stream if(streamIndex == _mainStreamIndex) { From 4457a3955b9e317f25a5b57034e59bbbdb37e0f0 Mon Sep 17 00:00:00 2001 From: Clement Champetier Date: Tue, 12 Jul 2016 13:01:35 +0200 Subject: [PATCH 09/12] Transcoder: updated log message in process method --- src/AvTranscoder/transcoder/Transcoder.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/AvTranscoder/transcoder/Transcoder.cpp b/src/AvTranscoder/transcoder/Transcoder.cpp index 81e9ab60..5082a84a 100644 --- a/src/AvTranscoder/transcoder/Transcoder.cpp +++ b/src/AvTranscoder/transcoder/Transcoder.cpp @@ -305,7 +305,7 @@ ProcessStat Transcoder::process(IProgress& progress) _outputFile.endWrap(); - LOG_INFO("End of process: " << frame << " frames processed") + LOG_INFO("End of process: " << ++frame << " frames processed") LOG_INFO("Get process statistics") ProcessStat processStat; From 09bc326e52951162d67e23fb131c1cd0e1ea1e4a Mon Sep 17 00:00:00 2001 From: Clement Champetier Date: Tue, 12 Jul 2016 14:42:46 +0200 Subject: [PATCH 10/12] pyTest: comment a test that transcodes a video with a positive offset --- test/pyTest/testOffset.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/pyTest/testOffset.py b/test/pyTest/testOffset.py index 8e9128bf..76bc0a0f 100644 --- a/test/pyTest/testOffset.py +++ b/test/pyTest/testOffset.py @@ -137,6 +137,8 @@ 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. From a90c1e365a2458c61d68529e2433aba8d580e1d4 Mon Sep 17 00:00:00 2001 From: Clement Champetier Date: Mon, 11 Jul 2016 21:07:39 +0200 Subject: [PATCH 11/12] StreamProperties: fixed access of AVCodecContext properties if several analysis are launched * There is no need to open/close a codec to access its options. * This update of the codec state (opened/closed) could be problem if there are transcoding operations after the analysis. --- src/AvTranscoder/properties/StreamProperties.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/AvTranscoder/properties/StreamProperties.cpp b/src/AvTranscoder/properties/StreamProperties.cpp index ffc230ec..1c4238bd 100644 --- a/src/AvTranscoder/properties/StreamProperties.cpp +++ b/src/AvTranscoder/properties/StreamProperties.cpp @@ -38,11 +38,7 @@ StreamProperties::StreamProperties(const FileProperties& fileProperties, const s if(_codec) { // load specific options of the codec - if(avcodec_open2(_codecContext, _codec, NULL) == 0) - { - loadOptions(_options, _codecContext); - avcodec_close(_codecContext); - } + loadOptions(_options, _codecContext); } } } From cb2d7c405727f860e2bb1ca18e0a14f4fe155b03 Mon Sep 17 00:00:00 2001 From: Clement Champetier Date: Tue, 12 Jul 2016 15:25:35 +0200 Subject: [PATCH 12/12] Fixed english spelling --- src/AvTranscoder/decoder/AudioDecoder.cpp | 2 +- src/AvTranscoder/decoder/VideoDecoder.cpp | 2 +- src/AvTranscoder/properties/VideoProperties.hpp | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/AvTranscoder/decoder/AudioDecoder.cpp b/src/AvTranscoder/decoder/AudioDecoder.cpp index 31cf94ac..38c6e0d4 100644 --- a/src/AvTranscoder/decoder/AudioDecoder.cpp +++ b/src/AvTranscoder/decoder/AudioDecoder.cpp @@ -97,7 +97,7 @@ bool AudioDecoder::decodeNextFrame(Frame& frameBuffer) &got_frame, &data.getAVPacket()); if(ret < 0) { - throw std::runtime_error("An error occured during audio decoding: " + getDescriptionFromErrorCode(ret)); + throw std::runtime_error("An error occurred during audio decoding: " + getDescriptionFromErrorCode(ret)); } // if no frame could be decompressed diff --git a/src/AvTranscoder/decoder/VideoDecoder.cpp b/src/AvTranscoder/decoder/VideoDecoder.cpp index 9e69eed3..bb6002c3 100644 --- a/src/AvTranscoder/decoder/VideoDecoder.cpp +++ b/src/AvTranscoder/decoder/VideoDecoder.cpp @@ -95,7 +95,7 @@ bool VideoDecoder::decodeNextFrame(Frame& frameBuffer) &got_frame, &data.getAVPacket()); if(ret < 0) { - throw std::runtime_error("An error occured during video decoding: " + getDescriptionFromErrorCode(ret)); + throw std::runtime_error("An error occurred during video decoding: " + getDescriptionFromErrorCode(ret)); } // if no frame could be decompressed diff --git a/src/AvTranscoder/properties/VideoProperties.hpp b/src/AvTranscoder/properties/VideoProperties.hpp index 0da11713..6867dec2 100644 --- a/src/AvTranscoder/properties/VideoProperties.hpp +++ b/src/AvTranscoder/properties/VideoProperties.hpp @@ -42,14 +42,14 @@ class AvExport VideoProperties : public StreamProperties /** * @return The video bitrate in bits/s. - * @warning If there is no such info available in the container, this data is estimate by decoding the first GOP. + * @warning If there is no such info available in the container, this data is estimated by decoding the first GOP. */ size_t getBitRate() const; size_t getMaxBitRate() const; size_t getMinBitRate() const; /** * @note 0 if unknown. - * @warning In case of a raw format, this data is estimate from the fps and the duration. + * @warning In case of a raw format, this data is estimated from the fps and the duration. */ size_t getNbFrames() const; size_t getTicksPerFrame() const; @@ -72,7 +72,7 @@ class AvExport VideoProperties : public StreamProperties /** * @brief Override method. * @return The stream duration in seconds, 0 if not available. - * @warning In case of a raw format, this data is estimate from the file size. + * @warning In case of a raw format, this data is estimated from the file size. */ float getDuration() const;