Skip to content

Commit fc8fb17

Browse files
committed
Merge pull request #209 from cchampet/fix_processAllDataOfInput
Default behavior: process all data of input
2 parents 2b99454 + 08a2d24 commit fc8fb17

File tree

7 files changed

+113
-49
lines changed

7 files changed

+113
-49
lines changed

src/AvTranscoder/file/InputFile.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ bool InputFile::readNextPacket(CodedData& data, const size_t streamIndex)
6868
const int ret = av_read_frame(&_formatContext.getAVFormatContext(), &data.getAVPacket());
6969
if(ret < 0) // error or end of file
7070
{
71-
LOG_INFO("No more data to read on file '" << _filename << "'")
71+
LOG_INFO("No more data to read on file '" << _filename << "' for stream " << streamIndex)
7272
return false;
7373
}
7474

src/AvTranscoder/transcoder/StreamTranscoder.cpp

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -327,21 +327,41 @@ void StreamTranscoder::preProcessCodecLatency()
327327
return;
328328

329329
// set a decoder to preload generated frames
330+
bool wasARewrapCase = false;
330331
if(getProcessCase() == eProcessCaseRewrap)
332+
{
331333
switchToGeneratorDecoder();
334+
wasARewrapCase = true;
335+
}
332336

333337
while((latency--) > 0)
334338
{
335339
processFrame();
336340
}
337341

338-
if(getProcessCase() == eProcessCaseRewrap)
342+
if(wasARewrapCase)
339343
_currentDecoder = NULL;
340344
}
341345

342346
bool StreamTranscoder::processFrame()
343347
{
344-
if(getProcessCase() == eProcessCaseGenerator)
348+
const EProcessCase processCase = getProcessCase();
349+
std::string msg = "Current process case of the stream is a ";
350+
switch(processCase)
351+
{
352+
case eProcessCaseTranscode:
353+
msg += "transcode.";
354+
break;
355+
case eProcessCaseRewrap:
356+
msg += "rewrap.";
357+
break;
358+
case eProcessCaseGenerator:
359+
msg += "generator.";
360+
break;
361+
}
362+
LOG_DEBUG(msg)
363+
364+
if(processCase == eProcessCaseGenerator)
345365
return processTranscode();
346366

347367
// Manage offset
@@ -363,7 +383,6 @@ bool StreamTranscoder::processFrame()
363383
// process generator
364384
if(_currentDecoder != _generator)
365385
{
366-
LOG_INFO("Switch to generator to process offset")
367386
switchToGeneratorDecoder();
368387
}
369388
}
@@ -381,7 +400,7 @@ bool StreamTranscoder::processFrame()
381400
}
382401
}
383402

384-
if(getProcessCase() == eProcessCaseRewrap)
403+
if(processCase == eProcessCaseRewrap)
385404
return processRewrap();
386405

387406
return processTranscode(_subStreamIndex);
@@ -531,9 +550,10 @@ void StreamTranscoder::needToSwitchToGenerator(const bool needToSwitch)
531550
if(needToSwitch && !canSwitchToGenerator())
532551
{
533552
std::stringstream os;
534-
os << "The stream " << _inputStream->getStreamIndex() << " has a duration of " << getDuration()
535-
<< "s. It needs to switch to a generator during the process, but it cannot.";
536-
throw std::runtime_error(os.str());
553+
LOG_WARN("The stream " << _inputStream->getStreamIndex() << " has a duration of " << getDuration()
554+
<< "s. It needs to switch to a generator during the process, but it cannot. "
555+
<< "No generator will be used for this stream.")
556+
return;
537557
}
538558
_needToSwitchToGenerator = needToSwitch;
539559
}
@@ -547,9 +567,9 @@ void StreamTranscoder::setOffset(const float offset)
547567

