Skip to content

Fix process all data of input #209

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
merged 18 commits into from
Jan 7, 2016
Merged
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 @@ -68,7 +68,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
38 changes: 29 additions & 9 deletions src/AvTranscoder/transcoder/StreamTranscoder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -327,21 +327,41 @@ void StreamTranscoder::preProcessCodecLatency()
return;

// set a decoder to preload generated frames
bool wasARewrapCase = false;
if(getProcessCase() == eProcessCaseRewrap)
{
switchToGeneratorDecoder();
wasARewrapCase = true;
}

while((latency--) > 0)
{
processFrame();
}

if(getProcessCase() == eProcessCaseRewrap)
if(wasARewrapCase)
_currentDecoder = NULL;
}

bool StreamTranscoder::processFrame()
{
if(getProcessCase() == eProcessCaseGenerator)
const EProcessCase processCase = getProcessCase();
std::string msg = "Current process case of the stream is a ";
switch(processCase)
{
case eProcessCaseTranscode:
msg += "transcode.";
break;
case eProcessCaseRewrap:
msg += "rewrap.";
break;
case eProcessCaseGenerator:
msg += "generator.";
break;
}
LOG_DEBUG(msg)

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

// Manage offset
Expand All @@ -363,7 +383,6 @@ bool StreamTranscoder::processFrame()
// process generator
if(_currentDecoder != _generator)
{
LOG_INFO("Switch to generator to process offset")
switchToGeneratorDecoder();
}
}
Expand All @@ -381,7 +400,7 @@ bool StreamTranscoder::processFrame()
}
}

if(getProcessCase() == eProcessCaseRewrap)
if(processCase == eProcessCaseRewrap)
return processRewrap();

return processTranscode(_subStreamIndex);
Expand Down Expand Up @@ -531,9 +550,10 @@ void StreamTranscoder::needToSwitchToGenerator(const bool needToSwitch)
if(needToSwitch && !canSwitchToGenerator())
{
std::stringstream os;
os << "The stream " << _inputStream->getStreamIndex() << " has a duration of " << getDuration()
<< "s. It needs to switch to a generator during the process, but it cannot.";
throw std::runtime_error(os.str());
LOG_WARN("The stream " << _inputStream->getStreamIndex() << " has a duration of " << getDuration()
<< "s. It needs to switch to a generator during the process, but it cannot. "
<< "No generator will be used for this stream.")
return;
}
_needToSwitchToGenerator = needToSwitch;
}
Expand All @@ -547,9 +567,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
12 changes: 6 additions & 6 deletions src/AvTranscoder/transcoder/StreamTranscoder.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ class AvExport StreamTranscoder
IEncoder* getEncoder() const { return _outputEncoder; }

/// Returns a reference to the object which transforms the decoded data
ITransform& getTransform() const { return *_transform; }
ITransform* getTransform() const { return _transform; }

/// Returns a reference to the stream which unwraps data
IInputStream* getInputStream() const { return _inputStream; }
Expand All @@ -102,10 +102,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 @@ -117,6 +113,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 All @@ -136,7 +136,7 @@ class AvExport StreamTranscoder
float _offset; ///< Offset, in seconds, at the beginning of the StreamTranscoder.

bool _needToSwitchToGenerator; ///< Set if need to switch to a generator during the process (because, of other streams
///duration, or an offset)
/// duration, or an offset)
};
}

Expand Down
71 changes: 54 additions & 17 deletions src/AvTranscoder/transcoder/Transcoder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ Transcoder::Transcoder(IOutputFile& outputFile)
, _streamTranscoders()
, _streamTranscodersAllocated()
, _profileLoader(true)
, _eProcessMethod(eProcessMethodBasedOnStream)
, _eProcessMethod(eProcessMethodLongest)
, _mainStreamIndex(0)
, _outputDuration(0)
{
Expand Down Expand Up @@ -234,16 +234,32 @@ 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)
if(!_streamTranscoders.at(streamIndex)->processFrame())
{
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(nbStreamsWithoutGenerator != 0 && nbStreamsWithoutGenerator == nbStreamProcessStatusFailed)
{
LOG_INFO("End of process because all streams (except generators) failed to process a new frame.")
return false;
}
return true;
}

Expand All @@ -266,33 +282,39 @@ ProcessStat Transcoder::process(IProgress& progress)

preProcessCodecLatency();

