Skip to content

Commit 647e3de

Browse files
authored
Merge pull request #304 from valnoel/muxing_silent_audio_channels
Muxing silent audio channels
2 parents d33ffd2 + d834fe3 commit 647e3de

File tree

5 files changed

+292
-19
lines changed

5 files changed

+292
-19
lines changed

src/AvTranscoder/transcoder/InputStreamDesc.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ struct InputStreamDesc
6363
bool demultiplexing() const { return !_channelIndexArray.empty(); }
6464

6565
public:
66-
std::string _filename; ///< Source file path.
66+
std::string _filename; ///< Source file path. If empty, a generator is used as source.
6767
size_t _streamIndex; ///< Source stream to extract.
6868
std::vector<size_t> _channelIndexArray; ///< List of source channels to extract from the stream
6969
};

src/AvTranscoder/transcoder/StreamTranscoder.cpp

Lines changed: 102 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ StreamTranscoder::StreamTranscoder(IInputStream& inputStream, IOutputFile& outpu
3333
, _outputEncoder(NULL)
3434
, _transform(NULL)
3535
, _filterGraph(NULL)
36+
, _firstInputStreamIndex(0)
3637
, _offset(offset)
3738
, _needToSwitchToGenerator(false)
3839
{
@@ -140,19 +141,35 @@ StreamTranscoder::StreamTranscoder(const std::vector<InputStreamDesc>& inputStre
140141
, _outputEncoder(NULL)
141142
, _transform(NULL)
142143
, _filterGraph(NULL)
144+
, _firstInputStreamIndex(std::numeric_limits<size_t>::max())
143145
, _offset(offset)
144146
, _needToSwitchToGenerator(false)
145147
{
146148
// add as many decoders as input streams
147149
size_t nbOutputChannels = 0;
148150
for(size_t index = 0; index < inputStreams.size(); ++index)
149151
{
150-
addDecoder(_inputStreamDesc.at(index), *_inputStreams.at(index));
151-
nbOutputChannels += _inputStreamDesc.at(index)._channelIndexArray.size();
152+
if(_inputStreams.at(index) != NULL)
153+
{
154+
LOG_INFO("add decoder for input stream " << index);
155+
addDecoder(_inputStreamDesc.at(index), *_inputStreams.at(index));
156+
nbOutputChannels += _inputStreamDesc.at(index)._channelIndexArray.size();
157+
if(_firstInputStreamIndex == std::numeric_limits<size_t>::max())
158+
_firstInputStreamIndex = index;
159+
}
160+
else
161+
{
162+
LOG_INFO("add generator for empty input " << index);
163+
addGenerator(_inputStreamDesc.at(index), profile);
164+
nbOutputChannels++;
165+
}
152166
}
153167

154-
IInputStream& inputStream = *_inputStreams.at(0);
155-
const InputStreamDesc& inputStreamDesc = inputStreamsDesc.at(0);
168+
if(_firstInputStreamIndex == std::numeric_limits<size_t>::max())
169+
throw std::runtime_error("Cannot handle empty only input streams");
170+
171+
IInputStream& inputStream = *_inputStreams.at(_firstInputStreamIndex);
172+
const InputStreamDesc& inputStreamDesc = inputStreamsDesc.at(_firstInputStreamIndex);
156173

157174
// create a transcode case
158175
switch(inputStream.getProperties().getStreamType())
@@ -278,6 +295,53 @@ void StreamTranscoder::addDecoder(const InputStreamDesc& inputStreamDesc, IInput
278295
}
279296
}
280297

298+
void StreamTranscoder::addGenerator(const InputStreamDesc& inputStreamDesc, const ProfileLoader::Profile& profile)
299+
{
300+
// create a transcode case
301+
if(profile.find(constants::avProfileType)->second == constants::avProfileTypeVideo)
302+
{
303+
VideoCodec inputVideoCodec(eCodecTypeEncoder, profile.find(constants::avProfileCodec)->second);
304+
VideoFrameDesc inputFrameDesc(profile);
305+
inputVideoCodec.setImageParameters(inputFrameDesc);
306+
307+
// generator decoder
308+
VideoGenerator* generator = new VideoGenerator(inputFrameDesc);
309+
_generators.push_back(generator);
310+
_currentDecoder = generator;
311+
312+
// buffers to process
313+
VideoFrameDesc outputFrameDesc = inputFrameDesc;
314+
outputFrameDesc.setParameters(profile);
315+
_decodedData.push_back(new VideoFrame(inputFrameDesc));
316+
317+
// no decoder for this input
318+
_inputDecoders.push_back(NULL);
319+
320+
}
321+
else if(profile.find(constants::avProfileType)->second == constants::avProfileTypeAudio)
322+
{
323+
// corresponding input codec
324+
AudioCodec inputAudioCodec(eCodecTypeEncoder, profile.find(constants::avProfileCodec)->second);
325+
AudioFrameDesc inputFrameDesc(profile);
326+
inputFrameDesc._nbChannels = 1;
327+
inputAudioCodec.setAudioParameters(inputFrameDesc);
328+
329+
// generator decoder
330+
AudioGenerator* generator = new AudioGenerator(inputFrameDesc);
331+
_generators.push_back(generator);
332+
_currentDecoder = generator;
333+
// buffers to get the decoded data
334+
_decodedData.push_back(new AudioFrame(inputFrameDesc));
335+
336+
// no decoder for this input
337+
_inputDecoders.push_back(NULL);
338+
}
339+
else
340+
{
341+
throw std::runtime_error("unupported stream type");
342+
}
343+
}
344+
281345
StreamTranscoder::StreamTranscoder(IOutputFile& outputFile, const ProfileLoader::Profile& profile)
282346
: _inputStreamDesc()
283347
, _inputStreams()
@@ -291,6 +355,7 @@ StreamTranscoder::StreamTranscoder(IOutputFile& outputFile, const ProfileLoader:
291355
, _outputEncoder(NULL)
292356
, _transform(NULL)
293357
, _filterGraph(NULL)
358+
, _firstInputStreamIndex(0)
294359
, _offset(0)
295360
, _needToSwitchToGenerator(false)
296361
{
@@ -375,7 +440,8 @@ StreamTranscoder::~StreamTranscoder()
375440

376441
for(std::vector<IDecoder*>::iterator it = _inputDecoders.begin(); it != _inputDecoders.end(); ++it)
377442
{
378-
delete(*it);
443+
if(*it != NULL)
444+
delete(*it);
379445
}
380446
for(std::vector<IDecoder*>::iterator it = _generators.begin(); it != _generators.end(); ++it)
381447
{
@@ -536,7 +602,8 @@ bool StreamTranscoder::processTranscode()
536602
std::vector<bool> decodingStatus(_generators.size(), true);
537603
for(size_t index = 0; index < _generators.size(); ++index)
538604
{
539-
if(getProcessCase() == eProcessCaseTranscode)
605+
EProcessCase processCase = getProcessCase(index);
606+
if(processCase == eProcessCaseTranscode)
540607
_currentDecoder = _inputDecoders.at(index);
541608
else
542609
_currentDecoder = _generators.at(index);
@@ -548,9 +615,9 @@ bool StreamTranscoder::processTranscode()
548615
}
549616

550617
// check the next data buffers in case of audio frames
551-
if(_decodedData.at(0)->isAudioFrame())
618+
if(_decodedData.at(_firstInputStreamIndex)->isAudioFrame())
552619
{
553-
const int nbInputSamplesPerChannel = _decodedData.at(0)->getAVFrame().nb_samples;
620+
const int nbInputSamplesPerChannel = _decodedData.at(_firstInputStreamIndex)->getAVFrame().nb_samples;
554621

555622
// Reallocate output frame
556623
if(nbInputSamplesPerChannel > _filteredData->getAVFrame().nb_samples)
@@ -670,7 +737,11 @@ float StreamTranscoder::getDuration() const
670737
float minStreamDuration = -1;
671738
for(size_t index = 0; index < _inputStreams.size(); ++index)
672739
{
673-
const StreamProperties& streamProperties = _inputStreams.at(index)->getProperties();
740+
IInputStream* inputStream = _inputStreams.at(index);
741+
if(inputStream == NULL)
742+
continue;
743+
744+
const StreamProperties& streamProperties = inputStream->getProperties();
674745
if(minStreamDuration == -1 || streamProperties.getDuration() < minStreamDuration)
675746
minStreamDuration = streamProperties.getDuration();
676747
}
@@ -722,13 +793,30 @@ void StreamTranscoder::setOffset(const float offset)
722793
}
723794
}
724795

725-
StreamTranscoder::EProcessCase StreamTranscoder::getProcessCase() const
796+
StreamTranscoder::EProcessCase StreamTranscoder::getProcessCase(const size_t decoderIndex) const
726797
{
727-
if(! _inputStreams.empty() && ! _inputDecoders.empty() && std::find(_inputDecoders.begin(), _inputDecoders.end(), _currentDecoder) != _inputDecoders.end() )
728-
return eProcessCaseTranscode;
729-
else if(! _inputStreams.empty() && _inputDecoders.empty() && !_currentDecoder)
730-
return eProcessCaseRewrap;
798+
if(_inputStreamDesc.size() <= 1)
799+
{
800+
if(! _inputStreams.empty() && ! _inputDecoders.empty() && std::find(_inputDecoders.begin(), _inputDecoders.end(), _currentDecoder) != _inputDecoders.end() )
801+
return eProcessCaseTranscode;
802+
else if(! _inputStreams.empty() && _inputDecoders.empty() && !_currentDecoder)
803+
return eProcessCaseRewrap;
804+
else
805+
return eProcessCaseGenerator;
806+
}
731807
else
808+
{
809+
if(! _inputStreams.empty() && _currentDecoder != NULL)
810+
{
811+
if( _inputStreams.at(decoderIndex) != NULL)
812+
return eProcessCaseTranscode;
813+
return eProcessCaseGenerator;
814+
}
815+
else if(! _inputStreams.empty() && _inputDecoders.empty() && !_currentDecoder)
816+
{
817+
return eProcessCaseRewrap;
818+
}
732819
return eProcessCaseGenerator;
820+
}
733821
}
734822
}

src/AvTranscoder/transcoder/StreamTranscoder.hpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ class AvExport StreamTranscoder
115115
eProcessCaseRewrap,
116116
eProcessCaseGenerator
117117
};
118-
EProcessCase getProcessCase() const;
118+
EProcessCase getProcessCase(const size_t decoderIndex = 0) const;
119119
//@}
120120

121121
private:
@@ -125,6 +125,7 @@ class AvExport StreamTranscoder
125125
* @param inputStream
126126
*/
127127
void addDecoder(const InputStreamDesc& inputStreamDesc, IInputStream& inputStream);
128+
void addGenerator(const InputStreamDesc& inputStreamDesc, const ProfileLoader::Profile& profile);
128129

129130
bool processRewrap();
130131
bool processTranscode();
@@ -147,6 +148,8 @@ class AvExport StreamTranscoder
147148

148149
FilterGraph* _filterGraph; ///< Filter graph (has ownership)
149150

151+
size_t _firstInputStreamIndex; ///< Index of the first non-null input stream.
152+
150153
float _offset; ///< Offset, in seconds, at the beginning of the StreamTranscoder.
151154

152155
bool _needToSwitchToGenerator; ///< Set if need to switch to a generator during the process (because, of other streams

src/AvTranscoder/transcoder/Transcoder.cpp

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,12 @@ void Transcoder::addTranscodeStream(const std::vector<InputStreamDesc>& inputStr
260260
AVMediaType commonStreamType = AVMEDIA_TYPE_UNKNOWN;
261261
for(std::vector<InputStreamDesc>::const_iterator it = inputStreamDescArray.begin(); it != inputStreamDescArray.end(); ++it)
262262
{
263+
if(it->_filename.empty())
264+
{
265+
inputStreams.push_back(NULL);
266+
continue;
267+
}
268+
263269
InputFile* referenceFile = addInputFile(it->_filename, it->_streamIndex, offset);
264270
inputStreams.push_back(&referenceFile->getStream(it->_streamIndex));
265271

@@ -329,7 +335,19 @@ ProfileLoader::Profile Transcoder::getProfileFromInputs(const std::vector<InputS
329335
assert(inputStreamDescArray.size() >= 1);
330336

331337
// Get properties from the first input
332-
const InputStreamDesc& inputStreamDesc = inputStreamDescArray.at(0);
338+
size_t nonEmptyFileName = std::numeric_limits<size_t>::max();
339+
for(size_t i = 0; i < inputStreamDescArray.size(); ++i)
340+
{
341+
if(!inputStreamDescArray.at(i)._filename.empty())
342+
{
343+
nonEmptyFileName = i;
344+
break;
345+
}
346+
}
347+
if(nonEmptyFileName == std::numeric_limits<size_t>::max())
348+
throw std::runtime_error("Cannot get profile from empty input streams");
349+
350+
const InputStreamDesc& inputStreamDesc = inputStreamDescArray.at(nonEmptyFileName);
333351
InputFile inputFile(inputStreamDesc._filename);
334352

335353
const StreamProperties* streamProperties = &inputFile.getProperties().getStreamPropertiesWithIndex(inputStreamDesc._streamIndex);
@@ -519,7 +537,19 @@ void Transcoder::fillProcessStat(ProcessStat& processStat)
519537
LOG_WARN("Cannot process statistics of generated stream.")
520538
continue;
521539
}
522-
const IInputStream* inputStream = _streamTranscoders.at(streamIndex)->getInputStreams().at(0);
540+
541+
size_t nonNullInputStreamIndex = 0;
542+
std::vector<IInputStream*> inputStreams = _streamTranscoders.at(streamIndex)->getInputStreams();
543+
for(size_t i = 0; i < inputStreams.size(); ++i)
544+
{
545+
if(inputStreams.at(i) != NULL)
546+
{
547+
nonNullInputStreamIndex = i;
548+
break;
549+
}
550+
}
551+
552+
const IInputStream* inputStream = inputStreams.at(nonNullInputStreamIndex);
523553
const AVMediaType mediaType = inputStream->getProperties().getStreamType();
524554
switch(mediaType)
525555
{

0 commit comments

Comments
 (0)