548568
StreamTranscoder::EProcessCase StreamTranscoder::getProcessCase() const
549569
{
550-
if(_inputStream && _inputDecoder)
570+
if(_inputStream && _inputDecoder && _currentDecoder == _inputDecoder)
551571
return eProcessCaseTranscode;
552-
else if(_inputStream && !_inputDecoder)
572+
else if(_inputStream && !_inputDecoder && !_currentDecoder)
553573
return eProcessCaseRewrap;
554574
else
555575
return eProcessCaseGenerator;

src/AvTranscoder/transcoder/StreamTranscoder.hpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ class AvExport StreamTranscoder
7777
IEncoder* getEncoder() const { return _outputEncoder; }
7878

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

8282
/// Returns a reference to the stream which unwraps data
8383
IInputStream* getInputStream() const { return _inputStream; }
@@ -102,10 +102,6 @@ class AvExport StreamTranscoder
102102
*/
103103
void setOffset(const float offset);
104104

105-
private:
106-
bool processRewrap();
107-
bool processTranscode(const int subStreamIndex = -1); ///< By default transcode all channels
108-
109105
//@{
110106
// Get the current process case.
111107
enum EProcessCase
@@ -117,6 +113,10 @@ class AvExport StreamTranscoder
117113
EProcessCase getProcessCase() const;
118114
//@}
119115

116+
private:
117+
bool processRewrap();
118+
bool processTranscode(const int subStreamIndex = -1); ///< By default transcode all channels
119+
120120
private:
121121
IInputStream* _inputStream; ///< Input stream to read next packet (has link, no ownership)
122122
IOutputStream* _outputStream; ///< Output stream to wrap next packet (has link, no ownership)
@@ -136,7 +136,7 @@ class AvExport StreamTranscoder
136136
float _offset; ///< Offset, in seconds, at the beginning of the StreamTranscoder.
137137

138138
bool _needToSwitchToGenerator; ///< Set if need to switch to a generator during the process (because, of other streams
139-
///duration, or an offset)
139+
/// duration, or an offset)
140140
};
141141
}
142142

src/AvTranscoder/transcoder/Transcoder.cpp

Lines changed: 54 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ Transcoder::Transcoder(IOutputFile& outputFile)
1616
, _streamTranscoders()
1717
, _streamTranscodersAllocated()
1818
, _profileLoader(true)
19-
, _eProcessMethod(eProcessMethodBasedOnStream)
19+
, _eProcessMethod(eProcessMethodLongest)
2020
, _mainStreamIndex(0)
2121
, _outputDuration(0)
2222
{
@@ -234,16 +234,32 @@ bool Transcoder::processFrame()
234234
if(_streamTranscoders.size() == 0)
235235
return false;
236236

237+
// For each stream, process a frame
238+
size_t nbStreamProcessStatusFailed = 0;
237239
for(size_t streamIndex = 0; streamIndex < _streamTranscoders.size(); ++streamIndex)
238240
{
239241
LOG_DEBUG("Process stream " << streamIndex << "/" << (_streamTranscoders.size() - 1))
240-
241-
bool streamProcessStatus = _streamTranscoders.at(streamIndex)->processFrame();
242-
if(!streamProcessStatus)
242+
if(!_streamTranscoders.at(streamIndex)->processFrame())
243243
{
244-
return false;
244+
LOG_WARN("Failed to process stream " << streamIndex)
245+
++nbStreamProcessStatusFailed;
245246
}
246247
}
248+
249+
// Get the number of streams without the generators (they always succeed)
250+
size_t nbStreamsWithoutGenerator = _streamTranscoders.size();
251+
for(size_t streamIndex = 0; streamIndex < _streamTranscoders.size(); ++streamIndex)
252+
{
253+
if(_streamTranscoders.at(streamIndex)->getProcessCase() == StreamTranscoder::eProcessCaseGenerator)
254+
--nbStreamsWithoutGenerator;
255+
}
256+
257+
// If all streams failed to process a new frame
258+
if(nbStreamsWithoutGenerator != 0 && nbStreamsWithoutGenerator == nbStreamProcessStatusFailed)
259+
{
260+
LOG_INFO("End of process because all streams (except generators) failed to process a new frame.")
261+
return false;
262+
}
247263
return true;
248264
}
249265

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

267283
preProcessCodecLatency();
268284

269-
const float outputDuration = getOutputDuration();
270-
LOG_INFO("Output duration of the process will be " << outputDuration << "s.")
285+
const float expectedOutputDuration = getExpectedOutputDuration();
286+
LOG_INFO("The expected output duration of the program will be " << expectedOutputDuration << "s.")
271287

