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