Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitd33ffd2

Browse files
authored
Merge pull request#303 from valnoel/filter_inputMethod
Fix: different frame size as inputs of the filter graph
2 parents93961f4 +0e49751 commitd33ffd2

File tree

4 files changed

+448
-9
lines changed

4 files changed

+448
-9
lines changed

‎src/AvTranscoder/filter/FilterGraph.cpp

Lines changed: 242 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
#include"FilterGraph.hpp"
22

33
#include<AvTranscoder/util.hpp>
4-
#include<AvTranscoder/data/decoded/AudioFrame.hpp>
54
#include<AvTranscoder/data/decoded/VideoFrame.hpp>
65

76
extern"C" {
@@ -16,6 +15,123 @@ extern "C" {
1615
namespaceavtranscoder
1716
{
1817

18+
19+
/******************
20+
21+
AudioFrameBuffer
22+
23+
******************/
24+
25+
AudioFrameBuffer::AudioFrameBuffer(const AudioFrameDesc& audioFrameDesc)
26+
: _audioFrameDesc(audioFrameDesc)
27+
, _frameQueue()
28+
, _totalDataSize(0)
29+
, _positionInFrontFrame(0)
30+
{
31+
}
32+
33+
AudioFrameBuffer::~AudioFrameBuffer()
34+
{
35+
for(size_t i =0; i < _frameQueue.size(); ++i)
36+
popFrame();
37+
}
38+
39+
size_tAudioFrameBuffer::getBytesPerSample()
40+
{
41+
returnav_get_bytes_per_sample(_audioFrameDesc._sampleFormat);
42+
}
43+
44+
voidAudioFrameBuffer::addFrame(IFrame* frame)
45+
{
46+
LOG_DEBUG("Add a new" << frame->getDataSize() <<" bytes frame to frame buffer. New buffer size:" << _frameQueue.size() +1);
47+
// Copy the input frame to store it into the queue
48+
AudioFrame* newAudioFrame =newAudioFrame(_audioFrameDesc,false);
49+
constsize_t expectedNbSamples = frame->getDataSize() / (newAudioFrame->getNbChannels() * newAudioFrame->getBytesPerSample());
50+
newAudioFrame->setNbSamplesPerChannel(expectedNbSamples);
51+
newAudioFrame->allocateData();
52+
newAudioFrame->copyData(*frame);
53+
54+
_totalDataSize += newAudioFrame->getDataSize();
55+
_frameQueue.push(newAudioFrame);
56+
}
57+
58+
voidAudioFrameBuffer::popFrame()
59+
{
60+
_frameQueue.pop();
61+
LOG_DEBUG("Pop frame from buffer. Remaining frames in buffer:" << _frameQueue.size());
62+
}
63+
64+
IFrame*AudioFrameBuffer::getFrame(constsize_t size)
65+
{
66+
LOG_DEBUG("Get a" << size <<" bytes frame from a" << _totalDataSize <<" bytes frame buffer");
67+
IFrame* next = _frameQueue.front();
68+
constsize_t nextFrameSize = next->getDataSize();
69+
70+
// If no expected size, or if the expected size equals the front frame of the queue (with no offset)
71+
if(size ==0 || (size == nextFrameSize && _positionInFrontFrame ==0))
72+
{
73+
// Directly return the front frame of the queue
74+
_totalDataSize -= nextFrameSize;
75+
popFrame();
76+
return next;
77+
}
78+
79+
// Create a new frame
80+
AudioFrame* newAudioFrame =newAudioFrame(_audioFrameDesc,false);
81+
constsize_t expectedNbSamples = size / (newAudioFrame->getNbChannels() * newAudioFrame->getBytesPerSample());
82+
newAudioFrame->setNbSamplesPerChannel(expectedNbSamples);
83+
newAudioFrame->allocateData();
84+
85+
// Concatenate frames data
86+
size_t extractedDataSize =0;
87+
unsignedchar* outputData =newunsignedchar[size];
88+
while(extractedDataSize != size && _frameQueue.size() !=0)
89+
{
90+
// Get the front frame from queue
91+
next = _frameQueue.front();
92+
size_t remainingDataInFrontFrame = next->getDataSize() - _positionInFrontFrame;
93+
94+
// Compute the data size to get from the frame
95+
size_t dataToGet = size - extractedDataSize;
96+
if(dataToGet > remainingDataInFrontFrame)
97+
dataToGet = remainingDataInFrontFrame;
98+
99+
// Copy the data from the frame to temporal buffer
100+
for(size_t i =0; i < dataToGet; i++)
101+
outputData[extractedDataSize++] = next->getData()[0][_positionInFrontFrame + i];
102+
103+
if(dataToGet < remainingDataInFrontFrame)
104+
{
105+
// Set new position into front frame
106+
_positionInFrontFrame += dataToGet;
107+
}
108+
else
109+
{
110+
// The whole front frame has been read, so pop it from queue
111+
popFrame();
112+
_positionInFrontFrame =0;
113+
}
114+
}
115+
116+
_totalDataSize -= extractedDataSize;
117+
newAudioFrame->assignBuffer(outputData);
118+
return newAudioFrame;
119+
}
120+
121+
IFrame*AudioFrameBuffer::getFrameSampleNb(constsize_t sampleNb)
122+
{
123+
constsize_t expectedSize = sampleNb *getBytesPerSample();
124+
returngetFrame(expectedSize);
125+
}
126+
127+
128+
129+
/******************
130+
131+
FilterGraph
132+
133+
******************/
134+
19135
FilterGraph::FilterGraph(const ICodec& codec)
20136
: _graph(avfilter_graph_alloc())
21137
, _filters()
@@ -28,31 +144,147 @@ FilterGraph::FilterGraph(const ICodec& codec)
28144

29145
FilterGraph::~FilterGraph()
30146
{
147+
_inputAudioFrameBuffers.clear();
31148
for(std::vector<Filter*>::iterator it = _filters.begin(); it < _filters.end(); ++it)
32149
{
33150
delete(*it);
34151
}
35152
avfilter_graph_free(&_graph);
36153
}
37154

155+
size_tFilterGraph::getAvailableFrameSize(const std::vector<IFrame*>& inputs,constsize_t& index)
156+
{
157+
size_t frameSize = inputs.at(index)->getDataSize();
158+
if(frameSize ==0)
159+
frameSize = _inputAudioFrameBuffers.at(index).getDataSize();
160+
return frameSize;
161+
}
162+
163+
size_tFilterGraph::getAvailableFrameSamplesNb(const std::vector<IFrame*>& inputs,constsize_t& index)
164+
{
165+
if(_inputAudioFrameBuffers.empty())
166+
throwstd::runtime_error("Cannot compute filter graph input samples number for non-audio frames.");
167+
168+
constsize_t bytesPerSample = _inputAudioFrameBuffers.at(index).getBytesPerSample();
169+
constsize_t availableSamplesNb =getAvailableFrameSize(inputs, index) / bytesPerSample;
170+
return availableSamplesNb;
171+
}
172+
173+
size_tFilterGraph::getMinInputFrameSamplesNb(const std::vector<IFrame*>& inputs)
174+
{
175+
if(!inputs.size())
176+
return0;
177+
178+
size_t minFrameSamplesNb =getAvailableFrameSamplesNb(inputs,0);
179+
for(size_t index =1; index < inputs.size(); ++index)
180+
{
181+
constsize_t availableFrameSampleNb =getAvailableFrameSamplesNb(inputs, index);
182+
if(minFrameSamplesNb > availableFrameSampleNb)
183+
minFrameSamplesNb = availableFrameSampleNb;
184+
}
185+
return minFrameSamplesNb;
186+
}
187+
188+
boolFilterGraph::hasBufferedFrames()
189+
{
190+
if(!_inputAudioFrameBuffers.size())
191+
returnfalse;
192+
193+
for(std::vector<AudioFrameBuffer>::iterator it = _inputAudioFrameBuffers.begin(); it != _inputAudioFrameBuffers.end(); ++it)
194+
{
195+
if(it->isEmpty())
196+
returnfalse;
197+
}
198+
returntrue;
199+
}
200+
201+
boolFilterGraph::hasBufferedFrames(constsize_t index)
202+
{
203+
if(index >= _inputAudioFrameBuffers.size())
204+
returnfalse;
205+
206+
return !_inputAudioFrameBuffers.at(index).isEmpty();
207+
}
208+
209+
boolFilterGraph::areInputFrameSizesEqual(const std::vector<IFrame*>& inputs)
210+
{
211+
if(!inputs.size() || inputs.size() ==1)
212+
returntrue;
213+
214+
constint frameSize = inputs.at(0)->getDataSize();
215+
for(size_t index =1; index < inputs.size(); ++index)
216+
{
217+
if(frameSize != inputs.at(index)->getDataSize())
218+
{
219+
if(_inputAudioFrameBuffers.empty())
220+
returnfalse;
221+
else
222+
{
223+
constsize_t refSampleNb = frameSize / _inputAudioFrameBuffers.at(0).getBytesPerSample();
224+
constsize_t sampleNb = inputs.at(index)->getDataSize() / _inputAudioFrameBuffers.at(index).getBytesPerSample();
225+
return (refSampleNb == sampleNb);
226+
}
227+
}
228+
}
229+
returntrue;
230+
}
231+
232+
boolFilterGraph::areFrameBuffersEmpty()
233+
{
234+
if(!_inputAudioFrameBuffers.size())
235+
returntrue;
236+
237+
for(std::vector<AudioFrameBuffer>::iterator it = _inputAudioFrameBuffers.begin(); it != _inputAudioFrameBuffers.end(); ++it)
238+
{
239+
if(!it->isEmpty())
240+
returnfalse;
241+
}
242+
returntrue;
243+
}
244+
38245
voidFilterGraph::process(const std::vector<IFrame*>& inputs, IFrame& output)
39246
{
40-
//init filter graph
247+
//Init the filter graph
41248
if(!_isInit)
42249
init(inputs, output);
43250

44-
// setup input frames
251+
// Check whether we can bypass the input audio buffers
252+
constbool bypassBuffers = _inputAudioFrameBuffers.empty() || (areInputFrameSizesEqual(inputs) &&areFrameBuffersEmpty());
253+
size_t minInputFrameSamplesNb =0;
254+
255+
if(!bypassBuffers)
256+
{
257+
// Fill the frame buffer with inputs
258+
for(size_t index =0; index < inputs.size(); ++index)
259+
{
260+
if(!inputs.at(index)->getDataSize())
261+
{
262+
LOG_DEBUG("Empty frame from filter graph input" << index <<". Remaining audio frames in buffer:" << _inputAudioFrameBuffers.at(index).getBufferSize());
263+
continue;
264+
}
265+
_inputAudioFrameBuffers.at(index).addFrame(inputs.at(index));
266+
}
267+
268+
// Get the minimum input frames size
269+
minInputFrameSamplesNb =getMinInputFrameSamplesNb(inputs);
270+
}
271+
272+
273+
// Setup input frames into the filter graph
45274
for(size_t index =0; index < inputs.size(); ++index)
46275
{
47-
constint ret =av_buffersrc_write_frame(_filters.at(index)->getAVFilterContext(), &inputs.at(index)->getAVFrame());
276+
// Retrieve frame from buffer or directly from input
277+
IFrame* inputFrame = (bypassBuffers)? inputs.at(index) : _inputAudioFrameBuffers.at(index).getFrameSampleNb(minInputFrameSamplesNb);
278+
constint ret =av_buffersrc_add_frame_flags(_filters.at(index)->getAVFilterContext(), &inputFrame->getAVFrame(), AV_BUFFERSRC_FLAG_PUSH);
279+
48280
if(ret <0)
49281
{
50282
throwstd::runtime_error("Error when adding a frame to the source buffer used to start to process filters:" +
51283
getDescriptionFromErrorCode(ret));
52284
}
53285
}
54286

55-
//pull filtered data from the filter graph
287+
//Pull filtered data from the filter graph
56288
for(;;)
57289
{
58290
constint ret =av_buffersink_get_frame(_filters.at(_filters.size() -1)->getAVFilterContext(), &output.getAVFrame());
@@ -150,6 +382,11 @@ void FilterGraph::addInBuffer(const std::vector<IFrame*>& inputs)
150382
filterOptions <<"sample_rate=" << audioFrame->getSampleRate() <<":";
151383
filterOptions <<"sample_fmt=" <<getSampleFormatName(audioFrame->getSampleFormat()) <<":";
152384
filterOptions <<"channel_layout=0x" << std::hex << audioFrame->getChannelLayout();
385+
386+
const AudioFrameDescaudioFrameDesc(audioFrame->getSampleRate(),
387+
audioFrame->getNbChannels(),
388+
getSampleFormatName(audioFrame->getSampleFormat()));
389+
_inputAudioFrameBuffers.insert(_inputAudioFrameBuffers.begin(),AudioFrameBuffer(audioFrameDesc));
153390
}
154391
// video frame
155392
elseif((*it)->isVideoFrame())

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp