Skip to content

Muxing silent audio channels #304

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Sep 28, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/AvTranscoder/transcoder/InputStreamDesc.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ struct InputStreamDesc
bool demultiplexing() const { return !_channelIndexArray.empty(); }

public:
std::string _filename; ///< Source file path.
std::string _filename; ///< Source file path. If empty, a generator is used as source.
size_t _streamIndex; ///< Source stream to extract.
std::vector<size_t> _channelIndexArray; ///< List of source channels to extract from the stream
};
Expand Down
116 changes: 102 additions & 14 deletions src/AvTranscoder/transcoder/StreamTranscoder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ StreamTranscoder::StreamTranscoder(IInputStream& inputStream, IOutputFile& outpu
, _outputEncoder(NULL)
, _transform(NULL)
, _filterGraph(NULL)
, _firstInputStreamIndex(0)
, _offset(offset)
, _needToSwitchToGenerator(false)
{
Expand Down Expand Up @@ -140,19 +141,35 @@ StreamTranscoder::StreamTranscoder(const std::vector<InputStreamDesc>& inputStre
, _outputEncoder(NULL)
, _transform(NULL)
, _filterGraph(NULL)
, _firstInputStreamIndex(std::numeric_limits<size_t>::max())
, _offset(offset)
, _needToSwitchToGenerator(false)
{
// add as many decoders as input streams
size_t nbOutputChannels = 0;
for(size_t index = 0; index < inputStreams.size(); ++index)
{
addDecoder(_inputStreamDesc.at(index), *_inputStreams.at(index));
nbOutputChannels += _inputStreamDesc.at(index)._channelIndexArray.size();
if(_inputStreams.at(index) != NULL)
{
LOG_INFO("add decoder for input stream " << index);
addDecoder(_inputStreamDesc.at(index), *_inputStreams.at(index));
nbOutputChannels += _inputStreamDesc.at(index)._channelIndexArray.size();
if(_firstInputStreamIndex == std::numeric_limits<size_t>::max())
_firstInputStreamIndex = index;
}
else
{
LOG_INFO("add generator for empty input " << index);
addGenerator(_inputStreamDesc.at(index), profile);
nbOutputChannels++;
}
}

IInputStream& inputStream = *_inputStreams.at(0);
const InputStreamDesc& inputStreamDesc = inputStreamsDesc.at(0);
if(_firstInputStreamIndex == std::numeric_limits<size_t>::max())
throw std::runtime_error("Cannot handle empty only input streams");

IInputStream& inputStream = *_inputStreams.at(_firstInputStreamIndex);
const InputStreamDesc& inputStreamDesc = inputStreamsDesc.at(_firstInputStreamIndex);

// create a transcode case
switch(inputStream.getProperties().getStreamType())
Expand Down Expand Up @@ -278,6 +295,53 @@ void StreamTranscoder::addDecoder(const InputStreamDesc& inputStreamDesc, IInput
}
}

void StreamTranscoder::addGenerator(const InputStreamDesc& inputStreamDesc, const ProfileLoader::Profile& profile)
{
// create a transcode case
if(profile.find(constants::avProfileType)->second == constants::avProfileTypeVideo)
{
VideoCodec inputVideoCodec(eCodecTypeEncoder, profile.find(constants::avProfileCodec)->second);
VideoFrameDesc inputFrameDesc(profile);
inputVideoCodec.setImageParameters(inputFrameDesc);

// generator decoder
VideoGenerator* generator = new VideoGenerator(inputFrameDesc);
_generators.push_back(generator);
_currentDecoder = generator;

// buffers to process
VideoFrameDesc outputFrameDesc = inputFrameDesc;
outputFrameDesc.setParameters(profile);
_decodedData.push_back(new VideoFrame(inputFrameDesc));

// no decoder for this input
_inputDecoders.push_back(NULL);

}
else if(profile.find(constants::avProfileType)->second == constants::avProfileTypeAudio)
{
// corresponding input codec
AudioCodec inputAudioCodec(eCodecTypeEncoder, profile.find(constants::avProfileCodec)->second);
AudioFrameDesc inputFrameDesc(profile);
inputFrameDesc._nbChannels = 1;
inputAudioCodec.setAudioParameters(inputFrameDesc);

// generator decoder
AudioGenerator* generator = new AudioGenerator(inputFrameDesc);
_generators.push_back(generator);
_currentDecoder = generator;
// buffers to get the decoded data
_decodedData.push_back(new AudioFrame(inputFrameDesc));

// no decoder for this input
_inputDecoders.push_back(NULL);
}
else
{
throw std::runtime_error("unupported stream type");
}
}

StreamTranscoder::StreamTranscoder(IOutputFile& outputFile, const ProfileLoader::Profile& profile)
: _inputStreamDesc()
, _inputStreams()
Expand All @@ -291,6 +355,7 @@ StreamTranscoder::StreamTranscoder(IOutputFile& outputFile, const ProfileLoader:
, _outputEncoder(NULL)
, _transform(NULL)
, _filterGraph(NULL)
, _firstInputStreamIndex(0)
, _offset(0)
, _needToSwitchToGenerator(false)
{
Expand Down Expand Up @@ -375,7 +440,8 @@ StreamTranscoder::~StreamTranscoder()

for(std::vector<IDecoder*>::iterator it = _inputDecoders.begin(); it != _inputDecoders.end(); ++it)
{
delete(*it);
if(*it != NULL)
delete(*it);
}
for(std::vector<IDecoder*>::iterator it = _generators.begin(); it != _generators.end(); ++it)
{
Expand Down Expand Up @@ -536,7 +602,8 @@ bool StreamTranscoder::processTranscode()
std::vector<bool> decodingStatus(_generators.size(), true);
for(size_t index = 0; index < _generators.size(); ++index)
{
if(getProcessCase() == eProcessCaseTranscode)
EProcessCase processCase = getProcessCase(index);
if(processCase == eProcessCaseTranscode)
_currentDecoder = _inputDecoders.at(index);
else
_currentDecoder = _generators.at(index);
Expand All @@ -548,9 +615,9 @@ bool StreamTranscoder::processTranscode()
}

// check the next data buffers in case of audio frames
if(_decodedData.at(0)->isAudioFrame())
if(_decodedData.at(_firstInputStreamIndex)->isAudioFrame())
{
const int nbInputSamplesPerChannel = _decodedData.at(0)->getAVFrame().nb_samples;
const int nbInputSamplesPerChannel = _decodedData.at(_firstInputStreamIndex)->getAVFrame().nb_samples;

// Reallocate output frame
if(nbInputSamplesPerChannel > _filteredData->getAVFrame().nb_samples)
Expand Down Expand Up @@ -670,7 +737,11 @@ float StreamTranscoder::getDuration() const
float minStreamDuration = -1;
for(size_t index = 0; index < _inputStreams.size(); ++index)
{
const StreamProperties& streamProperties = _inputStreams.at(index)->getProperties();
IInputStream* inputStream = _inputStreams.at(index);
if(inputStream == NULL)
continue;

const StreamProperties& streamProperties = inputStream->getProperties();
if(minStreamDuration == -1 || streamProperties.getDuration() < minStreamDuration)
minStreamDuration = streamProperties.getDuration();
}
Expand Down Expand Up @@ -722,13 +793,30 @@ void StreamTranscoder::setOffset(const float offset)
}
}

StreamTranscoder::EProcessCase StreamTranscoder::getProcessCase() const
StreamTranscoder::EProcessCase StreamTranscoder::getProcessCase(const size_t decoderIndex) const
{
if(! _inputStreams.empty() && ! _inputDecoders.empty() && std::find(_inputDecoders.begin(), _inputDecoders.end(), _currentDecoder) != _inputDecoders.end() )
return eProcessCaseTranscode;
else if(! _inputStreams.empty() && _inputDecoders.empty() && !_currentDecoder)
return eProcessCaseRewrap;
if(_inputStreamDesc.size() <= 1)
{
if(! _inputStreams.empty() && ! _inputDecoders.empty() && std::find(_inputDecoders.begin(), _inputDecoders.end(), _currentDecoder) != _inputDecoders.end() )
return eProcessCaseTranscode;
else if(! _inputStreams.empty() && _inputDecoders.empty() && !_currentDecoder)
return eProcessCaseRewrap;
else
return eProcessCaseGenerator;
}
else
{
if(! _inputStreams.empty() && _currentDecoder != NULL)
{
if( _inputStreams.at(decoderIndex) != NULL)
return eProcessCaseTranscode;
return eProcessCaseGenerator;
}
else if(! _inputStreams.empty() && _inputDecoders.empty() && !_currentDecoder)
{
return eProcessCaseRewrap;
}
return eProcessCaseGenerator;
}
}
}
5 changes: 4 additions & 1 deletion src/AvTranscoder/transcoder/StreamTranscoder.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ class AvExport StreamTranscoder
eProcessCaseRewrap,
eProcessCaseGenerator
};
EProcessCase getProcessCase() const;
EProcessCase getProcessCase(const size_t decoderIndex = 0) const;
//@}

private:
Expand All @@ -125,6 +125,7 @@ class AvExport StreamTranscoder
* @param inputStream
*/
void addDecoder(const InputStreamDesc& inputStreamDesc, IInputStream& inputStream);
void addGenerator(const InputStreamDesc& inputStreamDesc, const ProfileLoader::Profile& profile);

bool processRewrap();
bool processTranscode();
Expand All @@ -147,6 +148,8 @@ class AvExport StreamTranscoder

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

size_t _firstInputStreamIndex; ///< Index of the first non-null input stream.

float _offset; ///< Offset, in seconds, at the beginning of the StreamTranscoder.

bool _needToSwitchToGenerator; ///< Set if need to switch to a generator during the process (because, of other streams
Expand Down
34 changes: 32 additions & 2 deletions src/AvTranscoder/transcoder/Transcoder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,12 @@ void Transcoder::addTranscodeStream(const std::vector<InputStreamDesc>& inputStr
AVMediaType commonStreamType = AVMEDIA_TYPE_UNKNOWN;
for(std::vector<InputStreamDesc>::const_iterator it = inputStreamDescArray.begin(); it != inputStreamDescArray.end(); ++it)
{
if(it->_filename.empty())
{
inputStreams.push_back(NULL);
continue;
}

InputFile* referenceFile = addInputFile(it->_filename, it->_streamIndex, offset);
inputStreams.push_back(&referenceFile->getStream(it->_streamIndex));

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

// Get properties from the first input
const InputStreamDesc& inputStreamDesc = inputStreamDescArray.at(0);
size_t nonEmptyFileName = std::numeric_limits<size_t>::max();
for(size_t i = 0; i < inputStreamDescArray.size(); ++i)
{
if(!inputStreamDescArray.at(i)._filename.empty())
{
nonEmptyFileName = i;
break;
}
}
if(nonEmptyFileName == std::numeric_limits<size_t>::max())
throw std::runtime_error("Cannot get profile from empty input streams");

const InputStreamDesc& inputStreamDesc = inputStreamDescArray.at(nonEmptyFileName);
InputFile inputFile(inputStreamDesc._filename);

const StreamProperties* streamProperties = &inputFile.getProperties().getStreamPropertiesWithIndex(inputStreamDesc._streamIndex);
Expand Down Expand Up @@ -519,7 +537,19 @@ void Transcoder::fillProcessStat(ProcessStat& processStat)
LOG_WARN("Cannot process statistics of generated stream.")
continue;
}
const IInputStream* inputStream = _streamTranscoders.at(streamIndex)->getInputStreams().at(0);

size_t nonNullInputStreamIndex = 0;
std::vector<IInputStream*> inputStreams = _streamTranscoders.at(streamIndex)->getInputStreams();
for(size_t i = 0; i < inputStreams.size(); ++i)
{
if(inputStreams.at(i) != NULL)
{
nonNullInputStreamIndex = i;
break;
}
}

const IInputStream* inputStream = inputStreams.at(nonNullInputStreamIndex);
const AVMediaType mediaType = inputStream->getProperties().getStreamType();
switch(mediaType)
{
Expand Down
Loading