diff --git a/src/AvTranscoder/file/InputFile.cpp b/src/AvTranscoder/file/InputFile.cpp index 38086a24..72e95f77 100644 --- a/src/AvTranscoder/file/InputFile.cpp +++ b/src/AvTranscoder/file/InputFile.cpp @@ -63,7 +63,7 @@ bool InputFile::readNextPacket( CodedData& data, const size_t streamIndex ) const int ret = av_read_frame( &_formatContext.getAVFormatContext(), &data.getAVPacket() ); if( ret < 0 ) // error or end of file { - LOG_INFO( "No more data to read on file '" << _filename << "'" ) + LOG_INFO( "No more data to read on file '" << _filename << "' for stream " << streamIndex ) return false; } diff --git a/src/AvTranscoder/transcoder/StreamTranscoder.cpp b/src/AvTranscoder/transcoder/StreamTranscoder.cpp index 4e90eead..7acb815b 100644 --- a/src/AvTranscoder/transcoder/StreamTranscoder.cpp +++ b/src/AvTranscoder/transcoder/StreamTranscoder.cpp @@ -556,9 +556,9 @@ void StreamTranscoder::setOffset( const float offset ) StreamTranscoder::EProcessCase StreamTranscoder::getProcessCase() const { - if( _inputStream && _inputDecoder ) + if( _inputStream && _inputDecoder && _currentDecoder == _inputDecoder ) return eProcessCaseTranscode; - else if( _inputStream && ! _inputDecoder ) + else if( _inputStream && ! _inputDecoder && ! _currentDecoder ) return eProcessCaseRewrap; else return eProcessCaseGenerator; diff --git a/src/AvTranscoder/transcoder/StreamTranscoder.hpp b/src/AvTranscoder/transcoder/StreamTranscoder.hpp index 912af924..181a90e3 100644 --- a/src/AvTranscoder/transcoder/StreamTranscoder.hpp +++ b/src/AvTranscoder/transcoder/StreamTranscoder.hpp @@ -101,10 +101,6 @@ class AvExport StreamTranscoder */ void setOffset( const float offset ); -private: - bool processRewrap(); - bool processTranscode( const int subStreamIndex = -1 ); ///< By default transcode all channels - //@{ // Get the current process case. enum EProcessCase { @@ -115,6 +111,10 @@ class AvExport StreamTranscoder EProcessCase getProcessCase() const; //@} +private: + bool processRewrap(); + bool processTranscode( const int subStreamIndex = -1 ); ///< By default transcode all channels + private: IInputStream* _inputStream; ///< Input stream to read next packet (has link, no ownership) IOutputStream* _outputStream; ///< Output stream to wrap next packet (has link, no ownership) diff --git a/src/AvTranscoder/transcoder/Transcoder.cpp b/src/AvTranscoder/transcoder/Transcoder.cpp index 984bf34d..44699cdd 100644 --- a/src/AvTranscoder/transcoder/Transcoder.cpp +++ b/src/AvTranscoder/transcoder/Transcoder.cpp @@ -209,16 +209,33 @@ bool Transcoder::processFrame() if( _streamTranscoders.size() == 0 ) 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 ) ) - - bool streamProcessStatus = _streamTranscoders.at( streamIndex )->processFrame(); - if( ! streamProcessStatus ) + const bool currentStreamProcessStatus = _streamTranscoders.at( streamIndex )->processFrame(); + if( ! currentStreamProcessStatus ) { - return false; + LOG_WARN( "Failed to process stream " << streamIndex ) + ++nbStreamProcessStatusFailed; } } + + // 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( nbStreamProcessStatusFailed == nbStreamsWithoutGenerator ) + { + LOG_INFO( "End of process because all streams (except generators) failed to process a new frame." ) + return false; + } return true; } @@ -241,32 +258,37 @@ ProcessStat Transcoder::process( IProgress& progress ) preProcessCodecLatency(); - const float outputDuration = getOutputDuration(); + const float outputDuration = getExpectedOutputDuration(); LOG_INFO( "Output duration of the process will be " << outputDuration << "s." ) size_t frame = 0; bool frameProcessed = true; while( frameProcessed ) { - const float progressDuration = _outputFile.getStream( 0 ).getStreamDuration(); + const float progressDuration = getCurrentOutputDuration(); // check if JobStatusCancel if( progress.progress( ( progressDuration > outputDuration ) ? outputDuration : progressDuration, outputDuration ) == eJobStatusCancel ) + { + LOG_INFO( "End of process because the job was canceled." ) break; + } // check progressDuration - if( progressDuration >= outputDuration ) + if( _eProcessMethod == eProcessMethodBasedOnDuration && progressDuration >= outputDuration ) + { + LOG_INFO( "End of process because the output program duration (" << progressDuration << "s) is equal or upper than " << outputDuration << "s." ) break; + } LOG_DEBUG( "Process frame " << frame ) frameProcessed = processFrame(); - ++frame; } _outputFile.endWrap(); - LOG_INFO( "End of process" ) + LOG_INFO( "End of process: " << frame << " frames processed" ) LOG_INFO( "Get process statistics" ) ProcessStat processStat; @@ -460,7 +482,7 @@ float Transcoder::getMaxTotalDuration() const return maxTotalDuration; } -float Transcoder::getOutputDuration() const +float Transcoder::getExpectedOutputDuration() const { switch( _eProcessMethod ) { @@ -479,6 +501,20 @@ float Transcoder::getOutputDuration() const } } +float Transcoder::getCurrentOutputDuration() const +{ + float currentOutputDuration = -1; + for( size_t streamIndex = 0; streamIndex < _streamTranscoders.size(); ++streamIndex ) + { + const float currentStreamDuration = _outputFile.getStream( streamIndex ).getStreamDuration(); + if( currentOutputDuration == -1 ) + currentOutputDuration = currentStreamDuration; + else if( currentStreamDuration < currentOutputDuration ) + currentOutputDuration = currentStreamDuration; + } + return currentOutputDuration; +} + void Transcoder::manageSwitchToGenerator() { for( size_t i = 0; i < _streamTranscoders.size(); ++i ) diff --git a/src/AvTranscoder/transcoder/Transcoder.hpp b/src/AvTranscoder/transcoder/Transcoder.hpp index b0407859..0f89c662 100644 --- a/src/AvTranscoder/transcoder/Transcoder.hpp +++ b/src/AvTranscoder/transcoder/Transcoder.hpp @@ -180,10 +180,17 @@ class AvExport Transcoder float getMaxTotalDuration() const; /** - * @brief Get the duration of the output program + * @brief Get the expected duration of the output program * @note Depends on the streams, the process method, and the main stream index. */ - float getOutputDuration() const; + float getExpectedOutputDuration() const; + + /** + * @brief Get the current duration of the output program + * @note Returns the duration of the smallest stream. + * @return -1 if there is no output stream. + */ + float getCurrentOutputDuration() const; /** * @brief Set for each StreamTranscoder if it can switch to generator at the end.