Skip to content

Commit 80017d6

Browse files
author
Valentin NOEL
committed
FilterGraph: add new internal FrameBuffer class
Used as frame buffers on the filter graph inputs. For the moment, this first version only handles audio frames.
1 parent 2dc9d24 commit 80017d6

File tree

2 files changed

+142
-1
lines changed

2 files changed

+142
-1
lines changed

src/AvTranscoder/filter/FilterGraph.cpp

Lines changed: 97 additions & 1 deletion
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,103 @@ extern "C" {
1615
namespace avtranscoder
1716
{
1817

18+
19+
/******************
20+
21+
FrameBuffer
22+
23+
******************/
24+
25+
FrameBuffer::FrameBuffer(const AudioFrameDesc& audioFrameDesc)
26+
: _audioFrameDesc(audioFrameDesc)
27+
, _frameQueue()
28+
, _totalDataSize(0)
29+
, _positionInFrontFrame(0)
30+
{
31+
}
32+
33+
FrameBuffer::~FrameBuffer()
34+
{
35+
for (int i = 0; i < _frameQueue.size(); ++i)
36+
popFrame();
37+
}
38+
39+
void FrameBuffer::addFrame(IFrame* frame)
40+
{
41+
AudioFrame* newAudioFrame = new AudioFrame(_audioFrameDesc, false);
42+
const size_t expectedNbSamples = frame->getDataSize() / (newAudioFrame->getNbChannels() * newAudioFrame->getBytesPerSample());
43+
newAudioFrame->setNbSamplesPerChannel(expectedNbSamples);
44+
newAudioFrame->allocateData();
45+
newAudioFrame->copyData(*frame);
46+
47+
_totalDataSize += newAudioFrame->getDataSize();
48+
_frameQueue.push(newAudioFrame);
49+
}
50+
51+
void FrameBuffer::popFrame()
52+
{
53+
_frameQueue.pop();
54+
}
55+
56+
IFrame* FrameBuffer::getFrame(const size_t size)
57+
{
58+
IFrame* next = _frameQueue.front();
59+
const size_t nextFrameSize = next->getDataSize();
60+
61+
// If no expected size, or if the expected size equals the front frame of the queue (with no offset)
62+
if(size == 0 || (size == nextFrameSize && _positionInFrontFrame == 0))
63+
{
64+
_totalDataSize -= nextFrameSize;
65+
popFrame();
66+
return next;
67+
}
68+
69+
// Create a new frame
70+
AudioFrame* newAudioFrame = new AudioFrame(_audioFrameDesc, false);
71+
const size_t expectedNbSamples = size / (newAudioFrame->getNbChannels() * newAudioFrame->getBytesPerSample());
72+
newAudioFrame->setNbSamplesPerChannel(expectedNbSamples);
73+
newAudioFrame->allocateData();
74+
75+
// Concatenate frames data
76+
size_t extractedDataSize = 0;
77+
unsigned char* outputData = new unsigned char[size];
78+
while(extractedDataSize != size && _frameQueue.size() != 0)
79+
{
80+
next = _frameQueue.front();
81+
size_t dataToGet = size - extractedDataSize;
82+
size_t remainingDataInNextFrame = next->getDataSize() - _positionInFrontFrame;
83+
84+
if(dataToGet > remainingDataInNextFrame)
85+
dataToGet = remainingDataInNextFrame;
86+
87+
for(size_t i = 0; i < dataToGet; i++)
88+
outputData[extractedDataSize++] = next->getData()[0][_positionInFrontFrame + i];
89+
90+
if(dataToGet < remainingDataInNextFrame)
91+
{
92+
_positionInFrontFrame += dataToGet;
93+
}
94+
else
95+
{
96+
popFrame();
97+
_positionInFrontFrame = 0;
98+
}
99+
}
100+
101+
_totalDataSize -= extractedDataSize;
102+
newAudioFrame->assignBuffer(outputData);
103+
104+
return newAudioFrame;
105+
}
106+
107+
108+
109+
/******************
110+
111+
FilterGraph
112+
113+
******************/
114+
19115
FilterGraph::FilterGraph(const ICodec& codec)
20116
: _graph(avfilter_graph_alloc())
21117
, _filters()

src/AvTranscoder/filter/FilterGraph.hpp

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,59 @@
55
#include <AvTranscoder/filter/Filter.hpp>
66
#include <AvTranscoder/codec/ICodec.hpp>
77
#include <AvTranscoder/data/decoded/IFrame.hpp>
8+
#include <AvTranscoder/data/decoded/AudioFrame.hpp>
89

910
#include <vector>
11+
#include <queue>
1012

1113
struct AVFilterGraph;
1214

1315
namespace avtranscoder
1416
{
1517

18+
/**
19+
* @brief Filter graph input frame buffer.
20+
* This FIFO buffer contains IFrame pointers and can deliver specific size frames.
21+
*
22+
* @todo Only for audio frame, for the moment. Make it usable with video frames.
23+
**/
24+
class FrameBuffer
25+
{
26+
public:
27+
FrameBuffer(const AudioFrameDesc& audioFrameDesc);
28+
~FrameBuffer();
29+
30+
/**
31+
* @brief Return whether the buffer is empty or not.
32+
*/
33+
bool isEmpty() { return _frameQueue.empty() && _totalDataSize == 0; }
34+
/**
35+
* @brief Return the total amount of data contained in the frames of the buffer.
36+
*/
37+
size_t getDataSize() { return _totalDataSize; }
38+
39+
/**
40+
* @brief Push a frame at the end of the buffer.
41+
*/
42+
void addFrame(IFrame* frame);
43+
44+
/**
45+
* @brief Retrieve a IFrame pointer of the specified size, from the beginning of the buffer.
46+
* If no size is specified, the whole first IFrame pointer is returned.
47+
*/
48+
IFrame* getFrame(const size_t size = 0);
49+
50+
private:
51+
void popFrame();
52+
53+
const AudioFrameDesc _audioFrameDesc;
54+
55+
std::queue<IFrame*> _frameQueue;
56+
size_t _totalDataSize;
57+
size_t _positionInFrontFrame;
58+
59+
};
60+
1661
/**
1762
* @brief Manager of filters.
1863
**/

0 commit comments

Comments
 (0)