272288
size_t frame = 0;
273289
bool frameProcessed = true;
274290
while(frameProcessed)
275291
{
276-
const float progressDuration = _outputFile.getStream(0).getStreamDuration();
292+
const float progressDuration = getCurrentOutputDuration();
277293

278294
// check if JobStatusCancel
279-
if(progress.progress((progressDuration > outputDuration) ? outputDuration : progressDuration, outputDuration) ==
280-
eJobStatusCancel)
295+
if(progress.progress((progressDuration > expectedOutputDuration) ? expectedOutputDuration : progressDuration,
296+
expectedOutputDuration) == eJobStatusCancel)
297+
{
298+
LOG_INFO("End of process because the job was canceled.")
281299
break;
300+
}
282301

283302
// check progressDuration
284-
if(progressDuration >= outputDuration)
303+
if(progressDuration >= expectedOutputDuration)
304+
{
305+
LOG_INFO("End of process because the output program duration ("
306+
<< progressDuration << "s) is equal or upper than " << expectedOutputDuration << "s.")
285307
break;
308+
}
286309

287310
LOG_DEBUG("Process frame " << frame)
288311
frameProcessed = processFrame();
289-
290312
++frame;
291313
}
292314

293315
_outputFile.endWrap();
294316

295-
LOG_INFO("End of process")
317+
LOG_INFO("End of process: " << frame << " frames processed")
296318

297319
LOG_INFO("Get process statistics")
298320
ProcessStat processStat;
@@ -501,7 +523,7 @@ float Transcoder::getMaxTotalDuration() const
501523
return maxTotalDuration;
502524
}
503525

504-
float Transcoder::getOutputDuration() const
526+
float Transcoder::getExpectedOutputDuration() const
505527
{
506528
switch(_eProcessMethod)
507529
{
@@ -520,6 +542,20 @@ float Transcoder::getOutputDuration() const
520542
}
521543
}
522544

