Skip to content

Fix rewrap based on stream with an estimate duration -> to arte snapshot #263

New issue

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

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

Already on GitHub? Sign in to your account

Merged
2 changes: 1 addition & 1 deletion src/AvTranscoder/decoder/AudioDecoder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion src/AvTranscoder/decoder/VideoDecoder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
15 changes: 12 additions & 3 deletions src/AvTranscoder/properties/VideoProperties.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 estimated 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 estimated from the fps and the duration.
*/
size_t getNbFrames() const;
size_t getTicksPerFrame() const;
size_t getWidth() const;
size_t getHeight() const;
Expand All @@ -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 estimated from the file size.
*/
float getDuration() const;

Expand Down
16 changes: 5 additions & 11 deletions src/AvTranscoder/transcoder/StreamTranscoder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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.";
Expand All @@ -371,9 +370,6 @@ bool StreamTranscoder::processFrame()
}
LOG_DEBUG(msg)

if(processCase == eProcessCaseGenerator)
return processTranscode();

// Manage offset
if(_offset > 0)
{
Expand All @@ -382,7 +378,7 @@ bool StreamTranscoder::processFrame()
{
LOG_INFO("End of positive offset")

if(getProcessCase() == eProcessCaseTranscode)
if(_inputDecoder)
switchToInputDecoder();
else
_currentDecoder = NULL;
Expand All @@ -392,9 +388,7 @@ bool StreamTranscoder::processFrame()
{
// process generator
if(_currentDecoder != _generator)
{
switchToGeneratorDecoder();
}
}
}
else if(_offset < 0)
Expand All @@ -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);
}

Expand Down
3 changes: 2 additions & 1 deletion src/AvTranscoder/transcoder/StreamTranscoder.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
60 changes: 31 additions & 29 deletions src/AvTranscoder/transcoder/Transcoder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -235,30 +235,21 @@ 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))
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)
++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;
}
LOG_WARN("Failed to process stream at index " << streamIndex)

// 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;
// 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;
}
}
}
return true;
}
Expand Down Expand Up @@ -304,7 +295,7 @@ ProcessStat Transcoder::process(IProgress& progress)
}

// check progressDuration
if(progressDuration >= expectedOutputDuration)
if(_eProcessMethod == eProcessMethodBasedOnDuration && progressDuration >= expectedOutputDuration)
{
LOG_INFO("End of process because the output program duration ("
<< progressDuration << "s) is equal or upper than " << expectedOutputDuration << "s.")
Expand All @@ -314,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;
Expand Down Expand Up @@ -498,32 +489,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<float>::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)
{
Expand Down
14 changes: 8 additions & 6 deletions src/AvTranscoder/transcoder/Transcoder.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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.
};
Expand Down
2 changes: 2 additions & 0 deletions test/pyTest/testOffset.py
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down