Skip to content

Commit 55a4bab

Browse files
author
Valentin NOEL
committed
StreamTranscoder: add null input stream to generate output channel
If the InputStreamDesc filename is empty, a generator is set up as input
1 parent d33ffd2 commit 55a4bab

File tree

3 files changed

+113
-10
lines changed

3 files changed

+113
-10
lines changed

src/AvTranscoder/transcoder/StreamTranscoder.cpp

Lines changed: 81 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -147,12 +147,22 @@ StreamTranscoder::StreamTranscoder(const std::vector<InputStreamDesc>& inputStre
147147
size_t nbOutputChannels = 0;
148148
for(size_t index = 0; index < inputStreams.size(); ++index)
149149
{
150-
addDecoder(_inputStreamDesc.at(index), *_inputStreams.at(index));
151-
nbOutputChannels += _inputStreamDesc.at(index)._channelIndexArray.size();
150+
if(_inputStreams.at(index) != NULL)
151+
{
152+
LOG_INFO("add decoder for input stream " << index);
153+
addDecoder(_inputStreamDesc.at(index), *_inputStreams.at(index));
154+
nbOutputChannels += _inputStreamDesc.at(index)._channelIndexArray.size();
155+
}
156+
else
157+
{
158+
LOG_INFO("add generator for empty input " << index);
159+
addGenerator(_inputStreamDesc.at(index), profile);
160+
}
152161
}
153162

154-
IInputStream& inputStream = *_inputStreams.at(0);
155-
const InputStreamDesc& inputStreamDesc = inputStreamsDesc.at(0);
163+
const size_t firstInputStreamIndex = getFirstInputStreamIndex();
164+
IInputStream& inputStream = *_inputStreams.at(firstInputStreamIndex);
165+
const InputStreamDesc& inputStreamDesc = inputStreamsDesc.at(firstInputStreamIndex);
156166

157167
// create a transcode case
158168
switch(inputStream.getProperties().getStreamType())
@@ -229,6 +239,16 @@ StreamTranscoder::StreamTranscoder(const std::vector<InputStreamDesc>& inputStre
229239
setOffset(offset);
230240
}
231241

242+
size_t StreamTranscoder::getFirstInputStreamIndex()
243+
{
244+
for(size_t index = 0; index < _inputStreams.size(); ++index)
245+
{
246+
if(_inputStreams.at(index) != NULL)
247+
return index;
248+
}
249+
throw std::runtime_error("Cannot handle only null input streams");
250+
}
251+
232252
void StreamTranscoder::addDecoder(const InputStreamDesc& inputStreamDesc, IInputStream& inputStream)
233253
{
234254
// create a transcode case
@@ -278,6 +298,53 @@ void StreamTranscoder::addDecoder(const InputStreamDesc& inputStreamDesc, IInput
278298
}
279299
}
280300

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

376443
for(std::vector<IDecoder*>::iterator it = _inputDecoders.begin(); it != _inputDecoders.end(); ++it)
377444
{
378-
delete(*it);
445+
if(*it != NULL)
446+
delete(*it);
379447
}
380448
for(std::vector<IDecoder*>::iterator it = _generators.begin(); it != _generators.end(); ++it)
381449
{
@@ -548,9 +616,10 @@ bool StreamTranscoder::processTranscode()
548616
}
549617

550618
// check the next data buffers in case of audio frames
551-
if(_decodedData.at(0)->isAudioFrame())
619+
const size_t firstInputStreamIndex = getFirstInputStreamIndex();
620+
if(_decodedData.at(firstInputStreamIndex)->isAudioFrame())
552621
{
553-
const int nbInputSamplesPerChannel = _decodedData.at(0)->getAVFrame().nb_samples;
622+
const int nbInputSamplesPerChannel = _decodedData.at(firstInputStreamIndex)->getAVFrame().nb_samples;
554623

555624
// Reallocate output frame
556625
if(nbInputSamplesPerChannel > _filteredData->getAVFrame().nb_samples)
@@ -670,7 +739,11 @@ float StreamTranscoder::getDuration() const
670739
float minStreamDuration = -1;
671740
for(size_t index = 0; index < _inputStreams.size(); ++index)
672741
{
673-
const StreamProperties& streamProperties = _inputStreams.at(index)->getProperties();
742+
IInputStream* inputStream = _inputStreams.at(index);
743+
if(inputStream == NULL)
744+
continue;
745+
746+
const StreamProperties& streamProperties = inputStream->getProperties();
674747
if(minStreamDuration == -1 || streamProperties.getDuration() < minStreamDuration)
675748
minStreamDuration = streamProperties.getDuration();
676749
}

src/AvTranscoder/transcoder/StreamTranscoder.hpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,10 +125,13 @@ 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();
131132

133+
size_t getFirstInputStreamIndex();
134+
132135
private:
133136
std::vector<InputStreamDesc> _inputStreamDesc; ///< Description of the data to extract from the input stream.
134137
std::vector<IInputStream*> _inputStreams; ///< List of input stream to read next packet (has link, no ownership)

src/AvTranscoder/transcoder/Transcoder.cpp

Lines changed: 29 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,16 @@ 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 = 0;
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+
const InputStreamDesc& inputStreamDesc = inputStreamDescArray.at(nonEmptyFileName);
333348
InputFile inputFile(inputStreamDesc._filename);
334349

335350
const StreamProperties* streamProperties = &inputFile.getProperties().getStreamPropertiesWithIndex(inputStreamDesc._streamIndex);
@@ -519,7 +534,19 @@ void Transcoder::fillProcessStat(ProcessStat& processStat)
519534
LOG_WARN("Cannot process statistics of generated stream.")
520535
continue;
521536
}
522-
const IInputStream* inputStream = _streamTranscoders.at(streamIndex)->getInputStreams().at(0);
537+
538+
size_t nonNullInputStreamIndex = 0;
539+
std::vector<IInputStream*> inputStreams = _streamTranscoders.at(streamIndex)->getInputStreams();
540+
for(size_t i = 0; i < inputStreams.size(); ++i)
541+
{
542+
if(inputStreams.at(i) != NULL)
543+
{
544+
nonNullInputStreamIndex = i;
545+
break;
546+
}
547+
}
548+
549+
const IInputStream* inputStream = inputStreams.at(nonNullInputStreamIndex);
523550
const AVMediaType mediaType = inputStream->getProperties().getStreamType();
524551
switch(mediaType)
525552
{

0 commit comments

Comments
 (0)