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