@@ -35,7 +35,7 @@ FilterGraph::~FilterGraph()
35
35
avfilter_graph_free (&_graph);
36
36
}
37
37
38
- void FilterGraph::process (const Frame& inputFrame , Frame& outputFrame )
38
+ void FilterGraph::process (const std::vector< Frame*>& inputs , Frame& output )
39
39
{
40
40
if (!hasFilters ())
41
41
{
@@ -45,20 +45,23 @@ void FilterGraph::process(const Frame& inputFrame, Frame& outputFrame)
45
45
46
46
// init filter graph
47
47
if (!_isInit)
48
- init (inputFrame, outputFrame );
48
+ init (inputs, output );
49
49
50
- // setup source frame
51
- int ret = av_buffersrc_write_frame (_filters.at (0 )->getAVFilterContext (), &inputFrame.getAVFrame ());
52
- if (ret < 0 )
50
+ // setup input frames
51
+ for (size_t index = 0 ; index < inputs.size (); ++index)
53
52
{
54
- throw std::runtime_error (" Error when adding a frame to the source buffer used to start to process filters: " +
55
- getDescriptionFromErrorCode (ret));
53
+ const int ret = av_buffersrc_write_frame (_filters.at (index)->getAVFilterContext (), &inputs.at (index)->getAVFrame ());
54
+ if (ret < 0 )
55
+ {
56
+ throw std::runtime_error (" Error when adding a frame to the source buffer used to start to process filters: " +
57
+ getDescriptionFromErrorCode (ret));
58
+ }
56
59
}
57
60
58
61
// pull filtered data from the filter graph
59
62
for (;;)
60
63
{
61
- ret = av_buffersink_get_frame (_filters.at (_filters.size () - 1 )->getAVFilterContext (), &outputFrame .getAVFrame ());
64
+ const int ret = av_buffersink_get_frame (_filters.at (_filters.size () - 1 )->getAVFilterContext (), &output .getAVFrame ());
62
65
if (ret == AVERROR_EOF || ret == AVERROR (EAGAIN))
63
66
break ;
64
67
if (ret < 0 )
@@ -77,22 +80,27 @@ Filter& FilterGraph::addFilter(const std::string& filterName, const std::string&
77
80
return *_filters.back ();
78
81
}
79
82
80
- void FilterGraph::init (const Frame& inputFrame , Frame& outputFrame )
83
+ void FilterGraph::init (const std::vector< Frame*>& inputs , Frame& output )
81
84
{
82
85
// push filters to the graph
83
- pushInBuffer (inputFrame );
86
+ pushInBuffer (inputs );
84
87
for (size_t i = 1 ; i < _filters.size (); ++i)
85
88
{
86
89
pushFilter (*_filters.at (i));
87
90
}
88
- pushOutBuffer (outputFrame );
91
+ pushOutBuffer (output );
89
92
90
93
// connect filters
91
94
for (size_t index = 0 ; index < _filters.size () - 1 ; ++index)
92
95
{
93
- LOG_INFO (" Connect filter " << _filters.at (index)->getName () << " to filter " << _filters.at (index + 1 )->getName ())
96
+ size_t indexOfFilterToConnect = index + 1 ;
97
+ // handle cases with several inputs
98
+ if (index < inputs.size ())
99
+ indexOfFilterToConnect = inputs.size ();
100
+
101
+ LOG_INFO (" Connect filter " << _filters.at (index)->getName () << " to filter " << _filters.at (indexOfFilterToConnect)->getName ())
94
102
const int err =
95
- avfilter_link (_filters.at (index)->getAVFilterContext (), 0 , _filters.at (index + 1 )->getAVFilterContext (), 0 );
103
+ avfilter_link (_filters.at (index)->getAVFilterContext (), 0 , _filters.at (indexOfFilterToConnect )->getAVFilterContext (), 0 );
96
104
if (err < 0 )
97
105
{
98
106
throw std::runtime_error (" Error when connecting filters." );
@@ -128,51 +136,54 @@ void FilterGraph::pushFilter(Filter& filter)
128
136
}
129
137
}
130
138
131
- void FilterGraph::pushInBuffer (const Frame& frame )
139
+ void FilterGraph::pushInBuffer (const std::vector< Frame*>& inputs )
132
140
{
133
- std::string filterName;
134
- std::stringstream filterOptions;
135
- // audio frame
136
- if (frame.isAudioFrame ())
137
- {
138
- filterName = " abuffer" ;
139
- const AudioFrame& audioFrame = dynamic_cast <const AudioFrame&>(frame);
140
- filterOptions << " time_base=" << _codec.getAVCodecContext ().time_base .num << " /"
141
- << _codec.getAVCodecContext ().time_base .den << " :" ;
142
- filterOptions << " sample_rate=" << audioFrame.getSampleRate () << " :" ;
143
- filterOptions << " sample_fmt=" << getSampleFormatName (audioFrame.getSampleFormat ()) << " :" ;
144
- filterOptions << " channel_layout=0x" << std::hex << audioFrame.getChannelLayout ();
145
- }
146
- // video frame
147
- else if (frame.isVideoFrame ())
141
+ for (std::vector<Frame*>::const_iterator it = inputs.begin (); it != inputs.end (); ++it)
148
142
{
149
- filterName = " buffer" ;
150
- const VideoFrame& videoFrame = dynamic_cast <const VideoFrame&>(frame);
151
- filterOptions << " video_size=" << videoFrame.getWidth () << " x" << videoFrame.getHeight () << " :" ;
152
- filterOptions << " pix_fmt=" << getPixelFormatName (videoFrame.getPixelFormat ()) << " :" ;
153
- filterOptions << " time_base=" << _codec.getAVCodecContext ().time_base .num << " /"
154
- << _codec.getAVCodecContext ().time_base .den << " :" ;
155
- filterOptions << " pixel_aspect=" << _codec.getAVCodecContext ().sample_aspect_ratio .num << " /"
156
- << _codec.getAVCodecContext ().sample_aspect_ratio .den ;
143
+ std::string filterName;
144
+ std::stringstream filterOptions;
145
+ // audio frame
146
+ if ((*it)->isAudioFrame ())
147
+ {
148
+ filterName = " abuffer" ;
149
+ const AudioFrame* audioFrame = dynamic_cast <const AudioFrame*>(*it);
150
+ filterOptions << " time_base=" << _codec.getAVCodecContext ().time_base .num << " /"
151
+ << _codec.getAVCodecContext ().time_base .den << " :" ;
152
+ filterOptions << " sample_rate=" << audioFrame->getSampleRate () << " :" ;
153
+ filterOptions << " sample_fmt=" << getSampleFormatName (audioFrame->getSampleFormat ()) << " :" ;
154
+ filterOptions << " channel_layout=0x" << std::hex << audioFrame->getChannelLayout ();
155
+ }
156
+ // video frame
157
+ else if ((*it)->isVideoFrame ())
158
+ {
159
+ filterName = " buffer" ;
160
+ const VideoFrame* videoFrame = dynamic_cast <const VideoFrame*>(*it);
161
+ filterOptions << " video_size=" << videoFrame->getWidth () << " x" << videoFrame->getHeight () << " :" ;
162
+ filterOptions << " pix_fmt=" << getPixelFormatName (videoFrame->getPixelFormat ()) << " :" ;
163
+ filterOptions << " time_base=" << _codec.getAVCodecContext ().time_base .num << " /"
164
+ << _codec.getAVCodecContext ().time_base .den << " :" ;
165
+ filterOptions << " pixel_aspect=" << _codec.getAVCodecContext ().sample_aspect_ratio .num << " /"
166
+ << _codec.getAVCodecContext ().sample_aspect_ratio .den ;
167
+ }
168
+ // invalid frame
169
+ else
170
+ throw std::runtime_error (" Cannot create input buffer of filter graph: the given frame is invalid." );
171
+
172
+ // add in buffer
173
+ Filter* in = new Filter (filterName, filterOptions.str (), " in" );
174
+ LOG_INFO (" Add filter '" << filterName << " ' at the beginning of the graph." )
175
+ _filters.insert (_filters.begin (), in);
176
+ pushFilter (*in);
157
177
}
158
- // invalid frame
159
- else
160
- throw std::runtime_error (" Cannot create input buffer of filter graph: the given frame is invalid." );
161
-
162
- // add in buffer
163
- Filter* in = new Filter (filterName, filterOptions.str (), " in" );
164
- LOG_INFO (" Add filter '" << filterName << " ' at the beginning of the graph." )
165
- _filters.insert (_filters.begin (), in);
166
- pushFilter (*in);
167
178
}
168
179
169
- void FilterGraph::pushOutBuffer (const Frame& frame )
180
+ void FilterGraph::pushOutBuffer (const Frame& output )
170
181
{
171
182
std::string filterName;
172
183
173
- if (frame .isAudioFrame ())
184
+ if (output .isAudioFrame ())
174
185
filterName = " abuffersink" ;
175
- else if (frame .isVideoFrame ())
186
+ else if (output .isVideoFrame ())
176
187
filterName = " buffersink" ;
177
188
else
178
189
throw std::runtime_error (" Cannot create output buffer of filter graph: the given frame is invalid." );
0 commit comments