Skip to content

Commit 6ddfb4a

Browse files
committed
Merge pull request #169 from cchampet/dev_ManageNegativeOffset
Manage negative offset
2 parents 5be6776 + 7ffd72a commit 6ddfb4a

File tree

10 files changed

+458
-85
lines changed

10 files changed

+458
-85
lines changed

src/AvTranscoder/file/OutputFile.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,8 @@ IOutputStream& OutputFile::getStream( const size_t streamId )
8888

8989
bool OutputFile::beginWrap( )
9090
{
91+
LOG_DEBUG( "Begin wrap of OutputFile" )
92+
9193
_formatContext.writeHeader();
9294
_frameCount.clear();
9395
_frameCount.resize( _outputStreams.size(), 0 );
@@ -127,6 +129,8 @@ IOutputStream::EWrappingStatus OutputFile::wrap( const CodedData& data, const si
127129

128130
bool OutputFile::endWrap( )
129131
{
132+
LOG_DEBUG( "End wrap of OutputFile" )
133+
130134
_formatContext.writeTrailer();
131135
_formatContext.closeRessource();
132136
return true;

src/AvTranscoder/transcoder/StreamTranscoder.cpp

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -332,9 +332,9 @@ bool StreamTranscoder::processFrame()
332332
bool endOfOffset = _outputStream->getStreamDuration() >= _offset;
333333
if( endOfOffset )
334334
{
335-
LOG_INFO( "End of offset" )
335+
LOG_INFO( "End of positive offset" )
336336

337-
if( _inputDecoder )
337+
if( isTranscodeCase() )
338338
switchToInputDecoder();
339339
else
340340
_currentDecoder = NULL;
@@ -350,6 +350,17 @@ bool StreamTranscoder::processFrame()
350350
}
351351
}
352352
}
353+
else if( _offset < 0 )
354+
{
355+
bool endOfStream = _outputStream->getStreamDuration() >= ( _inputStream->getDuration() + _offset );
356+
if( endOfStream )
357+
{
358+
LOG_INFO( "End of negative offset" )
359+
360+
switchToGeneratorDecoder();
361+
_offset = 0;
362+
}
363+
}
353364

354365
if( isRewrapCase() )
355366
return processRewrap();
@@ -479,6 +490,11 @@ double StreamTranscoder::getDuration() const
479490
if( _inputStream )
480491
{
481492
double totalDuration = _inputStream->getDuration() + _offset;
493+
if( totalDuration < 0 )
494+
{
495+
LOG_WARN( "Offset of " << _offset << "s applied to a stream with a duration of " << _inputStream->getDuration() << "s. Set its duration to 0s." )
496+
return 0.;
497+
}
482498
return totalDuration;
483499
}
484500
else

src/AvTranscoder/transcoder/StreamTranscoder.hpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,9 @@ class AvExport StreamTranscoder
6464
//@}
6565

6666
/**
67-
* @brief Get the duration of the stream, in seconds
67+
* @brief Get the total duration (in seconds), ie. duration of the stream and the offset applies
6868
* @note if it's a generated stream, return limit of double.
69+
* @note if offset > duration of the stream, return 0
6970
*/
7071
double getDuration() const;
7172

src/AvTranscoder/transcoder/Transcoder.cpp

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -248,20 +248,19 @@ void Transcoder::process( IProgress& progress )
248248
bool frameProcessed = true;
249249
while( frameProcessed )
250250
{
251-
LOG_INFO( "Process frame " << frame )
252-
253-
frameProcessed = processFrame();
254-
255251
double progressDuration = _outputFile.getStream( 0 ).getStreamDuration();
256252

257-
// check progressDuration
258-
if( progressDuration > outputDuration )
259-
break;
260-
261253
// check if JobStatusCancel
262254
if( progress.progress( ( progressDuration > outputDuration ) ? outputDuration : progressDuration, outputDuration ) == eJobStatusCancel )
263255
break;
264256

257+
// check progressDuration
258+
if( progressDuration >= outputDuration )
259+
break;
260+
261+
LOG_INFO( "Process frame " << frame )
262+
frameProcessed = processFrame();
263+
265264
++frame;
266265
}
267266

@@ -281,7 +280,7 @@ void Transcoder::addRewrapStream( const std::string& filename, const size_t stre
281280
{
282281
LOG_INFO( "Add rewrap stream from file '" << filename << "' / index=" << streamIndex << " / offset=" << offset << "s" )
283282

284-
InputFile* referenceFile = addInputFile( filename, streamIndex );
283+
InputFile* referenceFile = addInputFile( filename, streamIndex, offset );
285284

286285
_streamTranscodersAllocated.push_back( new StreamTranscoder( referenceFile->getStream( streamIndex ), _outputFile, offset ) );
287286
_streamTranscoders.push_back( _streamTranscodersAllocated.back() );
@@ -310,7 +309,7 @@ void Transcoder::addTranscodeStream( const std::string& filename, const size_t s
310309
LOG_INFO( "Add transcode stream from file '" << filename << "' / index=" << streamIndex << " / channel=" << subStreamIndex << " / encodingProfile=" << profile.at( constants::avProfileIdentificatorHuman ) << " / offset=" << offset << "s" )
311310

312311
// Add input file
313-
InputFile* referenceFile = addInputFile( filename, streamIndex );
312+
InputFile* referenceFile = addInputFile( filename, streamIndex, offset );
314313

315314
switch( referenceFile->getStream( streamIndex ).getStreamType() )
316315
{
@@ -343,7 +342,7 @@ void Transcoder::addDummyStream( const ProfileLoader::Profile& profile, const IC
343342
_streamTranscoders.push_back( _streamTranscodersAllocated.back() );
344343
}
345344

346-
InputFile* Transcoder::addInputFile( const std::string& filename, const size_t streamIndex )
345+
InputFile* Transcoder::addInputFile( const std::string& filename, const size_t streamIndex, const double offset )
347346
{
348347
InputFile* referenceFile = NULL;
349348

@@ -368,6 +367,10 @@ InputFile* Transcoder::addInputFile( const std::string& filename, const size_t s
368367

369368
referenceFile->activateStream( streamIndex );
370369

370+
// If negative offset, move forward in the input stream
371+
if( offset < 0 )
372+
referenceFile->seekAtTime( -offset );
373+
371374
return referenceFile;
372375
}
373376

src/AvTranscoder/transcoder/Transcoder.hpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@ class AvExport Transcoder
5454
* @brief Add a stream and set a profile
5555
* @note If profileName is empty, rewrap.
5656
* @note offset in seconds
57+
* If offset is positive, the transcoder will generate black images or silence (depending on the type of stream) before the stream to process.
58+
* If offset is negative, the transcoder will seek in the stream and start process at this specific time.
5759
*/
5860
void add( const std::string& filename, const size_t streamIndex, const std::string& profileName = "", const double offset = 0 );
5961
/*
@@ -155,7 +157,7 @@ class AvExport Transcoder
155157

156158
void addDummyStream( const ProfileLoader::Profile& profile, const ICodec& codec );
157159

158-
InputFile* addInputFile( const std::string& filename, const size_t streamIndex );
160+
InputFile* addInputFile( const std::string& filename, const size_t streamIndex, const double offset );
159161

160162
ProfileLoader::Profile getProfileFromFile( InputFile& inputFile, const size_t streamIndex ); ///< The function analyses the inputFile
161163

test/pyTest/testEProcessMethod.py

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
import os
2+
3+
# Check if environment is setup to run the tests
4+
if os.environ.get('AVTRANSCODER_TEST_VIDEO_FILE') is None or os.environ.get('AVTRANSCODER_TEST_AUDIO_MOV_FILE') is None or os.environ.get('AVTRANSCODER_TEST_AUDIO_WAVE_FILE') is None:
5+
from nose.plugins.skip import SkipTest
6+
raise SkipTest("Need to define environment variables AVTRANSCODER_TEST_VIDEO_FILE / AVTRANSCODER_TEST_AUDIO_MOV_FILE / AVTRANSCODER_TEST_AUDIO_WAVE_FILE")
7+
8+
from nose.tools import *
9+
10+
from pyAvTranscoder import avtranscoder as av
11+
12+
av.preloadCodecsAndFormats()
13+
av.Logger.setLogLevel(av.AV_LOG_QUIET)
14+
15+
16+
def testEProcessMethodShortest():
17+
"""
18+
Process with method eProcessMethodShortest, check output duration.
19+
"""
20+
inputFileName_longest = os.environ['AVTRANSCODER_TEST_VIDEO_FILE']
21+
inputFileName_shortest = os.environ['AVTRANSCODER_TEST_AUDIO_MOV_FILE']
22+
outputFileName = "testEProcessMethodShortest.mov"
23+
24+
ouputFile = av.OutputFile( outputFileName )
25+
transcoder = av.Transcoder( ouputFile )
26+
transcoder.setProcessMethod( av.eProcessMethodShortest )
27+
28+
transcoder.add( inputFileName_longest, 0, "" )
29+
transcoder.add( inputFileName_shortest, 0, "" )
30+
31+
progress = av.ConsoleProgress()
32+
transcoder.process( progress )
33+
34+
# get src file
35+
src_inputFile_shortest = av.InputFile( inputFileName_shortest )
36+
src_properties_shortest = src_inputFile_shortest.getProperties()
37+
38+
# get dst file
39+
dst_inputFile = av.InputFile( outputFileName )
40+
dst_properties = dst_inputFile.getProperties()
41+
42+
assert_equals( dst_properties.getDuration(), src_properties_shortest.getDuration() )
43+
44+
45+
def testEProcessMethodLongest():
46+
"""
47+
Process with method eProcessMethodLongest, check output duration.
48+
"""
49+
inputFileName_longest = os.environ['AVTRANSCODER_TEST_VIDEO_FILE']
50+
inputFileName_shortest = os.environ['AVTRANSCODER_TEST_AUDIO_MOV_FILE']
51+
outputFileName = "testEProcessMethodLongest.mov"
52+
53+
ouputFile = av.OutputFile( outputFileName )
54+
transcoder = av.Transcoder( ouputFile )
55+
transcoder.setProcessMethod( av.eProcessMethodLongest )
56+
57+
transcoder.add( inputFileName_longest, 0, "" )
58+
transcoder.add( inputFileName_shortest, 0, "" )
59+
60+
progress = av.ConsoleProgress()
61+
transcoder.process( progress )
62+
63+
# get src file
64+
src_inputFile_longest = av.InputFile( inputFileName_longest )
65+
src_properties_longest = src_inputFile_longest.getProperties()
66+
67+
# get dst file
68+
dst_inputFile = av.InputFile( outputFileName )
69+
dst_properties = dst_inputFile.getProperties()
70+
71+
assert_equals( dst_properties.getDuration(), src_properties_longest.getDuration() )
72+
73+
74+
def testEProcessMethodBasedOnStream():
75+
"""
76+
Process with method testEProcessMethodBasedOnStream, check output duration.
77+
"""
78+
inputFileName_first = os.environ['AVTRANSCODER_TEST_VIDEO_FILE']
79+
inputFileName_second = os.environ['AVTRANSCODER_TEST_AUDIO_WAVE_FILE']
80+
inputFileName_third = os.environ['AVTRANSCODER_TEST_AUDIO_MOV_FILE']
81+
outputFileName = "testEProcessMethodShortest.mov"
82+
83+
ouputFile = av.OutputFile( outputFileName )
84+
transcoder = av.Transcoder( ouputFile )
85+
transcoder.setProcessMethod( av.eProcessMethodBasedOnStream, 1 )
86+
87+
transcoder.add( inputFileName_first, 0, "" )
88+
transcoder.add( inputFileName_second, 0, "" )
89+
transcoder.add( inputFileName_third, 0, "" )
90+
91+
progress = av.ConsoleProgress()
92+
transcoder.process( progress )
93+
94+
# get src file
95+
src_inputFile_second = av.InputFile( inputFileName_second )
96+
src_properties_second = src_inputFile_second.getProperties()
97+
98+
# get dst file
99+
dst_inputFile = av.InputFile( outputFileName )
100+
dst_properties = dst_inputFile.getProperties()
101+
102+
assert_equals( dst_properties.getDuration(), src_properties_second.getDuration() )
103+
104+
105+
def testEProcessMethodBasedOnDuration():
106+
"""
107+
Process with method eProcessMethodBasedOnDuration, check output duration.
108+
"""
109+
inputFileName_first = os.environ['AVTRANSCODER_TEST_VIDEO_FILE']
110+
inputFileName_second = os.environ['AVTRANSCODER_TEST_AUDIO_WAVE_FILE']
111+
inputFileName_third = os.environ['AVTRANSCODER_TEST_AUDIO_MOV_FILE']
112+
outputFileName = "testEProcessMethodBasedOnDuration.mov"
113+
114+
ouputFile = av.OutputFile( outputFileName )
115+
transcoder = av.Transcoder( ouputFile )
116+
transcoder.setProcessMethod( av.eProcessMethodBasedOnDuration, 0, 50 )
117+
118+
transcoder.add( inputFileName_first, 0, "" )
119+
transcoder.add( inputFileName_second, 0, "" )
120+
transcoder.add( inputFileName_third, 0, "" )
121+
122+
progress = av.ConsoleProgress()
123+
transcoder.process( progress )
124+
125+
# get dst file
126+
dst_inputFile = av.InputFile( outputFileName )
127+
dst_properties = dst_inputFile.getProperties()
128+
129+
assert_equals( dst_properties.getDuration(), 50 )
130+
File renamed without changes.
File renamed without changes.

0 commit comments

Comments
 (0)