const float outputDuration = getOutputDuration();
LOG_INFO("Output duration of the process will be " << outputDuration << "s.")
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)
{
const float progressDuration = _outputFile.getStream(0).getStreamDuration();
const float progressDuration = getCurrentOutputDuration();

// check if JobStatusCancel
if(progress.progress((progressDuration > outputDuration) ? outputDuration : progressDuration, outputDuration) ==
eJobStatusCancel)
if(progress.progress((progressDuration > expectedOutputDuration) ? expectedOutputDuration : progressDuration,
expectedOutputDuration) == eJobStatusCancel)
{
LOG_INFO("End of process because the job was canceled.")
break;
}

// check progressDuration
if(progressDuration >= outputDuration)
if(progressDuration >= expectedOutputDuration)
{
LOG_INFO("End of process because the output program duration ("
<< progressDuration << "s) is equal or upper than " << expectedOutputDuration << "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 @@ -501,7 +523,7 @@ float Transcoder::getMaxTotalDuration() const
return maxTotalDuration;
}

float Transcoder::getOutputDuration() const
float Transcoder::getExpectedOutputDuration() const
{
switch(_eProcessMethod)
{
Expand All @@ -520,6 +542,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 Expand Up @@ -563,9 +599,10 @@ void Transcoder::fillProcessStat(ProcessStat& processStat)
for(size_t streamIndex = 0; streamIndex < _streamTranscoders.size(); ++streamIndex)
{
IOutputStream& stream = _streamTranscoders.at(streamIndex)->getOutputStream();
const IInputStream* inputStream = _streamTranscoders.at( streamIndex )->getInputStream();
if(inputStream == NULL) {
LOG_WARN( "Cannot process statistics of generated stream." )
const IInputStream* inputStream = _streamTranscoders.at(streamIndex)->getInputStream();
if(inputStream == NULL)
{
LOG_WARN("Cannot process statistics of generated stream.")
continue;
}
const AVMediaType mediaType = inputStream->getProperties().getStreamType();
Expand Down
27 changes: 17 additions & 10 deletions src/AvTranscoder/transcoder/Transcoder.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,14 @@ namespace avtranscoder
{

/**
* @brief Enum to set a policy of how we manage the transcode in case of several streams.
* eProcessMethodShortest: stop transcode at the end of the shortest stream.
* eProcessMethodLongest: stop transcode at the end of the longest stream.
* eProcessMethodBasedOnStream: stop transcode at the end of an indicated stream (@see _indexBasedStream attribute of
* @brief Enum to set a policy of how we manage the process in case of several streams.
* eProcessMethodShortest: stop the process at the end of the shortest stream.
* eProcessMethodLongest: stop the process at the end of the longest stream.
* eProcessMethodBasedOnStream: stop the process at the end of an indicated stream (@see _indexBasedStream attribute of
* Transcoder).
* eProcessMethodBasedOnDuration: stop transcode at the end of an indicated duration, in seconds (@see _outputDuration
* eProcessMethodBasedOnDuration: stop the process at the end of an indicated duration, in seconds (@see _outputDuration
* attribute of Transcoder).
* eProcessMethodInfinity: stop transcode by outside of avTranscoder (streaming mode)
* eProcessMethodInfinity: stop the process by outside of avTranscoder (streaming mode)
*/
enum EProcessMethod
{
Expand Down Expand Up @@ -207,10 +207,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 All @@ -231,11 +238,11 @@ class AvExport Transcoder

ProfileLoader _profileLoader; ///< Objet to get existing profiles, and add new ones for the Transcoder.

EProcessMethod _eProcessMethod; ///< Transcoding policy
EProcessMethod _eProcessMethod; ///< Processing policy
size_t
_mainStreamIndex; ///< Index of stream used to stop the process of transcode in case of eProcessMethodBasedOnStream.
float _outputDuration; ///< Duration of output media used to stop the process of transcode in case of
///eProcessMethodBasedOnDuration.
/// eProcessMethodBasedOnDuration.
};
}

Expand Down
9 changes: 6 additions & 3 deletions test/pyTest/testEProcessMethod.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@ def testEProcessMethodShortest():
dst_inputFile = av.InputFile( outputFileName )
dst_properties = dst_inputFile.getProperties()

assert_equals( dst_properties.getDuration(), src_properties_shortest.getDuration() )
for dst_stream_properties in dst_properties.getStreamProperties():
assert_almost_equals( dst_stream_properties.getDuration(), src_properties_shortest.getDuration(), delta=0.05 )


def testEProcessMethodLongest():
Expand Down Expand Up @@ -70,7 +71,8 @@ def testEProcessMethodLongest():
dst_inputFile = av.InputFile( outputFileName )
dst_properties = dst_inputFile.getProperties()

assert_equals( dst_properties.getDuration(), src_properties_longest.getDuration() )
for dst_stream_properties in dst_properties.getStreamProperties():
assert_almost_equals( dst_stream_properties.getDuration(), src_properties_longest.getDuration(), delta=0.05 )


def testEProcessMethodBasedOnStream():
Expand Down Expand Up @@ -130,5 +132,6 @@ def testEProcessMethodBasedOnDuration():
dst_inputFile = av.InputFile( outputFileName )
dst_properties = dst_inputFile.getProperties()

assert_equals( dst_properties.getDuration(), outputDuration )
for dst_stream_properties in dst_properties.getStreamProperties():
assert_almost_equals( dst_stream_properties.getDuration(), outputDuration, delta=0.05 )

3 changes: 0 additions & 3 deletions test/pyTest/testTranscoderAdd.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,5 @@ def testAddAllStreamsOfAGivenFile():
import testTranscoderRewrap
# for each stream
for src_stream, dst_stream in zip(src_streams_properties, dst_streams_properties):
# FIXME: analyse only the first stream because all the input audio data are not read
if src_stream.getStreamId() != 1:
continue
# check properties
testTranscoderRewrap.checkStream(src_stream, dst_stream)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy