1
1
#include " FilterGraph.hpp"
2
2
3
3
#include < AvTranscoder/util.hpp>
4
- #include < AvTranscoder/data/decoded/AudioFrame.hpp>
5
4
#include < AvTranscoder/data/decoded/VideoFrame.hpp>
6
5
7
6
extern " C" {
@@ -16,6 +15,123 @@ extern "C" {
16
15
namespace avtranscoder
17
16
{
18
17
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_t AudioFrameBuffer::getBytesPerSample ()
40
+ {
41
+ return av_get_bytes_per_sample (_audioFrameDesc._sampleFormat );
42
+ }
43
+
44
+ void AudioFrameBuffer::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 =new AudioFrame (_audioFrameDesc,false );
49
+ const size_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
+ void AudioFrameBuffer::popFrame ()
59
+ {
60
+ _frameQueue.pop ();
61
+ LOG_DEBUG (" Pop frame from buffer. Remaining frames in buffer:" << _frameQueue.size ());
62
+ }
63
+
64
+ IFrame*AudioFrameBuffer::getFrame (const size_t size)
65
+ {
66
+ LOG_DEBUG (" Get a" << size <<" bytes frame from a" << _totalDataSize <<" bytes frame buffer" );
67
+ IFrame* next = _frameQueue.front ();
68
+ const size_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 =new AudioFrame (_audioFrameDesc,false );
81
+ const size_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
+ unsigned char * outputData =new unsigned char [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 (const size_t sampleNb)
122
+ {
123
+ const size_t expectedSize = sampleNb *getBytesPerSample ();
124
+ return getFrame (expectedSize);
125
+ }
126
+
127
+
128
+
129
+ /* *****************
130
+
131
+ FilterGraph
132
+
133
+ ******************/
134
+
19
135
FilterGraph::FilterGraph (const ICodec& codec)
20
136
: _graph(avfilter_graph_alloc())
21
137
, _filters()
@@ -28,31 +144,147 @@ FilterGraph::FilterGraph(const ICodec& codec)
28
144
29
145
FilterGraph::~FilterGraph ()
30
146
{
147
+ _inputAudioFrameBuffers.clear ();
31
148
for (std::vector<Filter*>::iterator it = _filters.begin (); it < _filters.end (); ++it)
32
149
{
33
150
delete (*it);
34
151
}
35
152
avfilter_graph_free (&_graph);
36
153
}
37
154
155
+ size_t FilterGraph::getAvailableFrameSize (const std::vector<IFrame*>& inputs,const size_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_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)
174
+ {
175
+ if (!inputs.size ())
176
+ return 0 ;
177
+
178
+ size_t minFrameSamplesNb =getAvailableFrameSamplesNb (inputs,0 );
179
+ for (size_t index =1 ; index < inputs.size (); ++index)
180
+ {
181
+ const size_t availableFrameSampleNb =getAvailableFrameSamplesNb (inputs, index);
182
+ if (minFrameSamplesNb > availableFrameSampleNb)
183
+ minFrameSamplesNb = availableFrameSampleNb;
184
+ }
185
+ return minFrameSamplesNb;
186
+ }
187
+
188
+ bool FilterGraph::hasBufferedFrames ()
189
+ {
190
+ if (!_inputAudioFrameBuffers.size ())
191
+ return false ;
192
+
193
+ for (std::vector<AudioFrameBuffer>::iterator it = _inputAudioFrameBuffers.begin (); it != _inputAudioFrameBuffers.end (); ++it)
194
+ {
195
+ if (it->isEmpty ())
196
+ return false ;
197
+ }
198
+ return true ;
199
+ }
200
+
201
+ bool FilterGraph::hasBufferedFrames (const size_t index)
202
+ {
203
+ if (index >= _inputAudioFrameBuffers.size ())
204
+ return false ;
205
+
206
+ return !_inputAudioFrameBuffers.at (index).isEmpty ();
207
+ }
208
+
209
+ bool FilterGraph::areInputFrameSizesEqual (const std::vector<IFrame*>& inputs)
210
+ {
211
+ if (!inputs.size () || inputs.size () ==1 )
212
+ return true ;
213
+
214
+ const int 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
+ 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
+ }
228
+ }
229
+ return true ;
230
+ }
231
+
232
+ bool FilterGraph::areFrameBuffersEmpty ()
233
+ {
234
+ if (!_inputAudioFrameBuffers.size ())
235
+ return true ;
236
+
237
+ for (std::vector<AudioFrameBuffer>::iterator it = _inputAudioFrameBuffers.begin (); it != _inputAudioFrameBuffers.end (); ++it)
238
+ {
239
+ if (!it->isEmpty ())
240
+ return false ;
241
+ }
242
+ return true ;
243
+ }
244
+
38
245
void FilterGraph::process (const std::vector<IFrame*>& inputs, IFrame& output)
39
246
{
40
- // init filter graph
247
+ // Init the filter graph
41
248
if (!_isInit)
42
249
init (inputs, output);
43
250
44
- // setup input frames
251
+ // Check whether we can bypass the input audio buffers
252
+ const bool 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
45
274
for (size_t index =0 ; index < inputs.size (); ++index)
46
275
{
47
- const int 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
+ const int ret =av_buffersrc_add_frame_flags (_filters.at (index)->getAVFilterContext (), &inputFrame->getAVFrame (), AV_BUFFERSRC_FLAG_PUSH);
279
+
48
280
if (ret <0 )
49
281
{
50
282
throw std::runtime_error (" Error when adding a frame to the source buffer used to start to process filters:" +
51
283
getDescriptionFromErrorCode (ret));
52
284
}
53
285
}
54
286
55
- // pull filtered data from the filter graph
287
+ // Pull filtered data from the filter graph
56
288
for (;;)
57
289
{
58
290
const int 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)
150
382
filterOptions <<" sample_rate=" << audioFrame->getSampleRate () <<" :" ;
151
383
filterOptions <<" sample_fmt=" <<getSampleFormatName (audioFrame->getSampleFormat ()) <<" :" ;
152
384
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));
153
390
}
154
391
// video frame
155
392
else if ((*it)->isVideoFrame ())