Skip to content

0.6.3: fixed process in case of several streams #205

New issue

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

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

Already on GitHub? Sign in to your account

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/AvTranscoder/file/InputFile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down
4 changes: 2 additions & 2 deletions src/AvTranscoder/transcoder/StreamTranscoder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
8 changes: 4 additions & 4 deletions src/AvTranscoder/transcoder/StreamTranscoder.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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)
Expand Down
56 changes: 46 additions & 10 deletions src/AvTranscoder/transcoder/Transcoder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand All @@ -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;
Expand Down Expand Up @@ -460,7 +482,7 @@ float Transcoder::getMaxTotalDuration() const
return maxTotalDuration;
}

float Transcoder::getOutputDuration() const
float Transcoder::getExpectedOutputDuration() const
{
switch( _eProcessMethod )
{
Expand All @@ -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 )
Expand Down
11 changes: 9 additions & 2 deletions src/AvTranscoder/transcoder/Transcoder.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down