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)
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