545+
float Transcoder::getCurrentOutputDuration() const
546+
{
547+
float currentOutputDuration = -1;
548+
for(size_t streamIndex = 0; streamIndex < _streamTranscoders.size(); ++streamIndex)
549+
{
550+
const float currentStreamDuration = _outputFile.getStream(streamIndex).getStreamDuration();
551+
if(currentOutputDuration == -1)
552+
currentOutputDuration = currentStreamDuration;
553+
else if(currentStreamDuration < currentOutputDuration)
554+
currentOutputDuration = currentStreamDuration;
555+
}
556+
return currentOutputDuration;
557+
}
558+
523559
void Transcoder::manageSwitchToGenerator()
524560
{
525561
for(size_t i = 0; i < _streamTranscoders.size(); ++i)
@@ -563,9 +599,10 @@ void Transcoder::fillProcessStat(ProcessStat& processStat)
563599
for(size_t streamIndex = 0; streamIndex < _streamTranscoders.size(); ++streamIndex)
564600
{
565601
IOutputStream& stream = _streamTranscoders.at(streamIndex)->getOutputStream();
566-
const IInputStream* inputStream = _streamTranscoders.at( streamIndex )->getInputStream();
567-
if(inputStream == NULL) {
568-
LOG_WARN( "Cannot process statistics of generated stream." )
602+
const IInputStream* inputStream = _streamTranscoders.at(streamIndex)->getInputStream();
603+
if(inputStream == NULL)
604+
{
605+
LOG_WARN("Cannot process statistics of generated stream.")
569606
continue;
570607
}
571608
const AVMediaType mediaType = inputStream->getProperties().getStreamType();

src/AvTranscoder/transcoder/Transcoder.hpp

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,14 @@ namespace avtranscoder
1717
{
1818

1919
/**
20-
* @brief Enum to set a policy of how we manage the transcode in case of several streams.
21-
* eProcessMethodShortest: stop transcode at the end of the shortest stream.
22-
* eProcessMethodLongest: stop transcode at the end of the longest stream.
23-
* eProcessMethodBasedOnStream: stop transcode at the end of an indicated stream (@see _indexBasedStream attribute of
20+
* @brief Enum to set a policy of how we manage the process in case of several streams.
21+
* eProcessMethodShortest: stop the process at the end of the shortest stream.
22+
* eProcessMethodLongest: stop the process at the end of the longest stream.
23+
* eProcessMethodBasedOnStream: stop the process at the end of an indicated stream (@see _indexBasedStream attribute of
2424
* Transcoder).
25-
* eProcessMethodBasedOnDuration: stop transcode at the end of an indicated duration, in seconds (@see _outputDuration
25+
* eProcessMethodBasedOnDuration: stop the process at the end of an indicated duration, in seconds (@see _outputDuration
2626
* attribute of Transcoder).
27-
* eProcessMethodInfinity: stop transcode by outside of avTranscoder (streaming mode)
27+
* eProcessMethodInfinity: stop the process by outside of avTranscoder (streaming mode)
2828
*/
2929
enum EProcessMethod
3030
{
@@ -207,10 +207,17 @@ class AvExport Transcoder
207207
float getMaxTotalDuration() const;
208208

209209
/**
210-
* @brief Get the duration of the output program
210+
* @brief Get the expected duration of the output program
211211
* @note Depends on the streams, the process method, and the main stream index.
212212
*/
213-
float getOutputDuration() const;
213+
float getExpectedOutputDuration() const;
214+
215+
/**
216+
* @brief Get the current duration of the output program
217+
* @note Returns the duration of the smallest stream.
218+
* @return -1 if there is no output stream.
219+
*/
220+
float getCurrentOutputDuration() const;
214221

215222
/**
216223
* @brief Set for each StreamTranscoder if it can switch to generator at the end.
@@ -231,11 +238,11 @@ class AvExport Transcoder
231238

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

234-
EProcessMethod _eProcessMethod; ///< Transcoding policy
241+
EProcessMethod _eProcessMethod; ///< Processing policy
235242
size_t
236243
_mainStreamIndex; ///< Index of stream used to stop the process of transcode in case of eProcessMethodBasedOnStream.
237244
float _outputDuration; ///< Duration of output media used to stop the process of transcode in case of
238-
///eProcessMethodBasedOnDuration.
245+
/// eProcessMethodBasedOnDuration.
239246
};
240247
}
241248

test/pyTest/testEProcessMethod.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,8 @@ def testEProcessMethodShortest():
4141
dst_inputFile = av.InputFile( outputFileName )
4242
dst_properties = dst_inputFile.getProperties()
4343

44-
assert_equals( dst_properties.getDuration(), src_properties_shortest.getDuration() )
44+
for dst_stream_properties in dst_properties.getStreamProperties():
45+
assert_almost_equals( dst_stream_properties.getDuration(), src_properties_shortest.getDuration(), delta=0.05 )
4546

4647

4748
def testEProcessMethodLongest():
@@ -70,7 +71,8 @@ def testEProcessMethodLongest():
7071
dst_inputFile = av.InputFile( outputFileName )
7172
dst_properties = dst_inputFile.getProperties()
7273

73-
assert_equals( dst_properties.getDuration(), src_properties_longest.getDuration() )
74+
for dst_stream_properties in dst_properties.getStreamProperties():
75+
assert_almost_equals( dst_stream_properties.getDuration(), src_properties_longest.getDuration(), delta=0.05 )
7476

7577

7678
def testEProcessMethodBasedOnStream():
@@ -130,5 +132,6 @@ def testEProcessMethodBasedOnDuration():
130132
dst_inputFile = av.InputFile( outputFileName )
131133
dst_properties = dst_inputFile.getProperties()
132134

133-
assert_equals( dst_properties.getDuration(), outputDuration )
135+
for dst_stream_properties in dst_properties.getStreamProperties():
136+
assert_almost_equals( dst_stream_properties.getDuration(), outputDuration, delta=0.05 )
134137

test/pyTest/testTranscoderAdd.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -86,8 +86,5 @@ def testAddAllStreamsOfAGivenFile():
8686
import testTranscoderRewrap
8787
# for each stream
8888
for src_stream, dst_stream in zip(src_streams_properties, dst_streams_properties):
89-
# FIXME: analyse only the first stream because all the input audio data are not read
90-
if src_stream.getStreamId() != 1:
91-
continue
9289
# check properties
9390
testTranscoderRewrap.checkStream(src_stream, dst_stream)

0 commit comments

Comments
 (0)