Skip to content

Commit 82382fc

Browse files
author
Valentin NOEL
committed
StreamTranscoder: flush filter graph buffers after decoding process
Add utility methods, documentation and logs into FilterGraph and FrameBuffer classes
1 parent 27cf448 commit 82382fc

File tree

3 files changed

+72
-16
lines changed

3 files changed

+72
-16
lines changed

src/AvTranscoder/filter/FilterGraph.cpp

Lines changed: 45 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ FrameBuffer::~FrameBuffer()
3838

3939
void FrameBuffer::addFrame(IFrame* frame)
4040
{
41+
LOG_DEBUG("Add a new frame to frame buffer. New buffer size: " << _frameQueue.size() + 1);
42+
// Copy the input frame to store it into the queue
4143
AudioFrame* newAudioFrame = new AudioFrame(_audioFrameDesc, false);
4244
const size_t expectedNbSamples = frame->getDataSize() / (newAudioFrame->getNbChannels() * newAudioFrame->getBytesPerSample());
4345
newAudioFrame->setNbSamplesPerChannel(expectedNbSamples);
@@ -51,16 +53,19 @@ void FrameBuffer::addFrame(IFrame* frame)
5153
void FrameBuffer::popFrame()
5254
{
5355
_frameQueue.pop();
56+
LOG_DEBUG("Pop frame from buffer. Remaining frames in buffer: " << _frameQueue.size());
5457
}
5558

5659
IFrame* FrameBuffer::getFrame(const size_t size)
5760
{
61+
LOG_DEBUG("Get a " << size << " bytes frame from a " << _totalDataSize << " bytes frame buffer");
5862
IFrame* next = _frameQueue.front();
5963
const size_t nextFrameSize = next->getDataSize();
6064

6165
// If no expected size, or if the expected size equals the front frame of the queue (with no offset)
6266
if(size == 0 || (size == nextFrameSize && _positionInFrontFrame == 0))
6367
{
68+
// Directly return the front frame of the queue
6469
_totalDataSize -= nextFrameSize;
6570
popFrame();
6671
return next;
@@ -77,30 +82,34 @@ IFrame* FrameBuffer::getFrame(const size_t size)
7782
unsigned char* outputData = new unsigned char[size];
7883
while(extractedDataSize != size && _frameQueue.size() != 0)
7984
{
85+
// Get the front frame from queue
8086
next = _frameQueue.front();
81-
size_t dataToGet = size - extractedDataSize;
82-
size_t remainingDataInNextFrame = next->getDataSize() - _positionInFrontFrame;
87+
size_t remainingDataInFrontFrame = next->getDataSize() - _positionInFrontFrame;
8388

84-
if(dataToGet > remainingDataInNextFrame)
85-
dataToGet = remainingDataInNextFrame;
89+
// Compute the data size to get from the frame
90+
size_t dataToGet = size - extractedDataSize;
91+
if(dataToGet > remainingDataInFrontFrame)
92+
dataToGet = remainingDataInFrontFrame;
8693

94+
// Copy the data from the frame to temporal buffer
8795
for(size_t i = 0; i < dataToGet; i++)
8896
outputData[extractedDataSize++] = next->getData()[0][_positionInFrontFrame + i];
8997

90-
if(dataToGet < remainingDataInNextFrame)
98+
if(dataToGet < remainingDataInFrontFrame)
9199
{
100+
// Set new position into front frame
92101
_positionInFrontFrame += dataToGet;
93102
}
94103
else
95104
{
105+
// The whole front frame has been read, so pop it from queue
96106
popFrame();
97107
_positionInFrontFrame = 0;
98108
}
99109
}
100110

101111
_totalDataSize -= extractedDataSize;
102112
newAudioFrame->assignBuffer(outputData);
103-
104113
return newAudioFrame;
105114
}
106115

@@ -155,6 +164,27 @@ size_t FilterGraph::getMinInputFrameSize(const std::vector<IFrame*>& inputs)
155164
return minFrameSize;
156165
}
157166

167+
bool FilterGraph::hasBufferedFrames()
168+
{
169+
if(!_inputFramesBuffer.size())
170+
return false;
171+
172+
for(std::vector<FrameBuffer>::iterator it = _inputFramesBuffer.begin(); it != _inputFramesBuffer.end(); ++it)
173+
{
174+
if(it->isEmpty())
175+
return false;
176+
}
177+
return true;
178+
}
179+
180+
bool FilterGraph::hasBufferedFrames(const size_t index)
181+
{
182+
if(index >= _inputFramesBuffer.size())
183+
return false;
184+
185+
return !_inputFramesBuffer.at(index).isEmpty();
186+
}
187+
158188
bool FilterGraph::areInputFrameSizeEqual(const std::vector<IFrame*>& inputs)
159189
{
160190
if(!inputs.size() || inputs.size() == 1)
@@ -196,7 +226,14 @@ void FilterGraph::process(const std::vector<IFrame*>& inputs, IFrame& output)
196226
{
197227
// Fill the frame buffer with inputs
198228
for(size_t index = 0; index < inputs.size(); ++index)
229+
{
230+
if(!inputs.at(index)->getDataSize())
231+
{
232+
LOG_DEBUG("Empty frame from filter graph input " << index << ". Remaining frames in buffer: " << _inputFramesBuffer.at(index).getBufferSize());
233+
continue;
234+
}
199235
_inputFramesBuffer.at(index).addFrame(inputs.at(index));
236+
}
200237

201238
// Get the minimum input frames size
202239
minInputFrameSize = getMinInputFrameSize(inputs);
@@ -206,12 +243,8 @@ void FilterGraph::process(const std::vector<IFrame*>& inputs, IFrame& output)
206243
// Setup input frames into the filter graph
207244
for(size_t index = 0; index < inputs.size(); ++index)
208245
{
209-
IFrame* inputFrame = NULL;
210-
if(bypassBuffers)
211-
inputFrame = inputs.at(index);
212-
else
213-
inputFrame = _inputFramesBuffer.at(index).getFrame(minInputFrameSize);
214-
246+
// Retrieve frame from buffer or directly from input
247+
IFrame* inputFrame = (bypassBuffers)? inputs.at(index) : _inputFramesBuffer.at(index).getFrame(minInputFrameSize);
215248
const int ret = av_buffersrc_add_frame_flags(_filters.at(index)->getAVFilterContext(), &inputFrame->getAVFrame(), AV_BUFFERSRC_FLAG_PUSH);
216249

217250
if(ret < 0)

src/AvTranscoder/filter/FilterGraph.hpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,10 @@ class FrameBuffer
3535
* @brief Return the total amount of data contained in the frames of the buffer.
3636
*/
3737
size_t getDataSize() const { return _totalDataSize; }
38+
/**
39+
* @brief Return the number of frames contained in the buffer.
40+
*/
41+
size_t getBufferSize() const { return _frameQueue.size(); }
3842

3943
/**
4044
* @brief Push a frame at the end of the buffer.
@@ -107,6 +111,9 @@ class AvExport FilterGraph
107111
*/
108112
bool hasFilters() const { return !_filters.empty(); }
109113

114+
bool hasBufferedFrames();
115+
bool hasBufferedFrames(const size_t index);
116+
110117
private:
111118
/**
112119
* @brief Initialize the graph of filters to process.

src/AvTranscoder/transcoder/StreamTranscoder.cpp

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -533,7 +533,7 @@ bool StreamTranscoder::processTranscode()
533533

534534
// Decode
535535
LOG_DEBUG("Decode next frame")
536-
bool decodingStatus = true;
536+
std::vector<bool> decodingStatus(_generators.size(), true);
537537
for(size_t index = 0; index < _generators.size(); ++index)
538538
{
539539
if(getProcessCase() == eProcessCaseTranscode)
@@ -542,15 +542,17 @@ bool StreamTranscoder::processTranscode()
542542
_currentDecoder = _generators.at(index);
543543

544544
if(! _inputStreamDesc.empty() && _inputStreamDesc.at(index).demultiplexing())
545-
decodingStatus = decodingStatus && _currentDecoder->decodeNextFrame(*_decodedData.at(index), _inputStreamDesc.at(index)._channelIndexArray);
545+
decodingStatus.at(index) = decodingStatus.at(index) && _currentDecoder->decodeNextFrame(*_decodedData.at(index), _inputStreamDesc.at(index)._channelIndexArray);
546546
else
547-
decodingStatus = decodingStatus && _currentDecoder->decodeNextFrame(*_decodedData.at(index));
547+
decodingStatus.at(index) = decodingStatus.at(index) && _currentDecoder->decodeNextFrame(*_decodedData.at(index));
548548
}
549549

550550
// check the next data buffers in case of audio frames
551551
if(_decodedData.at(0)->isAudioFrame())
552552
{
553553
const int nbInputSamplesPerChannel = _decodedData.at(0)->getAVFrame().nb_samples;
554+
555+
// Reallocate output frame
554556
if(nbInputSamplesPerChannel > _filteredData->getAVFrame().nb_samples)
555557
{
556558
LOG_WARN("The buffer of filtered data corresponds to a frame of " << _filteredData->getAVFrame().nb_samples << " samples. The decoded buffer contains " << nbInputSamplesPerChannel << " samples. Reallocate it.")
@@ -569,7 +571,21 @@ bool StreamTranscoder::processTranscode()
569571

570572
// Transform
571573
CodedData data;
572-
if(decodingStatus)
574+
bool continueProcess = true;
575+
for(size_t index = 0; index < decodingStatus.size(); ++index)
576+
{
577+
if(!decodingStatus.at(index))
578+
{
579+
if(!_filterGraph->hasFilters() || !_filterGraph->hasBufferedFrames(index))
580+
{
581+
continueProcess = false;
582+
continue;
583+
}
584+
LOG_DEBUG("Some frames remain into filter graph buffer " << index);
585+
}
586+
}
587+
588+
if(continueProcess)
573589
{
574590
IFrame* dataToTransform = NULL;
575591
if(_filterGraph->hasFilters())

0 commit comments

Comments
 (0)