Skip to content

Commit 2dcdc1c

Browse files
author
Valentin NOEL
committed
FilterGraph: fix audio frames management with different sample formats
Comparing the frame sizes in samples (instead of bytes)
1 parent d2a7f54 commit 2dcdc1c

File tree

2 files changed

+48
-12
lines changed

2 files changed

+48
-12
lines changed

src/AvTranscoder/filter/FilterGraph.cpp

Lines changed: 40 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,11 @@ AudioFrameBuffer::~AudioFrameBuffer()
3636
popFrame();
3737
}
3838

39+
size_t AudioFrameBuffer::getBytesPerSample()
40+
{
41+
return av_get_bytes_per_sample(_audioFrameDesc._sampleFormat);
42+
}
43+
3944
void AudioFrameBuffer::addFrame(IFrame* frame)
4045
{
4146
LOG_DEBUG("Add a new " << frame->getDataSize() << " bytes frame to frame buffer. New buffer size: " << _frameQueue.size() + 1);
@@ -113,6 +118,12 @@ IFrame* AudioFrameBuffer::getFrame(const size_t size)
113118
return newAudioFrame;
114119
}
115120

121+
IFrame* AudioFrameBuffer::getFrameSampleNb(const size_t sampleNb)
122+
{
123+
const size_t expectedSize = sampleNb * getBytesPerSample();
124+
return getFrame(expectedSize);
125+
}
126+
116127

117128

118129
/******************
@@ -149,19 +160,29 @@ size_t FilterGraph::getAvailableFrameSize(const std::vector<IFrame*>& inputs, co
149160
return frameSize;
150161
}
151162

152-
size_t FilterGraph::getMinInputFrameSize(const std::vector<IFrame*>& inputs)
163+
size_t FilterGraph::getAvailableFrameSamplesNb(const std::vector<IFrame*>& inputs, const size_t& index)
164+
{
165+
if(_inputAudioFrameBuffers.empty())
166+
throw std::runtime_error("Cannot compute filter graph input samples number for non-audio frames.");
167+
168+
const size_t bytesPerSample = _inputAudioFrameBuffers.at(index).getBytesPerSample();
169+
const size_t availableSamplesNb = getAvailableFrameSize(inputs, index) / bytesPerSample;
170+
return availableSamplesNb;
171+
}
172+
173+
size_t FilterGraph::getMinInputFrameSamplesNb(const std::vector<IFrame*>& inputs)
153174
{
154175
if(!inputs.size())
155176
return 0;
156177

157-
size_t minFrameSize = getAvailableFrameSize(inputs, 0);
178+
size_t minFrameSamplesNb = getAvailableFrameSamplesNb(inputs, 0);
158179
for(size_t index = 1; index < inputs.size(); ++index)
159180
{
160-
const size_t availableFrameSize = getAvailableFrameSize(inputs, index);
161-
if(minFrameSize > availableFrameSize)
162-
minFrameSize = availableFrameSize;
181+
const size_t availableFrameSampleNb = getAvailableFrameSamplesNb(inputs, index);
182+
if(minFrameSamplesNb > availableFrameSampleNb)
183+
minFrameSamplesNb = availableFrameSampleNb;
163184
}
164-
return minFrameSize;
185+
return minFrameSamplesNb;
165186
}
166187

167188
bool FilterGraph::hasBufferedFrames()
@@ -194,7 +215,16 @@ bool FilterGraph::areInputFrameSizesEqual(const std::vector<IFrame*>& inputs)
194215
for(size_t index = 1; index < inputs.size(); ++index)
195216
{
196217
if(frameSize != inputs.at(index)->getDataSize())
197-
return false;
218+
{
219+
if(_inputAudioFrameBuffers.empty())
220+
return false;
221+
else
222+
{
223+
const size_t refSampleNb = frameSize / _inputAudioFrameBuffers.at(0).getBytesPerSample();
224+
const size_t sampleNb = inputs.at(index)->getDataSize() / _inputAudioFrameBuffers.at(index).getBytesPerSample();
225+
return (refSampleNb == sampleNb);
226+
}
227+
}
198228
}
199229
return true;
200230
}
@@ -220,7 +250,7 @@ void FilterGraph::process(const std::vector<IFrame*>& inputs, IFrame& output)
220250

221251
// Check whether we can bypass the input audio buffers
222252
const bool bypassBuffers = _inputAudioFrameBuffers.empty() || (areInputFrameSizesEqual(inputs) && areFrameBuffersEmpty());
223-
size_t minInputFrameSize = 0;
253+
size_t minInputFrameSamplesNb = 0;
224254

225255
if(!bypassBuffers)
226256
{
@@ -236,15 +266,15 @@ void FilterGraph::process(const std::vector<IFrame*>& inputs, IFrame& output)
236266
}
237267

238268
// Get the minimum input frames size
239-
minInputFrameSize = getMinInputFrameSize(inputs);
269+
minInputFrameSamplesNb = getMinInputFrameSamplesNb(inputs);
240270
}
241271

242272

243273
// Setup input frames into the filter graph
244274
for(size_t index = 0; index < inputs.size(); ++index)
245275
{
246276
// Retrieve frame from buffer or directly from input
247-
IFrame* inputFrame = (bypassBuffers)? inputs.at(index) : _inputAudioFrameBuffers.at(index).getFrame(minInputFrameSize);
277+
IFrame* inputFrame = (bypassBuffers)? inputs.at(index) : _inputAudioFrameBuffers.at(index).getFrameSampleNb(minInputFrameSamplesNb);
248278
const int ret = av_buffersrc_add_frame_flags(_filters.at(index)->getAVFilterContext(), &inputFrame->getAVFrame(), AV_BUFFERSRC_FLAG_PUSH);
249279

250280
if(ret < 0)

src/AvTranscoder/filter/FilterGraph.hpp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,10 @@ class AudioFrameBuffer
3939
* @brief Return the number of frames contained in the buffer.
4040
*/
4141
size_t getBufferSize() const { return _frameQueue.size(); }
42+
/**
43+
* @brief Return the number of bytes by sample from the internal AudioFrameDesc.
44+
*/
45+
size_t getBytesPerSample();
4246

4347
/**
4448
* @brief Push a frame at the end of the buffer.
@@ -50,6 +54,7 @@ class AudioFrameBuffer
5054
* If no size is specified, the whole first IFrame pointer is returned.
5155
*/
5256
IFrame* getFrame(const size_t size = 0);
57+
IFrame* getFrameSampleNb(const size_t sampleNb);
5358

5459
private:
5560
void popFrame();
@@ -138,10 +143,11 @@ class AvExport FilterGraph
138143
* @brief Return the input frame size if not null, or the available size into the corresponding frame buffer
139144
*/
140145
size_t getAvailableFrameSize(const std::vector<IFrame*>& inputs, const size_t& index);
146+
size_t getAvailableFrameSamplesNb(const std::vector<IFrame*>& inputs, const size_t& index);
141147
/**
142-
* @brief Get the minimum size between input frames, or available frame buffers
148+
* @brief Get the minimum samples number between input frames, or available frame buffers
143149
*/
144-
size_t getMinInputFrameSize(const std::vector<IFrame*>& inputs);
150+
size_t getMinInputFrameSamplesNb(const std::vector<IFrame*>& inputs);
145151

146152
bool areInputFrameSizesEqual(const std::vector<IFrame*>& inputs);
147153
bool areFrameBuffersEmpty();

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